~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

The runner host deploys with main

Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:deploy/runner-host-with-main
.knotless/workflows/deploy.yml+26−1
@@ -26,12 +26,19 @@
# an app password of theirs granted to pushes to main as release.yml's is.
# It is then `docker pull knotless.dev/chadtmiller.com/knotless/knotless-server`:
# one image for serve, the pages, the runner and the triager, as here.
#
# Last, the runner host (deploy/runner-host) takes the same image, copied
# from this host only when its runner's build differs, and is restarted
# with the settings below, so the runner that lands other repositories'
# merge queues reads their rules as main does. It is reached with
# RUNNER_HOST_SSH_KEY, granted to pushes to main alone, which its root
# takes only from this host's addresses.
on:
push:
refs: [refs/heads/main]
superseded: finish
image: docker:28-cli
secrets: [DEPLOY_SSH_KEY, RELEASE_PASSWORD]
secrets: [DEPLOY_SSH_KEY, RELEASE_PASSWORD, RUNNER_HOST_SSH_KEY]
env:
KNOTLESS_HOST: root@knotless.dev
KNOTLESS_DOMAIN: knotless.dev
@@ -58,6 +65,17 @@ env:
# The runner host's account (deploy/runner-host), which a new public
# repository names unless its owner names others: it runs anyone's.
KNOTLESS_DEFAULT_RUNNER_DID: did:plc:4bocpkn5zkwe4wuu4plrj5kt
# That host, deployed after this one (deploy/runner-host/deploy.sh), as
# runner.knotless.dev. It lands the merge queues of the repositories
# that name it, and runs knotless's pulls alone, under runc for the
# owner and their organization (README.md there).
KNOTLESS_RUNNER_HOST: root@runner.knotless.dev
KNOTLESS_RUNNER_DOMAIN: runner.knotless.dev
KNOTLESS_RUNNER_DID: did:plc:4bocpkn5zkwe4wuu4plrj5kt
KNOTLESS_RUNNER_ARGS: --queue --pulls-only chadtmiller.com/knotless --unmetered did:plc:bcgltzqazw5tb6k2g3ttenbj --unmetered did:plc:e7rftrdyz5e2rw4y6ocszew2 --trust did:plc:bcgltzqazw5tb6k2g3ttenbj --trust did:plc:e7rftrdyz5e2rw4y6ocszew2 --pull-jobs 2
KNOTLESS_RUNNER_CPUS: "4"
KNOTLESS_RUNNER_JOBS: "2"
KNOTLESS_RUNNER_MEMORY: "7"
# The oldest client this asks for: 0.6.0 deletes a deleted ref's record
# and starts a new ref at the time, and an older client making a branch
# again under a name deleted within the day can have its pushes refused.
@@ -194,3 +212,10 @@ steps:
tar -x -C "$dir"
knotless publish "$REPO" knotless-server "$VERSION" --oci "$dir" --commit "$SHA"
'
- name: runner host
run: |
[ ! -e ~/.moved ] && [ -e ~/.up ] || exit 0
[ -n "$RUNNER_HOST_SSH_KEY" ] || { echo "no RUNNER_HOST_SSH_KEY: not deploying the runner host"; exit 0; }
printf '%s\n' "$RUNNER_HOST_SSH_KEY" > ~/.ssh/runner_host && chmod 600 ~/.ssh/runner_host
printf 'Host %s\n IdentityFile ~/.ssh/runner_host\n' "${KNOTLESS_RUNNER_HOST#*@}" >> ~/.ssh/config
KNOTLESS_RUNNER_IMAGE_FROM="$KNOTLESS_HOST" deploy/runner-host/deploy.sh
deploy/runner-host/deploy.sh+19−5
@@ -23,7 +23,11 @@
# - optional: KNOTLESS_RUNNER_ARGS, more of its command line (`--queue`);
# KNOTLESS_RUNNER_JOBS (4), _CPUS (2), _MEMORY (3, GiB), _TIMEOUT
# (3600 s), _ALLOWANCE (2000) and _PRIVATE_ALLOWANCE (500), as
# docker-compose.yml passes them; KNOTLESS_LOG (info).
# docker-compose.yml passes them; KNOTLESS_LOG (info);
# - optional: KNOTLESS_RUNNER_IMAGE_FROM, an SSH destination whose
# knotless:current to run rather than building here, copied only when
# its runner's build differs: main's deploy sets it to the main host,
# so both run the same knotless (.knotless/workflows/deploy.yml).
#
# The image is built on the host, from this checkout's HEAD as `git
# archive` gives it (so commit first): a build driven over SSH by a local
@@ -40,10 +44,20 @@ SSH="ssh -o StrictHostKeyChecking=accept-new $DEST"
COMMIT="$(git rev-parse HEAD 2>/dev/null || echo local)"
if [ -n "${KNOTLESS_RUNNER_IMAGE_FROM:-}" ]; then
# A box too small to build knotless takes the image another host built.
echo "==> copying knotless:current from $KNOTLESS_RUNNER_IMAGE_FROM to $DEST"
ssh -o StrictHostKeyChecking=accept-new "$KNOTLESS_RUNNER_IMAGE_FROM" 'docker save knotless:current | gzip -1' |
$SSH 'gunzip | docker load -q'
# A box too small to build knotless, or a deploy of main, takes the image
# another host built, unless the runner here is that build already: as
# the main host's deploy does (deploy/deploy.sh), a runner whose build
# is the same is left running, since a restart cancels its runs.
FROM="ssh -o StrictHostKeyChecking=accept-new $KNOTLESS_RUNNER_IMAGE_FROM"
PRINT='docker run --rm --entrypoint cat knotless:current /etc/knotless-run.fingerprint'
NEW=$($FROM "$PRINT" 2>/dev/null || true)
OLD=$($SSH "$PRINT" 2>/dev/null || true)
if [[ $NEW =~ ^[0-9a-f]{64}$ ]] && [ "$NEW" = "$OLD" ]; then
echo "==> its runner is ${NEW:0:12} on $KNOTLESS_RUNNER_IMAGE_FROM too: keeping its image"
else
echo "==> copying knotless:current (${NEW:0:12}, here ${OLD:0:12}) from $KNOTLESS_RUNNER_IMAGE_FROM to $DEST"
$FROM 'docker save knotless:current | gzip -1' | $SSH 'gunzip | docker load -q'
fi
else
echo "==> building knotless at ${COMMIT:0:12} on $DEST"
git archive --format=tar HEAD |
deploy/runner-host/README.md+25−0
@@ -204,6 +204,31 @@ elsewhere](../../docs/design/runner.md#where-pushes-run-elsewhere)). The
first pull over an empty cache builds in full; the ones after start from
what it left, the `test` workflow's stored coverage runs among it.
## Deployed with main
Each deploy of main deploys this host too, last
(`.knotless/workflows/deploy.yml`, its `runner host` step), so the
runner that lands other repositories' merge queues reads their records
as main does: an older one ejects a pull whose rule holds what it does
not know (`what this version does not know: gates; update knotless`).
It runs `deploy.sh` with `KNOTLESS_RUNNER_IMAGE_FROM` the main host,
whose image it copies only when its runner's build (the fingerprint
the main host's deploy compares) differs from this host's: a deploy
that leaves the runner as it was restarts nothing here, as on the main
host. Its settings are the `KNOTLESS_RUNNER_*` in that workflow, which
`deploy/local.env` repeats for a deploy by hand.
It reaches the host with `RUNNER_HOST_SSH_KEY`, a key of its own,
granted to pushes to main alone (`knotless secret … set
RUNNER_HOST_SSH_KEY --ref refs/heads/main`). Root takes it only from the
main host's addresses, as `setup.sh` installs its public half:
```sh
KNOTLESS_RUNNER_DEPLOY_KEY="ssh-ed25519 AAAA… knotless deploy of main" \
KNOTLESS_RUNNER_DEPLOY_FROM="178.104.222.99,2a01:4f8:c015:4df4::/64" \
deploy/runner-host/setup.sh
```
## Running it
- **Pause someone:** edit `/etc/knotless/paused.json` on the host, as
deploy/runner-host/setup.sh+16−1
@@ -26,7 +26,8 @@
# through NAT rules gVisor does not apply, so runs name public ones.
#
# It ends by checking from inside a gVisor container on that network that
# the internet answers and the metadata service and private ranges do not.
# the internet answers and the metadata service and private ranges do not;
# then, given KNOTLESS_RUNNER_DEPLOY_KEY, lets main's deploy in with it.
set -euo pipefail
cd "$(dirname "$0")/../.."
@@ -180,3 +181,17 @@ docker run --rm --runtime runsc --network knotless-runs \
dmesg 2>/dev/null | head -1 | grep -q gVisor && echo "kernel: gVisor" || echo "kernel: NOT gVisor"
'
HOST
# The key main's deploy reaches this host with (.knotless/workflows/
# deploy.yml, RUNNER_HOST_SSH_KEY), its public half: root takes it only
# from the main host's addresses, KNOTLESS_RUNNER_DEPLOY_FROM, so the key
# alone reaches nothing from anywhere else.
if [ -n "${KNOTLESS_RUNNER_DEPLOY_KEY:-}" ]; then
from="${KNOTLESS_RUNNER_DEPLOY_FROM:?KNOTLESS_RUNNER_DEPLOY_KEY takes KNOTLESS_RUNNER_DEPLOY_FROM, the addresses of the main host}"
printf 'from="%s" %s\n' "$from" "$KNOTLESS_RUNNER_DEPLOY_KEY" |
ssh -o StrictHostKeyChecking=accept-new "$DEST" '
f=/root/.ssh/authorized_keys
read -r line
grep -qxF "$line" "$f" || printf "%s\n" "$line" >> "$f"
'
fi