name: CI # The release workflow gates a tag, which is late: a broken commit sits green until # somebody decides to publish. This runs the same checks on the way in. # # push is scoped to main rather than all branches so that a branch pushed as part of a # pull request is not checked twice. # # No actions/checkout, deliberately -- same as the letsvisit and charts workflows. The # runner image is ubuntu:22.04 whose `nodejs` package is Node 12, and actions/checkout@v4 # is built with ES2022 static initialiser blocks, so it dies with # `SyntaxError: Unexpected token '{'` before running. Cloning with git directly avoids JS # actions entirely. This repo is public, so the clone needs no credential at all. # # `${{ }}` values are passed through `env:` and referenced as quoted shell variables: a # ref name is attacker-influenced by anyone who can push a branch or open a PR, and # expanding one straight into `run:` is a shell-injection vector. on: push: branches: [main] pull_request: # A rapid series of pushes only needs the last one checked. concurrency: group: ci-${{ github.ref }} cancel-in-progress: true env: REPO_URL: https://git.ryuvia.com/niklas/terdut-server.git jobs: test: runs-on: ubuntu-latest container: # Runs inside the toolchain image rather than installing Go per job. Note this puts # the job on the dind bridge, which cannot reach github.com or get.helm.sh -- # proxy.golang.org and git.ryuvia.com are reachable, which is all this job needs. image: golang:1.26.6-bookworm # act_runner destroys a job's own volumes when it finishes, so without these every # run re-downloads the whole module graph. The names must appear in the runner's # container.valid_volumes allowlist (charts/act-runner in the k8s repo); unlisted # volumes are dropped silently, so a workflow that looks correct can still be # running uncached. volumes: - go-mod-cache:/go/pkg/mod - go-build-cache:/root/.cache/go-build - gobin-cache:/go/bin steps: - name: Checkout env: REF_NAME: ${{ github.ref_name }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | if [ -n "$HEAD_SHA" ]; then # A pull_request ref_name is "/merge", which is not a fetchable branch. git clone "$REPO_URL" . git checkout -q "$HEAD_SHA" else git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" . fi # The gate is the Makefile's rather than a second copy of it here, the way riksdata # and rd-web already do it. `make fmt lint test` is exactly what a developer runs, so # a green pipeline and a green working copy mean the same thing by construction # instead of by remembering to update two files together. # # The reasoning that used to live here moved with the targets: why gofmt is checked # at all (import order survives `go vet`, and both repos sat unformatted through a # green run and a release -- 9046f6e), why both of gofmt's failure modes need # handling, and why `test` adds -race when this job does not have to. - name: Format, vet and test run: make fmt lint test # Runs on every push and pull request, unlike the image scan, which needs something # published to scan and so lives in release.yaml. Both are needed: govulncheck reads the # source and its module graph, trivy reads the built artifact, and neither sees what the # other does. security: runs-on: ubuntu-latest container: image: golang:1.26.6-bookworm volumes: - go-mod-cache:/go/pkg/mod - go-build-cache:/root/.cache/go-build - gobin-cache:/go/bin steps: - name: Checkout env: REF_NAME: ${{ github.ref_name }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | if [ -n "$HEAD_SHA" ]; then git clone "$REPO_URL" . git checkout -q "$HEAD_SHA" else git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" . fi - name: Go vulnerability scan (govulncheck) run: make security-go - name: Secret scan (gitleaks) run: make security-secrets # Host mode, no `container:`: helm is baked into the runner image, and a container job # could not install it -- get.helm.sh is unreachable from the dind bridge. Same reason # release.yaml's chart job runs on the host. # # The chart had no lint step in any workflow until 2026-09-01: release.yaml packaged and # pushed it without rendering it first, so a template that did not compile would have # been found by Flux rather than here. chart: runs-on: ubuntu-latest steps: - name: Checkout env: REF_NAME: ${{ github.ref_name }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | if [ -n "$HEAD_SHA" ]; then git clone "$REPO_URL" . git checkout -q "$HEAD_SHA" else git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" . fi - name: Lint and render the chart run: make helm-lint