Repository navigation
Closed
2 / 22 of 2 issues completedClosed
2 / 22 of 2 issues completed
Copy link
Labels
enhancementNew feature or requestNew feature or request
Description
Problem
Found while deploying Abecra's staging on 2026-10-19. The API's schema is managed by Alembic. cloudfall_deploy unpacks the release, runs uv sync, switches current, restarts the unit and gates on the health check; there is no step where a declared command runs against the new release before (or after) traffic moves to it. component.schema.json has no field for one: service.command is the only command a component declares.
The workaround, after cloudfall deploy returns, is an SSH command that sources shared/env/<component>.env by hand and runs .venv/bin/alembic upgrade head from current/ as the app user. That means:
- the health gate checks a release against the old schema, so a release whose code needs the new schema either fails the gate (and rolls back) or passes it and then serves errors until the manual step runs
- a failed migration leaves no receipt and does not stop or roll back the deploy
- the environment the migration sees is reassembled by hand instead of the unit's own
EnvironmentFile
Proposal
A declared release command, run by the deploy role on one server after uv sync and before the current switch:
spec:
release:
command: [.venv/bin/alembic, upgrade, head]
workingDirectory: services/api
timeoutSeconds: 300- Runs as the application's
linuxUser, in the new release directory, with the same environment file the systemd unit gets - Runs once per deploy even when
deployment.serverslists several servers (on the first server only, recorded in the receipt) - A non-zero exit or timeout fails the deploy before
currentmoves; the previous release keeps serving. The command's exit code and the tail of its output go into the release receipt cloudfall deploywithout--yesshows the command in the plan- Rollback does not run it (downgrades stay a human decision); the plan says so
Alternatives
- Run migrations at application start: works for one server but races on several, and turns a failed migration into a failed health check with less evidence
- A separate
cloudfall run <component> -- <command>one-off command: useful on its own (shells, backfills), but it leaves ordering with the deploy to the operator
Acceptance
- A component with
release.commandthat adds a table: aftercloudfall deploy --yesthe table exists, and the receipt records the command, exit code 0 and output tail - A release command that exits 1: the deploy fails with
ENGINE_STEP_FAILED,currentstill points at the previous release, and the service was not restarted - With two servers declared, the command runs once
- The command sees every variable from the component's
environmentandsecretRefs
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
shipmill-romamo commentedon Oct 20, 2026
Triage: feature.
Confirmed on main (348ed73):
cloudfall_deployunpacks, runsuv sync, switchescurrent, restarts and gates on health, andcomponent.schema.jsondeclares no command besidesservice.command. A declared release command run before thecurrentswitch is a new component field, a new deploy step, new receipt fields and a once-per-deploy rule across servers, so it gets a spec with acceptance criteria first.Writing it alongside #87's spec, since both extend the deploy plan and receipts.
The spec PR is being written now (
docs/specs/005-release-command.md); I'll put its link and the hold line here. Merging it is the approval.shipmill-romamo commentedon Oct 20, 2026
The spec is in #102 (
docs/specs/005-release-command.md). Where it departs from the issue, following the code: a failed release command writes no release receipt, becauseReleaseReceiptonly records a passed health check, so the evidence is theENGINE_STEP_FAILEDmessage. "First server" means the first entry ofdeployment.servers, and the deploy runs that server first. The output tail (2000 characters) is stored without redaction. Each of these is a choice to settle in review.On hold: the build waits on #102, the spec
Spec a release command for #88 (#102)
shipmill-romamo commentedon Oct 27, 2026
The spec merged in #102 on your approval:
docs/specs/005-release-command.md. Its build is split into #119 (the release command in the deploy role) and #120 (the deploy and rollback plans, after #119); this issue closes when the last of them does.shipmill-romamo commentedon Oct 27, 2026
Done: spec S-005 (
docs/specs/005-release-command.md) isstatus: built, every criterion verified, and each build issue has closed:54995c8)8c2bad0)A component can now declare
release.command(for example a database migration);deployruns it once on the release server before any server switches, androllbacknever runs it. It ships in the next release candidate after v0.8.0rc6. Not yet run on a live Debian/systemd host.