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.

Containers, registry, sandboxes, webhooks, schedules, LFS and pull requests

took 43s Raw logs
Failed at Wait for jobs to start on the deployed runner image
Process completed with exit code 22.

    runs=$(api GET "/repos/$OWNER/$REPO/actions/runs?event=workflow_dispatch")
    if [ "$(jq '.workflow_runs | length' <<<"$runs")" -gt "$before" ]; then
      run=$(jq -c '.workflow_runs[0]' <<<"$runs")
      [ "$(jq -r .status <<<"$run")" = completed ] && break
    fi
    sleep 5
  done
  [ -n "$run" ] || { echo "::error::the probe workflow didn't start"; exit 1; }
  probe=$(api GET "/repos/$OWNER/$REPO/actions/runs/$(jq -r .id <<<"$run")/jobs")
  images=$(jq -r '.jobs[] | .runner.image // "no image reported"' <<<"$probe")
  echo "probe jobs ran on: $(sort <<<"$images" | uniq -c | sed 's/^ *//' | paste -sd ','), started again $(jq '[.jobs[].placementTries // 0] | add // 0' <<<"$probe") time(s) in all"
  [ "$(grep -cxF "$expected" <<<"$images" || true)" = 3 ] && { echo "jobs start on $expected"; exit 0; }
  if [ "$(date +%s)" -ge "$deadline" ]; then
    echo "::error::15 minutes after the deploy, jobs still start on a runner image other than the deployed $expected"
    exit 1
  fi
  sleep 20
