The release pipeline
Every repository releases in the same order: check the files, bring the environment up to
date, build, publish the static sites, deploy the workers and the runtime, check that it
works. That order is one workflow we keep, replicator-release.yml. Your repository keeps
only what is yours: which events start a release, which stages it targets and the commands
that build and check it. A repository’s release file is about thirty lines.
name: Release
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened, closed]
permissions:
contents: read
jobs:
release:
# A pull request from this repository only: a fork never receives the credential.
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
uses: clankerlabs/CLANKERNET/.github/workflows/replicator-release.yml@<40-character SHA> # v1
permissions:
contents: read
with:
replicator_ref: <40-character SHA> # v1
action: ${{ github.event.action == 'closed' && 'remove' || 'release' }}
stage: ${{ github.event_name == 'push' && 'production' || format('pr-{0}', github.event.number) }}
ref: ${{ github.event.pull_request.head.sha || github.sha }}
state_account: 0123456789abcdef0123456789abcdef
build_command: npm ci && npm run build
workers_command: ./scripts/deploy-workers.sh
smoke_command: ./scripts/smoke.sh
secrets:
REPLICATOR_STATE_TOKEN: ${{ secrets.REPLICATOR_STATE_TOKEN }}
Pin the 40-character SHA on the uses: line and in replicator_ref, as the
quickstart does. The one secret is REPLICATOR_STATE_TOKEN. The engine is read
with the workflow’s own token, so the repository that holds it has to be readable by yours.
The steps
| Step | What it does |
|---|---|
| validate | Reads replicator.config.ts and says what the stage is (a listed stage or a preview, protected or not), and checks the shape of the static file. |
| infra | Deploys the stage with replicator infra deploy (only the diff with action: diff), and writes the stage’s outputs to a private file. |
| build | Runs your build_command. The state credential is not in its environment. |
| static | When the config has a static block: builds the toolkit’s contract from it, seals the build, loads the credential, publishes (Static sites). |
| workers | Runs your workers_command. |
| runtime | Runs your runtime_command. |
| smoke | Runs your smoke_command. |
A command left empty is skipped. A failing step stops the release, and nothing after it
runs. Your commands run with bash -euo pipefail and see REPLICATOR_STAGE,
REPLICATOR_OUTPUTS_FILE (the stage’s addresses and names, never a secret) and
FACTORY_BIN (the engine, so a command can read a stored value with
replicator infra secrets get). The workers and runtime commands also receive
REPLICATOR_STATE_TOKEN; the build and the smoke do not.
The commands are reviewed code in your workflow file. Never build one from a dispatch input or from pull-request text.
Inputs
All strings; only stage is required.
| Input | Meaning |
|---|---|
action | release (default), diff (the infra diff and nothing else) or remove. |
stage | The stage: staging, production, or a preview’s name such as pr-12. |
config, state_account, policy | The environment file, the account that holds the state, and a fleet file whose policy: the diff is judged by. |
imports, allow_destroy, confirm | As for the infra actions. |
build_command, workers_command, runtime_command, smoke_command | Your own commands. |
static_environment, static_branch, static_env | Which environment of the static file, which branch, and plain STATIC_SITE_<NAME>=value lines (an origin it requires). |
ref, replicator_ref | The caller’s ref to check out, and the engine’s ref. |
By default a release of production uses the static file’s production environment, a preview
uses preview, and any other stage uses the environment of its own name. The Pages branch is
main, or the stage’s name for a preview.
Protected stages and removing one
A release of a protected stage is the same release: the diff must pass the policy, so nothing
is deleted that you did not name in allow_destroy. Putting a person in front of it is your
workflow’s choice (a branch rule, or a manual trigger).
action: remove takes a stage down. A preview stage is removed
with no confirmation, because it holds nothing that outlives it. Any other stage needs
confirm: remove <stage>, and a protected one also allow_destroy: '*', exactly as the infra
actions do. The run stops before it starts if either is missing.
A preview whose pull request closed without the release workflow seeing it is removed once it
is older than its ttl by the scheduled preview expiry; a
scheduled drift check of each stage is a separate
reusable workflow. Both are called from a cron of your own and use the one secret,
REPLICATOR_STATE_TOKEN.
Runs queue, never cancel
Releases and manual environment runs of one repository and stage share one queue
(infra:<repository>:<stage>): they run one at a time and are never cancelled half way.
Pull requests
A pull request never receives publishing credentials, so on a pull_request the static step is
skipped with a notice and the preview is its environment. If you want the static site of a
preview published, start the same call from a manual trigger on a trusted branch, with
stage: pr-<number>.