Task 1: Module scaffold, GPLv3 licence, CI on the arm64 runner #1

Closed
opened 2026-09-10 17:14:21 +00:00 by Cordy · 1 comment
Owner

Work tasks in numerical order. Read CLAUDE.md first.

Goal

A Go module that builds, with CI green on the self-hosted Forgejo runner.

Files

  • Create: go.mod, LICENSE, .forgejo/workflows/ci.yml
  • Modify: README.md (auto-created at repo init)

Produces

Module path cairn.ch/desktop; a CI job named test.

Steps

  • Init the module. go mod init cairn.ch/desktop, then pin the toolchain in go.mod:
module cairn.ch/desktop

go 1.25
  • Add the licence. Full GPLv3 text in LICENSE, fetched from https://www.gnu.org/licenses/gpl-3.0.txt. No App Store exception here — that belongs on cairn-ios only.

  • Add the CI workflow at .forgejo/workflows/ci.yml:

name: ci
on: [push, workflow_dispatch]

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - name: checkout
        run: |
          set -eux
          rm -rf src && mkdir src && cd src
          git init -q
          git remote add origin http://x-access-token:${GITHUB_TOKEN}@192.168.10.245/Cordy/cairn-desktop.git
          git fetch -q --depth 1 origin "${GITHUB_SHA}"
          git checkout -q FETCH_HEAD

      - name: install Go
        run: |
          set -eux
          GOVER=1.25.5
          case "$(uname -m)" in
            x86_64)        GOARCH=amd64 ;;
            aarch64|arm64) GOARCH=arm64 ;;
            *) echo "unsupported arch $(uname -m)"; exit 1 ;;
          esac
          if ! /usr/local/go/bin/go version 2>/dev/null | grep -q "go${GOVER}"; then
            curl -fsSL -o /tmp/go.tgz "https://go.dev/dl/go${GOVER}.linux-${GOARCH}.tar.gz"
            rm -rf /usr/local/go && tar -C /usr/local -xzf /tmp/go.tgz
          fi
          /usr/local/go/bin/go version

      - name: vet and test
        working-directory: src
        run: |
          set -eux
          export PATH=/usr/local/go/bin:$PATH CGO_ENABLED=0 GOFLAGS=-mod=mod
          go mod tidy
          go vet ./...
          go test -count=1 ./...
  • Commit with sign-off. git commit -s -m "chore: scaffold module, GPLv3 licence, CI"
  • Dispatch ci and confirm green. Read output from the runner pod — the job-log API 404s on this Forgejo version:
kubectl logs -n forgejo-runner deploy/forgejo-runner --tail=100

Why the workflow looks like that

The runner executes in host mode: no Docker, no job containers, and node-based actions (actions/checkout, actions/setup-go) do not work — hence plain-git checkout and a hand-rolled Go install. Jobs land on amd64 or arm64 despite the ubuntu-latest label, so arch detection is mandatory. The pod persists between runs, so the Go install is skip-if-present.

Acceptance criteria

  • go vet ./... and go test ./... both succeed in CI with no packages to test.
  • The commit carries a Signed-off-by: trailer.
