Files
website/.gitea/workflows/ci.yml
T
Christian ManivongandClaude Opus 5 c40fa97cd1
CI / TypeScript — type-check (pull_request) Successful in 10s
CI / Publish — build & push image (pull_request) Skipped
CI / TypeScript — type-check (push) Successful in 9m48s
CI / Publish — build & push image (push) Skipped
feat(ci): publish to Gitea's registry, and stop deploying to a random host
The image moves off registry.netork.io. That registry is plain registry:2 with
htpasswd auth, which knows nothing about repositories: every account that can log
in reads and writes everything on it, including the accounts issued to customer
instances. Verified -- a customer server's credentials list the whole catalogue.
It keeps the images those instances are meant to pull; the marketing site is not
one of them. Gitea scopes packages to their owning account, and no customer has
one. netOrk #172.

Login uses a REGISTRY_TOKEN secret (a Gitea token with write:package). The token
Actions injects per run does not work here -- the package registry rejects it
with a bare "unauthorized", which is a confusing way to spend an afternoon.

The deploy job is removed rather than migrated, because it had quietly stopped
being correct. It ran `docker run` against whatever runner picked the job up,
which worked while exactly one runner existed. There are now several --
netork-runner-12 on .12, netork-runner-13 on .13, plus the original
netork-runner -- and none of them is on 10.7.224.11, where this site runs and
where the proxy-net it attaches to lives. The next push would have started a
second website container on the wrong host and reported success while netork.io
went on serving the old one. Nothing had failed yet; the last deploy was
2026-07-17, back when the pool was one runner.

scripts/deploy.sh replaces it: it names the target, pulls before it removes
anything, compares the running container's image id against what was pulled, and
finishes by checking that netork.io actually answers 200.

Push-to-deploy can come back by registering a runner on .11 with a label of its
own and pinning `runs-on:` to it, or by giving CI an ssh key. Both decide where a
credential lives, so neither was decided here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 23:41:10 +02:00

92 lines
3.3 KiB
YAML

name: CI
on:
push:
branches: ['**']
tags: ['v*']
pull_request:
branches: ['**']
jobs:
typecheck:
name: TypeScript — type-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install
run: npm ci
- name: Type-check (tsc)
run: npx tsc --noEmit
publish:
name: Publish — build & push image
runs-on: ubuntu-latest
needs: [typecheck]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
# Gitea's registry, not registry.netork.io.
#
# registry.netork.io is plain registry:2 with htpasswd auth, which knows
# nothing about repositories: every account that can log in reads and
# writes everything on it, including the accounts issued to customer
# instances. It keeps the images those instances are meant to pull
# (netork/engine, netork/ui, netork/satellite); the marketing site is not
# one of them. Gitea scopes packages to their owning account, and no
# customer has one. netOrk issue #172.
#
# REGISTRY_TOKEN is a Gitea access token with write:package — the token
# Actions injects per run is scoped to the repository API and the package
# registry rejects it outright.
- name: Login to registry
run: |
set -euo pipefail
if [ -z "${{ secrets.REGISTRY_TOKEN }}" ]; then
echo "::error::REGISTRY_TOKEN is not set (Gitea token with write:package)."
exit 1
fi
LOGIN_USER="${{ secrets.REGISTRY_USER }}"
[ -n "$LOGIN_USER" ] || LOGIN_USER="${{ github.actor }}"
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.netork.io -u "$LOGIN_USER" --password-stdin
- name: Build & push
run: |
set -euo pipefail
SHA=$(git rev-parse --short HEAD)
docker build \
-t git.netork.io/netork/website:latest \
-t git.netork.io/netork/website:main-${SHA} \
.
docker push git.netork.io/netork/website:latest
docker push git.netork.io/netork/website:main-${SHA}
- name: Logout
if: always()
run: docker logout git.netork.io
# The deploy job that used to live here has been removed, deliberately.
#
# It ran `docker run` against whatever runner picked the job up, which worked
# while exactly one runner existed. There are now several (netork-runner-12 on
# .12, netork-runner-13 on .13, and the original netork-runner) and none of them
# is on 10.7.224.11, where this site actually runs and where the proxy-net it
# attaches to lives. The job would therefore have started a second website
# container on the wrong host and reported success, while netork.io went on
# serving the old one.
#
# Deployment is now an explicit step: scripts/deploy.sh, run from a workstation,
# which targets .11 by name and verifies afterwards that the container really is
# on the image that was pulled.
#
# To get push-to-deploy back, either register a runner on .11 with a label of its
# own and pin `runs-on:` to it, or give CI an ssh key for .11. Both are choices
# about where a credential lives, so neither was made here.