ci/forgejo-actions #2

Merged
picklemustard merged 3 commits from ci/forgejo-actions into main 2026-08-22 14:45:48 +00:00
No description provided.
feat(deploy): Publish images from CI, pull from registry
Some checks failed
CI / test (pull_request) Failing after 1m19s
CI / publish (pull_request) Has been skipped
84f671477c
Replaces `docker save | k3s ctr images import` with a Forgejo
container registry round trip, and builds the image in Forgejo
Actions instead of by hand.

- Workflows ported from Homelab/lab-endpoint-automation, which
  already solved this against the same runner and registry:
  ci.yml gates main and PRs, release.yml handles v* tags, and
  both call the reusable image.yml through a `needs:` edge --
  Forgejo Actions has no workflow_run event.
- image.yml uses podman, not docker. The runner's config sets
  container.docker_host to '-', so no daemon socket reaches a
  job container and `docker build` has nothing to talk to.
- Dockerfile base images gain their docker.io/library prefix
  for the same reason: podman resolves a short name against the
  host's unqualified-search-registries, and Debian's package
  defines none.
- Cluster overlay drops the bundled Postgres for the shared
  instance, adds the forgejo-registry pull secret to both
  workloads, and pins ingressClassName.
- CI publishes but never deploys: the overlay's `newTag` is
  what the cluster runs, and bumping it is the deploy.

Requires REGISTRY_USER and REGISTRY_TOKEN under repo Settings,
Actions, Secrets; both callers pass `secrets: inherit`.
fix(ci): run tests as an unprivileged user, trigger on all branches
Some checks failed
CI / test (push) Failing after 1m38s
CI / publish (push) Has been skipped
38098e9ffa
The runner executes steps as uid 0 -- the same fact image.yml relies on
for a rootful podman build. PostgreSQL's initdb refuses to run as root,
and every DB-backed test package starts embedded-postgres, so cmd/server,
internal/api, internal/collect and internal/store all failed at Start()
with "initdb: error: cannot be run as root". Nothing was wrong with the
tests; the uid was.

So the test step now drops to an unprivileged `ci` user for the test run
only -- gofmt, vet and build are unaffected by the uid and stay as root.
runuser -u keeps the caller's environment, so HOME/GOPATH/GOCACHE are
passed explicitly: the Go caches under root's HOME are not writable by
ci, and embedded-postgres caches its downloaded binaries under
$HOME/.embedded-postgres-go. The setup-go toolchain and the checked-out
workspace are root-owned, hence the chmod and chown.

The runtime dirs are also cleared first. The tests pin RuntimePath to
fixed /tmp/lab-skimmer-epg-* paths and embedded-postgres skips initdb
when the data dir already exists, so a half-initialised dir left by an
earlier failed run on a reused runner would poison the next one.

release.yml runs the same `make cover-ci` as root and would have failed
identically on the next v* tag, so it gets the same treatment.

Separately, CI now runs on a push to any branch rather than only main: a
feature branch with no PR open got no run at all, so a change to CI could
only be exercised by opening one. Publishing stays main-only -- the
publish job's `if:` already required a push to refs/heads/main, and that
guard is now the only thing keeping it there rather than the trigger.
Branches are matched as '**' rather than a bare `push:` so that v* tags
stay release.yml's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fix(ci): keep git usable as root after the test step chowns the workspace
All checks were successful
CI / test (push) Successful in 1m44s
CI / publish (push) Has been skipped
CI / test (pull_request) Successful in 1m35s
CI / publish (pull_request) Has been skipped
e978d2828f
Run 30 reported every step green -- checkout, setup-go, gofmt, vet, build,
test at 78.3% coverage, coverage -- and then failed with a bare
`exitcode '128'`, attributed to nothing.

That was the `job end` step, not the post-job phase it announces. Its
third echo never printed, so it died on the line between: the
`remote=$(git ls-remote origin ...)` branch comparison. Two facts
combine. Forgejo runs steps as `bash --noprofile --norc -e -o pipefail`,
where a failing command substitution in a bare assignment aborts the step
with the command's status. And git exits 128 there because the previous
commit added `chown -R ci:ci "$GITHUB_WORKSPACE"` so initdb could run as
an unprivileged user: afterwards .git is owned by uid 1001 while every
later step is still uid 0, and git's ownership check applies to root too.
`2>/dev/null` discarded "detected dubious ownership", which is why the
log carried no reason. The Post actions/checkout hook ran git against the
same tree seconds later and succeeded -- because it sets safe.directory
under a temporary HOME first, which is exactly what this workflow was
missing.

So the workspace is declared safe for root's git once, right after the
checkout, where root's HOME persists for the rest of the job. The test
step also chowns the tree back to root when it is done, on failure as
well as success, so the "everything outside the test run is uid 0"
invariant holds instead of being repaired step by step. $CI_HOME stays
ci-owned; that is the Go and embedded-postgres cache for a reused runner.
release.yml has the same chown and gets the same restore.

`job end` no longer assigns from a bare command substitution, and keeps
git's stderr rather than discarding it. It is a diagnostic step; it must
never be the reason a job fails, and when its own git call fails the
message needs to reach the log.

Finally, post-mortem moves below `job end`. It runs `if: failure()` and
was the step above, so it structurally could not report a `job end`
failure -- the one failure that step is capable of producing, and the one
that just happened.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
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
Homelab/lab-skimmer!2
No description provided.