diff options
| -rw-r--r-- | Dockerfile | 2 | ||||
| -rw-r--r-- | Makefile | 20 | ||||
| -rw-r--r-- | cmd/generate/main.go | 44 | ||||
| -rw-r--r-- | cmd/home/main.go | 132 | ||||
| -rw-r--r-- | embed.go | 4 | ||||
| -rw-r--r-- | go.mod | 12 | ||||
| -rw-r--r-- | go.sum | 12 | ||||
| -rw-r--r-- | posts/001.md | 35 | ||||
| -rw-r--r-- | public/index.html | 99 | ||||
| -rw-r--r-- | public/posts.html | 59 | ||||
| -rw-r--r-- | templates/index.html | 2 | ||||
| -rw-r--r-- | templates/layouts/default.html | 3 | ||||
| -rw-r--r-- | templates/layouts/header.html | 5 | ||||
| -rw-r--r-- | templates/post.html | 5 | ||||
| -rw-r--r-- | templates/posts.html | 7 |
15 files changed, 218 insertions, 223 deletions
@@ -6,7 +6,7 @@ COPY go.mod go.sum ./ RUN go mod download && go mod verify COPY . . -RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /usr/local/bin/app ./... +RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /usr/local/bin/app ./cmd/home/ FROM scratch @@ -1,12 +1,18 @@ -.PHONY: fly +VERSION=0.0.1 +DOCKER_IMAGE=alexemery/home:${VERSION} +.PHONY: fly fly: cd proxy && fly deploy -.PHONY: content -content: - go run ./cmd/generate - -.PHONY: serve -serve: content +.PHONY: serve +serve: go run ./cmd/home + +.PHONY: image +image: + docker build . -t ${DOCKER_IMAGE} + +.PHONY: public +public: image + docker push ${DOCKER_IMAGE} diff --git a/cmd/generate/main.go b/cmd/generate/main.go deleted file mode 100644 index a739fea..0000000 --- a/cmd/generate/main.go +++ /dev/null @@ -1,44 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - "path/filepath" - "text/template" -) - -func Run() error { - t, err := template.ParseGlob("./templates/layouts/*.html") - // t, err := template.ParseFiles("index.html", "header.html") - if err != nil { - return fmt.Errorf("Failed to parse layouts: %v", err) - } - - for _, page := range []string{"index.html", "posts.html"} { - file, err := os.Create(filepath.Join("public", page)) - if err != nil { - return fmt.Errorf("Failed to create file: %v", err) - } - - defer file.Close() - - foo, err := t.ParseFiles("./templates/" + page) - if err != nil { - return fmt.Errorf("Parse template file: %v", err) - } - - err = foo.ExecuteTemplate(file, "index.html", nil) - if err != nil { - return fmt.Errorf("Failed to generate file: %v", err) - } - } - - return nil - -} -func main() { - if err := Run(); err != nil { - log.Fatal(err) - } -} diff --git a/cmd/home/main.go b/cmd/home/main.go index f284c30..01bddee 100644 --- a/cmd/home/main.go +++ b/cmd/home/main.go @@ -1,15 +1,131 @@ package main import ( + "bytes" + "fmt" + "io" "io/fs" "log" "net/http" + "path/filepath" + "strings" + "text/template" "time" "git.sr.ht/~a73x/home" + "github.com/yuin/goldmark" + "github.com/yuin/goldmark/parser" + "go.abhg.dev/goldmark/frontmatter" "go.uber.org/zap" ) +type CommonData struct { + Posts []PostData +} + +type PostData struct { + Title string + Path string +} + +func GeneratePosts(mux *http.ServeMux) ([]PostData, error) { + converter := goldmark.New( + goldmark.WithExtensions( + &frontmatter.Extender{}, + )) + + t, err := template.ParseFS(home.Content, "templates/layouts/*.html") + if err != nil { + return nil, fmt.Errorf("failed to parse layouts: %v", err) + } + + final := []PostData{} + posts, err := fs.Glob(home.Content, "posts/*.md") + if err != nil { + return nil, fmt.Errorf("failed to glob posts: %v", err) + } + + for _, post := range posts { + postName := filepath.Base(post) + postName = strings.Split(postName, ".")[0] + ".html" + + // parse markdown + input, err := fs.ReadFile(home.Content, post) + if err != nil { + return nil, fmt.Errorf("failed to read post: %v", err) + } + + var b bytes.Buffer + ctx := parser.NewContext() + if err := converter.Convert(input, &b, parser.WithContext(ctx)); err != nil { + return nil, err + } + + d := frontmatter.Get(ctx) + var meta map[string]string + if err := d.Decode(&meta); err != nil { + return nil, err + } + + foo, err := t.ParseFS(home.Content, "templates/post.html") + if err != nil { + return nil, fmt.Errorf("failed to parse post template: %v", err) + } + + content, err := io.ReadAll(&b) + if err != nil { + return nil, fmt.Errorf("failed to read post template: %v", err) + } + + mux.HandleFunc("/posts/"+postName, func(w http.ResponseWriter, r *http.Request) { + if err := foo.ExecuteTemplate(w, "post.html", string(content)); err != nil { + fmt.Println(err) + } + }) + + final = append(final, PostData{ + Title: meta["title"], + Path: "posts/" + postName, + }) + } + + return final, nil +} + +func loadTemplates(mux *http.ServeMux, data any) error { + tmplFiles, err := fs.ReadDir(home.Content, "templates") + if err != nil { + return fmt.Errorf("failed to parse template layouts") + } + + for _, tmpl := range tmplFiles { + if tmpl.IsDir() { + continue + } + + pt, err := template.ParseFS(home.Content, "templates/"+tmpl.Name(), "templates/layouts/*.html") + if err != nil { + return fmt.Errorf("failed to parse template "+tmpl.Name(), err) + } + + if tmpl.Name() == "index.html" { + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + pt.ExecuteTemplate(w, tmpl.Name(), data) + }) + } else if tmpl.Name() == "page.html" { + continue + } else { + mux.HandleFunc("/"+tmpl.Name(), func(w http.ResponseWriter, r *http.Request) { + pt, err := template.ParseFS(home.Content, "templates/"+tmpl.Name(), "templates/layouts/*.html") + if err != nil { + fmt.Printf("failed to parse template "+tmpl.Name(), err) + } + pt.ExecuteTemplate(w, tmpl.Name(), data) + }) + } + } + return nil +} func main() { logger, _ := zap.NewProduction() loggingMiddleware := func(next http.Handler) http.Handler { @@ -26,13 +142,25 @@ func main() { } mux := http.NewServeMux() + postData, err := GeneratePosts(mux) + data := CommonData{ + Posts: postData, + } + + if err != nil { + log.Fatal("failed to generate posts", err) + } + + if err := loadTemplates(mux, data); err != nil { + log.Fatal("failed to parse templates", err) + } - staticFs, err := fs.Sub(home.Content, "public") + staticFs, err := fs.Sub(home.Content, "public/static") if err != nil { log.Fatal(err) } - mux.Handle("GET /", http.FileServer(http.FS(staticFs))) + mux.Handle("GET /static", http.FileServer(http.FS(staticFs))) server := http.Server{ Addr: ":8080", @@ -3,5 +3,7 @@ package home import "embed" //go:embed public/static/*.woff2 -//go:embed public/*.html +//go:embed templates/*.html +//go:embed templates/layouts/*.html +//go:embed posts/*.md var Content embed.FS @@ -2,6 +2,14 @@ module git.sr.ht/~a73x/home go 1.22.5 -require go.uber.org/zap v1.27.0 +require ( + github.com/yuin/goldmark v1.7.4 + go.abhg.dev/goldmark/frontmatter v0.2.0 + go.uber.org/zap v1.27.0 +) -require go.uber.org/multierr v1.10.0 // indirect +require ( + github.com/BurntSushi/toml v1.2.1 // indirect + go.uber.org/multierr v1.10.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) @@ -1,14 +1,22 @@ +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= +github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= +go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/posts/001.md b/posts/001.md new file mode 100644 index 0000000..9942c2f --- /dev/null +++ b/posts/001.md @@ -0,0 +1,35 @@ +--- +title: "Go Benchmarking" +--- +## Benchmarking +1. write a benchmark +2. run a benchmark +3. get a profile +4. optimise +5. run your tests +6. goto 2. +### cpuprofile +`go test -test=XXX -bench <regex> -cpuprofile <file>` + +### memprofile +`go test -test=XXX -bench <regex> -memprofile <file> -benchmem` + +### pprof +[pprof usage](https://github.com/google/pprof/blob/main/doc/README.md) + +`go pprof -http=:8080 profile.pb.gz` +will show a web UI for analysing the profile. + +#### views: +- flame graph: `localhost:8080/ui/flamegraph` + - shows percentage breakdown of how much resource each "call" made. + - clicking a box will make it "100%" allowing for deep diving + - right click "show source code" to view +- top: `localhost:8080/ui/top` + - shows top functions + - `flat`: profile samples in this function + - `cum`: (cumulative) profile samples in this function and its callees +- source: `localhost:8080/ui/source` + - each source line is annotated with the time spent in that source line + - the first number does not count time spent in functions called from the source line + - the second number does
\ No newline at end of file diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 61413a8..0000000 --- a/public/index.html +++ /dev/null @@ -1,99 +0,0 @@ - -<!DOCTYPE html> -<html lang="en"> - -<head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - <meta name="description" content="Home for a73x" /> - <meta name="author" content="a73x" /> - <meta name="viewport" - content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" /> - <title>a73x</title> - <style> - @font-face { - font-family: 'Mono'; - src: url('./static/V1-ServerMono-Regular.woff2') format('woff2'); - font-weight: normal; - font-style: normal; - } - - body { - font-family: "Mono"; - } - - code { - font-family: "Mono"; - color: crimson; - background-color: #f1f1f1; - padding: 2px; - } - - nav ul { - display: flex; - list-style: none; - } - - nav ul li { - margin-right: 20px; - } - </style> -</head> - -<body> - <!-- templates/header.html --> -<h1>a73x</h1> -<nav> - <ul> - <li><a href="/">Home</a></li> - <li><a href="/posts">Posts</a></li> - </ul> -</nav> - - - <ul> - <li>backend cloud software engineer</li> - <li>lang: go</li> - <li>infra: kubernetes</li> - </ul> - <h2>daily learnings</h2> - <h3>#go</h3> - <ul> - <li>layout packages by what they do, not by their abstract type</li> - <li>use channels sparingly. write synchronous methods and allow the caller to make it async</li> - <li><code>append</code> modifies the underlying slice, you'll only make this mistake once</li> - <li>define interfaces where you use them</li> - <li><code>make([]int, 5)</code> has a length and capacity of 5. <code>([]int, 0,5)</code> has a length - of 0 and capacity of 5. - <br /> - <code>append()</code> will only do what you want with the latter - </li> - <li>don't use <code>init()</code></li> - <li>TFBO (test, fix, benchmark, optimise)</li> - </ul> - <h3>#git</h3> - <ul> - <li><code>git commit --fixup=<COMMITSH></code> - <br /> - <code>git rebase origin/main --autosquash</code> - </li> - </ul> - - <h2>Books</h2> - <ul> - <li><a href=https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063 />Designing - Data Intensive Applications</a></li> - <li><a href=https://www.oreilly.com/library/view/database-internals/9781492040330 />Database Internals - </a> - </li> - <li> - <a href=https://www.oreilly.com/library/view/efficient-go/9781098105709 /> Efficient Go</a> - - </li> - - </ul> - -</body> - -</html> - - diff --git a/public/posts.html b/public/posts.html deleted file mode 100644 index b63f4da..0000000 --- a/public/posts.html +++ /dev/null @@ -1,59 +0,0 @@ - -<!DOCTYPE html> -<html lang="en"> - -<head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - <meta name="description" content="Home for a73x" /> - <meta name="author" content="a73x" /> - <meta name="viewport" - content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" /> - <title>a73x</title> - <style> - @font-face { - font-family: 'Mono'; - src: url('./static/V1-ServerMono-Regular.woff2') format('woff2'); - font-weight: normal; - font-style: normal; - } - - body { - font-family: "Mono"; - } - - code { - font-family: "Mono"; - color: crimson; - background-color: #f1f1f1; - padding: 2px; - } - - nav ul { - display: flex; - list-style: none; - } - - nav ul li { - margin-right: 20px; - } - </style> -</head> - -<body> - <!-- templates/header.html --> -<h1>a73x</h1> -<nav> - <ul> - <li><a href="/">Home</a></li> - <li><a href="/posts">Posts</a></li> - </ul> -</nav> - - -<h1>Posts</h1> - -</body> - -</html> - - diff --git a/templates/index.html b/templates/index.html index ee1a64c..8f07cc0 100644 --- a/templates/index.html +++ b/templates/index.html @@ -28,7 +28,7 @@ </li> </ul> - <h2>Books</h2> + <h2>books</h2> <ul> <li><a href=https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063 />Designing Data Intensive Applications</a></li> diff --git a/templates/layouts/default.html b/templates/layouts/default.html index cfb0c17..5c8bf64 100644 --- a/templates/layouts/default.html +++ b/templates/layouts/default.html @@ -12,12 +12,13 @@ <style> @font-face { font-family: 'Mono'; - src: url('./static/V1-ServerMono-Regular.woff2') format('woff2'); + src: url('/static/V1-ServerMono-Regular.woff2') format('woff2'); font-weight: normal; font-style: normal; } body { + max-width: 70ch; font-family: "Mono"; } diff --git a/templates/layouts/header.html b/templates/layouts/header.html index be02def..f1d2d18 100644 --- a/templates/layouts/header.html +++ b/templates/layouts/header.html @@ -1,8 +1,7 @@ -<!-- templates/header.html --> <h1>a73x</h1> <nav> <ul> - <li><a href="/">Home</a></li> - <li><a href="/posts">Posts</a></li> + <li><a href="/">home</a></li> + <li><a href="/posts.html">posts</a></li> </ul> </nav> diff --git a/templates/post.html b/templates/post.html new file mode 100644 index 0000000..69c17e2 --- /dev/null +++ b/templates/post.html @@ -0,0 +1,5 @@ +{{template "base" .}} +{{define "content"}} +{{ . }} +{{end}} + diff --git a/templates/posts.html b/templates/posts.html index 75d3801..c68fb73 100644 --- a/templates/posts.html +++ b/templates/posts.html @@ -1,4 +1,9 @@ {{template "base" .}} {{define "content"}} -<h1>Posts</h1> +<h1>posts</h1> +<ul> + {{range .Posts}} + <li><a href="{{.Path}}">{{.Title}}</a></li> +{{end}} +</ul> {{end}} |
