Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
111 changes: 111 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
name: DevOps Intro Workflow

on:
push:
branches: [ main ]
paths:
- 'app/**'
- '.github/workflows/**'
pull_request:
branches: [ main ]
paths:
- 'app/**'
- '.github/workflows/**'

permissions:
contents: read

env:
GOFLAGS: -buildvcs=false

jobs:
vet:
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1

- name: Setup Go compiler
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: '1.24'
cache: true
cache-dependency-path: app/go.sum

- name: Run go vet
run: go vet ./...
working-directory: app

test:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
go: ['1.23', '1.24']
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1

- name: Setup Go compiler
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ matrix.go }}
cache: true
cache-dependency-path: app/go.sum

- name: Run unit tests
run: go test -race -count=1 ./...
working-directory: app

lint:
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1

- name: Setup Go compiler
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: '1.24'
cache: true
cache-dependency-path: app/go.sum

- name: Run golangci-lint
uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd # v7.0.0
with:
version: v2.5.0
working-directory: app


govulncheck:
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1

- name: Run govulncheck
uses: golang/govulncheck-action@032d45514ae346b1db93c04b0c90b841c370344f # v1.1.0
with:
go-version-input: '1.25'
work-dir: app

ci-ok:
if: always()
needs: [vet, test, lint, govulncheck]
runs-on: ubuntu-24.04
steps:
- name: Check status of dependent jobs
run: |
if ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}; then
echo "One or more dependent jobs failed or were cancelled."
exit 1
fi
echo "All dependent jobs completed successfully."
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,6 @@ Thumbs.db
# wasm/main.go, spin.toml, go.sum (Lab 12)
data/
app/data/
zap-report.*
zap-report-after.*
Comment on lines +66 to +67

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Anchor ZAP report ignores to avoid hiding lab evidence

Because this ignore pattern has no slash, Git applies it to matching files in any directory, even though the note just above says Lab 9 ZAP reports are deliverables students must be able to commit. A student who generates a new untracked zap-report.html/.json under their submission or evidence directory will have it silently ignored unless they force-add it; if these are only meant to be root scratch files, anchor the patterns with /.

Useful? React with 👍 / 👎.

zap.yaml
24 changes: 24 additions & 0 deletions app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# syntax=docker/dockerfile:1

FROM golang:1.24.6-bookworm AS builder

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Build the image with the patched Go toolchain

This pins the shipped binary to Go 1.24.6, but the committed Trivy image report shows the resulting app/quicknotes binary has 15 HIGH/CRITICAL stdlib findings at v1.24.6, including fixes available in 1.24.12/1.24.13. Because the new CI job uses go-version-input: '1.24' rather than this Dockerfile pin, CI can pass with a newer patch while the container artifact remains vulnerable; bump the builder image to a patched 1.24.x tag or otherwise align the image build with the gate.

Useful? React with 👍 / 👎.

WORKDIR /src
COPY go.mod go.su[m] ./

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop requiring an absent go.sum in the Docker build

In a fresh checkout this Dockerfile cannot build because app/go.sum is not tracked, while Docker treats go.su[m] as a glob that only matches go.sum, not as an optional source. The failure happens before go mod download, so any docker compose build/Lab 6 image rebuild from the committed tree stops at this COPY; either add a real go.sum or avoid copying it until it exists.

Useful? React with 👍 / 👎.

RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build \
-trimpath \
-ldflags='-s -w' \
-o /out/quicknotes .
RUN mkdir -p /data-empty

FROM busybox:1.37-uclibc AS busybox

FROM gcr.io/distroless/static:nonroot
WORKDIR /app
COPY --from=builder /out/quicknotes /app/quicknotes
COPY --from=builder /src/seed.json /app/seed.json
COPY --from=busybox /bin/wget /bin/wget
COPY --from=builder --chown=65532:65532 /data-empty /data
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app/quicknotes"]
3 changes: 3 additions & 0 deletions app/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ func (sw *statusWriter) WriteHeader(code int) {
func (s *Server) wrap(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
sw := &statusWriter{ResponseWriter: w, code: 200}
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Cross-Origin-Resource-Policy", "same-origin")
w.Header().Set("Cache-Control", "no-store")
h(sw, r)
s.requestsTotal.Add(1)
if c, ok := s.requestsByCode[sw.code]; ok {
Expand Down
1 change: 0 additions & 1 deletion app/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,3 @@ func TestMetrics_ExposesPrometheusFormat(t *testing.T) {
}
}
}

29 changes: 29 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
services:
quicknotes:
build: ./app
image: quicknotes:lab6
ports:
- "8080:8080"
environment:
ADDR: ":8080"
DATA_PATH: /data/notes.json
SEED_PATH: /app/seed.json
healthcheck:
test: ["CMD", "/bin/wget", "-q", "-O", "-", "http://127.0.0.1:8080/health"]
interval: 10s
timeout: 3s
retries: 3
start_period: 5s
cap_drop:
- ALL
read_only: true
tmpfs:
- /tmp
security_opt:
- no-new-privileges:true
volumes:
- quicknotes-data:/data
restart: unless-stopped

volumes:
quicknotes-data:
1 change: 1 addition & 0 deletions security/govulncheck.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
No vulnerabilities found.
Loading
Loading