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/18] chore: . --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c2bec0368b7..849142ee2c3 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/18] 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 00000000000..a2cf2a837ae --- /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/18] 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 a2cf2a837ae..59c79383a54 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/18] 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 59c79383a54..6d1b2483779 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/18] 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 6d1b2483779..1f067ffbdfc 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 6cbe03f8673..17aedc7e794 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 00000000000..1bdeaca8b72 --- /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/18] test --- middleware_auth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleware_auth.go b/middleware_auth.go index 17aedc7e794..6cbe03f8673 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/18] 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 1f067ffbdfc..cfd07e80700 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/18] img --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 849142ee2c3..a535a27a77c 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/18] 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 cfd07e80700..884bae33a96 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 61f5bf46c81..acdfb5c9435 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/18] 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 884bae33a96..54ce00d9802 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 acdfb5c9435..61f5bf46c81 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/18] 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 54ce00d9802..66fa2beeff1 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 19d7366c5f7..0cdadac81f6 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/18] fix linting --- main.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/main.go b/main.go index 0cdadac81f6..19d7366c5f7 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/18] 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 66fa2beeff1..18c438f4c40 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/18] 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 18c438f4c40..5aaa798a6b6 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/18] 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 5aaa798a6b6..ba4b73fbf01 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/18] 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 ba4b73fbf01..58ea8f89d35 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/18] fix gosec --- json.go | 7 ++++++- main.go | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/json.go b/json.go index 1e6e7985e18..0eb3a3f3cd6 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 19d7366c5f7..81242470257 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/18] fix --- json.go | 4 ++-- main.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/json.go b/json.go index 0eb3a3f3cd6..65dd4b24954 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 81242470257..7e27e693547 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, }