vike
Developer

Release gates

Five gates over what Vike Trader ships — the container image, the shipped units, the fxcm-linked artifact, the public mirror, and the dispatcher's boot behaviour.

A release leaves the repository as bytes nobody re-reads: an image, a set of unit files, a handful of binaries, a published source tree. Five gates in crates/vike-ops/tests/ hold the properties of those artifacts that no compiler can see — each chosen because its violation stays invisible until the artifact is run in production.

The container image

crates/vike-ops/tests/container_image_gate.rs opens with the fact that shapes it: no runner has a container runtime. Measured 2026-08-24 on the box the release workflow is pinned to, none of the four common runtimes is installed and the docker socket does not exist, while a control probe finds the ordinary shell tools — "so that is a fact about the runner and not about a broken check."

Coverage is split by what is provable without one. The entrypoint is executable shell, so it is run: the_entrypoints_own_selftest_passes drives the real script through the stamp, the verification, the wholesale swap and every refusal. The Dockerfile is text, so the rest are text rules. the_entrypoint_execs_the_daemon is called "the single most dangerous line". Without exec the shell stays PID 1, and a shell does not forward SIGTERM to its children: docker stop waits out its timeout then SIGKILLs, so cancel_orders_on_shutdown never runs and "the resting book is ABANDONED at the venue" — the defect crates/vike-ops/tests/graceful_stop_pin.rs exists to keep fixed, reached through the container instead of the unit file. Alongside it: the base image is pinned by digest, no packages are installed, both released binaries are present, the stop timeout outlasts the daemon's own shutdown deadline, and no_baked_environment_variable_is_a_removed_setting — vike_config::REMOVED_ENV names variables whose presence is a hard startup refusal, and one baked as an ENV line would make every container of that image refuse to start.

What the image gate cannot prove

That the image builds, that the base's glibc satisfies the binaries, or that the entrypoint works under a real PID 1. crates/vike-ops/tests/container_image_gate.rs says so itself, in its What it deliberately does NOT prove section: none of it is reachable without a container runtime, so the release script that stages and builds the image carries the runtime check instead — "the only place the glibc-too-old failure can be observed at all."

That check runs --version on every version-capable link — six of them, all symlinks into one dispatcher — inside the freshly built image before anything is published. crates/vike/src/lib.rs's Route::Version records the same rule from the dispatcher's side: "the image smoke runs --version through every link, the dispatcher's included." One link is not enough — a released image once answered vike-tradehub --version with that tool's usage error, a break a single-link smoke catches only for the link it runs.

The shipped units

crates/vike-ops/tests/deploy_layout_gate.rs holds one rule — every shipped daemon unit describes one project folder, and the same one throughout — and names two defects that shipped before it existed. The first was a layout that no longer existed anywhere, so a fresh deploy rebuilt an abandoned three-location shape. The second was worse: EnvironmentFile= pointed at the credential store. Nothing was exposed, but the route shipped, and it inverts a guarantee four gates rest on — the live, control, reconcile and Telegram flags are read off the real process environment precisely because the store never reaches there.

The write grant is the instructive rule, because its first version caused what it looked like it prevented. It demanded exactly one ReadWritePaths= naming exactly one path, on the argument that a second path is a second location. It is not: every path was already required to be under the unit's own root, so a second path inside one folder is a narrower grant. The rule forced the one daemon that legitimately writes in two places to grant the only single path covering both — the root — which on a shared folder covered a live daemon's binaries, its notional ceiling, its credential store and its armed kill switch. Containment is checked instead: no granted path may reach ExecStart='s binary or any ExecStartPre= binary — not the executable and not a directory holding it, since write permission there is enough to unlink and replace the file — nor the settings directory the unit names. The gate states its own limit: intent is all a text gate can read.

The fxcm-linked artifact

crates/vike-ops/tests/release_fxcm_artifact_gate.rs governs a second daemon binary built from the same tagged commit with --features fxcm. Its rule is one line: a release may grow an fxcm-linked artifact; it may not change the one everybody deploys. A feature build writes to the same output path the default build just produced, so getting it wrong silently replaces the binary the deploy installs — with one that dies at exec, before main. The extra asset rides in the checksum manifest but is never installed, checked over a derived subject rather than a hand list, because "an absence check never opens the file nobody remembered to add, and reports a pass for it." Third, an asset named -fxcm must actually be linked: with no SDK the identical command produces a stub that builds green, so the script reads the ELF's dynamic section rather than trusting an exit code, and the gate runs it against a fake cargo — the only way to prove the guard is wired into the build.

A return from a test body is a pass

This gate's behavioural half once opened with an early return on a missing toolchain, so a runner without a C compiler reported it green over a release script none of it had executed. Since 2026-08-28 the cases differ: off an ELF platform they are #[ignore]d with the reason attached, and a missing tool on Linux fails, because a box that can build the workspace already has all three.

The public mirror and the dispatcher

crates/vike-ops/tests/publish_mirror_gate.rs guards the script deciding what leaves the private repository, on two properties. ALLOW is an allowlist — a catch-all turns the script into "publish everything except…", which fails in the wrong direction, silently, and once. And the forbidden-token scan refuses rather than warns: "redaction alone is a habit; redaction plus a refusal is a gate." Neither is checkable by reading the script, so the gate runs it over the real tree and inspects the result.

crates/vike-ops/tests/multicall_gate.rs requires the multicall dispatcher to do nothing before handing over, and one tool to run per process. It performs the process's single environment sweep, then hands control to a tool that boots for itself — if the dispatcher also booted, one process would walk for settings twice, and the second walk is blind to the settings-directory override. That is the defect that once put a live daemon on no policy, no config and no credentials, every venue silently on paper, no error anywhere. The boot-ownership gate cannot catch it: it keys on crate directories containing a boot call, so "the dispatcher boots and the tool it calls boots" reads as two crates each booting once. The one-tool rule follows from process-global state — a second tool would inherit the first's logging and handlers in a process that may be signing orders — so the dispatcher panics, and the gate proves the panic is real.

Related: Supply chain · Drift gates · Safety gates

On this page