6.5 KiB
CI Workflow Implementation Plan (Plan 4d)
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Add a single Gitea Actions CI workflow that runs go vet + gofmt check + go build + go test -race + shellcheck + goreleaser check inside an archlinux:latest container on every push and PR.
Architecture: One workflow file (.gitea/workflows/ci.yml), one job with sequential steps. The Arch container gives environmental fidelity; actions/setup-go@v5 pins Go via go-version-file: go.mod for reproducibility.
Tech Stack: Gitea Actions, archlinux:latest container, Go (version pinned in go.mod), shellcheck, goreleaser v2.
Spec: docs/superpowers/specs/2026-04-14-ci-workflow-design.md
File Structure
New files:
.gitea/workflows/ci.yml— single-job CI workflow
No other files change.
Task 1: Pre-flight — verify all CI steps pass locally
Before writing the workflow, run every command it will execute locally to confirm the repo is in a CI-passing state. If any command fails, either the plan's step is wrong or the repo has a latent issue — either way, CI will fail without this check.
Files: none (validation only)
- Step 1:
go vet ./...
cd /home/marvin/git-clones/ArduinoArchSetup
go vet ./...
Expected: exit 0, no output.
If warnings appear, STOP and report — fixing them is out of scope for this plan but must happen before CI can land.
- Step 2:
gofmtcheck
cd /home/marvin/git-clones/ArduinoArchSetup
diff=$(gofmt -l .)
if [ -n "$diff" ]; then echo "FILES NEEDING FMT:"; echo "$diff"; exit 1; fi
echo "gofmt clean"
Expected: gofmt clean.
If any files are listed, STOP and report. Fixing formatting is out of scope — do NOT auto-fix in this plan. The user should decide whether to format in a separate commit first.
- Step 3:
go build ./...
cd /home/marvin/git-clones/ArduinoArchSetup
go build ./...
Expected: exit 0, no output.
- Step 4:
go test -race ./...
cd /home/marvin/git-clones/ArduinoArchSetup
go test -race ./...
Expected: all packages report ok or no test files. Failures = STOP and report. Race detector findings = STOP and report (they indicate real concurrency bugs).
- Step 5:
shellcheck bootstrap.sh
command -v shellcheck || { echo "shellcheck not installed; install via: sudo pacman -S shellcheck"; exit 1; }
shellcheck /home/marvin/git-clones/ArduinoArchSetup/bootstrap.sh
Expected: exit 0, no output.
If shellcheck isn't installed locally, install it (sudo pacman -S shellcheck) and retry. If findings appear, STOP and report — bootstrap.sh was validated by bash -n only, so this is the first shellcheck run.
- Step 6:
goreleaser check
command -v goreleaser || command -v /home/marvin/go/bin/goreleaser || { echo "goreleaser missing"; exit 1; }
(command -v goreleaser && goreleaser check) || /home/marvin/go/bin/goreleaser check
Expected: • 1 configuration file(s) validated or equivalent success message.
- Step 7: No commit
This task is informational. If all six steps passed, proceed to Task 2. If any failed, report findings to the controller and HALT — the CI workflow cannot land until the repo is in a passing state.
Task 2: Author .gitea/workflows/ci.yml
Files:
-
Create:
.gitea/workflows/ci.yml -
Step 1: Write the workflow file
Create /home/marvin/git-clones/ArduinoArchSetup/.gitea/workflows/ci.yml:
name: ci
on:
push:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
container:
image: archlinux:latest
steps:
- name: Install container prereqs
run: pacman -Sy --needed --noconfirm base-devel git shellcheck
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: go vet
run: go vet ./...
- name: gofmt check
run: |
diff=$(gofmt -l .)
if [ -n "$diff" ]; then
echo "files need gofmt:"
echo "$diff"
exit 1
fi
- name: go build
run: go build ./...
- name: go test -race
run: go test -race ./...
- name: shellcheck bootstrap.sh
run: shellcheck bootstrap.sh
- name: Install goreleaser
run: go install github.com/goreleaser/goreleaser/v2@latest
- name: goreleaser check
run: $(go env GOPATH)/bin/goreleaser check
- Step 2: Validate YAML syntax
cd /home/marvin/git-clones/ArduinoArchSetup
python3 -c "import yaml; yaml.safe_load(open('.gitea/workflows/ci.yml'))" && echo "yaml ok"
Expected: yaml ok.
- Step 3: Sanity-check step ordering against spec
Open the file and confirm the step order matches the spec's Section "Job steps":
- Install container prereqs
- Checkout
- Setup Go
- go vet
- gofmt check
- go build
- go test -race
- shellcheck bootstrap.sh
- Install goreleaser
- goreleaser check
No grouping or reordering. This is only a human-verified check (no command).
- Step 4: Commit
cd /home/marvin/git-clones/ArduinoArchSetup
git add .gitea/workflows/ci.yml
git commit -m "ci: add Gitea Actions workflow for test, vet, fmt, build, shellcheck, goreleaser check"
Do NOT add any Co-Authored-By trailer — repo convention forbids it.
Notes for the executing agent
- One file, one job. Don't split into multiple jobs or multiple workflows. The spec is explicit.
- Do not try to run the workflow itself — that requires a Gitea Actions runner (Plan 4c Task 9, currently deferred). The workflow will queue when pushed until a runner is online; that's fine.
- If Task 1 reveals failures in
go vet,gofmt,go test -race, orshellcheck, stop and escalate. Those are pre-existing issues the controller needs to address in a separate commit/plan; this plan only adds the workflow that detects them. - Why
$(go env GOPATH)/bin/goreleaserexplicitly in step 10:go installputs binaries inGOPATH/bin, which isn't on$PATHinside the stock Arch container. Using the absolute path is simpler than mutating PATH. - YAML indentation is significant. Use 2-space indents matching the example above. Do not substitute tabs.