The plan doc served its purpose through #494 (merge) → #498
(scaffolding) → #502 / #503 / #504 / #506 / #509 / #510 (cutover).
v2.0.5+claude1.3883.0 is the first release through the new pipeline,
verified end-to-end on five distros. #493 is closed.
Removes docs/worker-apt-plan.md and the two architecture-pointer
comments in worker/src/worker.js and worker/wrangler.toml that
referenced it. Both files now carry a short self-contained summary
of what the Worker does and why.
Also corrects worker.js's CDN-hostname reference from
objects.githubusercontent.com (the old name) to release-assets
(current, matches #509's regex fix).
Git history retains the full plan doc for anyone who needs the
design rationale; nothing is actually lost.
Once the CNAME file is in place on gh-pages (Phase 4a-APT), GitHub
Pages auto-301s all aaddrick.github.io/claude-desktop-debian/* traffic
to pkg.claude-desktop-debian.dev/*. The Worker's origin fetch against
aaddrick.github.io gets 301'd by Pages, the 301 passes through to the
client, the client follows it back to pkg.<domain>, and the Worker
runs again — infinite loop.
Observed immediately after merging #503 and Pages finishing the CNAME
build:
$ curl -I https://pkg.claude-desktop-debian.dev/dists/stable/InRelease
HTTP/2 301
location: http://pkg.claude-desktop-debian.dev/dists/stable/InRelease
x-github-request-id: 3C94:286425:...
x-served-by: cache-yyz4566-YYZ
via: 1.1 varnish
(Scheme-downgrade to http is a separate Pages quirk when
https_enforced=false, which is the case here because DNS points
at Cloudflare, not Pages, so Pages can't provision a cert.)
raw.githubusercontent.com serves the same gh-pages branch content
without Pages' routing layer. All five metadata paths verified to
return 200:
/dists/stable/InRelease
/dists/stable/main/binary-amd64/Packages
/KEY.gpg
/rpm/x86_64/repodata/repomd.xml
/rpm/x86_64/repodata/repomd.xml.asc
Also fixes the deploy-worker.yml post-deploy probe which still
hardcoded pkg-staging. That's what made #503's deploy show as
failed in the Actions UI even though the wrangler deploy itself
succeeded — route bound and Worker live, but the probe was
resolving a hostname wrangler had just removed.
Refs #493, #503
Co-authored-by: Claude <claude@anthropic.com>
Phase 2 container validation passed against
pkg-staging.claude-desktop-debian.dev — APT (debian:stable,
ubuntu:24.04, debian:testing) and DNF (fedora:latest, rockylinux:9)
both install the current pool version via the Worker chain. The one
remaining failure is #500's sha256 mismatch on RPM download, and
PR #502's gh release upload --clobber fix runs on the next release
that reaches update-dnf-repo.
This flip binds the Worker to pkg.claude-desktop-debian.dev. Once
this is deployed, the strip step's liveness probe in update-apt-repo
and update-dnf-repo will start succeeding, stripping .debs/.rpms from
the local pool tree before push — the original #493 blocker.
Pre-merge checklist (manual, outside this PR):
1. Add CNAME file containing pkg.claude-desktop-debian.dev to the
gh-pages branch root (via Pages settings UI or direct push).
2. Wait for GitHub Pages cert provisioning. Typical ~1h; verify in
repo Settings > Pages that the green cert indicator shows.
3. Merge this PR. CI deploys the Worker to the new route via
deploy-worker.yml.
4. Confirm production probe responds:
curl -fsI https://pkg.claude-desktop-debian.dev/dists/stable/InRelease
5. Re-run the failed update-apt-repo + update-dnf-repo jobs from the
v2.0.3+claude1.3883.0 run (gh run rerun 24836419696 --failed) —
this simultaneously validates #500's fix and completes the v2.0.3
release for apt/dnf users.
Rollback: remove the CNAME file from gh-pages, unbind the Worker
route via the Cloudflare dashboard. gh-pages .deb assets from the
pre-strip history still exist and serve directly via github.io.
Refs #493, #500
Co-authored-by: Claude <claude@anthropic.com>
* feat: APT/DNF Worker scaffolding (#493)
Adds the implementation scaffolding for the Cloudflare Worker that
fronts the APT/DNF repo, per docs/worker-apt-plan.md.
New files:
- worker/src/worker.js: redirects /pool/.../*.deb and /rpm/*/*.rpm
to GitHub Release assets via 302; passes metadata through to
the gh-pages origin
- worker/wrangler.toml: bound to pkg-staging.claude-desktop-debian.dev
initially; Phase 4a switches to pkg.claude-desktop-debian.dev
- .github/workflows/deploy-worker.yml: deploys Worker on worker/**
push, post-deploy probe verifies route bound + Worker responding
- .github/workflows/apt-repo-heartbeat.yml: daily cron, deb+rpm
matrix, walks ordered redirect chain + size match against Releases
asset, opens format-specific tracking issue on failure (auto-close
on recovery), gates on Worker liveness (skips silently before
Phase 4a)
Modified:
- .github/workflows/ci.yml: gated strip step + ordered-chain smoke
test added to update-apt-repo and update-dnf-repo; the destructive
strip only fires when the production Worker probe succeeds, so this
PR can land before Phase 4a without affecting current behavior
- docs/worker-apt-plan.md: bake in real domain values, mark Decisions
table entries as concrete, fix Cloudflare API token permissions
list (current names: Workers Scripts Edit, Account Settings Read,
Workers Routes Edit; previous "Zone:Zone:Read" name no longer
matches the dropdown)
Pre-Phase-4a behavior: the strip step's liveness probe targets the
production hostname which doesn't exist yet, so it always skips and
.debs/.rpms are pushed to gh-pages exactly as today. Smoke tests skip
on the same gate. Heartbeat workflow's gate skips before the Worker
is live. Nothing destructive happens until Phase 4a explicitly cuts
the Worker over to production.
Co-Authored-By: Claude <claude@anthropic.com>
* refactor: simplify worker scaffolding per cdd-code-simplifier review
- worker.js: use named capture group `asset` instead of opaque `m[1]`
positional reference; inline single-use `tagFor()` helper; demote
unused `arch` capture to non-capturing group.
- ci.yml: hoist `WORKER_DOMAIN` from per-step env to job-level env in
both `update-apt-repo` and `update-dnf-repo` (matches the pattern
already used in `apt-repo-heartbeat.yml`).
- apt-repo-heartbeat.yml: use github-script's native `context.serverUrl`
/ `context.runId` instead of reconstructing from process.env; spread
`...context.repo` instead of repeating owner/repo on every API call;
destructure `{ data: open }` to flatten `open.data` references.
All changes preserve behaviour. The contrarian-fix mechanisms (positive
Worker liveness probe gating the strip step, hop-by-hop ordered chain
walk in smoke tests) are unchanged. APT/DNF strip + smoke pairs remain
in-place per reviewer-readability preference.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>