shiftlabs Start free
Menu Releases

Releases

Stage a new version of each workflow, then make them all current in one step. Every workflow moves, or none does.

Stage, then release

A release makes new versions of several workflows current at once, for a change that spans them. Deploy each workflow with ?stage=1 first, then name the versions in one release.

shellcurl
# Stage each workflow (developer key). Answers {"versionHash", "staged": true, "warnings"}.
# Runs keep starting on the current version.
curl -X PUT "https://api.shiftlabs.org/v1/workflows/refund-check?stage=1" \
  -H "authorization: Bearer $SHIFTLABS_API_KEY" \
  --data-binary @refund-check.ts

curl -X PUT "https://api.shiftlabs.org/v1/workflows/refund-notify?stage=1" \
  -H "authorization: Bearer $SHIFTLABS_API_KEY" \
  --data-binary @refund-notify.ts

# Make both current together. Answers 201 {"release", "changed"}.
curl -X POST https://api.shiftlabs.org/v1/releases \
  -H "authorization: Bearer $SHIFTLABS_API_KEY" -H "content-type: application/json" \
  -d '{"workflows": {"refund-check": "<versionHash>", "refund-notify": "<versionHash>"}}'

A staged deploy is a full deploy. The source is bundled and scanned, Python is loaded and its packages are built, and your quotas apply. The version is stored, but webhooks and manual runs keep starting on the current one until a release names it.

A Python deploy with new packages answers 202 with a deployId. When GET /v1/deploys/:id shows live, the version is stored, still staged, and result.versionHash is the hash to release. A staged version of a workflow that has never been current can be dropped after a day, so release it before then.

What a release changes

Everything is checked before anything changes. A release that is refused changes nothing.

  • The body

    {"workflows": {"name": "versionHash"}} names 1 to 50 workflows, each with the full 64-character versionHash of one of its stored versions. A hash that isn't a stored version of that workflow returns 409 with the workflow's name.

  • All or nothing

    Every workflow named moves to its version in one step, or none does.

  • Runs

    Webhooks and manual runs start on the new versions from then on. Runs already queued or sleeping finish on the version they started on.

  • New workflows

    A workflow that has never been current needs a free workflow slot, to be staged and again to be released. Over your quota, the release returns 403 {"error": "quota exceeded", "limit": "workflows", "max"}.

  • Nothing to change

    If every workflow is already on the version named, no release is recorded and the answer is 200 {"release": null, "changed"}. A CI job can send the same release on every push.

  • One workflow

    A deploy without ?stage=1 and POST /v1/workflows/:workflow/rollback still change one workflow at once. They aren't releases and don't appear in the history.

History and rollback

Each release gets the next number, its seq. A rollback releases an earlier release's versions again as a new release, so the history only moves forward.

shellcurl
# The newest releases first, 20 at most.
curl https://api.shiftlabs.org/v1/releases \
  -H "authorization: Bearer $SHIFTLABS_API_KEY"

# Make release 3's versions current again. Answers 201 {"release", "changed"},
# with the new release's seq.
curl -X POST https://api.shiftlabs.org/v1/releases/3/rollback \
  -H "authorization: Bearer $SHIFTLABS_API_KEY"
  • release

    {seq, workflows, releasedBy, releasedAt}: its number, each workflow's version hash, the email of the person or the id of the API key that released it, and the time in milliseconds since the epoch.

  • changed.workflows

    Each {name, from, to} that moved. from is null for a workflow the release made current for the first time.

  • release: null

    Nothing moved, so nothing was recorded.

We keep the last 20 releases and every workflow version they name. A workflow deleted since then takes its versions with it, and rolling back to a release that names it returns 409.

Routes
RouteMethodMinimum role
/v1/releases the newest first; ?limit= from 1 to 20, default 20GETviewer
/v1/releases {"workflows": {"name": "versionHash"}}, 1 to 50 workflowsPOSTdeveloper
/v1/releases/:seq one release, or 404 {"error": "release not found"}GETviewer
/v1/releases/:seq/rollback no body; that release's versions, current again as a new releasePOSTdeveloper
  • Viewers can list and read releases. Developers and admins release and roll back.
  • A key whose scope names some workflows can release only those. It sees and rolls back only releases whose every workflow it reaches, and gets 403 for any other workflow.
  • Each release is written to the audit log as release, with what changed and, for a rollback, rollbackOf.
  • Staged deploys count like any deploy: toward 20 deploys a minute and the new versions you can add in 24 hours. See Rate limits.