Work tasks in numerical order. Read `CLAUDE.md` first. ## Goal A Go module that builds, with CI green on the self-hosted Forgejo runner. ## Files - Create: `go.mod`, `LICENSE`, `.forgejo/workflows/ci.yml` - Modify: `README.md` (auto-created at repo init) ## Produces Module path `cairn.ch/desktop`; a CI job named `test`. ## Steps - [ ] **Init the module.** `go mod init cairn.ch/desktop`, then pin the toolchain in `go.mod`: ``` module cairn.ch/desktop go 1.25 ``` - [ ] **Add the licence.** Full GPLv3 text in `LICENSE`, fetched from <https://www.gnu.org/licenses/gpl-3.0.txt>. No App Store exception here — that belongs on `cairn-ios` only. - [ ] **Add the CI workflow** at `.forgejo/workflows/ci.yml`: ```yaml name: ci on: [push, workflow_dispatch] jobs: test: runs-on: ubuntu-latest timeout-minutes: 20 steps: - name: checkout run: | set -eux rm -rf src && mkdir src && cd src git init -q git remote add origin http://x-access-token:${GITHUB_TOKEN}@192.168.10.245/Cordy/cairn-desktop.git git fetch -q --depth 1 origin "${GITHUB_SHA}" git checkout -q FETCH_HEAD - name: install Go run: | set -eux GOVER=1.25.5 case "$(uname -m)" in x86_64) GOARCH=amd64 ;; aarch64|arm64) GOARCH=arm64 ;; *) echo "unsupported arch $(uname -m)"; exit 1 ;; esac if ! /usr/local/go/bin/go version 2>/dev/null | grep -q "go${GOVER}"; then curl -fsSL -o /tmp/go.tgz "https://go.dev/dl/go${GOVER}.linux-${GOARCH}.tar.gz" rm -rf /usr/local/go && tar -C /usr/local -xzf /tmp/go.tgz fi /usr/local/go/bin/go version - name: vet and test working-directory: src run: | set -eux export PATH=/usr/local/go/bin:$PATH CGO_ENABLED=0 GOFLAGS=-mod=mod go mod tidy go vet ./... go test -count=1 ./... ``` - [ ] **Commit with sign-off.** `git commit -s -m "chore: scaffold module, GPLv3 licence, CI"` - [ ] **Dispatch `ci` and confirm green.** Read output from the runner pod — the job-log API 404s on this Forgejo version: ```bash kubectl logs -n forgejo-runner deploy/forgejo-runner --tail=100 ``` ## Why the workflow looks like that The runner executes in **host mode**: no Docker, no job containers, and node-based actions (`actions/checkout`, `actions/setup-go`) do not work — hence plain-git checkout and a hand-rolled Go install. Jobs land on **amd64 or arm64** despite the `ubuntu-latest` label, so arch detection is mandatory. The pod persists between runs, so the Go install is skip-if-present. ## Acceptance criteria - `go vet ./...` and `go test ./...` both succeed in CI with no packages to test. - The commit carries a `Signed-off-by:` trailer.
Cordy added this to the phase-1-engine milestone 2026-09-10 17:14:21 +00:00
Author
Owner

Done

  • d4e5c72 chore: scaffold module, GPLv3 licence, CI
  • aae1ec2 ci: install curl on the Alpine runner when missing

What was built

  • go.mod (module cairn.ch/desktop, go 1.25, no toolchain line)
  • Full GPLv3 LICENSE fetched from gnu.org, no App Store exception
  • .forgejo/workflows/ci.yml, verbatim from the issue: job test (checkout, install Go, vet and test)
  • A command -v curl || apk add curl guard added to the install-Go step — turned out to be a no-op, the runner image already has curl (ruling R16)

