Skip to content

Deployment

Three things ship out of this repository on their own schedules: the composite action, the broker, and this site.

What serves the broker today

The two broker hostnames both answer from AWS Lambda behind API Gateway in eu-west-1.

flowchart LR
    A["api.diatreme.magmamoose.com<br/>(DNS only)"] -->|HTTPS| G["API Gateway<br/>eu-west-1"]
    B["broker-diatreme.magmamoose.com<br/>(proxied)"] -->|HTTPS| CF[Cloudflare proxy]
    CF -->|HTTPS| G
    G -->|invoke| L[Lambda broker]
    L -->|HTTPS| GH[api.github.com]
    L -->|HTTPS| J["token.actions.githubusercontent.com<br/>JWKS"]

api.diatreme.magmamoose.com is the default token-broker-url frozen into every published version of the action, so it carries the consumer traffic. It resolves straight to the API Gateway custom domain with no proxy in front. broker-diatreme.magmamoose.com is the shipped fallback and reaches the same gateway through the Cloudflare proxy.

Confirm which is which at any time:

dig +short api.diatreme.magmamoose.com CNAME
dig +short broker-diatreme.magmamoose.com

Editing worker/ does not change production

Both broker hostnames answer from AWS Lambda running the Python broker implementation in broker/. The TypeScript Cloudflare Worker (worker/) remains in the repository as the rollback target, but it is not what consumers hit. See Architecture for more.

Rolling back to Cloudflare

The Cloudflare Worker stays deployed and configured precisely so the hostnames can be pointed back at it. Rollback is a DNS change plus a Cloudflare route, not a redeploy. Verify with the smoke workflow below before and after.

Deploying the broker (Cloudflare)

deploy-worker.yaml runs on every push to main touching worker/** or the workflow itself. It installs, runs npm run check (typecheck, tests, and a wrangler dry run), injects the KV namespace IDs, then deploys.

Required repository secrets:

Secret Purpose
CLOUDFLARE_API_TOKEN Wrangler auth.
CLOUDFLARE_ACCOUNT_ID Target account.

Optional repository variables:

Variable Purpose
DIATREME_JWKS_CACHE_ID KV namespace holding last-known-good JWKS snapshots.
COPILOT_QUOTA_KV_ID KV namespace caching the /releases aggregate.

The injection step is skipped when both are empty, and the deploy still succeeds. Namespace IDs are injected rather than committed so a self-hoster never inherits someone else's namespace.

A deleted namespace fails the deploy, not the request

If one of those variables points at a namespace that no longer exists, every deploy fails at the wrangler step while the running broker keeps serving. The symptom is that merges stop reaching production with nothing obviously broken. Check the workflow's history, not the broker's logs.

Deploy by hand from a working tree:

cd worker
npm ci
npm run check
wrangler deploy

Secrets are set once per environment and are not in the repository:

wrangler secret put GITHUB_APP_ID
wrangler secret put GITHUB_APP_PRIVATE_KEY
wrangler secret put PROCESS_TRIGGER_SECRET

Every variable is described in Configuration.

Public entry points are off on purpose

workers_dev and preview_urls are both false in worker/wrangler.jsonc. Each would be a publicly reachable door to a live token minter, inheriting production secrets and sitting outside whatever rules are bound to the custom domain. Leave them off.

Verifying the broker end to end

Synthetic probes prove routing and the error ladder, but they can only ever be rejected, so they can't prove the thing that matters: that a genuine Actions OIDC token comes back as a usable installation token. Only a real runner can mint one.

broker-smoke-aws.yml does that. It runs Mondays at 06:00 UTC and on demand. For each hostname it mints a real OIDC token, exchanges it, then uses the returned token against the GitHub API and asserts it authenticates as the expected repository.

Run it on demand:

gh workflow run broker-smoke-aws.yml

A failure means an expired App key, a revoked installation, or an IAM, SSM or routing change. It costs one Lambda invocation and two API calls a week.

Releasing the action

release.yaml dogfoods the action against itself with uses: ./, then force-updates the floating major tag once semantic-release publishes a stable version. Consumers pin @v2, a full tag like @v2.4.6, or a SHA.

Because consumers pin by SHA, action input names, defaults, behaviour, and the broker's wire responses are frozen. Changing one breaks repositories whose maintainers cannot be reached. Treat both as append-only.

Publishing this site

docs.yml builds with mkdocs build --strict and deploys to GitHub Pages on every push to main touching docs/** or mkdocs.yml. Pages must be set to the "GitHub Actions" source in repository settings.

Build it locally first:

pip install -r docs/requirements.txt
mkdocs build --strict

Strict mode fails on broken internal links, which is what the published build enforces too.