Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
82c8a19
chnaged README.md
anthonytobiesq Jul 22, 2026
3678a6d
ADD: github/ci.yml
anthonytobiesq Jul 23, 2026
62a97bf
ADD: github/workflows/ci.yml
anthonytobiesq Jul 23, 2026
9e4fa98
FIX: github/workflows/ci.yml
anthonytobiesq Jul 23, 2026
90b7f4d
test ci for failing unit tests
anthonytobiesq Jul 25, 2026
79c3715
TEST: unit tests for get api key func
anthonytobiesq Jul 25, 2026
e1f5117
REFACTOR: CI to run go test -cover ./...
anthonytobiesq Jul 25, 2026
22abb43
ADD: CI badge to read.ME on github
anthonytobiesq Jul 25, 2026
ae34306
Merge pull request #1 from anthonytobiesq/addtests
anthonytobiesq Jul 25, 2026
09769d8
ADD: style job in CI
anthonytobiesq Jul 26, 2026
c26cd6e
ADD: linter support with staticheck in CI
anthonytobiesq Jul 26, 2026
2399430
FIX: linter support with staticheck in CI
anthonytobiesq Jul 26, 2026
9f7851a
FIX: remove unused func in main.go caught by staticheck
anthonytobiesq Jul 26, 2026
d8eb146
ADD: gosec to ci
anthonytobiesq Aug 3, 2026
1d7a41a
FIX: gosec ERRORS: main.go, json.go
anthonytobiesq Aug 3, 2026
6d83199
ADD: cd.yaml
anthonytobiesq Aug 3, 2026
c914a40
Merge pull request #2 from anthonytobiesq/addtests
anthonytobiesq Aug 3, 2026
6618570
Refactor: cd.yaml chnage job name to Deploy
anthonytobiesq Aug 3, 2026
c8118a1
Merge pull request #3 from anthonytobiesq/addtests
anthonytobiesq Aug 3, 2026
cd07195
ADD: gcloud cli support, push docker image, artifact registry
anthonytobiesq Aug 3, 2026
22d4e9f
Merge pull request #4 from anthonytobiesq/addtests
anthonytobiesq Aug 3, 2026
148ebf2
CHANGE H1 TO TEST CD
anthonytobiesq Aug 4, 2026
64a0e1e
Merge pull request #5 from anthonytobiesq/addtests
anthonytobiesq Aug 4, 2026
b1b574f
ADD: persistence with Turbo, add tables via goose migrations script, …
anthonytobiesq Aug 4, 2026
54b2538
Merge pull request #6 from anthonytobiesq/addtests
anthonytobiesq Aug 4, 2026
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
50 changes: 50 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: cd

on:
push:
branches: [ main ]

jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}

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: Build app
run: ./scripts/buildprod.sh

- id: 'auth'
uses: 'google-github-actions/auth@v2'
with:
credentials_json: '${{ secrets.GCP_CREDENTIALS }}'

- name: 'Set up Cloud SDK'
uses: 'google-github-actions/setup-gcloud@v3'

- name: 'Use gcloud CLI'
run: 'gcloud info'


- name: Install goose
run: go install github.com/pressly/goose/v3/cmd/goose@latest

- name: Run migrations
run: ./scripts/migrateup.sh


- name: Build and push Docker image
run: gcloud builds submit --tag us-central1-docker.pkg.dev/notely-504410/notely-ar-repo/anthonytobiesqdev/notely:latest .

- name: Deploy to Cloud Run
run: gcloud run deploy notely --image us-central1-docker.pkg.dev/notely-504410/notely-ar-repo/anthonytobiesqdev/notely:latest --region us-central1 --allow-unauthenticated --project notely-504410 --max-instances=4

52 changes: 52 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
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 Unit tests
run: go test -cover ./...

- name: Install gosec
run: go install github.com/securego/gosec/v2/cmd/gosec@latest

- name: Run Security checks
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: Install staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@latest

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

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


10 changes: 10 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/go.imports.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/learn-cicd-starter.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# learn-cicd-starter (Notely)
![CI](https://github.com/anthonytobiesq/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).

Expand All @@ -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!

Anthony Tobi's version of Boot.dev's Notely app.

67 changes: 67 additions & 0 deletions internal/auth/get_api_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package auth

import (
"errors"
"net/http"
"testing"
)

func TestGetAPIKey(t *testing.T) {
tests := []struct {
name string
headers http.Header
expectedKey string
expectedError error
}{
{
name: "Valid header",
headers: http.Header{"Authorization": []string{"ApiKey my-secret-key"}},
expectedKey: "my-secret-key",
expectedError: nil,
},
{
name: "Missing Authorization header",
headers: http.Header{},
expectedKey: "",
expectedError: ErrNoAuthHeaderIncluded,
},
{
name: "Empty Authorization header",
headers: http.Header{"Authorization": []string{""}},
expectedKey: "",
expectedError: ErrNoAuthHeaderIncluded,
},
{
name: "Malformed Authorization header - no space separator",
headers: http.Header{"Authorization": []string{"ApiKey-my-secret-key"}},
expectedKey: "",
expectedError: errors.New("malformed authorization header"),
},
{
name: "Malformed Authorization header - no ApiKey keyword",
headers: http.Header{"Authorization": []string{"Bearer my-secret-key"}},
expectedKey: "",
expectedError: errors.New("malformed authorization header"),
},
{
name: "Malformed Authorization header - no key provided",
headers: http.Header{"Authorization": []string{"ApiKey"}},
expectedKey: "",
expectedError: errors.New("malformed authorization header"),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
key, err := GetAPIKey(tt.headers)

if key != tt.expectedKey {
t.Errorf("expected key: %v, got: %v", tt.expectedKey, key)
}

if (err != nil && tt.expectedError == nil) || (err == nil && tt.expectedError != nil) || (err != nil && tt.expectedError != nil && err.Error() != tt.expectedError.Error()) {
t.Errorf("expected error: %v, got: %v", tt.expectedError, err)
}
})
}
}
6 changes: 5 additions & 1 deletion json.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
log.Printf("Error writing response: %s", err)
return
}
}
16 changes: 13 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"log"
"net/http"
"os"
"strconv"
"time"

"github.com/go-chi/chi"
"github.com/go-chi/cors"
Expand Down Expand Up @@ -89,10 +91,18 @@ func main() {

router.Mount("/v1", v1Router)
srv := &http.Server{
Addr: ":" + port,
Handler: router,
Addr: ":" + port,
Handler: router,
ReadHeaderTimeout: 5 * time.Second, // Fixes G112: Prevents Slowloris attacks
ReadTimeout: 10 * time.Second, // Recommended production hygiene
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
}

log.Printf("Serving on port: %s\n", port)
portNum, err := strconv.Atoi(port)
if err != nil {
log.Fatalf("Invalid PORT: %v", err)
}
log.Printf("Serving on port: %d\n", portNum)
log.Fatal(srv.ListenAndServe())
}
2 changes: 1 addition & 1 deletion static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</head>

<body class="section">
<h1>Notely</h1>
<h1>Welcome to Notely</h1>

<div id="userCreationContainer" class="section">
<input id="nameField" type="text" placeholder="Enter your name">
Expand Down