Tests

  • Run 2858 (run #1, commit aae1ec2) went red at go vet ./...: "no packages to vet" — Go 1.25.5 exits 1 on a zero-package module, so acceptance criterion 1 as literally worded cannot pass alone.
  • Run 2864 (run #2, commit 6257370, arm64/linux, Go 1.25.5): go vet ./... and go test -count=1 ./... both green, job test succeeded. This is the first green run that also contains #2's arch guard package, so #1 closes on it (ledger ruling F1).
  • One fix round briefly committed #2's deliverable inside a #1 fix round and then reverted it; both commits were never pushed and were dropped from history (R14) — main's history carries neither.

Acceptance criteria

  • "go vet ./... and go test ./... both succeed with no packages to test" — not achievable as literally worded on Go 1.25.5, which errors on zero packages; read as "the scaffold's CI is green," met on run 2864.
  • "The commit carries a Signed-off-by: trailer" — met on both commits.

Rulings

  • R1: go.mod stays exactly go 1.25, no toolchain line.
  • R6: #1 leaves README.md unchanged; #15 owns it.
  • R11: an issue closes only after its commits are on main and that push's CI run is green.
  • R12: commit subjects verbatim, git commit -s, plus Co-Authored-By trailer.
  • F1: Go 1.25.5 fails vet/test on zero packages; #1 closes on the first green run that also contains #2's package, not the red aae1ec2 run alone.
  • R15: run 2858's red was a controller sequencing defect (Task 1 pushed alone); #1 stayed pending and closes together with #2.
  • R16: the curl guard stays even though the runner already has curl — a harmless no-op line.
  • R14: the unpushed pair committing #2's deliverable inside a Task 1 fix round, then reverting it, was dropped from history before pushing.

Deferred

  • Parked review findings (token visible in set -x checkout trace but masked in runner logs; unverified go.dev tarball checksum; single-replica-runner assumptions) — accepted as-is per progress.md, not re-opened.

Implemented and reviewed by Claude (subagent-driven), landed on main after review and green CI.

**Done** - [d4e5c72](http://192.168.10.245/Cordy/cairn-desktop/commit/d4e5c7212937af9c6679f2aa7bbfa763b8d085f9) chore: scaffold module, GPLv3 licence, CI - [aae1ec2](http://192.168.10.245/Cordy/cairn-desktop/commit/aae1ec262def0b931fbcbd0e75890809dee5b014) ci: install curl on the Alpine runner when missing **What was built** - `go.mod` (`module cairn.ch/desktop`, `go 1.25`, no `toolchain` line) - Full GPLv3 `LICENSE` fetched from gnu.org, no App Store exception - `.forgejo/workflows/ci.yml`, verbatim from the issue: job `test` (checkout, install Go, vet and test) - A `command -v curl || apk add curl` guard added to the install-Go step — turned out to be a no-op, the runner image already has curl (ruling R16) **Tests** - Run 2858 (run #1, commit aae1ec2) went red at `go vet ./...`: "no packages to vet" — Go 1.25.5 exits 1 on a zero-package module, so acceptance criterion 1 as literally worded cannot pass alone. - Run 2864 (run #2, commit 6257370, **arm64/linux**, Go 1.25.5): `go vet ./...` and `go test -count=1 ./...` both green, job `test` succeeded. This is the first green run that also contains #2's arch guard package, so #1 closes on it (ledger ruling F1). - One fix round briefly committed #2's deliverable inside a #1 fix round and then reverted it; both commits were never pushed and were dropped from history (R14) — main's history carries neither. **Acceptance criteria** - "`go vet ./...` and `go test ./...` both succeed with no packages to test" — not achievable as literally worded on Go 1.25.5, which errors on zero packages; read as "the scaffold's CI is green," met on run 2864. - "The commit carries a `Signed-off-by:` trailer" — met on both commits. **Rulings** - R1: go.mod stays exactly `go 1.25`, no toolchain line. - R6: #1 leaves README.md unchanged; #15 owns it. - R11: an issue closes only after its commits are on main and that push's CI run is green. - R12: commit subjects verbatim, `git commit -s`, plus Co-Authored-By trailer. - F1: Go 1.25.5 fails vet/test on zero packages; #1 closes on the first green run that also contains #2's package, not the red aae1ec2 run alone. - R15: run 2858's red was a controller sequencing defect (Task 1 pushed alone); #1 stayed pending and closes together with #2. - R16: the curl guard stays even though the runner already has curl — a harmless no-op line. - R14: the unpushed pair committing #2's deliverable inside a Task 1 fix round, then reverting it, was dropped from history before pushing. **Deferred** - Parked review findings (token visible in `set -x` checkout trace but masked in runner logs; unverified go.dev tarball checksum; single-replica-runner assumptions) — accepted as-is per progress.md, not re-opened. _Implemented and reviewed by Claude (subagent-driven), landed on main after review and green CI._
Cordy closed this issue 2026-09-10 20:01:44 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/cairn-desktop#1
No description provided.