Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f725585
Update README.md
Joselinekahunde Sep 18, 2025
c10a143
Add my version line to README
Sep 23, 2025
407e971
Clean up README: remove conflict markers and keep final line
Joselinekahunde Sep 23, 2025
e55e51e
Add failing CI workflow (Force Failure)
Joselinekahunde Sep 23, 2025
7d1576e
CI: print Go version instead of force failure
Joselinekahunde Sep 23, 2025
50fa12f
ci: run on pull_request to main; print Go version
Joselinekahunde Sep 24, 2025
75e7a2e
CI: run go test ./... (replace go version step)
Joselinekahunde Sep 25, 2025
2d52a53
test: intentional failure to verify CI
Joselinekahunde Sep 25, 2025
93fe28a
test: remove intentional failure
Joselinekahunde Sep 25, 2025
cb9e8fb
ci: run tests with coverage reporting
Joselinekahunde Sep 26, 2025
bc40923
fix(ci): correct yaml indentation and add coverage flag
Joselinekahunde Sep 26, 2025
eae4a41
ci: ensure 'go test -cover ./...' (ASCII hyphen) and push trigger
Joselinekahunde Sep 26, 2025
dcacbe4
Add style job with go fmt and staticcheck
Joselinekahunde Sep 30, 2025
54737d4
Introduce unused function to trigger staticcheck failure
Joselinekahunde Sep 30, 2025
a119b53
Remove unused function to fix staticcheck failure
Joselinekahunde Sep 30, 2025
4634fe3
Fix formatting issues for CI
Joselinekahunde Sep 30, 2025
d0fa9fa
Add gosec step to CI workflow
Joselinekahunde Oct 1, 2025
ae0b387
Fix gosec issues: handle writes and add server timeouts
Joselinekahunde Oct 2, 2025
ee34e20
Fix security: handle response writes and add server timeouts (gosec c…
Joselinekahunde Oct 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: ci

on:
push:
branches: ["**"]
pull_request:
branches: [main]

jobs:
tests:
name: Tests
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Run go fmt
run: test -z "$(go fmt ./...)"

- name: Install staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@latest

- name: Run staticcheck
run: staticcheck ./...

- name: Run unit tests with coverage
run: go test -cover ./...
- name: Install gosec
run: go install github.com/securego/gosec/v2/cmd/gosec@latest

- name: Add Go bin to PATH
run: echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"

- name: Run gosec (intentionally fails for first push)
run: gosec ./...
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ out
.env
learn-cicd-starter
notely
gosec-report.json
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ go build -o notely && ./notely
*This starts the server in non-database mode.* It will serve a simple webpage at `http://localhost:8080`.

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!

Joseline Kahunde's version of Boot.dev's Notely app.


12 changes: 9 additions & 3 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,28 @@ func respondWithError(w http.ResponseWriter, code int, msg string, logErr error)
if code > 499 {
log.Printf("Responding with 5XX error: %s", msg)
}

type errorResponse struct {
Error string `json:"error"`
}

respondWithJSON(w, code, errorResponse{
Error: msg,
})
}

func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
w.Header().Set("Content-Type", "application/json")

dat, err := json.Marshal(payload)
if err != nil {
log.Printf("Error marshalling JSON: %s", err)
w.WriteHeader(500)
log.Printf("Error marshalling JSON: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(code)
w.Write(dat)
if _, err := w.Write(dat); err != nil {
log.Printf("warning: response write failed: %v", err)
}
}
15 changes: 12 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"
"net/http"
"os"
"time"

"github.com/go-chi/chi"
"github.com/go-chi/cors"
Expand Down Expand Up @@ -88,11 +89,19 @@ func main() {
v1Router.Get("/healthz", handlerReadiness)

router.Mount("/v1", v1Router)
// after: router.Mount("/v1", v1Router)

srv := &http.Server{
Addr: ":" + port,
Handler: router,
Addr: ":" + port,
Handler: router,
ReadHeaderTimeout: 10 * time.Second, // fixes G112
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}

log.Printf("Serving on port: %s\n", port)
log.Fatal(srv.ListenAndServe())
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("server failed: %v", err)
}
}