docs(plan): Plan 4d CI workflow implementation plan
This commit is contained in:
205
docs/superpowers/plans/2026-04-14-ci-workflow.md
Normal file
205
docs/superpowers/plans/2026-04-14-ci-workflow.md
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
# 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 ./...`**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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 ./...`**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/marvin/git-clones/ArduinoArchSetup
|
||||||
|
go build ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: exit 0, no output.
|
||||||
|
|
||||||
|
- [ ] **Step 4: `go test -race ./...`**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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`**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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`**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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.
|
||||||
Reference in New Issue
Block a user