Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

Live test: push big registry layers only when the registry could have changed (#35)

The 150 MB and 120 MB registry images are pushed on manual runs and when the registry, the runner image or the live test changed since the last successful live test; other deploys push small images through the same paths. The sync and the live test print each Diffinery job's duration.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ruyx3Qr4jYrZEpPi466deb
Canberk Demirci authored · GitHub committed signed1 parent 7bbb8edcommit c9005de0717221b0906e0151f518b4051a416da4Browse files
2 files changed+41−9
modified.github/workflows/live-test.yml+36−7View file
@@ -33,6 +33,7 @@
3333 DIFFINERY: https://diffinery.com
3434 TOKEN: ${{ secrets.DIFFINERY_LIVE_TOKEN }}
3535 REPO: live-${{ github.run_id }}-${{ github.run_attempt }}
36+ HEAD_SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
3637 steps:
3738 - name: Check the token
3839 id: token
@@ -46,6 +47,32 @@
4647 echo "OWNER=$login" >> "$GITHUB_ENV"
4748 echo "testing as $login in $login/$REPO"
4849
50+ - name: Choose the registry check's image sizes
51+ if: steps.token.outputs.skip != 'true'
52+ run: |
53+ set -euo pipefail
54+ # Layers over Cloudflare's 100 MB request limit (which hosted runners push through
55+ # the registry relay) take minutes to push and pull. They're pushed on manual runs and
56+ # whenever the registry, the runner image or this test changed since the last
57+ # successful live test; other deploys push small images through the same path.
58+ full=true
59+ if [ "$GITHUB_EVENT_NAME" = workflow_run ]; then
60+ api() { curl -fsS "$DIFFINERY/api/v3/repos/$GITHUB_REPOSITORY$1" -H "Authorization: Bearer $TOKEN"; }
61+ last=$(api "/actions/runs?workflow=live-test.yml&status=success&per_page=1" | jq -r '.workflow_runs[0].head_sha // empty' || true)
62+ if [ -n "$last" ] && files=$(api "/compare/$last...$HEAD_SHA" | jq -r '.files[].filename'); then
63+ grep -qE '^(apps/diffinery/src/registry/|containers/runner/|\.github/workflows/live-test\.yml$)' <<<"$files" || full=false
64+ echo "changed since $last: $(wc -l <<<"$files") files"
65+ fi
66+ fi
67+ if [ "$full" = true ]; then
68+ echo "BIG=150000000" >> "$GITHUB_ENV"
69+ echo "BUILDX=120000000" >> "$GITHUB_ENV"
70+ else
71+ echo "BIG=5000000" >> "$GITHUB_ENV"
72+ echo "BUILDX=4000000" >> "$GITHUB_ENV"
73+ fi
74+ echo "registry check: full=$full"
75+
4976 - name: Profile picture upload (WASM resize in the Worker)
5077 if: steps.token.outputs.skip != 'true'
5178 run: |
@@ -173,8 +200,9 @@
173200 printf 'PING\r\n' >&3
174201 read -r line <&3
175202 echo "service ok ${line%$'\r'}"
176- # Container registry: a layer over Cloudflare's 100 MB request limit, pushed with
177- # the job's GITHUB_TOKEN, plus the docker/*-action route most ghcr.io workflows use.
203+ # Container registry: a layer pushed with the job's GITHUB_TOKEN (over Cloudflare's
204+ # 100 MB request limit on full runs), plus the docker/*-action route most ghcr.io
205+ # workflows use. __BIG__ and __BUILDX__ are the layer sizes.
178206 publish:
179207 runs-on: ubuntu-latest
180208 permissions:
@@ -183,7 +211,7 @@
183211 - run: |
184212 image="diffinery.com/${GITHUB_REPOSITORY,,}"
185213 echo "${{ '${{' }} secrets.GITHUB_TOKEN }}" | docker login diffinery.com -u "${{ '${{' }} github.actor }}" --password-stdin
186- head -c 150000000 /dev/urandom > big.bin
214+ head -c __BIG__ /dev/urandom > big.bin
187215 sha256sum big.bin | cut -d' ' -f1 > big.sha
188216 printf 'FROM scratch\nCOPY big.bin big.sha /\n' > Dockerfile
189217 docker build -q -t "$image:live" .
@@ -196,7 +224,7 @@
196224 steps:
197225 - run: |
198226 echo "IMAGE=diffinery.com/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"
199- head -c 120000000 /dev/urandom > big.bin
227+ head -c __BUILDX__ /dev/urandom > big.bin
200228 printf 'FROM scratch\nCOPY big.bin /\n' > Dockerfile
201229 - uses: docker/setup-buildx-action@v3
202230 - uses: docker/login-action@v3
@@ -237,6 +265,7 @@
237265 steps:
238266 - run: echo "scheduled ok"
239267 EOF
268+ sed -i "s/__BIG__/$BIG/g; s/__BUILDX__/$BUILDX/g" .github/workflows/ci.yml
240269 git add -A && git commit -q -m "Live test"
241270 git push -q "https://x-token:${TOKEN}@${DIFFINERY#https://}/$OWNER/$REPO.git" main
242271 git lfs ls-files
@@ -276,7 +305,7 @@
276305 echo "$run" | jq '{id, status, conclusion}'
277306 id=$(jq -r .id <<<"$run")
278307 jobs=$(api "/repos/$OWNER/$REPO/actions/runs/$id/jobs")
279- jq -r '.jobs[] | " \(.name): \(.conclusion)\(if .failure then " - " + (.failure.message // "") else "" end)"' <<<"$jobs"
308+ jq -r '.jobs[] | " \(.name): \(.conclusion)\(if .failure then " - " + (.failure.message // "") else "" end)\(try " (\((.completed_at | fromdateiso8601) - (.started_at | fromdateiso8601))s)" catch "")"' <<<"$jobs"
280309 if [ "$(jq -r .conclusion <<<"$run")" != success ]; then
281310 for job in $(jq -r '.jobs[] | select(.conclusion == "failure" or .conclusion == "timed_out") | .id' <<<"$jobs"); do
282311 echo "::group::Last log lines of job $job"
@@ -296,8 +325,8 @@
296325 grep -F "service ok +PONG" <<<"$log" || { echo "::error::the redis service container was not reachable"; exit 1; }
297326 job=$(jq -r '.jobs[] | select(.name == "pull") | .id' <<<"$jobs")
298327 log=$(api "/repos/$OWNER/$REPO/actions/jobs/$job/logs")
299- grep -F "registry ok 150000000 bytes" <<<"$log" || { echo "::error::the image pushed with a 150 MB layer did not come back intact from the registry"; exit 1; }
300- grep -F "buildx ok 120000000 bytes" <<<"$log" || { echo "::error::the image pushed by docker/build-push-action did not come back from the registry"; exit 1; }
328+ grep -F "registry ok $BIG bytes" <<<"$log" || { echo "::error::the image pushed with a $BIG-byte layer did not come back intact from the registry"; exit 1; }
329+ grep -F "buildx ok $BUILDX bytes" <<<"$log" || { echo "::error::the image pushed by docker/build-push-action did not come back from the registry"; exit 1; }
301330 api "/users/$OWNER/packages/container/${REPO,,}/versions" | jq -c '.[] | {tags: .metadata.container.tags, size, platforms}'
302331
303332 - name: An organization's packages page keeps its tabs
modifiedscripts/diffinery-wait-runs.sh+5−2View file
@@ -32,9 +32,12 @@
3232 failed=0
3333 for id in $(jq -r '.workflow_runs[].id' <<<"$runs"); do
3434 run=$(api "/actions/runs/$id")
35- jq -r '"\(.name) [\(.event)]: \(.conclusion) \(.html_url)"' <<<"$run"
35+ jq -r '"\(.name) [\(.event)]: \(.conclusion)\(try " in \((.updated_at | fromdateiso8601) - (.created_at | fromdateiso8601))s" catch "") \(.html_url)"' <<<"$run"
3636 jobs=$(api "/actions/runs/$id/jobs")
37- jq -r '.jobs[] | " \(.name): \(.conclusion)\(if .failure then " - " + (.failure.message // "") else "" end)"' <<<"$jobs"
37+ # Each job's time, and its steps that took over 20 seconds, to see where a sync spends it.
38+ jq -r 'def secs: try ((.completed_at | fromdateiso8601) - (.started_at | fromdateiso8601)) catch null;
39+ .jobs[] | " \(.name): \(.conclusion)\(if .failure then " - " + (.failure.message // "") else "" end)\(if secs then " (\(secs)s)" else "" end)",
40+ (.steps[]? | select((secs // 0) > 20) | " \(secs)s \(.name)")' <<<"$jobs"
3841 if [ "$(jq -r .conclusion <<<"$run")" != success ]; then
3942 failed=1
4043 for job in $(jq -r '.jobs[] | select(.conclusion == "failure" or .conclusion == "timed_out") | .id' <<<"$jobs"); do