Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
4ebd858
Updated Readme
reiffle Sep 17, 2025
e706d47
Updated Readme (#1)
reiffle Sep 17, 2025
4ea47dc
Made basic .yml file
reiffle Sep 18, 2025
56fa4e3
Changed yml to check Go version
reiffle Sep 19, 2025
fd72b6d
Tried to fix Go version check
reiffle Sep 19, 2025
0e4aaf4
Tried to fix Go version check again
reiffle Sep 19, 2025
070ab51
Tried to fix Go version a third time
reiffle Sep 19, 2025
8fe5e0b
Added Tests for Api Key
reiffle Sep 23, 2025
1781dc9
Added tests, broke code to make sure they work
reiffle Sep 24, 2025
6b4f112
Fixed broken code
reiffle Sep 24, 2025
206940a
Added Coverage flag
reiffle Sep 26, 2025
babc835
Added Readme badge for tests
reiffle Sep 26, 2025
83d2471
Made basic .yml file
reiffle Sep 18, 2025
fd4c5b3
Changed yml to check Go version
reiffle Sep 19, 2025
f8f678b
Tried to fix Go version check
reiffle Sep 19, 2025
ec473f0
Tried to fix Go version check again
reiffle Sep 19, 2025
ef7633b
Tried to fix Go version a third time
reiffle Sep 19, 2025
d9b666f
Added Tests for Api Key
reiffle Sep 23, 2025
d8329ff
Added tests, broke code to make sure they work
reiffle Sep 24, 2025
5d1c2aa
Fixed broken code
reiffle Sep 24, 2025
4b82d96
Added Coverage flag
reiffle Sep 26, 2025
9a9eea4
Added Readme badge for tests
reiffle Sep 26, 2025
1742d04
FIxed badge url address
reiffle Sep 26, 2025
6b4b4ff
Update README.md badge url
reiffle Sep 26, 2025
f2ad506
Added formatting check
reiffle Sep 28, 2025
cb30095
Redid .yml to hopefully run formatting
reiffle Sep 28, 2025
a144726
Made a yml change to hopefully run formatting.
reiffle Sep 28, 2025
eee94a8
Hopefully resolved conflicts
reiffle Sep 28, 2025
3a448de
Hopefully fixed conflicts
reiffle Sep 28, 2025
f405186
Added staticcheck code
reiffle Sep 30, 2025
ab65ecf
Set gosec check
reiffle Oct 1, 2025
ecfaf78
Fixed security issues
reiffle Oct 1, 2025
84e4be1
Put gosec yml code into tests rather than style
reiffle Oct 1, 2025
10b1f0d
CD.yml added to build app on merge
reiffle Oct 6, 2025
26129a6
Ignore local gcloud SDK artifacts
reiffle Oct 12, 2025
b52e704
Ignore Google Cloud Stuff
reiffle Oct 12, 2025
8fdb645
Added GCP code
reiffle Oct 12, 2025
c46d1b8
Automatically depoy changes on push
reiffle Oct 13, 2025
996107c
Made minor change to header in static site
reiffle Oct 13, 2025
4eb0374
Changed deployed image to latest
reiffle Oct 13, 2025
bbbfc4d
Set up TURSO online database and set migrations in workflow
reiffle Oct 18, 2025
2d3448b
Changed goose install to after setting up Go
reiffle Oct 19, 2025
b3df960
Fixed Type on cd.yml
reiffle Oct 19, 2025
a16944a
Fixed another typo
reiffle Oct 19, 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
53 changes: 53 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: cd

on:
push:
branches: [main]

jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest

#Get the database url from Github secrets and put it in an environment variable for the job to access
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}

steps:
- name: Check out code
uses: actions/checkout@v4
# yaml
#- name: Mark workspace as safe
# run: |
# git config --global --add safe.directory "$GITHUB_WORKSPACE"

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25.1"

# Must install goose after setting up Go
- name: Install Goose
run: go install github.com/pressly/goose/v3/cmd/goose@latest

- name: Build Application
run: ./scripts/buildprod.sh

- name: Set up gcloud auth
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_CREDENTIALS }}
project_id: balmy-elf-474204-h5

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

- name: Build and push image to Artifact Registry
run: |
gcloud builds submit --tag us-central1-docker.pkg.dev/balmy-elf-474204-h5/notely-ar-repo/notely:latest .

- name: Migrate Database
run: ./scripts/migrateup.sh

- name: Deploy to Cloud Run
run: gcloud run deploy notely --image us-central1-docker.pkg.dev/balmy-elf-474204-h5/notely-ar-repo/notely:latest --region us-central1 --allow-unauthenticated --project balmy-elf-474204-h5 --max-instances=4
50 changes: 50 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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: Test Go code
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 code style
run: test -z $(go fmt ./...)

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

- name: run staticcheck
run: staticcheck ./...
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ out
.env
learn-cicd-starter
notely
google-cloud-cli-linux-x86_64.tar.gz
google-cloud-sdk/
Empty file added FETCH_HEAD
Empty file.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
![Test Verification Status](https://github.com/reiffle/learn-cicd-starter/actions/workflows/ci.yml/badge.svg)

![Test Verification Status](https://github.com/reiffle/learn-cicd-starter/actions/workflows/ci.yml/badge.svg)

# 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).
Expand All @@ -21,3 +25,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!

"Peder's version of Boot.dev's Notely app."
69 changes: 69 additions & 0 deletions internal/auth/auth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package auth

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

func TestGetAPIKey(t *testing.T) {
// Create slice of test cases
tests := []struct {
name string
headers http.Header
wantKey string
expectErr bool
errMessage string
}{
//First test case: No Authorization Header
{
name: "No Authorization Header",
headers: http.Header{}, // Empty headers
expectErr: true,
errMessage: "no authorization header included",
},
//Second test case: Malformed Authorization Header - No Space
{
name: "Malformed Authorization Header - No Space",
headers: http.Header{
"Authorization": []string{"ApiKey12345"}, //http.Header in Go is defined as map[string][]string
},
expectErr: true,
errMessage: "malformed authorization header",
},
//Third test case: Malformed Authorization Header - Wrong Scheme
{
name: "Malformed Authorization Header",
headers: http.Header{
"Authorization": []string{"Bearer 12345"},
},
expectErr: true,
errMessage: "malformed authorization header",
},
//Fourth test case: Valid Authorization Header
{
name: "Valid Authorization Header",
headers: http.Header{
"Authorization": []string{"ApiKey 12345"},
},
wantKey: "12345",
expectErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotKey, err := GetAPIKey(tt.headers)
if (err != nil) != tt.expectErr { // Check if error presence matches expectation (True/False)
t.Errorf("GetAPIKey() error = %v, expectErr %v", err, tt.expectErr)
return
}
if err != nil && !strings.Contains(err.Error(), tt.errMessage) { // Check if error message contains expected substring
t.Errorf("GetAPIKey() error = %v, expected error message to contain %v", err, tt.errMessage)
}
if gotKey != tt.wantKey { // Check if returned key matches expected key
t.Errorf("GetAPIKey() gotKey = %v, want %v", gotKey, tt.wantKey)
}
})
}
}
5 changes: 4 additions & 1 deletion json.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ 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)
}
}
7 changes: 5 additions & 2 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 @@ -89,8 +90,10 @@ func main() {

router.Mount("/v1", v1Router)
srv := &http.Server{
Addr: ":" + port,
Handler: router,
Addr: ":" + port,
Handler: router,
ReadTimeout: 5 * time.Second,
WriteTimeout: 7 * time.Second,
}

log.Printf("Serving on port: %s\n", port)
Expand Down
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