From ad7bf16ef3175f62613f63ffb11683de6b9ca2fe Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Mon, 20 Jul 2026 19:43:58 +0800 Subject: [PATCH 01/21] chore: . --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c2bec0368b..849142ee2c 100644 --- a/README.md +++ b/README.md @@ -20,4 +20,5 @@ go build -o notely && ./notely *This starts the server in non-database mode.* It will serve a simple webpage at `http://localhost:8080`. +vadhe version of Boot.dev's Notely app. You do *not* need to set up a database or any interactivity on the webpage yet. Instructions for that will come later in the course! From ff9b2c467a594236dc88e353064e4f6d4cb7b915 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Mon, 20 Jul 2026 19:52:12 +0800 Subject: [PATCH 02/21] chore: ci --- .github/workflows/ci.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..a2cf2a837a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +name: ci + +on: + pull_request: + branches: [main] + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.26.0" + + - name: Force Failure + run: (exit 1) From 4c2fb82608f78ff3fd4074cae613c4c4815d060d Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Mon, 20 Jul 2026 19:54:55 +0800 Subject: [PATCH 03/21] chore: ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2cf2a837a..59c79383a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,4 +19,4 @@ jobs: go-version: "1.26.0" - name: Force Failure - run: (exit 1) + run: go --version From 92cb6e418e53325f572cd5c30f66d02bdd3045de Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Mon, 20 Jul 2026 19:56:56 +0800 Subject: [PATCH 04/21] chore: ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59c79383a5..6d1b248377 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,4 +19,4 @@ jobs: go-version: "1.26.0" - name: Force Failure - run: go --version + run: go version From 65836fb38499f2f3e3e5c141ec28ab417d10afb7 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:38:37 +0800 Subject: [PATCH 05/21] test --- .github/workflows/ci.yml | 4 ++-- middleware_auth.go | 2 +- middleware_auth_test.go | 43 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 middleware_auth_test.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d1b248377..1f067ffbdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,5 +18,5 @@ jobs: with: go-version: "1.26.0" - - name: Force Failure - run: go version + - name: Run Tests + run: go test ./... diff --git a/middleware_auth.go b/middleware_auth.go index 6cbe03f867..17aedc7e79 100644 --- a/middleware_auth.go +++ b/middleware_auth.go @@ -13,7 +13,7 @@ func (cfg *apiConfig) middlewareAuth(handler authedHandler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { apiKey, err := auth.GetAPIKey(r.Header) if err != nil { - respondWithError(w, http.StatusUnauthorized, "Couldn't find api key", err) + respondWithError(w, http.StatusOK, "Couldn't find api key", err) return } diff --git a/middleware_auth_test.go b/middleware_auth_test.go new file mode 100644 index 0000000000..1bdeaca8b7 --- /dev/null +++ b/middleware_auth_test.go @@ -0,0 +1,43 @@ +package main + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/bootdotdev/learn-cicd-starter/internal/database" +) + +func TestAuthMiddleware(t *testing.T) { + tests := []struct { + name string + token string + expected int + }{ + { + name: "invalid token", + token: "Bearer invalid", + expected: http.StatusUnauthorized, + }, + } + + apiCfg := apiConfig{} + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "/", nil) + req.Header.Set("Authorization", tt.token) + rr := httptest.NewRecorder() + + nextHandler := func(w http.ResponseWriter, r *http.Request, user database.User) { + w.WriteHeader(http.StatusOK) + } + handler := apiCfg.middlewareAuth(nextHandler) + handler.ServeHTTP(rr, req) + + if rr.Code != tt.expected { + t.Errorf("expected status code %d, got %d", tt.expected, rr.Code) + } + }) + } +} From aa911573f80b51ea2af5d3b6f9cb110e545c50c6 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:39:52 +0800 Subject: [PATCH 06/21] test --- middleware_auth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleware_auth.go b/middleware_auth.go index 17aedc7e79..6cbe03f867 100644 --- a/middleware_auth.go +++ b/middleware_auth.go @@ -13,7 +13,7 @@ func (cfg *apiConfig) middlewareAuth(handler authedHandler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { apiKey, err := auth.GetAPIKey(r.Header) if err != nil { - respondWithError(w, http.StatusOK, "Couldn't find api key", err) + respondWithError(w, http.StatusUnauthorized, "Couldn't find api key", err) return } From fcf29ff1aabb1c9a935cdd62bf532b0d7d2f1646 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:48:11 +0800 Subject: [PATCH 07/21] cover --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f067ffbdf..cfd07e8070 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,4 +19,4 @@ jobs: go-version: "1.26.0" - name: Run Tests - run: go test ./... + run: go test ./... -cover From 10475b43a5f34f11796a07d2a0fb8ba2dc67a11d Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:52:41 +0800 Subject: [PATCH 08/21] img --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 849142ee2c..a535a27a77 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,6 @@ go build -o notely && ./notely vadhe version of Boot.dev's Notely app. You do *not* need to set up a database or any interactivity on the webpage yet. Instructions for that will come later in the course! + + +![alt text goes here](https://github.com/vadhe/learn-cicd-starter/actions/workflows/ci.yml/badge.svg) From 4bcedc81bf5bdf66288f369808cb4119186538ea Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:03:57 +0800 Subject: [PATCH 09/21] test fmt --- .github/workflows/ci.yml | 2 ++ internal/database/db.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cfd07e8070..884bae33a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,8 @@ jobs: uses: actions/setup-go@v6 with: go-version: "1.26.0" + - name: Run Format + run: test -z $(go fmt ./...) - name: Run Tests run: go test ./... -cover diff --git a/internal/database/db.go b/internal/database/db.go index 61f5bf46c8..acdfb5c943 100644 --- a/internal/database/db.go +++ b/internal/database/db.go @@ -17,7 +17,7 @@ type DBTX interface { } func New(db DBTX) *Queries { - return &Queries{db: db} +return &Queries{db: db} } type Queries struct { From 73fbfd58ab235efb694f5200a082ab7b0bd4703e Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:12:31 +0800 Subject: [PATCH 10/21] style --- .github/workflows/ci.yml | 17 +++++++++++++++-- internal/database/db.go | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 884bae33a9..54ce00d980 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,8 +17,21 @@ jobs: uses: actions/setup-go@v6 with: go-version: "1.26.0" - - name: Run Format - run: test -z $(go fmt ./...) - name: Run Tests run: go test ./... -cover + style: + name: Style + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.26.0" + + - name: Run Style + run: test -z $(go fmt ./...) diff --git a/internal/database/db.go b/internal/database/db.go index acdfb5c943..61f5bf46c8 100644 --- a/internal/database/db.go +++ b/internal/database/db.go @@ -17,7 +17,7 @@ type DBTX interface { } func New(db DBTX) *Queries { -return &Queries{db: db} + return &Queries{db: db} } type Queries struct { From 893d57766855bf8ee2da987dc6c4a74e4f372ba3 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:37:07 +0800 Subject: [PATCH 11/21] linting --- .github/workflows/ci.yml | 17 +++++++++++++++++ main.go | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54ce00d980..66fa2beeff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,23 @@ on: branches: [main] jobs: + linting: + name: Linting + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.26.0" + - uses: dominikh/staticcheck-action@v1 + with: + version: "latest" + - name: Run Linting + run: staticcheck ./... tests: name: Tests runs-on: ubuntu-latest diff --git a/main.go b/main.go index 19d7366c5f..0cdadac81f 100644 --- a/main.go +++ b/main.go @@ -96,3 +96,8 @@ func main() { log.Printf("Serving on port: %s\n", port) log.Fatal(srv.ListenAndServe()) } + +func unused() { + // this function does nothing + // and is called nowhere +} From a457044e61c5c0fc78fa4b3e128428bf723dec04 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:38:44 +0800 Subject: [PATCH 12/21] fix linting --- main.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/main.go b/main.go index 0cdadac81f..19d7366c5f 100644 --- a/main.go +++ b/main.go @@ -96,8 +96,3 @@ func main() { log.Printf("Serving on port: %s\n", port) log.Fatal(srv.ListenAndServe()) } - -func unused() { - // this function does nothing - // and is called nowhere -} From 5181a8f298fe69c9449c8d5b6f25c2da75660316 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:41:09 +0800 Subject: [PATCH 13/21] lint --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66fa2beeff..18c438f4c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: branches: [main] jobs: - linting: + staticcheck: name: Linting runs-on: ubuntu-latest From c9ce931ecc97a20946a1e1f948a32c10e5f3ccf0 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:43:18 +0800 Subject: [PATCH 14/21] linting --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18c438f4c4..5aaa798a6b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - uses: dominikh/staticcheck-action@v1 with: version: "latest" - - name: Run Linting + - name: Run staticcheck run: staticcheck ./... tests: name: Tests From 643746c278a584aa6a3a64b0d2e1759646e235ff Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:53:27 +0800 Subject: [PATCH 15/21] fix --- .github/workflows/ci.yml | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5aaa798a6b..ba4b73fbf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,23 +5,6 @@ on: branches: [main] jobs: - staticcheck: - name: Linting - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v6 - - - name: Set up Go - uses: actions/setup-go@v6 - with: - go-version: "1.26.0" - - uses: dominikh/staticcheck-action@v1 - with: - version: "latest" - - name: Run staticcheck - run: staticcheck ./... tests: name: Tests runs-on: ubuntu-latest @@ -52,3 +35,9 @@ jobs: - name: Run Style run: test -z $(go fmt ./...) + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... From 25d7ed9907d328e5961a41c6545eddcaf92526c3 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:06:33 +0800 Subject: [PATCH 16/21] add go sec --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba4b73fbf0..58ea8f89d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,12 @@ jobs: - name: Run Tests run: go test ./... -cover + + - name: Install gosec + run: go install github.com/securego/gosec/v2/cmd/gosec@latest + + - name: Run gosec + run: gosec ./... style: name: Style runs-on: ubuntu-latest From f521724f6e4cc490d8d754096717c13c8b5e1f0b Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:16:45 +0800 Subject: [PATCH 17/21] fix gosec --- json.go | 7 ++++++- main.go | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/json.go b/json.go index 1e6e7985e1..0eb3a3f3cd 100644 --- a/json.go +++ b/json.go @@ -30,5 +30,10 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { return } w.WriteHeader(code) - w.Write(dat) + _, err = w.Write(dat) + if err != nil { + // Tangani error, misalnya log atau kirim internal server error + log.Printf("Gagal menulis data ke response: %v", err) + } + } diff --git a/main.go b/main.go index 19d7366c5f..8124247025 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "log" "net/http" "os" + "strconv" "github.com/go-chi/chi" "github.com/go-chi/cors" @@ -34,6 +35,10 @@ func main() { if port == "" { log.Fatal("PORT environment variable is not set") } + portInt, err := strconv.Atoi(port) + if err != nil { + log.Fatal("Format port tidak valid") + } apiCfg := apiConfig{} @@ -91,8 +96,9 @@ func main() { srv := &http.Server{ Addr: ":" + port, Handler: router, + ReadTimeout: 60 * 60 * 60, } - log.Printf("Serving on port: %s\n", port) + log.Printf("Serving on port: %d\n", portInt) log.Fatal(srv.ListenAndServe()) } From 0e9dd5f699e3cf95bde19fb54fb780743c9113d2 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:19:29 +0800 Subject: [PATCH 18/21] fix --- json.go | 4 ++-- main.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/json.go b/json.go index 0eb3a3f3cd..65dd4b2495 100644 --- a/json.go +++ b/json.go @@ -32,8 +32,8 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { w.WriteHeader(code) _, err = w.Write(dat) if err != nil { - // Tangani error, misalnya log atau kirim internal server error - log.Printf("Gagal menulis data ke response: %v", err) + // Tangani error, misalnya log atau kirim internal server error + log.Printf("Gagal menulis data ke response: %v", err) } } diff --git a/main.go b/main.go index 8124247025..7e27e69354 100644 --- a/main.go +++ b/main.go @@ -37,7 +37,7 @@ func main() { } portInt, err := strconv.Atoi(port) if err != nil { - log.Fatal("Format port tidak valid") + log.Fatal("Format port tidak valid") } apiCfg := apiConfig{} @@ -94,8 +94,8 @@ func main() { router.Mount("/v1", v1Router) srv := &http.Server{ - Addr: ":" + port, - Handler: router, + Addr: ":" + port, + Handler: router, ReadTimeout: 60 * 60 * 60, } From f90e8c5ae0b85feb046fc4cf00d6ec97f5d07f22 Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Wed, 22 Jul 2026 04:41:12 +0800 Subject: [PATCH 19/21] add cd --- .github/workflows/cd.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/cd.yml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000000..2106f61bc2 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,19 @@ + + +on: + pull_request: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.26.0" + - name: Build + run: ./scripts/buildprod.sh From 2d3145938c1dc3d9bf9fed4c1681f111eff381ae Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Wed, 22 Jul 2026 04:49:08 +0800 Subject: [PATCH 20/21] cd --- .github/workflows/cd.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 2106f61bc2..2623b9f680 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,11 +1,10 @@ - - on: pull_request: branches: [main] jobs: deploy: + name: Deploy runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From cb9f8953e5966c8eaa14940105b6b8c5171cd25b Mon Sep 17 00:00:00 2001 From: Rivaldi Putra <36479850+vadhe@users.noreply.github.com> Date: Wed, 22 Jul 2026 04:50:37 +0800 Subject: [PATCH 21/21] cd --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2092f54e78..5e8d8d28bd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ out .env learn-cicd-starter notely +node_modules