| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- name: CI
- # Enforces the contribution rules documented in CLAUDE.md.
- # Formatting and the convention checker are scoped to the change's diff so that
- # grandfathered legacy code is not punished; build/test run module-wide, and
- # go vet runs module-wide but advisory-only (it never fails CI on legacy code).
- on:
- push:
- branches: ["**"]
- pull_request:
- permissions:
- contents: read
- jobs:
- verify:
- runs-on: ubuntu-latest
- defaults:
- run:
- working-directory: src
- steps:
- - name: Checkout (full history for diffing)
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - name: Set up Go
- uses: actions/setup-go@v5
- with:
- go-version: "1.24"
- cache-dependency-path: src/go.sum
- - name: Resolve diff base
- id: base
- working-directory: ${{ github.workspace }}
- run: |
- if [ "${{ github.event_name }}" = "pull_request" ]; then
- base="${{ github.event.pull_request.base.sha }}"
- else
- base="${{ github.event.before }}"
- fi
- # Use the base only if it is a real commit present in this checkout.
- # Push events can report a github.event.before that was force-pushed
- # away or never fetched (git then errors "fatal: bad object"); fall
- # back to HEAD's parent, and finally to empty so the diff-scoped steps
- # below skip gracefully instead of crashing the job under `bash -e`.
- if ! git rev-parse --verify --quiet "${base}^{commit}" >/dev/null 2>&1; then
- base="$(git rev-parse --verify --quiet 'HEAD~1^{commit}' 2>/dev/null || true)"
- fi
- echo "sha=$base" >> "$GITHUB_OUTPUT"
- echo "Diff base: ${base:-<none; diff-scoped checks skipped>}"
- - name: Convention checker (rules 1-5, diff only)
- if: steps.base.outputs.sha != ''
- working-directory: ${{ github.workspace }}
- run: sh scripts/check-conventions.sh --diff "${{ steps.base.outputs.sha }}"
- - name: gofmt (changed Go files)
- if: steps.base.outputs.sha != ''
- working-directory: ${{ github.workspace }}
- run: |
- files=$(git diff --name-only --diff-filter=ACM "${{ steps.base.outputs.sha }}" -- '*.go' || true)
- [ -z "$files" ] && { echo "No Go files changed."; exit 0; }
- unformatted=$(gofmt -l $files)
- if [ -n "$unformatted" ]; then
- echo "These files are not gofmt-clean:"; echo "$unformatted"
- echo "Run: gofmt -w <file>"; exit 1
- fi
- - name: go vet (advisory — never blocks CI)
- # Module-wide vet surfaces pre-existing issues in grandfathered legacy
- # code that this project intentionally does not modify, so it is run for
- # visibility only and never fails the build. Enforcement of the
- # contribution rules on NEW code is handled by the diff-scoped
- # convention checker above.
- continue-on-error: true
- run: go vet ./...
- - name: go build (all packages, native)
- run: go build ./...
- - name: Cross-compile smoke test (portability, rule 5)
- # Mirrors the release targets in the Makefile: the shipped binary must
- # build for other OSes from a single, dependency-free codebase.
- run: |
- GOOS=windows GOARCH=amd64 go build -o /dev/null .
- GOOS=darwin GOARCH=arm64 go build -o /dev/null .
- GOOS=linux GOARCH=arm GOARM=6 go build -o /dev/null .
- - name: go test
- run: go test -count=1 ./...
|