diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 00000000000..d3ec14b35a9 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,48 @@ +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: 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.26.0" + + - name: build + 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' + with: + version: '>= 363.0.0' + + - name: docker + run: gcloud builds submit --tag us-central1-docker.pkg.dev/solid-binder-491221-g5/notely-ar-repo/notely:latest . + + - name: migrate + run: ./scripts/migrateup.sh + + - name: Deploy to Cloud Run + run: gcloud run deploy notely --image us-central1-docker.pkg.dev/solid-binder-491221-g5/notely-ar-repo/notely:latest --region us-central1 --allow-unauthenticated --project solid-binder-491221-g5 --max-instances=4 + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..0ccf45f68dc --- /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.26.0" + + - name: Install gosec + run: go install github.com/securego/gosec/v2/cmd/gosec@latest + + - name: go test + run: go test -cover ./... + + - name: gosec test + 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.26.0" + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: style + run: test -z $(go fmt ./...) + + - name: staticcheck + run: staticcheck ./... + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2092f54e78a..304ab93e03e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ out .env learn-cicd-starter -notely + diff --git a/README.md b/README.md index c2bec0368b7..789e4629f87 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # 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). ## Local Development @@ -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! + +Dylan's version of Boot.dev's Notely app. diff --git a/go.sum b/go.sum index e3c6163bd09..236876a135d 100644 --- a/go.sum +++ b/go.sum @@ -54,6 +54,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tursodatabase/libsql-client-go v0.0.0-20240220085343-4ae0eb9d0898 h1:1MvEhzI5pvP27e9Dzz861mxk9WzXZLSJwzOU67cKTbU= github.com/tursodatabase/libsql-client-go v0.0.0-20240220085343-4ae0eb9d0898/go.mod h1:9bKuHS7eZh/0mJndbUOrCx8Ej3PlsRDszj4L7oVYMPQ= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go new file mode 100644 index 00000000000..e06ca0a4296 --- /dev/null +++ b/internal/auth/auth_test.go @@ -0,0 +1,55 @@ +package auth + +import ( + "fmt" + "net/http" + "strings" + "testing" +) + +func TestAPIKey(t *testing.T) { + tests := []struct { + key string + value string + expect string + err string + }{ + { + err: "no authorization header", + }, + { + key: "Authorization", + err: "no authorization header", + }, + { + key: "Authorization", + value: "h293hr928h3", + err: "malformed authorization header", + }, + { + key: "Authorization", + value: "ApiKey hf29hd923", + expect: "hf29hd923", + err: "none", + }, + } + for i, test := range tests { + t.Run(fmt.Sprintf("TestGetAPIKey Case #%v:", i), func(t *testing.T) { + header := http.Header{} + header.Add(test.key, test.value) + + output, err := GetAPIKey(header) + if err != nil { + if strings.Contains(err.Error(), test.err) { + return + } + t.Error(err) + return + } + if output != test.expect { + t.Error(err) + return + } + }) + } +} diff --git a/json.go b/json.go index 1e6e7985e18..f563b20fc69 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 { + log.Printf("Error writing: %v", err) + return + } } diff --git a/main.go b/main.go index 19d7366c5f7..8eea9fe835c 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,6 @@ package main +// for the change import ( "database/sql" "embed" @@ -7,6 +8,7 @@ import ( "log" "net/http" "os" + "time" "github.com/go-chi/chi" "github.com/go-chi/cors" @@ -24,17 +26,14 @@ type apiConfig struct { //go:embed static/* var staticFiles embed.FS +const port = "8080" + 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 @@ -89,10 +88,14 @@ func main() { router.Mount("/v1", v1Router) srv := &http.Server{ - Addr: ":" + port, - Handler: router, + Addr: ":" + port, + Handler: router, + ReadHeaderTimeout: time.Second * 30, } log.Printf("Serving on port: %s\n", port) - log.Fatal(srv.ListenAndServe()) + err = srv.ListenAndServe() + if err != nil { + log.Fatal(err) + } } diff --git a/notely b/notely new file mode 100755 index 00000000000..7cf6e691f13 Binary files /dev/null and b/notely differ diff --git a/static/index.html b/static/index.html index 72be101028c..d184d84edaa 100644 --- a/static/index.html +++ b/static/index.html @@ -3,11 +3,11 @@
-