On this page

Staging: a candidate used for real before it reaches a live account

A release that passes its gates and is published can still stop the people who use it: a hook catalogue that refuses every tool call of an agent session, a service that starts and serves nothing, a CLI whose first command refuses the configuration every account already has. Gates read the source and run its tests; none of them runs the candidate the way an account will. Staging does: before any delivery reaches a live account, the published candidate is installed into an account of its own on a fleet host and used there by the product's own journeys, and only a staging whose journeys passed lets the live deliveries run.

Stado places the delivery on a host, makes the staging account, installs the candidate there with the product's live installer, runs the journeys the product's manifest declares in that account, keeps the deliveries after it waiting and keeps the receipt. A journey is a program of the released source that uses the installed candidate as its users do; the product says what its journeys are, and its exit status is the journey's answer.

Declared as a delivery

Staging is one delivery of the manifest, and every delivery that reaches a live account names it in after, so it is queued only once staging passed (Publication and deliveries):

"deliveries": [
  {"name": "staging", "platform": "darwin-arm64", "required": true,
   "argv": ["stado", "release", "stage", "--install", "operator-account"]},
  {"name": "operator-account", "platform": "darwin-arm64", "required": true,
   "after": ["staging"],
   "argv": ["stado", "release", "local", "install", "--member", "bin/tool"]}
],
"staging": {"journeys": [
  {"name": "first-run", "argv": ["tests/staging/first-run.sh"]}
]}

--install names the live delivery whose program installs the product on an account: every product installs itself its own way, and staging runs exactly that program, so what is staged is what the account will get. It names a delivery of the same manifest that declares after: ["staging"]; any other name is refused by stado release stage before anything is installed (install-unknown below).

staging.journeys lists the product's journeys in the order they run: each has a name and an argv, run from the exported source.

What stado release stage does

The queue places the job on a host of the delivery's platform, and the delivery worker runs it as it runs every delivery: in the exported source, with WISENT_RELEASE_ARCHIVE and WISENT_RELEASE_SHA256 naming the candidate's archive, WISENT_PRODUCT, WISENT_VERSION, WISENT_PLATFORM, WISENT_SOURCE_DIR and WISENT_OUTPUT_DIR. There stado release stage:

  1. makes the staging account <WISENT_OUTPUT_DIR>/staging/home, owner-only and empty;
  2. runs the --install delivery's program from the exported source with the same variables, HOME and WISENT_STAGING_HOME set to the staging home and its bin, .local/bin and .stado/bin leading PATH, so the candidate is placed, signed and linked exactly as it will be on a live account and nothing of the host's own accounts is read or written; its output is kept in <WISENT_OUTPUT_DIR>/staging/install.log;
  3. runs each journey of staging.journeys in order, the same way, its output kept in <WISENT_OUTPUT_DIR>/staging/<name>.log; a journey that fails or cannot be started stops the journeys after it, and a failed install runs none;
  4. removes the staging home;
  5. writes <WISENT_OUTPUT_DIR>/staging-receipt.json: the product, version, platform, archive digest, passed, staging_home_removed, the install and each journey that ran as {name, argv, exit, ended, started_at, ended_at, log}. It exits 0 only when the install and every journey exited 0 and the staging home was removed, printing staged <product> <version> <platform>: installed by <delivery> and used by <n> journey(s); receipt <path>, and the delivery passes on that, as every delivery does.

What the manifest is held to

stado release submit, and every command that reads the manifest, holds staging to these rules before anything is built:

  • a delivery named staging needs staging.journeys, since without the product's journeys every candidate would pass;
  • staging.journeys needs a delivery named staging, since no other delivery runs them;
  • there is at least one journey, each with a unique name of letters, digits, ., _ and -, and a non-empty argv.

Refusals

Cause Meaning
stado.release.stage.outside-delivery a variable the delivery worker sets (WISENT_RELEASE_ARCHIVE, WISENT_SOURCE_DIR, WISENT_OUTPUT_DIR, …) is unset or empty, naming it: the command runs as a delivery, not by hand
stado.release.stage.manifest-unread the exported source's .wisent-release.json could not be read as JSON, naming the path and the error
stado.release.stage.install-unknown --install names no delivery of the manifest, or one that does not declare after: ["staging"], naming the deliveries after staging and every delivery the manifest declares
stado.release.stage.no-journey the manifest's staging.journeys lists no journey, or one without a valid name or a non-empty argv; nothing was installed
stado.release.stage.home-unmade the staging home could not be made owner-only and empty on this host, naming the path and the system's answer; nothing was installed
stado.release.stage.install-failed the candidate's installer could not start or did not exit 0 in the staging account, with what it said last and where its output is kept; no journey ran
stado.release.stage.journey-unstarted a journey's program could not be started, naming the journey, the program and the error; the journeys after it did not run
stado.release.stage.journey-failed a journey exited non-zero or was ended by a signal using the staged candidate, naming the journey, how it ended and where its output is kept; the journeys after it did not run
stado.release.stage.home-unremoved the candidate passed, but the staging home could not be removed, naming the path and the error; the receipt says staging_home_removed: false and the delivery fails, since the host keeps an account the release made
stado.release.stage.receipt-unwritten the receipt could not be written, naming the path; the delivery is failed, as one with no receipt is

stado errors show stado.release.stage lists the same causes with their remedies and the test that provokes each.

Every refusal leaves the live accounts untouched: the deliveries that name staging in after are recorded not queued: delivery staging did not pass, and a required staging that did not pass fails the release run, as every required delivery's failure does.

Real tests

tests/release/staging.rs runs the real stado release stage as the delivery worker runs it, in an exported source of the case's own with the variables the worker sets naming a real archive. The fixture product installs itself by unpacking its archive into $HOME, and its journeys run the installed program. A candidate whose journeys pass is staged and its receipt says so; a failing journey stops the journeys after it; a failing install stops every journey; each refusal of stado.release.stage is provoked. The process's own HOME is a directory of the case, read back empty after every case. tests/release/staging_manifest.rs holds manifests to the rules above through the real stado quality format. Queuing the deliveries after staging only once it passes is the release's ordering of after, which Publication and deliveries describes.

Source: this website