fix: add git-daemon so git-http-backend exists, plus a publish script #1

Merged
markus merged 2 commits from claude/fix/git-http-backend into master 2026-08-20 12:25:30 +00:00
Member

Two commits: the one-line fix that unbreaks zegit's Gitea CI, and a script so publishing this image stops being a four-obstacle exercise.

git-daemon

Alpine splits git-http-backend out of the git package — git alone ships git-remote-http/https but not the CGI backend. So the runner had git 2.52.0 and no backend, and zegit's internal/forgeprobe smart-HTTP tests died with fork/exec git-http-backend: no such file or directory, reporting three FAILURES for a missing tool.

That turned Gitea CI red on every zegit master commit while GitHub stayed green, for hours, unnoticed — GitHub is the release oracle, which is exactly why a red mirror is invisible.

Verified on the real base image, not alpine:3: on code.forgejo.org/forgejo/runner:12.11.1 (Alpine 3.23), apk add git git-daemon puts the backend at /usr/libexec/git-core/git-http-backend, and git --exec-path resolves there — the exact lookup the test harness performs. So the tests run rather than skip, coverage returns over the 85% floor, and cover-check stops failing without widening any gate.

push-image.sh

Publishing by hand hit 413 (Cloudflare body cap), a Docker Hub auth refusal (a bare MagicDNS name is parsed as a Docker Hub namespace, since a registry host needs a dot or colon), insufficient_scope (needs write:package), and multi-arch.

The image reference must keep the hostname gitea.langenoja.se because that is what the cluster pulls — so the script keeps the NAME and changes only the ROUTE, pinning it to the Istio gateway on the LAN. That gateway serves a *.langenoja.se wildcard cert, so TLS validates normally.

Assumptions & Decisions

  • Gateway IP 10.40.0.10 is a default, overridable via GATEWAY_IP. Verified: GET /v2/ → 401 with ssl_verify_result=0.
  • The pin carries a marker comment so a leftover (run died before its trap) is distinguishable from a deliberate one. Without it, a leftover survived every later run and had to be reverted by hand — which happened. --unpin clears one; an unmarked pin is never touched.
  • Rejected: the Tailscale route. gitea-tailscale-http exposes port 3000 plain HTTP, nothing on 443, so it cannot serve a correctly-named registry push.
  • Rejected: insecure-registries. Unnecessary once the gateway's real cert is used, and it would weaken every pull from that host.
  • Multi-arch is not optional — forgejo-runner is on arm64, zegit-runner on amd64, neither sets a nodeSelector.
  • Not done here: in-cluster CI for this build. It needs buildah (the runners are host-mode, no docker daemon) and arch-labelled runners that do not exist yet.

After merge: ./push-image.sh 12.11.1-ci4, then bump -ci3 → -ci4 in flux-config's deployment-zegit-runner.yaml and deployment-forgejo-runner.yaml.

