Skip to content

ci: one deploy job instead of two, so the work rounds once not twice - #4

Open
h0bnobs wants to merge 1 commit into
mainfrom
ci/one-deploy-job
Open

ci: one deploy job instead of two, so the work rounds once not twice#4
h0bnobs wants to merge 1 commit into
mainfrom
ci/one-deploy-job

Conversation

@h0bnobs

@h0bnobs h0bnobs commented Aug 24, 2026

Copy link
Copy Markdown
Member

deploy_api and deploy_frontend become a single deploy job. Same steps, same inputs, one rounding.

Why

GitHub bills each job rounded up to a whole minute. Measured over the last 30 days across honeycomb, forager, nasonov and claude-project-setup:

billable jobs 977
real work 1070 min
billed 1708 min
per-job rounding 638 min, 37% of the bill

921 of those jobs ran in under 60 seconds and each was charged a full minute. These two deploy jobs are a clean instance: 1.6 min and 1.8 min, so 4 billed minutes for 3.4 minutes of work, on every push to main. Merged that is 4 billed minutes instead of 5, plus one checkout instead of two. Roughly 118 minutes a month on honeycomb's push volume, and it scales with each app that adopts the pipeline.

Caching was the obvious first idea and it is not the lever. Dependency install is 44 min a month across the whole estate and apt is 12, so under 6% combined, and pip and npm are already cached in gate.

API first, deliberately

Sequential execution means the order decides which half-deployed state a failure can leave. A new API serving an old frontend is survivable, because the frontend calls endpoints that still exist. A new frontend calling an API that has not got its new endpoints is the outage. So the API deploys and passes its smoke test before the SWA upload starts, and that smoke test now gates the frontend as well.

What is unchanged

  • The 31-input caller contract is byte-identical. No caller needs an edit.
  • No step added, removed or reordered within a half.
  • gate is untouched.
  • Both halves stay independently switchable. The job-level if moved onto every step, so stinger's deploy_api: false skips the API steps exactly as before. Callers checked: honeycomb uses both halves on defaults, stinger uses the SWA half only.

What this costs

Wall-clock. A deploy takes about 3.4 minutes rather than about 1.8, because the halves no longer overlap. That is the trade. timeout-minutes goes 15 to 25 to cover both end to end, since the API smoke test can legitimately spend 5 minutes waiting for a cold Consumption worker.

Verification

  • actionlint clean, and confirmed non-vacuous by seeding a bad input reference and watching it fail.
  • Parsed both versions and diffed: inputs identical, step list identical, gate identical, every step after checkout carries an if guard.
  • Not yet exercised against a real deploy. First push to main on a caller is the live test.

🤖 Generated with Claude Code

https://claude.ai/code/session_011iqk1x2Tg1m4ZCwEVmVEz1

GitHub bills every job rounded up to a whole minute. deploy_api averaged 1.6
minutes and deploy_frontend 1.8, so a push to main paid 4 billed minutes for
3.4 minutes of work. Across the estate that per-job rounding was 37% of the
30-day Actions bill: 1070 minutes of real work billed as 1708.

Merging them keeps the work identical and pays one rounding and one checkout
instead of two. Roughly 118 minutes a month back on honeycomb's volume alone.

The API half runs first and its smoke test now gates the SWA upload, because
sequential execution means the order decides which half-deployed state is
reachable: a new API serving an old frontend is survivable, a new frontend
calling an API without its endpoints is the outage.

Both halves stay independently switchable. The job-level 'if' moved onto every
step, so stinger's deploy_api: false keeps skipping the API half exactly as it
did. The 31-input caller contract is unchanged and no step was added or lost.

Costs wall-clock: a deploy takes ~3.4 min rather than ~1.8, since the halves no
longer overlap. timeout-minutes raised 15 -> 25 to cover both end to end.

Verified: actionlint clean, input contract diffs identical, step list identical.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant