diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..f6948ae --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,29 @@ +name: cd + +on: + push: + paths: + - '.github/workflows/ci.yml' + - 'learn-cicd/**' + branches: [main] + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./learn-cicd + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.27.1" + + - name: Build app + run: ./scripts/buildprod.sh diff --git a/.github/workflows/chirpy.yml b/.github/workflows/chirpy.yml new file mode 100644 index 0000000..237942f --- /dev/null +++ b/.github/workflows/chirpy.yml @@ -0,0 +1,59 @@ +name: chirpy + +on: + pull_request: + paths: + - '.github/workflows/chirpy.yml' + - 'chirpy/**' + branches: [main] + push: + paths: + - '.github/workflows/chirpy.yml' + - 'chirpy/**' + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./chirpy + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.26.4" + + - name: Run unit tests + run: go test ./... -cover + + style: + name: Style + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./chirpy + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.27.1" + + - name: Run style checks + run: test -z $(go fmt ./...) + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ce56c9..a01a6bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,7 @@ name: ci on: pull_request: paths: + - '.github/workflows/ci.yml' - 'learn-cicd/**' branches: [main] @@ -25,4 +26,36 @@ jobs: go-version: "1.27.1" - name: Run unit tests - run: go test ./... -cover \ No newline at end of file + 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 + + defaults: + run: + working-directory: ./learn-cicd + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.27.1" + + - name: Run style checks + run: test -z $(go fmt ./...) + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... diff --git a/.github/workflows/gator.yml b/.github/workflows/gator.yml new file mode 100644 index 0000000..f8fce29 --- /dev/null +++ b/.github/workflows/gator.yml @@ -0,0 +1,59 @@ +name: gator + +on: + pull_request: + paths: + - '.github/workflows/gator.yml' + - 'gator/**' + branches: [main] + push: + paths: + - '.github/workflows/gator.yml' + - 'gator/**' + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./gator + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.26.4" + + - name: Run unit tests + run: go test ./... -cover + + style: + name: Style + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./gator + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.27.1" + + - name: Run style checks + run: test -z $(go fmt ./...) + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... diff --git a/.github/workflows/http-from-tcp.yml b/.github/workflows/http-from-tcp.yml new file mode 100644 index 0000000..ddd30ec --- /dev/null +++ b/.github/workflows/http-from-tcp.yml @@ -0,0 +1,59 @@ +name: http-from-tcp + +on: + pull_request: + paths: + - '.github/workflows/http-from-tcp.yml' + - 'http-from-tcp/**' + branches: [main] + push: + paths: + - '.github/workflows/http-from-tcp.yml' + - 'http-from-tcp/**' + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./http-from-tcp + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.27.1" + + - name: Run unit tests + run: go test ./... -cover + + style: + name: Style + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./http-from-tcp + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.26.4" + + - name: Run style checks + run: test -z $(go fmt ./...) + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... diff --git a/.github/workflows/learn-pub-sub.yml b/.github/workflows/learn-pub-sub.yml new file mode 100644 index 0000000..8b1572c --- /dev/null +++ b/.github/workflows/learn-pub-sub.yml @@ -0,0 +1,59 @@ +name: learn-pub-sub + +on: + pull_request: + paths: + - '.github/workflows/learn-pub-sub.yml' + - 'learn-pub-sub/**' + branches: [main] + push: + paths: + - '.github/workflows/learn-pub-sub.yml' + - 'learn-pub-sub/**' + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./learn-pub-sub + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.26.4" + + - name: Run unit tests + run: go test ./... -cover + + style: + name: Style + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./learn-pub-sub + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.27.1" + + - name: Run style checks + run: test -z $(go fmt ./...) + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... diff --git a/.github/workflows/pokedexcli.yml b/.github/workflows/pokedexcli.yml new file mode 100644 index 0000000..8d405f1 --- /dev/null +++ b/.github/workflows/pokedexcli.yml @@ -0,0 +1,59 @@ +name: pokedexcli + +on: + pull_request: + paths: + - '.github/workflows/pokedexcli.yml' + - 'pokedexcli/**' + branches: [main] + push: + paths: + - '.github/workflows/pokedexcli.yml' + - 'pokedexcli/**' + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./learn-cicd + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.27.1" + + - name: Run unit tests + run: go test ./... -cover + + style: + name: Style + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./learn-cicd + + steps: + - name: Check out code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.27.1" + + - name: Run style checks + run: test -z $(go fmt ./...) + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: staticcheck ./... diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/README.md b/README.md index f238ae1..05eef6f 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ A collection of projects completed as part of my coursework on [Boot.dev](https: | Project | CI | Description | | --- | --- | --- | -| [`chirpy`](./chirpy) | | HTTP web server built from scratch in Go, including routing, JSON handling, and a REST API backed by a database. | -| [`pokedexcli`](./pokedexcli) | | A CLI Pokedex in Go that consumes the PokeAPI REST API, with caching and a REPL-style interface. | -| [`gator`](./gator) | | RSS feed aggregator CLI in Go with persistent storage (PostgreSQL) and scheduled feed fetching. | -| [`http-from-tcp`](./http-from-tcp) | | Implements an HTTP server from raw TCP sockets in Go, without using the standard `net/http` package, to understand the protocol at a low level. | -| [`learn-pub-sub`](./learn-pub-sub) | | Pub/sub messaging system in Go using RabbitMQ, built around a multiplayer game simulation. | +| [`chirpy`](./chirpy) | ![chirpy](https://github.com/lennago/bootdev/actions/workflows/chirpy.yml/badge.svg) | HTTP web server built from scratch in Go, including routing, JSON handling, and a REST API backed by a database. | +| [`pokedexcli`](./pokedexcli) | ![pokedexcli](https://github.com/lennago/bootdev/actions/workflows/pokedexcli.yml/badge.svg) | A CLI Pokedex in Go that consumes the PokeAPI REST API, with caching and a REPL-style interface. | +| [`gator`](./gator) | ![gator](https://github.com/lennago/bootdev/actions/workflows/gator.yml/badge.svg) | RSS feed aggregator CLI in Go with persistent storage (PostgreSQL) and scheduled feed fetching. | +| [`http-from-tcp`](./http-from-tcp) | ![http-from-tcp](https://github.com/lennago/bootdev/actions/workflows/http-from-tcp.yml/badge.svg) | Implements an HTTP server from raw TCP sockets in Go, without using the standard `net/http` package, to understand the protocol at a low level. | +| [`learn-pub-sub`](./learn-pub-sub) | ![learn-pub-sub](https://github.com/lennago/bootdev/actions/workflows/learn-pub-sub.yml/badge.svg) | Pub/sub messaging system in Go using RabbitMQ, built around a multiplayer game simulation. | | [`kubernetes`](./kubernetes) | | Deploying and orchestrating an application with Kubernetes. | | [`static-site-generator`](./static-site-generator) | | A static site generator written in Python that converts Markdown files into HTML pages. | | [`asteroids`](./asteroids) | | A recreation of the classic Asteroids arcade game in Python using Pygame. | diff --git a/learn-cicd/json.go b/learn-cicd/json.go index 1e6e798..c382d65 100644 --- a/learn-cicd/json.go +++ b/learn-cicd/json.go @@ -30,5 +30,8 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { return } w.WriteHeader(code) - w.Write(dat) + if _, err := w.Write(dat); err != nil { + log.Printf("Critical error writing response: %s", err) + return + } } diff --git a/learn-cicd/main.go b/learn-cicd/main.go index 19d7366..1882728 100644 --- a/learn-cicd/main.go +++ b/learn-cicd/main.go @@ -7,6 +7,8 @@ import ( "log" "net/http" "os" + "strconv" + "time" "github.com/go-chi/chi" "github.com/go-chi/cors" @@ -89,10 +91,11 @@ func main() { router.Mount("/v1", v1Router) srv := &http.Server{ - Addr: ":" + port, - Handler: router, + Addr: ":" + port, + Handler: router, + ReadHeaderTimeout: time.Second * 5, } - log.Printf("Serving on port: %s\n", port) + log.Printf("Serving on port: %s\n", strconv.Quote(port)) log.Fatal(srv.ListenAndServe()) }