Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update README.md #1105

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
da78ead
Update README.md
JonathanPetrone Feb 4, 2025
702546d
added yaml
JonathanPetrone Feb 4, 2025
b8da727
changes in github
JonathanPetrone Feb 4, 2025
800b4f7
added change to yaml to make test pass
JonathanPetrone Feb 4, 2025
b8adf61
added change to yaml to make test pass
JonathanPetrone Feb 4, 2025
3ccd11a
added tests for auth
JonathanPetrone Feb 4, 2025
d0a66a6
added tests for auth
JonathanPetrone Feb 4, 2025
842cb30
added cover as a parameter in yaml tests
JonathanPetrone Feb 4, 2025
18ee05f
added text for test status img with readme
JonathanPetrone Feb 4, 2025
c6b9694
added logic for style checking in ci.yml
JonathanPetrone Feb 6, 2025
9bbf7e7
fixed file removed line
JonathanPetrone Feb 6, 2025
f99fdc1
added go linter in ci.yml
JonathanPetrone Feb 6, 2025
c4802c2
removed unused func
JonathanPetrone Feb 6, 2025
6e24c5a
added sec scheck
JonathanPetrone Feb 7, 2025
455c1ad
fixed check
JonathanPetrone Feb 7, 2025
b127b2d
added cd workflow
JonathanPetrone Feb 8, 2025
131e94a
added steps to push to gcp
JonathanPetrone Feb 8, 2025
6bb7a98
added steps to push to gcp
JonathanPetrone Feb 8, 2025
db5101d
added expose 8080
JonathanPetrone Feb 8, 2025
de37569
added steps to docker file
JonathanPetrone Feb 8, 2025
6cf194f
added steps to docker file
JonathanPetrone Feb 8, 2025
3d0d6ea
added steps to docker file
JonathanPetrone Feb 8, 2025
93e2f4b
deploy to cloud run
JonathanPetrone Feb 8, 2025
81b401a
deploy to cloud run
JonathanPetrone Feb 8, 2025
0a0c46d
deploy to cloud run
JonathanPetrone Feb 8, 2025
e8b0ae5
added steps regarding migration
JonathanPetrone Feb 8, 2025
063122b
added steps regarding migration
JonathanPetrone Feb 8, 2025
1169fa3
added steps regarding migration
JonathanPetrone Feb 8, 2025
5783272
fixed typo
JonathanPetrone Feb 8, 2025
093d61c
fixed typo
JonathanPetrone Feb 8, 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
47 changes: 47 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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@v4

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

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

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

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

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

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

- name: Build and Push Image
run: |
gcloud config set project notely-450310
gcloud builds submit --tag europe-north1-docker.pkg.dev/notely-450310/notely-ar-repo/notely:latest .

- name: Deploy to Cloud Run
run: gcloud run deploy notely --image europe-north1-docker.pkg.dev/notely-450310/notely-ar-repo/notely:latest --region europe-north1 --allow-unauthenticated --project notely-450310 --max-instances=4
51 changes: 51 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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.23.0"

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

- name: Run tests
run: go test ./... -cover

- name: Check security
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.23.0"

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

- name: Check formatting
run: test -z $(go fmt ./...)

- name: Use Go linter
run: staticcheck ./...

16 changes: 12 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
FROM --platform=linux/amd64 debian:stable-slim
FROM debian:stable-slim

RUN apt-get update && apt-get install -y ca-certificates
RUN apt-get update && apt-get install -y ca-certificates file

ADD notely /usr/bin/notely
WORKDIR /app
COPY notely .

CMD ["notely"]
RUN chmod +x notely

EXPOSE 8080
ENV PORT=8080

# Be explicit about listening on all interfaces
ENV HOST=0.0.0.0
CMD ["./notely"]
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
![Test status](https://github.com/jonathanpetrone/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 +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!

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

import (
"net/http"
"testing"
)

func TestGetAPIKey(t *testing.T) {
t.Run("valid API key exists in the context", func(t *testing.T) {
headers := make(http.Header)
headers.Add("Authorization", "ApiKey test-key-123")

got, err := GetAPIKey(headers)
if err != nil {
t.Errorf("expected no error, got %v", err)
}

want := "test-key-123"
if got != want {
t.Errorf("got %q, want %q", got, want)
}
})
t.Run("no API key exists", func(t *testing.T) {
headers := make(http.Header)
// Don't add any Authorization header

got, err := GetAPIKey(headers)
if err != ErrNoAuthHeaderIncluded {
t.Errorf("Expected ErrNoAuthHeaderIncluded, got %v", err)
}

if got != "" {
t.Errorf("Expected empty string, got %v", got)
}

})
t.Run("malformed authorization header", func(t *testing.T) {
headers := make(http.Header)
headers.Add("Authorization", "Bearer test-key-123") // Wrong prefix

got, err := GetAPIKey(headers)
if err == nil {
t.Error("expected error, got nil")
}
if err.Error() != "malformed authorization header" {
t.Errorf("expected 'malformed authorization header', got %v", err)
}
if got != "" {
t.Errorf("expected empty string, got %q", got)
}
})
}
5 changes: 4 additions & 1 deletion json.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,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 data: %s", err)
}
}
36 changes: 29 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import (
"log"
"net/http"
"os"
"strings"
"time"

"github.com/go-chi/chi"
"github.com/go-chi/cors"
"github.com/joho/godotenv"

"github.com/bootdotdev/learn-cicd-starter/internal/database"

Expand All @@ -24,15 +25,35 @@ type apiConfig struct {
//go:embed static/*
var staticFiles embed.FS

func main() {
err := godotenv.Load(".env")
func getCurrentDirectory() string {
dir, err := os.Getwd()
if err != nil {
return err.Error()
}
return dir
}

func listFiles(dir string) string {
files, err := os.ReadDir(dir)
if err != nil {
log.Printf("warning: assuming default configuration. .env unreadable: %v", err)
return err.Error()
}
var fileNames []string
for _, file := range files {
fileNames = append(fileNames, file.Name())
}
return strings.Join(fileNames, ", ")
}

func main() {
log.Printf("Starting application...")
log.Printf("Current working directory: %s", getCurrentDirectory())
log.Printf("Files in current directory: %s", listFiles("."))

port := os.Getenv("PORT")
if port == "" {
log.Fatal("PORT environment variable is not set")
log.Println("PORT environment variable not set, defaulting to 8080")
port = "8080"
}

apiCfg := apiConfig{}
Expand Down Expand Up @@ -89,8 +110,9 @@ func main() {

router.Mount("/v1", v1Router)
srv := &http.Server{
Addr: ":" + port,
Handler: router,
Addr: "0.0.0.0:" + port, // explicitly bind to all interfaces
Handler: router,
ReadHeaderTimeout: 5 * time.Second,
}

log.Printf("Serving on port: %s\n", port)
Expand Down
2 changes: 1 addition & 1 deletion scripts/buildprod.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o notely
GOOS=linux GOARCH=amd64 go build -o notely .
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