From 3521704d445316a8512d13636d74501cdd28e861 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 7 Jan 2026 09:14:39 +0100 Subject: [PATCH 01/33] Add name to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index c2bec0368b..2d8454f35c 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ PORT="8080" ``` Run the server: +Sadia Aschrafi's version of Boot.dev's Notely app. ```bash go build -o notely && ./notely @@ -21,3 +22,6 @@ 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! +Sadia Aschrafi's version of Boot.dev's Notely app. + + From 93b97f4cbddee319ad0a2f86b95a94167bfe219f Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 7 Jan 2026 12:32:14 +0100 Subject: [PATCH 02/33] ci --- .github/workflows/ci.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) 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..e69de29bb2 From 264b4fa32c4b543302208893d68fc8358b6ceae0 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 7 Jan 2026 14:28:44 +0100 Subject: [PATCH 03/33] insert the initila code in to ci.yml --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e69de29bb2..76753dbd4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: ci + +on: + 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: "1.25.1" + + - name: Force Failure + run: (exit 1) + + \ No newline at end of file From d058cc73f0c5b41b706c9512c0d719e65e4f68f0 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 7 Jan 2026 14:53:05 +0100 Subject: [PATCH 04/33] change froce failure to force success --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76753dbd4c..edd24043f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: with: go-version: "1.25.1" - - name: Force Failure - run: (exit 1) - + - name: Force sucess + run: (exit 0) + \ No newline at end of file From c094828f2a337ed39a0246efe887a778a9e3c97b Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 7 Jan 2026 15:04:44 +0100 Subject: [PATCH 05/33] change back to force failure --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index edd24043f7..76db5dfd06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: with: go-version: "1.25.1" - - name: Force sucess - run: (exit 0) + - name: Force Failure + run: (exit 1) \ No newline at end of file From 1a1a979c7eb8ba4c88d9cc2646dfe21be60a6a26 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 7 Jan 2026 15:31:32 +0100 Subject: [PATCH 06/33] change force failure to go version --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76db5dfd06..c50734ea51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: with: go-version: "1.25.1" - - name: Force Failure - run: (exit 1) + - name: go version + run: (exit 0) \ No newline at end of file From 7252bc22eb73da35cc4adb55b3b09704764fb72a Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Thu, 8 Jan 2026 00:19:45 +0100 Subject: [PATCH 07/33] Add unit tests for GetAPIKey function --- internal/auth/auth_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 internal/auth/auth_test.go diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go new file mode 100644 index 0000000000..eebf45ef08 --- /dev/null +++ b/internal/auth/auth_test.go @@ -0,0 +1,38 @@ +package auth + +import ( + "net/http" + "testing" +) + +func TestGetAPIKey(t *testing.T) { + t.Run("returns API key when header is valid", func(t *testing.T) { + headers := http.Header{} + headers.Set("Authorization", "ApiKey test123") + + key, err := GetAPIKey(headers) + + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if key != "test123" { + t.Errorf("Expected 'test123', got %s", key) + } + }) + + t.Run("returns error when no authorization header", func(t *testing.T) { + headers := http.Header{} + + key, err := GetAPIKey(headers) + + if err == nil { + t.Error("Expected error, got nil") + } + if err != ErrNoAuthHeaderIncluded { + t.Errorf("Expected ErrNoAuthHeaderIncluded, got %v", err) + } + if key != "" { + t.Errorf("Expected empty key, got %s", key) + } + }) +} From 1d52f26ce8fc5cfa88d71f9f1ee9420f6a1e6938 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Thu, 8 Jan 2026 00:44:33 +0100 Subject: [PATCH 08/33] Update CI to run tests and add failing test --- .github/workflows/ci.yml | 6 ++---- internal/auth/auth_test.go | 5 +++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c50734ea51..3284fa9f2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,5 @@ jobs: with: go-version: "1.25.1" - - name: go version - run: (exit 0) - - \ No newline at end of file + - name: Run tests + run: go test ./... diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go index eebf45ef08..918f9cf6fd 100644 --- a/internal/auth/auth_test.go +++ b/internal/auth/auth_test.go @@ -35,4 +35,9 @@ func TestGetAPIKey(t *testing.T) { t.Errorf("Expected empty key, got %s", key) } }) + + // This will FAIL on purpose + t.Run("forced failure", func(t *testing.T) { + t.Error("Breaking CI on purpose") + }) } From fb718b07ce9131fb6c8333e8f986fd8e49be68b4 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Thu, 8 Jan 2026 00:49:16 +0100 Subject: [PATCH 09/33] Fix tests - remove forced failure --- internal/auth/auth_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go index 918f9cf6fd..eebf45ef08 100644 --- a/internal/auth/auth_test.go +++ b/internal/auth/auth_test.go @@ -35,9 +35,4 @@ func TestGetAPIKey(t *testing.T) { t.Errorf("Expected empty key, got %s", key) } }) - - // This will FAIL on purpose - t.Run("forced failure", func(t *testing.T) { - t.Error("Breaking CI on purpose") - }) } From 6f22b6d49e8eb48548e0cd3c6c1d5c1545dd7e72 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Thu, 8 Jan 2026 00:58:39 +0100 Subject: [PATCH 10/33] Add code coverage reporting to CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3284fa9f2c..ce54aad547 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,5 +18,5 @@ jobs: with: go-version: "1.25.1" - - name: Run tests - run: go test ./... + - name: Run tests with coverage + run: go test ./... -cover From 9273f6838d506b9c6247c141a98e15ca179efb72 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Thu, 8 Jan 2026 12:44:54 +0100 Subject: [PATCH 11/33] Add CI badge to README --- README.md | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 2d8454f35c..5fef6968d1 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,8 @@ -# learn-cicd-starter (Notely) +![CI Status](https://github.com/sadiaaschrafi/learn-cicd-starter/actions/workflows/ci.yml/badge.svg) -This repo contains the starter code for the "Notely" application for the "Learn CICD" course on [Boot.dev](https://boot.dev). - -## Local Development - -Make sure you're on Go version 1.22+. - -Create a `.env` file in the root of the project with the following contents: - -```bash -PORT="8080" -``` - -Run the server: -Sadia Aschrafi's version of Boot.dev's Notely app. - -```bash -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! -Sadia Aschrafi's version of Boot.dev's Notely app. +# learn-cicd-starter +Your existing README content here... +sadiaaschrafi's version of Boot.dev's Notely app. +![CI Tests](https://github.com/sadiaaschrafi/learn-cicd-starter/actions/workflows/ci.yml/badge.svg) From 191556898701554b00bf2a921b1e9e5c9c9da13f Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Fri, 9 Jan 2026 09:38:00 +0100 Subject: [PATCH 12/33] use REDME.md --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index 5fef6968d1..52a7d4023a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,2 @@ -![CI Status](https://github.com/sadiaaschrafi/learn-cicd-starter/actions/workflows/ci.yml/badge.svg) +https://github.com///actions/workflows//badge.svg -# learn-cicd-starter - -Your existing README content here... - -sadiaaschrafi's version of Boot.dev's Notely app. -![CI Tests](https://github.com/sadiaaschrafi/learn-cicd-starter/actions/workflows/ci.yml/badge.svg) From b24603d1c0ff265171a8fd4911ff48c4538b6de3 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Fri, 9 Jan 2026 09:56:11 +0100 Subject: [PATCH 13/33] Add Style job for formatting checks and update README badge --- .github/workflows/ci.yml | 22 ++++++++++++++++++++++ README.md | 17 ++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce54aad547..e1fe890e9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,3 +20,25 @@ jobs: - name: Run tests with coverage run: go test ./... -cover + + style: + name: Style + 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: "1.25.1" + + - name: Check Go formatting + run: | + # Check if any files need formatting + if [ -n "$(go fmt ./...)" ]; then + echo "::error::Some Go files need formatting. Please run 'go fmt ./...' locally." + exit 1 + fi + echo "✓ All Go files are properly formatted!" diff --git a/README.md b/README.md index 52a7d4023a..133458ba21 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,17 @@ -https://github.com///actions/workflows//badge.svg +[![CI Status](https://github.com/sadiaaschrafi/learn-cicd-starter/actions/workflows/ci.yml/badge.svg)](https://github.com/sadiaaschrafi/learn-cicd-starter/actions) +# learn-cicd-starter + +This is a starter project for learning CI/CD concepts. + +## Features +- Automated testing with Go +- CI/CD pipeline with GitHub Actions +- Code formatting checks + +## Getting Started +1. Clone the repository +2. Run `go mod tidy` +3. Run `go test ./...` to run tests + +sadiaaschrafi's version of Boot.dev's Notely app. From cd8f4785361491161e277bdb5a4e3dd5e4ec8dc8 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Fri, 9 Jan 2026 11:29:44 +0100 Subject: [PATCH 14/33] Fix Style job name and use test -z command --- .github/workflows/ci.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1fe890e9a..20cb126a46 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - name: Run tests with coverage run: go test ./... -cover - style: + Style: name: Style runs-on: ubuntu-latest @@ -35,10 +35,4 @@ jobs: go-version: "1.25.1" - name: Check Go formatting - run: | - # Check if any files need formatting - if [ -n "$(go fmt ./...)" ]; then - echo "::error::Some Go files need formatting. Please run 'go fmt ./...' locally." - exit 1 - fi - echo "✓ All Go files are properly formatted!" + run: test -z "$(go fmt ./...)" From 43fdc22ee99942bbc028cc22c64e082c2b13d672 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Fri, 9 Jan 2026 11:45:49 +0100 Subject: [PATCH 15/33] Fix Style job with test -z command --- .github/workflows/ci.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20cb126a46..3b2f230dc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,31 +8,25 @@ 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: "1.25.1" - - name: Run tests with coverage run: go test ./... -cover Style: name: Style 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: "1.25.1" - - - name: Check Go formatting + - name: Check formatting with test -z run: test -z "$(go fmt ./...)" From 59532032cd08fbeb9ea1734df6deee4fc06953de Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Fri, 9 Jan 2026 12:40:37 +0100 Subject: [PATCH 16/33] Fix duplicate step name in Style job --- main.go | 96 ++------------------------------------------------------- 1 file changed, 2 insertions(+), 94 deletions(-) diff --git a/main.go b/main.go index 19d7366c5f..5a16bc5781 100644 --- a/main.go +++ b/main.go @@ -1,98 +1,6 @@ package main -import ( - "database/sql" - "embed" - "io" - "log" - "net/http" - "os" - - "github.com/go-chi/chi" - "github.com/go-chi/cors" - "github.com/joho/godotenv" - - "github.com/bootdotdev/learn-cicd-starter/internal/database" - - _ "github.com/tursodatabase/libsql-client-go/libsql" -) - -type apiConfig struct { - DB *database.Queries -} - -//go:embed static/* -var staticFiles embed.FS - func main() { - err := godotenv.Load(".env") - if err != nil { - log.Printf("warning: assuming default configuration. .env unreadable: %v", err) - } - - port := os.Getenv("PORT") - if port == "" { - log.Fatal("PORT environment variable is not set") - } - - apiCfg := apiConfig{} - - // https://github.com/libsql/libsql-client-go/#open-a-connection-to-sqld - // libsql://[your-database].turso.io?authToken=[your-auth-token] - dbURL := os.Getenv("DATABASE_URL") - if dbURL == "" { - log.Println("DATABASE_URL environment variable is not set") - log.Println("Running without CRUD endpoints") - } else { - db, err := sql.Open("libsql", dbURL) - if err != nil { - log.Fatal(err) - } - dbQueries := database.New(db) - apiCfg.DB = dbQueries - log.Println("Connected to database!") - } - - router := chi.NewRouter() - - router.Use(cors.Handler(cors.Options{ - AllowedOrigins: []string{"https://*", "http://*"}, - AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, - AllowedHeaders: []string{"*"}, - ExposedHeaders: []string{"Link"}, - AllowCredentials: false, - MaxAge: 300, - })) - - router.Get("/", func(w http.ResponseWriter, r *http.Request) { - f, err := staticFiles.Open("static/index.html") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - defer f.Close() - if _, err := io.Copy(w, f); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - }) - - v1Router := chi.NewRouter() - - if apiCfg.DB != nil { - v1Router.Post("/users", apiCfg.handlerUsersCreate) - v1Router.Get("/users", apiCfg.middlewareAuth(apiCfg.handlerUsersGet)) - v1Router.Get("/notes", apiCfg.middlewareAuth(apiCfg.handlerNotesGet)) - v1Router.Post("/notes", apiCfg.middlewareAuth(apiCfg.handlerNotesCreate)) - } - - v1Router.Get("/healthz", handlerReadiness) - - router.Mount("/v1", v1Router) - srv := &http.Server{ - Addr: ":" + port, - Handler: router, - } - - log.Printf("Serving on port: %s\n", port) - log.Fatal(srv.ListenAndServe()) + app := NewApp() + app.Run() } From 7975e33323975deb2dba4d841941bae589f0200f Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Sun, 11 Jan 2026 01:04:04 +0100 Subject: [PATCH 17/33] Add style job for go fmt --- .github/workflows/ci.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b2f230dc9..138826e10b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,3 +30,43 @@ jobs: go-version: "1.25.1" - name: Check formatting with test -z run: test -z "$(go fmt ./...)" + + name: ci + +on: + 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: "1.25.1" + + - name: Run tests with coverage + run: go test ./... -cover + + style: + name: Style + 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: "1.25.1" + + - name: Check Go formatting + run: | + test -z "$(go fmt ./...)" From 9203f597c8a8dee2f15cd44891f02d31fc4508d3 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Sun, 11 Jan 2026 01:54:38 +0100 Subject: [PATCH 18/33] Fix Style job and format code --- .github/workflows/ci.yml | 2 +- internal/auth/auth_test.go | 62 ++++++++++++++++++------------------- internal/database/models.go | 2 -- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 138826e10b..bbf31b7b34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,4 +69,4 @@ jobs: - name: Check Go formatting run: | - test -z "$(go fmt ./...)" + test -z "$(go fmt ./...)" diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go index eebf45ef08..e0583ae322 100644 --- a/internal/auth/auth_test.go +++ b/internal/auth/auth_test.go @@ -1,38 +1,38 @@ package auth import ( - "net/http" - "testing" + "net/http" + "testing" ) func TestGetAPIKey(t *testing.T) { - t.Run("returns API key when header is valid", func(t *testing.T) { - headers := http.Header{} - headers.Set("Authorization", "ApiKey test123") - - key, err := GetAPIKey(headers) - - if err != nil { - t.Errorf("Expected no error, got %v", err) - } - if key != "test123" { - t.Errorf("Expected 'test123', got %s", key) - } - }) - - t.Run("returns error when no authorization header", func(t *testing.T) { - headers := http.Header{} - - key, err := GetAPIKey(headers) - - if err == nil { - t.Error("Expected error, got nil") - } - if err != ErrNoAuthHeaderIncluded { - t.Errorf("Expected ErrNoAuthHeaderIncluded, got %v", err) - } - if key != "" { - t.Errorf("Expected empty key, got %s", key) - } - }) + t.Run("returns API key when header is valid", func(t *testing.T) { + headers := http.Header{} + headers.Set("Authorization", "ApiKey test123") + + key, err := GetAPIKey(headers) + + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if key != "test123" { + t.Errorf("Expected 'test123', got %s", key) + } + }) + + t.Run("returns error when no authorization header", func(t *testing.T) { + headers := http.Header{} + + key, err := GetAPIKey(headers) + + if err == nil { + t.Error("Expected error, got nil") + } + if err != ErrNoAuthHeaderIncluded { + t.Errorf("Expected ErrNoAuthHeaderIncluded, got %v", err) + } + if key != "" { + t.Errorf("Expected empty key, got %s", key) + } + }) } diff --git a/internal/database/models.go b/internal/database/models.go index 70333ba1ab..050e28b38b 100644 --- a/internal/database/models.go +++ b/internal/database/models.go @@ -4,8 +4,6 @@ package database -import () - type Note struct { ID string CreatedAt string From c165d86c5ce220e81664270f6819a44c5ef621ff Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Mon, 12 Jan 2026 10:40:53 +0100 Subject: [PATCH 19/33] Fix tests job --- .github/workflows/ci.yml | 39 +++------------------------------------ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbf31b7b34..9bcfbd5102 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,40 +5,7 @@ on: 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: "1.25.1" - - name: Run tests with coverage - run: go test ./... -cover - - Style: - name: Style - 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: "1.25.1" - - name: Check formatting with test -z - run: test -z "$(go fmt ./...)" - - name: ci - -on: - pull_request: - branches: [main] - -jobs: - tests: + tests: ← HERE (this already exists) name: Tests runs-on: ubuntu-latest @@ -54,7 +21,7 @@ jobs: - name: Run tests with coverage run: go test ./... -cover - style: + style: ← SAME LEVEL as tests (no folder) name: Style runs-on: ubuntu-latest @@ -69,4 +36,4 @@ jobs: - name: Check Go formatting run: | - test -z "$(go fmt ./...)" + test -z "$(go fmt ./...)" \ No newline at end of file From eb97314cc70f124696aca5a6fc609b9f59271d53 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Mon, 12 Jan 2026 10:47:50 +0100 Subject: [PATCH 20/33] Fix tests job --- .github/workflows/ci.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9bcfbd5102..2fd6309c66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,39 @@ jobs: name: Style 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: "1.25.1" + + - name: Check Go formatting + run: | + test -z "$(go fmt ./...)" + 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: "1.25.1" + + - name: Run tests with coverage + run: go test ./... -cover + + style: + name: Style + runs-on: ubuntu-latest + steps: - name: Check out code uses: actions/checkout@v4 From 6e220aa4b55ce62aea33803c4d893257d9c003d9 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Mon, 12 Jan 2026 14:09:45 +0100 Subject: [PATCH 21/33] remove duplicate code from ci.yml --- .github/workflows/ci.yml | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fd6309c66..bb201679dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: branches: [main] jobs: - tests: ← HERE (this already exists) + tests: name: Tests runs-on: ubuntu-latest @@ -21,7 +21,7 @@ jobs: - name: Run tests with coverage run: go test ./... -cover - style: ← SAME LEVEL as tests (no folder) + style: name: Style runs-on: ubuntu-latest @@ -38,35 +38,3 @@ jobs: run: | test -z "$(go fmt ./...)" 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: "1.25.1" - - - name: Run tests with coverage - run: go test ./... -cover - - style: - name: Style - 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: "1.25.1" - - - name: Check Go formatting - run: | - test -z "$(go fmt ./...)" \ No newline at end of file From 8b6f0fb47cb05aad82bd8bad886b8e5f51791ce2 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Mon, 12 Jan 2026 14:18:54 +0100 Subject: [PATCH 22/33] restor main.go --- main.go | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 5a16bc5781..dd9f84f90e 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,98 @@ package main -func main() { - app := NewApp() - app.Run() +import ( + "database/sql" + "embed" + "io" + "log" + "net/http" + "os" + + "github.com/go-chi/chi" + "github.com/go-chi/cors" + "github.com/joho/godotenv" + + "github.com/bootdotdev/learn-cicd-starter/internal/database" + + _ "github.com/tursodatabase/libsql-client-go/libsql" +) + +type apiConfig struct { + DB *database.Queries } + +//go:embed static/* +var staticFiles embed.FS + +func main() { + err := godotenv.Load(".env") + if err != nil { + log.Printf("warning: assuming default configuration. .env unreadable: %v", err) + } + + port := os.Getenv("PORT") + if port == "" { + log.Fatal("PORT environment variable is not set") + } + + apiCfg := apiConfig{} + + // https://github.com/libsql/libsql-client-go/#open-a-connection-to-sqld + // libsql://[your-database].turso.io?authToken=[your-auth-token] + dbURL := os.Getenv("DATABASE_URL") + if dbURL == "" { + log.Println("DATABASE_URL environment variable is not set") + log.Println("Running without CRUD endpoints") + } else { + db, err := sql.Open("libsql", dbURL) + if err != nil { + log.Fatal(err) + } + dbQueries := database.New(db) + apiCfg.DB = dbQueries + log.Println("Connected to database!") + } + + router := chi.NewRouter() + + router.Use(cors.Handler(cors.Options{ + AllowedOrigins: []string{"https://*", "http://*"}, + AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, + AllowedHeaders: []string{"*"}, + ExposedHeaders: []string{"Link"}, + AllowCredentials: false, + MaxAge: 300, + })) + + router.Get("/", func(w http.ResponseWriter, r *http.Request) { + f, err := staticFiles.Open("static/index.html") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + defer f.Close() + if _, err := io.Copy(w, f); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + }) + + v1Router := chi.NewRouter() + + if apiCfg.DB != nil { + v1Router.Post("/users", apiCfg.handlerUsersCreate) + v1Router.Get("/users", apiCfg.middlewareAuth(apiCfg.handlerUsersGet)) + v1Router.Get("/notes", apiCfg.middlewareAuth(apiCfg.handlerNotesGet)) + v1Router.Post("/notes", apiCfg.middlewareAuth(apiCfg.handlerNotesCreate)) + } + + v1Router.Get("/healthz", handlerReadiness) + + router.Mount("/v1", v1Router) + srv := &http.Server{ + Addr: ":" + port, + Handler: router, + } + + log.Printf("Serving on port: %s\n", port) + log.Fatal(srv.ListenAndServe()) +} \ No newline at end of file From 0b8233e01260c2533e7fe5bf6864b9b9ce719963 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Mon, 12 Jan 2026 14:28:43 +0100 Subject: [PATCH 23/33] fixed the style job --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb201679dd..6f7359a7fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,4 @@ jobs: go-version: "1.25.1" - name: Check Go formatting - run: | - test -z "$(go fmt ./...)" - jobs: + run: test -z "$(go fmt ./...)" From 48fd7cf6e73e2cbb67f7f9a4ba93c3c60597ce6c Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Mon, 12 Jan 2026 14:54:03 +0100 Subject: [PATCH 24/33] fix fomatting main.go --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index dd9f84f90e..19d7366c5f 100644 --- a/main.go +++ b/main.go @@ -95,4 +95,4 @@ func main() { log.Printf("Serving on port: %s\n", port) log.Fatal(srv.ListenAndServe()) -} \ No newline at end of file +} From 5d5d7735955c1652dbd846db0444cb48d5cc0501 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Tue, 13 Jan 2026 09:18:13 +0100 Subject: [PATCH 25/33] changes added --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f7359a7fd..99f6a0597e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,3 +36,4 @@ jobs: - name: Check Go formatting run: test -z "$(go fmt ./...)" + \ No newline at end of file From 9817a667d93d49bbee37bc1d5280089c3b4a64bb Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Tue, 13 Jan 2026 21:01:05 +0100 Subject: [PATCH 26/33] Add gosec security checks to CI --- .github/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99f6a0597e..394efc5be6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: branches: [main] jobs: - tests: + tests: name: Tests runs-on: ubuntu-latest @@ -21,7 +21,13 @@ jobs: - name: Run tests with coverage run: go test ./... -cover - style: + - 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 128ed22d31f32eb7af179ac2539bac403c2aedfa Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Tue, 13 Jan 2026 23:46:52 +0100 Subject: [PATCH 27/33] Add ReadHeaderTimeout to HTTP server --- main.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 19d7366c5f..15ee531c5d 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "log" "net/http" "os" + "time" "github.com/go-chi/chi" "github.com/go-chi/cors" @@ -89,8 +90,9 @@ func main() { router.Mount("/v1", v1Router) srv := &http.Server{ - Addr: ":" + port, - Handler: router, + Addr: ":" + port, + Handler: router, + ReadHeaderTimeout: 5 * time.Second, } log.Printf("Serving on port: %s\n", port) From 6c955a058d6c0fa01988df47d5272ff303027857 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Tue, 13 Jan 2026 23:54:31 +0100 Subject: [PATCH 28/33] Handle error when writing JSON response --- json.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/json.go b/json.go index 1e6e7985e1..2596275fb1 100644 --- a/json.go +++ b/json.go @@ -30,5 +30,7 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { return } w.WriteHeader(code) - w.Write(dat) + if _, err := w.Write(dat); err != nil { + log.Println("error writing response:", err) + } } From b7fa2588b30233d55bf65c4971f3905e933a2b21 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 14 Jan 2026 00:00:36 +0100 Subject: [PATCH 29/33] Fix gosec G104 by handling http response write error --- json.go | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/json.go b/json.go index 2596275fb1..621cb5439d 100644 --- a/json.go +++ b/json.go @@ -6,16 +6,7 @@ import ( "net/http" ) -func respondWithError(w http.ResponseWriter, code int, msg string, logErr error) { - if logErr != nil { - log.Println(logErr) - } - if code > 499 { - log.Printf("Responding with 5XX error: %s", msg) - } - type errorResponse struct { - Error string `json:"error"` - } +func respondWithError(w http.ResponseWriter, code int, msg string) { respondWithJSON(w, code, errorResponse{ Error: msg, }) @@ -23,12 +14,14 @@ func respondWithError(w http.ResponseWriter, code int, msg string, logErr error) 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) + w.WriteHeader(http.StatusInternalServerError) return } + w.WriteHeader(code) if _, err := w.Write(dat); err != nil { log.Println("error writing response:", err) From 41843b10e691e23aa614857921eefb7d1820bd30 Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 14 Jan 2026 00:08:17 +0100 Subject: [PATCH 30/33] Fix gosec G104 and define errorResponse --- json.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/json.go b/json.go index 621cb5439d..e07bd28406 100644 --- a/json.go +++ b/json.go @@ -6,6 +6,10 @@ import ( "net/http" ) +type errorResponse struct { + Error string `json:"error"` +} + func respondWithError(w http.ResponseWriter, code int, msg string) { respondWithJSON(w, code, errorResponse{ Error: msg, From 0a7a148ac92a50c28ac72ecb294db845352c6c1a Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 14 Jan 2026 11:08:14 +0100 Subject: [PATCH 31/33] changes is fixed --- json.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/json.go b/json.go index e07bd28406..46d6115e88 100644 --- a/json.go +++ b/json.go @@ -11,9 +11,9 @@ type errorResponse struct { } func respondWithError(w http.ResponseWriter, code int, msg string) { - respondWithJSON(w, code, errorResponse{ - Error: msg, - }) + respondWithJSON(w, code, errorResponse{ + Error: msg, + }) } func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { From 27e50c5a8925e104c4ef4ad84a3bf3cef0b999ab Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Wed, 14 Jan 2026 12:10:12 +0100 Subject: [PATCH 32/33] Add gosec security scanning to CI --- .github/workflows/ci.yml | 48 +++++++++++++--------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 394efc5be6..9fd206cb36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,45 +1,27 @@ -name: ci +name: CI on: + push: + branches: [ main ] pull_request: - branches: [main] + 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 + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 with: - go-version: "1.25.1" - - - name: Run tests with coverage - run: go test ./... -cover - + go-version: '1.21' + + - 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@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: "1.25.1" - - - name: Check Go formatting - run: test -z "$(go fmt ./...)" - \ No newline at end of file + + - name: Run gosec security scan + run: gosec ./... \ No newline at end of file From 244f6ac81384d8eafcde45dadcc20b0cd008b88c Mon Sep 17 00:00:00 2001 From: sadia aschrafi Date: Sat, 17 Jan 2026 18:13:06 +0100 Subject: [PATCH 33/33] just added user email and password --- handler_notes.go | 71 +++++++++++++++++++-------------- handler_user.go | 72 +++++++--------------------------- internal/database/db.go | 2 +- internal/database/models.go | 2 +- internal/database/notes.sql.go | 2 +- internal/database/users.sql.go | 4 +- json.go | 10 ++--- 7 files changed, 68 insertions(+), 95 deletions(-) diff --git a/handler_notes.go b/handler_notes.go index 85a8e3415d..d53d4316fb 100644 --- a/handler_notes.go +++ b/handler_notes.go @@ -1,6 +1,9 @@ package main import ( + "crypto/rand" + "crypto/sha256" + "encoding/hex" "encoding/json" "net/http" "time" @@ -9,25 +12,9 @@ import ( "github.com/google/uuid" ) -func (cfg *apiConfig) handlerNotesGet(w http.ResponseWriter, r *http.Request, user database.User) { - posts, err := cfg.DB.GetNotesForUser(r.Context(), user.ID) - if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't get posts for user", err) - return - } - - postsResp, err := databasePostsToPosts(posts) - if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't convert posts", err) - return - } - - respondWithJSON(w, http.StatusOK, postsResp) -} - -func (cfg *apiConfig) handlerNotesCreate(w http.ResponseWriter, r *http.Request, user database.User) { +func (cfg *apiConfig) handlerUsersCreate(w http.ResponseWriter, r *http.Request) { type parameters struct { - Note string `json:"note"` + Name string `json:"name"` } decoder := json.NewDecoder(r.Body) params := parameters{} @@ -37,30 +24,56 @@ func (cfg *apiConfig) handlerNotesCreate(w http.ResponseWriter, r *http.Request, return } - id := uuid.New().String() - err = cfg.DB.CreateNote(r.Context(), database.CreateNoteParams{ - ID: id, + apiKey, err := generateRandomSHA256Hash() + if err != nil { + respondWithError(w, http.StatusInternalServerError, "Couldn't gen apikey", err) + return + } + + err = cfg.DB.CreateUser(r.Context(), database.CreateUserParams{ + ID: uuid.New().String(), CreatedAt: time.Now().UTC().Format(time.RFC3339), UpdatedAt: time.Now().UTC().Format(time.RFC3339), - Note: params.Note, - UserID: user.ID, + Name: params.Name, + ApiKey: apiKey, }) if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't create note", err) + respondWithError(w, http.StatusInternalServerError, "Couldn't create user", err) + return + } + + user, err := cfg.DB.GetUser(r.Context(), apiKey) + if err != nil { + respondWithError(w, http.StatusInternalServerError, "Couldn't get user", err) return } - note, err := cfg.DB.GetNote(r.Context(), id) + userResp, err := databaseUserToUser(user) if err != nil { - respondWithError(w, http.StatusNotFound, "Couldn't get note", err) + respondWithError(w, http.StatusInternalServerError, "Couldn't convert user", err) return } + respondWithJSON(w, http.StatusCreated, userResp) +} + +func generateRandomSHA256Hash() (string, error) { + randomBytes := make([]byte, 32) + _, err := rand.Read(randomBytes) + if err != nil { + return "", err + } + hash := sha256.Sum256(randomBytes) + hashString := hex.EncodeToString(hash[:]) + return hashString, nil +} + +func (cfg *apiConfig) handlerUsersGet(w http.ResponseWriter, r *http.Request, user database.User) { - noteResp, err := databaseNoteToNote(note) + userResp, err := databaseUserToUser(user) if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't convert note", err) + respondWithError(w, http.StatusInternalServerError, "Couldn't convert user", err) return } - respondWithJSON(w, http.StatusCreated, noteResp) + respondWithJSON(w, http.StatusOK, userResp) } diff --git a/handler_user.go b/handler_user.go index d53d4316fb..b207254805 100644 --- a/handler_user.go +++ b/handler_user.go @@ -1,79 +1,37 @@ package main import ( - "crypto/rand" - "crypto/sha256" - "encoding/hex" "encoding/json" "net/http" - "time" "github.com/bootdotdev/learn-cicd-starter/internal/database" - "github.com/google/uuid" ) func (cfg *apiConfig) handlerUsersCreate(w http.ResponseWriter, r *http.Request) { type parameters struct { - Name string `json:"name"` + Email string `json:"email"` + Password string `json:"password"` } + decoder := json.NewDecoder(r.Body) params := parameters{} - err := decoder.Decode(¶ms) - if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't decode parameters", err) + if err := decoder.Decode(¶ms); err != nil { + respondWithError(w, http.StatusBadRequest, "invalid JSON body") return } - apiKey, err := generateRandomSHA256Hash() - if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't gen apikey", err) - return - } - - err = cfg.DB.CreateUser(r.Context(), database.CreateUserParams{ - ID: uuid.New().String(), - CreatedAt: time.Now().UTC().Format(time.RFC3339), - UpdatedAt: time.Now().UTC().Format(time.RFC3339), - Name: params.Name, - ApiKey: apiKey, + user := cfg.DB.CreateUser(r.Context(), database.CreateUserParams{ + Email: params.Email, + HashedPassword: params.Password, }) - if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't create user", err) - return - } - - user, err := cfg.DB.GetUser(r.Context(), apiKey) - if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't get user", err) - return - } - userResp, err := databaseUserToUser(user) - if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't convert user", err) - return - } - respondWithJSON(w, http.StatusCreated, userResp) -} - -func generateRandomSHA256Hash() (string, error) { - randomBytes := make([]byte, 32) - _, err := rand.Read(randomBytes) - if err != nil { - return "", err - } - hash := sha256.Sum256(randomBytes) - hashString := hex.EncodeToString(hash[:]) - return hashString, nil + respondWithJSON(w, http.StatusCreated, user) } -func (cfg *apiConfig) handlerUsersGet(w http.ResponseWriter, r *http.Request, user database.User) { - - userResp, err := databaseUserToUser(user) - if err != nil { - respondWithError(w, http.StatusInternalServerError, "Couldn't convert user", err) - return - } - - respondWithJSON(w, http.StatusOK, userResp) +func (cfg *apiConfig) handlerUsersGet( + w http.ResponseWriter, + r *http.Request, + user database.User, +) { + respondWithJSON(w, http.StatusOK, user) } diff --git a/internal/database/db.go b/internal/database/db.go index 61f5bf46c8..85d4b8c654 100644 --- a/internal/database/db.go +++ b/internal/database/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.30.0 package database diff --git a/internal/database/models.go b/internal/database/models.go index 050e28b38b..834aabbb89 100644 --- a/internal/database/models.go +++ b/internal/database/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.30.0 package database diff --git a/internal/database/notes.sql.go b/internal/database/notes.sql.go index 234dd4c131..3dd01b0c66 100644 --- a/internal/database/notes.sql.go +++ b/internal/database/notes.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.30.0 // source: notes.sql package database diff --git a/internal/database/users.sql.go b/internal/database/users.sql.go index 737b0d1d5f..4bfb5cde12 100644 --- a/internal/database/users.sql.go +++ b/internal/database/users.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.30.0 // source: users.sql package database @@ -26,6 +26,8 @@ type CreateUserParams struct { UpdatedAt string Name string ApiKey string + Email string + HashedPassword string } func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) error { diff --git a/json.go b/json.go index 46d6115e88..8296efca95 100644 --- a/json.go +++ b/json.go @@ -11,15 +11,15 @@ type errorResponse struct { } func respondWithError(w http.ResponseWriter, code int, msg string) { - respondWithJSON(w, code, errorResponse{ - Error: msg, - }) + 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) + data, err := json.Marshal(payload) if err != nil { log.Printf("Error marshalling JSON: %s", err) w.WriteHeader(http.StatusInternalServerError) @@ -27,7 +27,7 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { } w.WriteHeader(code) - if _, err := w.Write(dat); err != nil { + if _, err := w.Write(data); err != nil { log.Println("error writing response:", err) } }