From 74edd16ea474b4f412d69e2299c4943ade20af35 Mon Sep 17 00:00:00 2001 From: Cristiano Betta Date: Mon, 19 Oct 2026 14:29:49 +0100 Subject: [PATCH 1/3] Run the remaining hosted jobs on jiji GitHub-hosted jobs no longer start (Actions billing), so ci-complete and merge move to jiji-ci with the rest of CI. The publish workflow's pin job stays hosted: it holds jiji's deploy key, which shouldn't reach the ci user. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f5683c..c4d5ae2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: ci-complete: needs: [checks, smoke] - runs-on: ubuntu-latest + runs-on: [self-hosted, jiji-ci] steps: - run: echo "All checks passed." @@ -49,7 +49,7 @@ jobs: github.event_name == 'pull_request' && (startsWith(github.head_ref, 'deps-factory/') || github.event.pull_request.user.login == 'dependabot[bot]') - runs-on: ubuntu-latest + runs-on: [self-hosted, jiji-ci] permissions: contents: read pull-requests: read From 82ae04f3997fd4a4d73abf5993122294fc79b776 Mon Sep 17 00:00:00 2001 From: Cristiano Betta Date: Mon, 19 Oct 2026 14:48:32 +0100 Subject: [PATCH 2/3] Let jiji pin the image The pin job pushed to cbetta/jiji with a write deploy key, and hosted runners are out. jiji's own pin.yml now pins the image from ghcr (the moving tag and the io.betta.jiji.tag label added here), so nothing in this repo holds a key to jiji. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/publish.yml | 69 ++++++----------------------------- 1 file changed, 12 insertions(+), 57 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c68e795..c2b9171 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,15 +1,15 @@ name: Publish to jiji # Push to master -> CI (ci.yml) -> build the image and push it to -# ghcr.io/cbetta/hackcoc -> pin that image in cbetta/jiji's docker-compose.yml, -# which triggers jiji's own deploy. jiji holds no copy of the site, only which -# image it runs, so master here is always what hackcodeofconduct.org serves. +# ghcr.io/cbetta/hackcoc -> cbetta/jiji's pin.yml pins it by tag and digest +# within 10 minutes, which deploys it. jiji holds no copy of the site, only +# which image it runs, so master here is always what hackcodeofconduct.org +# serves. # -# Three jobs, so the jiji deploy key (a push to jiji deploys to the home -# server) never shares a machine with anything else: the build runs inside -# BuildKit with no secrets, and the pin job only checks out jiji and edits -# one line. jiji pins the image by digest as well as tag. Actions are pinned -# by commit (their version in the comment). +# Nothing here can write to cbetta/jiji: publish runs on jiji's walled-off CI +# runners, so the deploy key stays with jiji's own pin.yml, which finds the +# new image through the moving :master tag and the io.betta.jiji.tag label. +# Actions are pinned by commit (their version in the comment). on: push: @@ -25,7 +25,7 @@ on: - ".github/workflows/publish.yml" workflow_dispatch: -# Serialised: two pushes in quick succession must not race to pin jiji. +# Serialised: two pushes in quick succession must not race to move the tags. concurrency: group: publish cancel-in-progress: false @@ -49,8 +49,6 @@ jobs: permissions: contents: read packages: write - outputs: - ref: ${{ steps.ref.outputs.ref }} steps: # Its own Docker config: the jiji-ci runners share one HOME, so a shared # config.json would hand another repo's publish this job's GHCR login, @@ -98,49 +96,6 @@ jobs: tags: | ghcr.io/cbetta/hackcoc:${{ steps.meta.outputs.tag }} ghcr.io/cbetta/hackcoc:master - labels: org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} - - - name: Image reference - id: ref - env: - TAG: ${{ steps.meta.outputs.tag }} - DIGEST: ${{ steps.build.outputs.digest }} - run: | - [[ "$DIGEST" =~ ^sha256:[0-9a-f]{64}$ ]] || { echo "::error::no digest for the image"; exit 1; } - echo "ref=$TAG@$DIGEST" >> "$GITHUB_OUTPUT" - - pin: - needs: publish - runs-on: ubuntu-latest - # The jiji-deploy environment only runs for master, and holds the key: no - # other branch (or dispatch from one), and no pull request, can get it. - environment: jiji-deploy - steps: - # JIJI_DEPLOY_KEY: a deploy key on cbetta/jiji with write access, a - # secret of the jiji-deploy environment. - - name: Check out jiji - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - repository: cbetta/jiji - ssh-key: ${{ secrets.JIJI_DEPLOY_KEY }} - path: jiji - - - name: Pin the image in jiji - env: - REF: ${{ needs.publish.outputs.ref }} - SOURCE: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} - run: | - set -euo pipefail - [[ "$REF" =~ ^sha-[0-9a-f]{7}@sha256:[0-9a-f]{64}$ ]] || { echo "::error::unexpected image reference $REF"; exit 1; } - cd jiji - sed -i -E "s#^(\s+image: ghcr\.io/cbetta/hackcoc):.*#\1:${REF}#" docker-compose.yml - grep -qF "image: ghcr.io/cbetta/hackcoc:${REF}" docker-compose.yml \ - || { echo "::error::jiji's docker-compose.yml has no 'image: ghcr.io/cbetta/hackcoc:…' line to pin"; exit 1; } - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add docker-compose.yml - if git diff --cached --quiet; then echo "jiji already runs ${REF%@*}."; exit 0; fi - git commit -m "hackcoc: deploy ${REF%@*}" -m "Automated by cbetta/hackcoc .github/workflows/publish.yml. Source: ${SOURCE}" - # jiji's main may have moved since the checkout. - for i in 1 2 3; do git push origin HEAD:main && exit 0; git pull --rebase origin main; done - exit 1 + labels: | + org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} + io.betta.jiji.tag=${{ steps.meta.outputs.tag }} From 79e2ad182228656622303ed85cdd0e0359106a7e Mon Sep 17 00:00:00 2001 From: Cristiano Betta Date: Mon, 19 Oct 2026 18:45:45 +0100 Subject: [PATCH 3/3] Point at jiji's pin timer jiji pins from a 1-minute systemd timer now, not pin.yml. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/publish.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c2b9171..d21af72 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,13 +1,13 @@ name: Publish to jiji # Push to master -> CI (ci.yml) -> build the image and push it to -# ghcr.io/cbetta/hackcoc -> cbetta/jiji's pin.yml pins it by tag and digest -# within 10 minutes, which deploys it. jiji holds no copy of the site, only +# ghcr.io/cbetta/hackcoc -> jiji's pin timer pins it by tag and digest within +# about a minute, which deploys it. jiji holds no copy of the site, only # which image it runs, so master here is always what hackcodeofconduct.org # serves. # # Nothing here can write to cbetta/jiji: publish runs on jiji's walled-off CI -# runners, so the deploy key stays with jiji's own pin.yml, which finds the +# runners, so the deploy key stays with jiji's own pin timer, which finds the # new image through the moving :master tag and the io.betta.jiji.tag label. # Actions are pinned by commit (their version in the comment).