Files
Archduino/docs/superpowers/plans/2026-04-14-ci-workflow.md
2026-04-14 21:30:01 +02:00

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: gofmt check
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":

  1. Install container prereqs
  2. Checkout
  3. Setup Go
  4. go vet
  5. gofmt check
  6. go build
  7. go test -race
  8. shellcheck bootstrap.sh
  9. Install goreleaser
  10. 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, or shellcheck, 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/goreleaser explicitly in step 10: go install puts binaries in GOPATH/bin, which isn't on $PATH inside 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.