name: Mirror distroless images # Keeps https://img.dieschoenewolke.de in step with gcr.io/distroless. # # The copying is done by zot's sync extension on the VPS, not by this job: the # registry diffs digests itself, pulls only what changed, and can do so while # the home Forgejo instance (and this runner) is down. This workflow is the # auditor — it compares upstream and mirror digests, pull-verifies anything new, # and only then writes a `synced---` marker tag. # # That is the same "marker last" discipline as the Pureblog release pipeline: # a marker exists only for a ref that was proven pullable by digest. A run that # dies before the push leaves no marker, so the next run retries. # # gcr.io load: one anonymous token request per repo plus one manifest request # per ref = 8 requests per run, every 6 hours. No per-request storm, no docker # login, nothing that could hit an anonymous rate limit. on: schedule: - cron: "17 */6 * * *" workflow_dispatch: inputs: verify_all: description: "Pull-verify every ref, not just new digests (1/0)" required: false default: "0" type: string concurrency: group: distroless-mirror-sync # Never cancel a run half way: a cancelled run could leave a tag pushed # without the verification it claims. Runs are minutes apart anyway. cancel-in-progress: false jobs: verify: runs-on: docker-cli timeout-minutes: 30 container: image: docker:29-cli steps: - name: Install workflow tools # nodejs is required by actions/checkout inside this image run: apk add --no-cache bash curl git jq nodejs - name: Check out the marker tags uses: https://github.com/actions/checkout@v4 with: fetch-depth: 0 - name: Compare upstream and mirror, verify, mark env: # same fixed path in the publish step: Forgejo's job schema has no # job-level env, and there is no runner.temp variable here. MARKERS_FILE: /tmp/mirror-markers # docker:cli keeps the CLI in /usr/local/bin; the runner's DOCKER_HOST # points at the daemon, so the pull goes over the public hostname and # the real TLS/edge path. VERIFY_PULL: ${{ inputs.verify_all == '1' && 'always' || 'new' }} run: ./scripts/verify-mirror.sh - name: Publish marker tags env: MARKERS_FILE: /tmp/mirror-markers run: | set -eu file="$MARKERS_FILE" [ -s "$file" ] || { echo "no new markers"; exit 0; } while read -r marker; do [ -n "$marker" ] || continue git push origin "refs/tags/$marker" echo "marked $marker" done <"$file"