done
curl: (22) The requested URL returned error: 500
Set up job
Diffinery runner: job live (Containers, registry, sandboxes, webhooks, schedules, LFS and pull requests) for codician/diffinery@f454e336a703Runner: image diffinery-runner:4d3bf17f06575e64ab4155b3, in ams21, WEUR, container db9a23704a7ebebd4d37c5ca08378ccdfaf41eeb875e15b44065de1fbbf6e61eRunner size: large (4 vCPU, 12 GiB of memory, 20 GB of disk), this job uses what a smaller runner doesn't have; runs-on: diffinery-large (or -medium, -small, -tiny) sets a sizeHost: AMD EPYC (family 25, model 17), 4 vCPUs, 2546 MHzWorkspace: /workspace/diffineryHost: 3% of the vCPUs' time went to other work on the host (steal)Job completed with conclusion: failureResources: 0.1 of 4 vCPUs busy on average (0.7 at the 95th percentile), peak memory 0.4 GiB of 11.9 GiB, peak disk 1.1 GB of 19.2 GB
Check the token2s
##[group]Run if [ "$GITHUB_EVENT_NAME" = workflow_run ]; then  # Deploy's gate skips a commit that is no longer main's tip (the newer commit's run deploys it):  # then nothing new is live, and this run would only test the site as it was.  deployed=$(curl -fsS "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/runs/$DEPLOY_RUN/jobs" -H "Authorization: Bearer $GH_TOKEN" | jq -r '[.jobs[] | select(.name == "Deploy to Cloudflare") | .conclusion][0] // "unknown"' || echo unknown)  if [ "$deployed" = skipped ]; then    echo "::notice::Deploy deployed nothing for $HEAD_SHA (main has moved on), so there is nothing new to test"    echo "skip=true" >> "$GITHUB_OUTPUT"    exit 0  fifiif [ -z "$TOKEN" ]; then  # After a deploy of diffinery.com a missing token is an error: a green run would mean nothing was tested.  if [ "$GITHUB_EVENT_NAME" = workflow_run ]; then    echo "::error::DIFFINERY_LIVE_TOKEN is not set in the production environment, so nothing was tested. Create a write token at $DIFFINERY/settings/tokens and save it as a production environment secret."    exit 1  fi  echo "::warning::DIFFINERY_LIVE_TOKEN is not set, so the live test is skipped. Create a write token at $DIFFINERY/settings/tokens and save it as a production environment secret."  echo "skip=true" >> "$GITHUB_OUTPUT"  exit 0filogin=$(curl -fsS "$DIFFINERY/api/v3/user" -H "Authorization: Bearer $TOKEN" | jq -r .login)echo "OWNER=$login" >> "$GITHUB_ENV"echo "testing as $login in $login/$REPO"env:  GH_TOKEN: ***  DEPLOY_RUN: 586##[endgroup]testing as cnbrkdmrci in cnbrkdmrci/live-587-1
Choose the registry check's image sizes2s
##[group]Run set -euo pipefail# Layers over Cloudflare's 100 MB request limit (which hosted runners push through# the registry relay) take minutes to push and pull. They're pushed on manual runs and# whenever the registry, the runner image or this test changed since the last# successful live test; other deploys push small images through the same path.full=trueif [ "$GITHUB_EVENT_NAME" = workflow_run ]; then  api() { curl -fsS "$DIFFINERY/api/v3/repos/$GITHUB_REPOSITORY$1" -H "Authorization: Bearer $TOKEN"; }  last=$(api "/actions/runs?workflow=live-test.yml&status=success&per_page=1" | jq -r '.workflow_runs[0].head_sha // empty' || true)  if [ -n "$last" ] && files=$(api "/compare/$last...$HEAD_SHA" | jq -r '.files[].filename'); then    grep -qE '^(apps/diffinery/src/registry/|containers/runner/|\.github/workflows/live-test\.yml$)' <<<"$files" || full=false    echo "changed since $last: $(wc -l <<<"$files") files"  fifiif [ "$full" = true ]; then  echo "BIG=150000000" >> "$GITHUB_ENV"  echo "BUILDX=120000000" >> "$GITHUB_ENV"else  echo "BIG=5000000" >> "$GITHUB_ENV"  echo "BUILDX=4000000" >> "$GITHUB_ENV"fiecho "registry check: full=$full"##[endgroup]changed since 4d9ceaac2e5ea85369b9b00d7912f159d9bd329f: 17 filesregistry check: full=false
Profile picture upload (WASM resize in the Worker)9s
##[group]Run set -euo pipefailav="$DIFFINERY/api/avatars/$OWNER"# Keep the account's current picture, if it has one, to put it back afterwards.had=$(curl -fsS -o before.webp -w '%{content_type}' "$av?s=256&v=1")restore() {  if [ "$had" = image/webp ]; then    curl -fsS -X PUT "$DIFFINERY/api/v3/user/avatar" -H "Authorization: Bearer $TOKEN" -H "content-type: image/webp" --data-binary @before.webp | jq -r '"restored the previous picture: \(.avatar_url)"'  else    curl -fsS -o /dev/null -X DELETE "$DIFFINERY/api/v3/user/avatar" -H "Authorization: Bearer $TOKEN"  fi}trap restore EXIT# A 600×400 PNG gradient; the server crops it to a square and makes small WebPs.python3 - <<'EOF'import struct, zlibw, h = 600, 400rows = b"".join(b"\0" + bytes(c for x in range(w) for c in (x * 255 // w, y * 255 // h, 128)) for y in range(h))chunk = lambda t, d: struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d))open("avatar.png", "wb").write(b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)) + chunk(b"IDAT", zlib.compress(rows)) + chunk(b"IEND", b""))EOFurl=$(curl -fsS -X PUT "$DIFFINERY/api/v3/user/avatar" -H "Authorization: Bearer $TOKEN" -H "content-type: image/png" --data-binary @avatar.png | jq -r .avatar_url)echo "uploaded: $url"v=${url##*v=}type=$(curl -fsS -o small.webp -w '%{content_type}' "$av?s=64&v=$v")[ "$type" = image/webp ] || { echo "::error::expected image/webp, got $type"; exit 1; }python3 - <<'EOF'import struct, sysb = open("small.webp", "rb").read()ok = b[:4] == b"RIFF" and b[8:12] == b"WEBP"if b[12:16] == b"VP8 ":    size = (struct.unpack("<H", b[26:28])[0] & 0x3FFF, struct.unpack("<H", b[28:30])[0] & 0x3FFF)elif b[12:16] == b"VP8X":    size = (int.from_bytes(b[24:27], "little") + 1, int.from_bytes(b[27:30], "little") + 1)else:    size = Noneprint(f"64 px avatar: {len(b)} bytes, {size}")if not ok or size != (64, 64) or len(b) > 5000:    print("::error::the 64 px avatar is not a 64x64 WebP under 5 KB"); sys.exit(1)EOFcurl -fsS -X DELETE "$DIFFINERY/api/v3/user/avatar" -H "Authorization: Bearer $TOKEN" >/dev/null# A `v` that is not current bypasses the edge cache, so this sees the removal from any colo.type=$(curl -fsS -o /dev/null -w '%{content_type}' "$av?s=64&v=1")[[ "$type" == image/svg+xml* ]] || { echo "::error::after removal expected the initials SVG, got $type"; exit 1; }echo "removed: initials again ($type)"##[endgroup]uploaded: https://diffinery.com/api/avatars/cnbrkdmrci?v=179268328064 px avatar: 256 bytes, (64, 64)removed: initials again (image/svg+xml; charset=utf-8)restored the previous picture: https://diffinery.com/api/avatars/cnbrkdmrci?v=1792683284
Public docs are served without signing in2s
##[group]Run set -euo pipefailcheck() { # path, content type, text it must contain  body=$(curl -fsS -D /tmp/h "$DIFFINERY$1")  grep -qi "content-type: $2" /tmp/h || { echo "::error::$1 is not $2"; exit 1; }  grep -qF -- "$3" <<<"$body" || { echo "::error::$1 doesn't contain: $3"; exit 1; }  echo "$1 ok ($(wc -c <<<"$body") bytes)"}check /docs "text/html" "Overview"check /docs/actions/workflow-syntax "text/html" "View as Markdown"check /docs/quickstart.md "text/markdown" "# Quickstart"check /llms.txt "text/plain" "/docs/actions/workflow-syntax.md"check /llms-full.txt "text/plain" "# REST API reference"check /docs/api/openapi.json "application/json" '"openapi": "3.1.0"'check /-/cli/diffinery.mjs "text/javascript" "#!/usr/bin/env node"md=$(curl -fsS -H "Accept: text/markdown" "$DIFFINERY/docs/agents/mcp")grep -q "^# MCP" <<<"$md" || { echo "::error::Accept: text/markdown didn't return Markdown"; exit 1; }curl -fsS "$DIFFINERY/-/cli/diffinery.mjs" -o /tmp/diffinery.mjs && node /tmp/diffinery.mjs --version##[endgroup]/docs ok (91341 bytes)/docs/actions/workflow-syntax ok (177167 bytes)/docs/quickstart.md ok (17010 bytes)/llms.txt ok (22991 bytes)/llms-full.txt ok (2534517 bytes)/docs/api/openapi.json ok (818665 bytes)/-/cli/diffinery.mjs ok (250493 bytes)diffinery 0.1.0
Email sending is configured2s
##[group]Run set -euo pipefails=$(curl -sS -w '\n%{http_code}' "$DIFFINERY/api/v3/diffinery/admin/email" -H "Authorization: Bearer $TOKEN")code=${s##*$'\n'}; s=${s%$'\n'*}# Only a site administrator's token reads the email settings, and the live-test account isn't one.if [ "$code" = 403 ]; then echo "::notice::skipped: the live-test token isn't a site administrator's"; exit 0; fi[ "$code" = 200 ] || { echo "::error::/diffinery/admin/email answered $code"; exit 1; }echo "$s" | jq '{sending, queue, from, last_24h}'[ "$(jq -r .sending <<<"$s")" = true ] || { echo "::error::the Worker has no Email Sending binding"; exit 1; }[ "$(jq -r .queue <<<"$s")" = true ] || { echo "::error::the Worker has no mail queue binding"; exit 1; }failed=$(jq -r .last_24h.failed <<<"$s")[ "$failed" = 0 ] || echo "::warning::$failed emails failed in the last 24 hours; see Settings -> Email in site administration"##[endgroup]{  "sending": true,  "queue": true,  "from": "notifications@diffinery.com",  "last_24h": {    "sent": 39,    "failed": 0,    "skipped": 0  }}
Create a throwaway repository with a webhook3s
##[group]Run set -euo pipefailapi() { curl -fsS -X "$1" "$DIFFINERY/api/v3$2" -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" ${3:+--data "$3"}; }api POST /user/repos "{\"name\":\"$REPO\",\"private\":true}" >/dev/null# Webhooks may only reach public hosts other than Diffinery itself; the push's delivery goes to example.com.code=$(curl -sS -o /dev/null -w '%{http_code}' -X POST "$DIFFINERY/api/v3/repos/$OWNER/$REPO/hooks" -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" --data "{\"config\":{\"url\":\"$DIFFINERY/healthz\"},\"events\":[\"push\"]}")[ "$code" = 422 ] || { echo "::error::a webhook to Diffinery itself answered $code, not 422"; exit 1; }api POST "/repos/$OWNER/$REPO/hooks" "{\"config\":{\"url\":\"https://example.com/diffinery-live-test\"},\"events\":[\"push\"]}" >/dev/nullecho "created $OWNER/$REPO"##[endgroup]created cnbrkdmrci/live-587-1
Wait for jobs to start on the deployed runner image18s
##[group]Run set -euo pipefail# A deploy's container rollout updates instances over a while after it starts, and an# instance not yet updated starts jobs on the previous runner image. Jobs report their# image (`runner.image`), so a probe workflow runs until three jobs in a row land on the# image the deploy set (/meta's runner_image) before the Docker and registry checks.api() { curl -fsS -X "$1" "$DIFFINERY/api/v3$2" -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" ${3:+--data "$3"}; }expected=$(api GET /meta | jq -r '.runner_image // empty')if [ -z "$expected" ]; then  echo "::warning::/meta doesn't name the deployed runner image, so jobs aren't checked against it"  exit 0fiecho "DEPLOYED_RUNNER_IMAGE=$expected" >> "$GITHUB_ENV"mkdir -p src/.github/workflows && cd srcgit init -q -b maingit config user.name "Live test" && git config user.email "live-test@diffinery.com"cat > .github/workflows/probe.yml <<'EOF'on: workflow_dispatchjobs:  probe:    runs-on: ubuntu-latest    strategy:      matrix:        n: [1, 2, 3]    steps:      - run: echo "probe ok"EOFgit add -A && git commit -q -m "Runner image probe"git push -q "https://x-token:${TOKEN}@${DIFFINERY#https://}/$OWNER/$REPO.git" maindeadline=$(( $(date +%s) + 15 * 60 ))while :; do  before=$(api GET "/repos/$OWNER/$REPO/actions/runs?event=workflow_dispatch" | jq '.workflow_runs | length')  api POST "/repos/$OWNER/$REPO/actions/workflows/probe.yml/dispatches" '{"ref":"main"}' >/dev/null  run=""  # Up to 10 minutes: a job turned away from a replaced image starts again after 30 s, 1, 2 and 4 minutes.  for i in $(seq 1 120); do    runs=$(api GET "/repos/$OWNER/$REPO/actions/runs?event=workflow_dispatch")    if [ "$(jq '.workflow_runs | length' <<<"$runs")" -gt "$before" ]; then      run=$(jq -c '.workflow_runs[0]' <<<"$runs")      [ "$(jq -r .status <<<"$run")" = completed ] && break    fi    sleep 5  done  [ -n "$run" ] || { echo "::error::the probe workflow didn't start"; exit 1; }  probe=$(api GET "/repos/$OWNER/$REPO/actions/runs/$(jq -r .id <<<"$run")/jobs")  images=$(jq -r '.jobs[] | .runner.image // "no image reported"' <<<"$probe")  echo "probe jobs ran on: $(sort <<<"$images" | uniq -c | sed 's/^ *//' | paste -sd ','), started again $(jq '[.jobs[].placementTries // 0] | add // 0' <<<"$probe") time(s) in all"  [ "$(grep -cxF "$expected" <<<"$images" || true)" = 3 ] && { echo "jobs start on $expected"; exit 0; }  if [ "$(date +%s)" -ge "$deadline" ]; then    echo "::error::15 minutes after the deploy, jobs still start on a runner image other than the deployed $expected"    exit 1  fi  sleep 20done##[endgroup]curl: (22) The requested URL returned error: 500##[error]Process completed with exit code 22.
Push workflows and an LFS file
Web UI features (highlighting, settings pages, view transitions, base permission, invitations)
Diffy placeholders, Actions settings, milestones and variables
Hosted Actions jobs (and Docker) run in Cloudflare Containers
An organization's packages page keeps its tabs
Git LFS round trip
Webhook delivered
Tokens can't mint tokens (API or web forms)
Agent sandbox
Agent jails (bubblewrap, no network but the allowlist proxy and the model proxy)
Pull requests and the merge queue
Import a public GitHub repository
Scheduled workflow
Delete the throwaway repositories3s
##[group]Run curl -sS -o /dev/null -w 'package %{http_code}\n' -X DELETE "$DIFFINERY/api/v3/users/$OWNER/packages/container/${REPO,,}" -H "Authorization: Bearer $TOKEN"curl -sS -o /dev/null -w '%{http_code}\n' -X DELETE "$DIFFINERY/api/v3/repos/$OWNER/$REPO" -H "Authorization: Bearer $TOKEN"[ -z "${PR_REPO:-}" ] || curl -sS -o /dev/null -w '%{http_code}\n' -X DELETE "$DIFFINERY/api/v3/repos/$OWNER/$PR_REPO" -H "Authorization: Bearer $TOKEN"[ -z "${IMPORT_REPO:-}" ] || curl -sS -o /dev/null -w '%{http_code}\n' -X DELETE "$DIFFINERY/api/v3/repos/$OWNER/$IMPORT_REPO" -H "Authorization: Bearer $TOKEN"##[endgroup]package 404204