Two commits: the one-line fix that unbreaks zegit's Gitea CI, and a script so publishing this image stops being a four-obstacle exercise. ## `git-daemon` Alpine splits `git-http-backend` **out of** the `git` package — `git` alone ships `git-remote-http/https` but not the CGI backend. So the runner had git 2.52.0 and no backend, and zegit's `internal/forgeprobe` smart-HTTP tests died with `fork/exec git-http-backend: no such file or directory`, reporting three FAILURES for a missing tool. That turned **Gitea CI red on every zegit master commit while GitHub stayed green**, for hours, unnoticed — GitHub is the release oracle, which is exactly why a red mirror is invisible. Verified on the real base image, not `alpine:3`: on `code.forgejo.org/forgejo/runner:12.11.1` (Alpine 3.23), `apk add git git-daemon` puts the backend at `/usr/libexec/git-core/git-http-backend`, and `git --exec-path` resolves there — the exact lookup the test harness performs. So the tests run rather than skip, coverage returns over the 85% floor, and `cover-check` stops failing **without widening any gate**. ## `push-image.sh` Publishing by hand hit 413 (Cloudflare body cap), a Docker Hub auth refusal (a bare MagicDNS name is parsed as a Docker Hub *namespace*, since a registry host needs a dot or colon), `insufficient_scope` (needs `write:package`), and multi-arch. The image reference must keep the hostname `gitea.langenoja.se` because that is what the cluster pulls — so the script keeps the NAME and changes only the ROUTE, pinning it to the Istio gateway on the LAN. That gateway serves a `*.langenoja.se` wildcard cert, so TLS validates normally. ## Assumptions & Decisions - Gateway IP `10.40.0.10` is a default, overridable via `GATEWAY_IP`. Verified: `GET /v2/` → 401 with `ssl_verify_result=0`. - The pin carries a marker comment so a leftover (run died before its trap) is distinguishable from a deliberate one. Without it, a leftover survived every later run and had to be reverted by hand — which happened. `--unpin` clears one; an unmarked pin is never touched. - Rejected: the Tailscale route. `gitea-tailscale-http` exposes port 3000 **plain HTTP**, nothing on 443, so it cannot serve a correctly-named registry push. - Rejected: `insecure-registries`. Unnecessary once the gateway's real cert is used, and it would weaken every pull from that host. - Multi-arch is not optional — `forgejo-runner` is on arm64, `zegit-runner` on amd64, neither sets a `nodeSelector`. - Not done here: in-cluster CI for this build. It needs buildah (the runners are host-mode, no docker daemon) and arch-labelled runners that do not exist yet. After merge: `./push-image.sh 12.11.1-ci4`, then bump `-ci3` → `-ci4` in flux-config's `deployment-zegit-runner.yaml` and `deployment-forgejo-runner.yaml`.
agent added 2 commits 2026-08-20 12:23:20 +00:00
Alpine splits git-http-backend OUT of the `git` package: git alone ships
git-remote-http/https but not the CGI backend. The runner therefore had git
2.52.0 and no git-http-backend, so zegit's internal/forgeprobe smart-HTTP tests
failed at request time with "fork/exec git-http-backend: no such file or
directory" and reported three FAILURES for a missing tool.

That turned Gitea CI red on every zegit master commit while GitHub stayed
green, for hours, with nobody looking — GitHub is the release oracle, which is
exactly why a red mirror is invisible.

Verified against the real base image, not just alpine:3 — on
code.forgejo.org/forgejo/runner:12.11.1 (Alpine 3.23), `apk add git git-daemon`
puts git-http-backend at /usr/libexec/git-core/git-http-backend, and
`git --exec-path` resolves to that directory, which is the lookup the test
harness performs.
Publishing this image by hand hit four obstacles in a row, each of which
recurs on every rebuild:

  413 Payload Too Large      gitea.langenoja.se is behind Cloudflare, which
                             caps request bodies below a registry layer
  Docker Hub auth refusal    the bare MagicDNS name was parsed as a Docker Hub
                             NAMESPACE — a registry host is only recognised
                             when it contains a dot or a colon
  insufficient_scope         the PAT needs write:package, not read:package
  wrong-arch pulls           forgejo-runner runs on arm64 and zegit-runner on
                             amd64, neither pins a nodeSelector, and both use
                             this one tag

The image reference must keep the hostname gitea.langenoja.se, because that is
what the cluster pulls. So the script keeps the NAME and changes only the
ROUTE: it pins that hostname to the Istio gateway on the LAN for the duration
of the push. The gateway serves a *.langenoja.se wildcard cert, so TLS
validates normally — no insecure-registries needed.

The pin carries a marker comment, which makes three cases distinguishable: a
leftover from a run that died before its trap fired (reuse, then remove), a
pin the operator added deliberately (never touch), and one pointing somewhere
other than the gateway (refuse to run). Without the marker a leftover pin was
indistinguishable from a deliberate one, so it survived every later run and
had to be reverted by hand. `--unpin` clears a leftover without building, and
the trap covers INT and TERM as well as EXIT.

It also verifies the published manifest really lists two architectures rather
than trusting the push's exit code.
markus merged commit 8c356b7e95 into master 2026-08-20 12:25:30 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: zegit-zoo/zegit-forgejo-runner#1