diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
new file mode 100644
index 00000000000..71b4f12b6b3
--- /dev/null
+++ b/.github/workflows/cd.yml
@@ -0,0 +1,19 @@
+name: cd.yml
+on:
+ push:
+ branches: [main]
+jobs:
+ name: Deploy
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: "1.25.1"
+
+ - name: Build the app
+ run: ./scripts/buildprod.sh
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000000..40f6e839288
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,50 @@
+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
+ 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: Install staticheck
+ run: go install honnef.co/go/tools/cmd/staticcheck@latest
+
+ - name: Style
+ run: test -z $(go fmt ./...)
+
+ - name: Linter
+ run: staticcheck ./...
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000000..ab1f4164edb
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/go.imports.xml b/.idea/go.imports.xml
new file mode 100644
index 00000000000..d7202f03e10
--- /dev/null
+++ b/.idea/go.imports.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/learn-cicd-starter.iml b/.idea/learn-cicd-starter.iml
new file mode 100644
index 00000000000..7ee078df7b0
--- /dev/null
+++ b/.idea/learn-cicd-starter.iml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000000..d0adac68cd7
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000000..35eb1ddfbbc
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index c2bec0368b7..ba971b13498 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-# learn-cicd-starter (Notely)
+
+
+# learn-cicd-starter (Notely)
This repo contains the starter code for the "Notely" application for the "Learn CICD" course on [Boot.dev](https://boot.dev).
@@ -21,3 +23,5 @@ 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!
+
+Kenedy228's version of Boot.dev's Notely app.
diff --git a/internal/auth/tests/auth_test.go b/internal/auth/tests/auth_test.go
new file mode 100644
index 00000000000..3717075b5d6
--- /dev/null
+++ b/internal/auth/tests/auth_test.go
@@ -0,0 +1,53 @@
+package tests
+
+import (
+ "net/http"
+ "testing"
+
+ "github.com/bootdotdev/learn-cicd-starter/internal/auth"
+)
+
+func TestAuthWithValidHeaders(t *testing.T) {
+ keys := []string{
+ "ApiKey 123",
+ "ApiKey abc",
+ "ApiKey ZZZHDAWHDASDRE",
+ }
+
+ expected := []string{
+ "123",
+ "abc",
+ "ZZZHDAWHDASDRE",
+ }
+
+ for i := range keys {
+ headers := http.Header{}
+ headers.Add("Authorization", keys[i])
+
+ key, err := auth.GetAPIKey(headers)
+
+ if err != nil {
+ t.Fatalf("An error occured while generating API key: %v", err)
+ }
+
+ if key != expected[i] {
+ t.Fatalf("An error occured while generating API key. Expected %v, got %v", expected[i], key)
+ }
+ }
+}
+
+func TestAuthWitnInvalidHeaders(t *testing.T) {
+ keys := []string{
+ "Bearer 123",
+ "Choco 3333",
+ "Hi asdfg",
+ }
+
+ for i := range keys {
+ headers := http.Header{}
+ headers.Add("Authorization", keys[i])
+ if _, err := auth.GetAPIKey(headers); err == nil {
+ t.Fatal("Expected error while generating API key. Got nil")
+ }
+ }
+}
diff --git a/json.go b/json.go
index 1e6e7985e18..8b389102610 100644
--- a/json.go
+++ b/json.go
@@ -30,5 +30,9 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
return
}
w.WriteHeader(code)
- w.Write(dat)
+ _, err = w.Write(dat)
+ if err != nil {
+ w.WriteHeader(500)
+ return
+ }
}
diff --git a/main.go b/main.go
index 19d7366c5f7..16cca5652c9 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: time.Minute,
}
log.Printf("Serving on port: %s\n", port)