End-of-session snapshot for /clear. In-flight compressed (four majors landed: zonos-gateway 0.2.1 emotion presets, soong-lab containerized cutover, Wyrd + wtsdk credential provisions). New Recent-decisions + Tried entries and three detail files capture the durable lessons (fleet Gitea build recipe, the vh-is-a-user package-write constraint, soong-lab deploy layout).
3.4 KiB
[2026-07-18]Fleet Gitea-Actions build recipe + thevh-is-a-user package-write constraint (learned the hard way across 3 failed soong-lab validation builds; reusable for ANY fleet CI image build or package publish).
The runner. One act_runner (gitea/act_runner) on ana-docker, labels
pfi-fleet / ana-docker → both map to job image node:20-bookworm-slim,
which has NO docker and NO git. Config /opt/docker/conf/gitea-runner/data/config.yaml:
valid_volumes: [] (no socket propagated to job containers). So:
actions/checkout@v4fails (needs git);docker/*marketplace actions fail (need docker) — a workflow built on those dies at the first step (~15s).
The working recipe (mirror Worldtree deploy.yml). Run the job in a
docker-capable image + drive docker with RAW commands, not the JS actions:
runs-on: pfi-fleet
container:
image: docker:24.0.7-cli # has docker+buildx; add git+node
steps:
- run: apk add --no-cache git nodejs # so actions/checkout@v4 works
- uses: actions/checkout@v4
- name: login # RAW, not docker/login-action
run: echo "$REGISTRY_TOKEN" | docker login gitea.phasefinal.com -u "$REGISTRY_USER" --password-stdin
- name: buildx builder
run: docker buildx create --name X --driver docker-container --use; docker buildx inspect --bootstrap
- name: build+push # RAW, not docker/build-push-action
run: docker buildx build --secret id=<name>,env=<TOKEN> -t <img>:latest --push .
The runner mounts the host docker socket into ITSELF; the docker:cli job reaches
the daemon through that. The docker/* JS actions are unreliable on act_runner —
raw commands are the fleet convention.
vh is a USER account, not an org. Consequences that bit repeatedly:
GET /api/v1/orgs/vh→ 404 "user redirect"; there are no org teams to add a service account to.- User-owned packages are OWNER-WRITE-ONLY. claude-bot (even repo
admin-collaborator on
vh/soong-lab, even withwrite:packagescope + full basic-auth) gets401 unauthorizedondocker pushtovh/soong-lab, andnpm publishtovh/npm/would 401 too. Onlyvhitself can write vh packages. → CI must authenticate ASvhfor the push (a vh-ownedwrite:packagePAT asREGISTRY_TOKEN+REGISTRY_USER=vh), exactly how WT pushesvh/worldtree. claude-bot CAN still: clone/read repos, READ packages (pulled the image fine), dispatch workflows, mint demo Worldtree keys. - Repo Actions secrets are OWNER-ONLY too —
PUT .../actions/secrets/Xas claude-bot (repo admin-collab) → 403 "user should be the owner of the repo". Onlyvhcan set a repo's secrets.
Other gotchas:
- Gitea reserves the
GITEA_secret-name prefix — a secret namedGITEA_PYPI_TOKENis illegal; use e.g.PYPI_TOKEN. - Gitea package auth is token-based / username-lenient —
docker login/ PyPI basic-auth authenticate via the token; the username is nominal (tested-u giteaand-u claude-botboth 200 against the vh PyPI). So a Dockerfile hardcodingUV_INDEX_GITEA_USERNAME=giteais fine with any valid token. - Homepage (esh-docker-vm) docker-label auto-discovery only covers the 5 endpoints
in its
docker.yaml(esh-vm-docker, ana-docker, ana-ml2, nh3-docker, irv-ml1); corviduo-dev is NOT watched → services there need a manualservices.yamlentry, not labels.
Applied in the soong-lab CI: 2026-07-18-soong-lab-containerize-cutover.