Files
the-custodian/docs/forgejo-repo-migration-pilot-glas-harness.md
codex 5d3270e564 Document tier-2 key-cape Forgejo image pilot (T10 complete)
Adds archive-checkout image workflow evidence and k3s pull verification;
tiers 0-2 satisfied before state-hub cutover.
2026-07-04 10:26:28 +02:00

6.0 KiB
Raw Blame History

Forgejo Repo Migration Pilots (tier 12)

Date: 2026-07-03 (tier 1), 2026-07-04 (tier 2)
Workplan: CUST-WP-0054-T04, RAIL-HO-WP-0005-T10
Pilots: glas-harness (tier 1), key-cape (tier 2)


Tier 1 — glas-harness

Pilot repo: coulomb/glas-harness (non-production tooling; safe routing drill)

Why this repo

Criterion glas-harness
Production dependency None — harness meta-framework, not deployed
Size / complexity 3 commits, no container image, no submodules
Blast radius Low — wrong remote or CI failure does not break triage, State Hub, or emission
State Hub registration Not in active production sweep set

Use lessons here before migrating state-hub (high value, high risk).

Pilot outcome (2026-07-03)

Step Result Notes
Create repo on Forgejo pass POST /api/v1/orgs/coulomb/repos
Mirror git history (HTTPS) pass main @ e35e287 pushed with admin token
SSH forgejo-remote push pass After adding id_gitea.pub to forgejo_admin; NodePort 92.205.62.239:30022
origin → Forgejo, gitea legacy remote pass origin=forgejo-remote:…, gitea=gitea-remote:…
Actions ci-smoke (host + container) pass host-smoke (self-hosted) + container-smoke (ubuntu-latest) both success
Gitea left intact pass No delete; Gitea still at e35e287 until mirror sync policy defined

Routing that works

Git remotes (workstation)

Add to ~/.ssh/config (see FORGEJO-REMOTE block):

Host forgejo-remote
    HostName 92.205.62.239
    Port 30022
    User git
    IdentityFile ~/.ssh/id_gitea
    StrictHostKeyChecking accept-new

Per-repo layout after cutover:

git remote rename origin gitea          # if still on Gitea
git remote add origin forgejo-remote:coulomb/<repo>.git
git push -u origin main

Canonical URL: https://forgejo.coulomb.social/coulomb/<repo>.git

HTTPS fallback (automation / first push)

Admin or user token with write:repository:

git push "https://<user>:<token>@forgejo.coulomb.social/coulomb/<repo>.git" main

CI runner labels (railiance01-build-01)

Label Works for Evidence
self-hosted Host runner smoke glas-harness host-smoke
ubuntu-latest Container step jobs glas-harness container-smoke
container-build Docker build/push jobs forgejo-actions-probe image-build

Registry / image CI (from prior probe)

  • Org secrets REGISTRY_USER / REGISTRY_TOKEN via PUT /api/v1/orgs/coulomb/actions/secrets/{name} with plaintext data (HTTPS API).
  • Host runner has no docker CLI and cannot apk add (non-root). Use static docker binary in the job step.
  • actions/checkout@v4 fails on host runner — use git clone in the job until resolved.

Routing that does not work yet

Gap Impact Mitigation for next repos
tegwick Gitea user not on Forgejo SSH as git@92.205.130.254 (Gitea) ≠ git@92.205.62.239 (Forgejo); keys are per-forge Register operator keys on Forgejo users before cutover; or use forgejo_admin interim
No automated Gitea→Forgejo mirror Gitea copy drifts after Forgejo becomes canonical Staged cutover: freeze Gitea pushes, one-way mirror, or retire Gitea remote after verification
actions/checkout@v4 on host runner Breaks multi-step workflows that depend on checkout git clone in run: step (see image-build probe)
Issues/wiki/releases/LFS Not exercised in pilot Classify per repo in migration inventory before production repos
State Hub remote_url field Still points at gitea-remote:… for most repos Update registration when repo is promoted (separate step; not done for glas-harness)

Repeatable procedure (non-production repo)

  1. Confirm repo is not in a production drain wave or has explicit operator approval.
  2. Create empty repo on Forgejo (auto_init: false if mirroring existing history).
  3. Push all branches/tags from workstation clone (HTTPS or SSH).
  4. Add forgejo-remote remote; rename Gitea remote to gitea; set origin to Forgejo.
  5. Add .forgejo/workflows/ smoke (and image workflow if applicable).
  6. Verify Actions green on Forgejo runner.
  7. Leave Gitea repo read-only; do not delete (safety contract).
  8. Record results in this doc or a per-repo row in the migration inventory.

Tier 2 — key-cape (2026-07-04)

Pilot repo: coulomb/key-cape — non-production identity tooling with a real multi-stage Dockerfile (Go build + distroless).

Step Result Notes
Mirror git to Forgejo pass main mirrored; origin=forgejo-remote
Port .gitea/workflows/image.yaml.forgejo/workflows/image.yaml pass Archive checkout + static docker-cli; no actions/checkout
Build and push on container-build pass build-and-push workflow success @ ec706da
k3s pull on railiance01 pass sudo crictl pull forgejo.coulomb.social/coulomb/key-cape:latest

Workflow pattern (tier 2+):

# Checkout: repo archive (no git binary required on non-root runner)
wget -qO /tmp/repo.tar.gz "https://forgejo.coulomb.social/${GITHUB_REPOSITORY}/archive/${GITHUB_SHA}.tar.gz"
tar xzf /tmp/repo.tar.gz -C buildctx --strip-components=1
# Build: static docker-cli + DOCKER_HOST=tcp://127.0.0.1:2375

Image: forgejo.coulomb.social/coulomb/key-cape:latest

Not ready for state-hub yet

Before state-hub, the ladder still needs:

  • Operator/user SSH identity on Forgejo (not only forgejo_admin)
  • Reusable workflow template with hub-core build context (multi-repo checkout)
  • State Hub remote_url + sweep checkout path update playbook
  • Gitea read-only mirror or push-disable policy for repos after cutover

References