halyard
A CLI that builds, signs and ships a release, runs a set of preflight checks against it before any traffic moves, and keeps the previous release warm so a rollback is one command instead of a rebuild.
Installation
bash# with npm
npm install --save-dev halyard
# with pnpm
pnpm add -D halyard
# or run without installing
npx halyard deploy
Quick Start
bash# 1. Generate a config file
npx halyard init
# 2. Build, sign and run preflight against staging
npx halyard deploy --env staging
# 3. Move traffic once preflight is green
npx halyard promote --env staging
Commands
halyard deploy [path]
Builds and signs the artifact at the given path (defaults to .), uploads it, and runs the preflight checks. Traffic is not moved.
| Flag | Description | Default |
|---|---|---|
--format | Output format: pretty, json, junit | pretty |
--env | Target environment: staging, production | staging |
--config | Path to a config file | .halyardrc.json |
--quiet | Suppress info-level output | false |
--skip | Skip a named preflight check (repeatable) | - (none) |
bashnpx halyard deploy ./ --format json --env production > release.json
halyard init
Interactively creates a .halyardrc.json config file in the current directory.
| Flag | Description | Default |
|---|---|---|
--yes | Skip prompts, use defaults | false |
--preset | Starting preset: strict, balanced, lenient | balanced |
halyard promote [build]
Moves traffic to a build that already passed preflight, and keeps the outgoing release warm for rollback.
| Flag | Description | Default |
|---|---|---|
--dry-run | Show what would change without moving traffic | false |
--keep-warm | How many superseded releases stay running | 1 |
halyard rollback
Sends traffic back to the warm release. No rebuild and no registry round trip, because the previous build is still running.
bashnpx halyard rollback --env production
npx halyard rollback --to 4f21c9e
Config Options
Configuration lives in .halyardrc.json at your project root.
.halyardrc.json{
"extends": "halyard:balanced",
"environments": ["staging", "production"],
"artifacts": ["dist/**", "public/**"],
"preflight": {
"healthcheck": "/readyz",
"env-drift": "error",
"bundle-size": ["warn", { "maxKb": [180, 240, 320] }],
"cold-start": ["warn", { "p95": 1.2 }]
},
"failOn": "error",
"keepWarm": true
}
| Key | Type | Description |
|---|---|---|
extends | string | Base preset to inherit check settings from |
environments | string[] | Environments this project is allowed to deploy to |
preflight | object | Per-check severity and options |
failOn | string | Severity level that triggers a non-zero exit code |
keepWarm | boolean | Keep the superseded release running for rollback |
CI Integration
Use the junit format to surface failed checks in your CI test report, or just fail the job on error-level checks:
.github/workflows/halyard.yml- name: Halyard deploy
run: npx halyard deploy --env production --format junit
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Preflight passed, nothing at or above the failOn level |
| 1 | Checks failed at or above the configured fail level; traffic unchanged |
| 2 | Configuration error (invalid .halyardrc.json, unknown environment) |
| 3 | Runtime error (artifact not found, signing key unreadable, upload failure) |