diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000000..2623b9f680 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,18 @@ +on: + pull_request: + branches: [main] + +jobs: + deploy: + name: 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 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..58ea8f89d3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +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: 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 + + 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 ./...) + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... 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 diff --git a/README.md b/README.md index c2bec0368b..a535a27a77 100644 --- a/README.md +++ b/README.md @@ -20,4 +20,8 @@ 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! + + +![alt text goes here](https://github.com/vadhe/learn-cicd-starter/actions/workflows/ci.yml/badge.svg) diff --git a/json.go b/json.go index 1e6e7985e1..65dd4b2495 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..7e27e69354 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{} @@ -89,10 +94,11 @@ func main() { router.Mount("/v1", v1Router) srv := &http.Server{ - Addr: ":" + port, - Handler: router, + 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()) } 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) + } + }) + } +}