Releases: adaouat/bifrost
Release list
v0.24.1
🐛 Bug Fixes
-
(atomic) Reject unsafe symlink targets during extraction - (f8642e1)
extractHandler validated entry names against path traversal but created
symlink entries with an unvalidated target. A crafted artifact could ship
a symlink whose target is absolute (/etc) or escapes via .., letting a
later entry written under it escape the release directory (the
symlink-based zip-slip variant).Add symlinkEscapes and reject symlink entries whose target is absolute or
resolves outside the release directory, before os.Symlink — matching the
existing entry-name traversal guard. Safe relative symlinks that resolve
inside the release directory are still extracted.Co-Authored-By:Claude noreply@anthropic.com
-
(deploy) Reject --interactive for remote (server) deploys - (ba5a0f3)
The M22 human+TTY guard runs before config load, so on a real TTY a
--interactivedeploy against a config withservers:passed the guard
and silently fell through to a client-mode SSH deploy — the flag was
accepted and ignored, because the remote agent runs in--output json
mode where per-step prompts are skipped.Reject
--interactivewith a Usage error (exit 1) after merge when the
config has servers, before the client-mode branch. Also correct spec 03,
which documented the guard's usage error as exit 2 (the code returns
cmderr.Usage = exit 1).IsTTY gains a SetIsTTY test seam (matching SetStatFile/SetInitWrite) so
the rejection can be unit-tested with a TTY forced on.Co-Authored-By:Claude noreply@anthropic.com
-
Bump forge to v0.17.1 - (d42f45a)
Inherits the updatecheck.Hinter.Print fix: the upgrade hint now
renders as multi-line and no longer prints a double trailing newline.go.mod/go.sum only.
📚 Documentation
-
(specs) Document archive extraction symlink safety - (896a2b7)
Spec 03 had no description of extraction safety. Document that step 6
treats the archive as untrusted: rejected entry names (absolute / ..),
rejected symlink targets (absolute, or relative escaping the release
dir), and that safe relative symlinks are extracted normally.Explain why absolute symlink targets are rejected unconditionally and
point to paths.shared as the sanctioned way to link a release file to a
fixed location outside the release.Co-Authored-By:Claude noreply@anthropic.com
Commit Statistics
- 4 commit(s) contributed to the release.
- 5 day(s) passed between the first and last commit.
- 4 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 9 day(s) passed between releases.
v0.24.0
🚀 Features
-
(cmd) Add --interactive deploy flag with TTY guard - (6e50cda) by @bchatard
Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
-
(deploy) Wire --interactive step-continue prompts into the deploy pipeline - (1fc7932) by @bchatard
Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
-
(tui) Add step-continue confirm prompt for interactive deploy - (841fee8) by @bchatard
Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
📚 Documentation
-
(roadmap) Add M22 --interactive deploy flag - (9217126) by @bchatard
Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
-
(specs) Document --interactive flag in spec 03 and spec 06 - (344d8f7) by @bchatard
Add --interactive to the deploy flag table, describe its TTY/mode
guard, and add a step-confirm UX section with prompt and abort examples.
🧪 Testing
-
(cmd) Integration test for --interactive scripted-confirm deploy - (e30209a) by @bchatard
Feed CRs one-per-300ms so each huh.Run() program receives exactly
one CR; writing all at once lets bubbletea consume them in a single
Read(4096) and starves subsequent prompts.ExecWithTTY gains an inputInterval parameter for byte-at-a-time writes.
Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
Commit Statistics
- 6 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 6 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.
v0.23.1
🧪 Testing
-
(cmd) Verify SIGINT after extraction warns and deploy completes - (37e93b8)
Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
Commit Statistics
- 1 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 1 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
v0.23.0
🚀 Features
-
(atomic) Warn once on post-extraction cancellation - (98cfc74) by @bchatard
Once Extract succeeds, the deploy pipeline ignores ctx and runs to
completion regardless of Ctrl+C. Surface that to the user with a
one-time warning instead of leaving the cancellation silently ignored.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
-
(tui) Add PrintWarning for one-time deploy cancellation notice - (b63250c) by @bchatard
Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
📚 Documentation
-
(roadmap) Add M21 deploy cancellation guard - (9d9a344) by @bchatard
Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
Commit Statistics
- 3 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 3 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
v0.22.0
🚀 Features
-
(config) Reject unsupported strategy values - (35709f3) by @bchatard
deploy hardcodes the atomic strategy, so a config with strategy: docker (or any
non-atomic value) was silently accepted and ignored. Validate now rejects an
explicit non-atomic strategy with a Config error (exit 2). An empty/unset strategy
is still valid — it defaults to atomic. Part of M20 (S5).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(config) Reject empty hook cmd at load time - (bb39dbc) by @bchatard
A hook with an empty cmd was accepted and would run 'sh -c ""' (a silent no-op).
ValidateHookCmds now rejects any hook with a blank cmd at every config level, and
Load reports it as a Config error (exit 2) alongside server-ref validation. Part of
M20 (S6).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(deploy) Cancel the deploy on SIGINT via cmd.Context() - (c897858) by @bchatard
deploy passed context.Background() to the deployer, so Ctrl-C couldn't interrupt a
long artifact extraction. Now that forge v0.17.0 wires fang.WithNotifySignal,
cmd.Context() is cancelled on SIGINT/SIGTERM; thread it into Deploy so cancellation
reaches Extract (which honors ctx). A guard test confirms Extract aborts with
context.Canceled. Other steps don't observe ctx yet — fuller cancellation is future
work. Part of M20 (S3).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(deps) Bump forge to v0.17.0 - (2f285a8) by @bchatard
cmd.Context() is now canceled on SIGINT/SIGTERM (forge cli.Run gains
fang.WithNotifySignal); previously Ctrl-C killed the process via Go's
default handler. exitcode.Interrupted (130) is also available for commands
that surface context.Canceled.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
🐛 Bug Fixes
-
(deploy) Log purge-plan errors instead of discarding them - (e26a80f) by @bchatard
When PurgePlan failed, purgePlan was set to nil silently, so the dry-run preview
and JSON purged list went empty with no indication why. Log the error via the
operator-debug logger before discarding. The path is defensive (releases_root is
valid by the purge step), so no dedicated test. Part of M20 (S10).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(transport) Bound agent downloads with an http.Client timeout - (5832a68) by @bchatard
downloadAgent and verifyChecksum used http.Get with the default client (no
timeout), so a hung GitHub could stall a deploy indefinitely. Route both through
a shared http.Client with a 120s timeout. Part of M20 (S9).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(tui) Raise event-stream line limit above 64 KB - (7bad1af) by @bchatard
A hook_output event carrying a large payload (e.g. a verbose migration log)
exceeded bufio.Scanner's 64 KB default token, which dropped the line and aborted
ForwardStream with 'token too long' — truncating the rest of the deploy stream.
Raise the scanner buffer to 16 MB. Part of M20 (S7).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
🚜 Refactor
-
(cmd) Extract shared config-resolution and hook helpers - (59ba701) by @bchatard
The flat-detect -> merge -> validate block was copied across deploy, release
list/activate/rollback; writeTempFlatConfig, the env-map helper, and the
interactive-confirm helper were each duplicated across the cmd and release
packages. Consolidate them: cmdutil.ResolveMergedConfig and WriteTempFlatConfig,
hooks.OSEnv, and tui.InteractiveHookConfirm. Behaviour-preserving — verified by
the full unit suite plus local-deploy, client-deploy, and release E2E tests.
Net -66 lines. Part of M20 (S1).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(deploy) Collapse the 8 hook-stage blocks into one helper - (eee16f7) by @bchatard
The deploy pipeline repeated the same ~7-line hook block eight times (run the
stage's hooks, wrap a failure with the stage name, render the step line). Extract
a single runHookStage closure and call it per stage. Behavior-preserving — verified
by the unit deploy tests and the hook-pipeline integration tests (firing, ordering,
JSON and error events). Part of M20 (S2).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(hooks) Use errors.AsType to match ssh.go - (0d599a7) by @bchatard
ssh.go uses the Go 1.26 errors.AsType generic; runner.go used the classic
errors.As. Standardize on AsType (the modernize linter's preference) so the two
error-inspection sites read the same. No behavior change. Part of M20 (S4).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(transport) Chmod the agent via SFTP, not a remote shell - (2c64e60) by @bchatard
Making the uploaded agent executable shelled out 'chmod +x' over SSH. Add
Staging.Chmod (delegating to the existing SFTP.Chmod) and use it instead — one
fewer remote shell exec and no command string to quote. Verified by the deploy
and release E2E tests (the agent must be executable to run). Part of M20 (S8).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
📚 Documentation
-
(testing) Allow t.TempDir in deployer FS-logic tests - (f476cd6) by @bchatard
Constraint #1 forbade t.TempDir(), but the deployer's own logic tests
(deploy_logging_test, deploy_hookoutput_test, deploy_exitcode_test) need a real
local filesystem — afero is banned precisely because it can't model the symlinks
the deployer relies on. Carve a narrow exception rather than leave three files
silently contradicting a hard constraint. Co-Authored-By:Claude Fable 5 noreply@anthropic.com
🧪 Testing
-
(cmd) Assert hook output is visible over SSH (S11) - (2789e1d) by @bchatard
Extract the deploy-over-SSH scaffolding (connect, stage, exec agent, forward the
JSON stream) into testutil.DeployOverSSH so it isn't duplicated; refactor the
existing client deploy E2E onto it. Add TestDeployCmd_HookOutputVisibleOverSSH:
deploy over SSH with a post_extract hook that echoes a marker and assert the marker
appears in the rendered output — the end-to-end proof of the M19 hook-output fix
that was deferred. Closes M20 (S11).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(cmd) Confirm deploy error via stderr, not the exec exit code - (236e130) by @bchatard
TestPlainOutput_NoColorCodes/TestNoColor_SuppressesColors asserted the deploy
errored via the container-exec exit code. testcontainers can read that code as 0
for a fast-exiting process under CI load (the attach EOFs before the exit status
is finalized), so the tests flaked on CI even though 'bifrost deploy' exits 1
deterministically. Confirm the error via non-empty stderr (read reliably to EOF)
instead. The ANSI color-code assertions — the tests' real purpose — are unchanged.Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(testutil) Unique known_hosts path to fix CI host-key race - (bca2aa2) by @bchatard
WriteKnownHosts wrote to a fixed /tmp/bifrost-test-known-hosts. The CMD and
RELEASE integration packages run in parallel and both write it, so under CI load
one clobbered the other's host key, failing the release E2E with 'knownhosts: key
is unknown'. S11's added SSH test raised the collision odds enough to trip it.
Write a unique per-call path instead. Full integration suite green (252).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
Commit Statistics
- 15 commit(s) contributed to the release.
- 1 day(s) passed between the first and last commit.
- 15 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.
v0.21.0
🚀 Features
-
(transport) Verify agent binary checksum before caching - (c332ddb) by @bchatard
The downloaded agent runs on the target (often via sudo) but was cached and
executed with no integrity check. verifyChecksum now fetches the release
checksums.txt and verifies the binary's SHA-256 before the cache write, failing
on a mismatch or a missing entry for the platform asset. --agent-binary still
bypasses both download and verification.Part of M19 (agent binary integrity verification). ADR-0011 updated.
Co-Authored-By:Claude Fable 5 noreply@anthropic.com
🐛 Bug Fixes
-
(deploy) Emit hook output as JSON events in --output json mode - (a3675e2) by @bchatard
In JSON mode the deployer wrote raw hook stdout/stderr to the same stream as the
JSON events, so over SSH the client's NDJSON parser silently dropped all hook
output (migrations, build logs) and a local --output json deploy produced invalid
NDJSON. A new tui.HookOutputWriter wraps each write as a hook_output event;
ForwardStream renders it; the deployer routes hook output through it in JSON mode
and writes raw to stdout as before in human/plain mode. A WithRunner seam lets a
fake runner drive the deployer test without real shell execution.Part of M19 (hook output over SSH / JSON mode).
Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(deploy) Classify hook and deploy runtime failures as exit 3 - (11755f3) by @bchatard
Hook, template, extraction, link, symlink, and purge failures returned bare
errors that forge resolved to exit 1 (Usage), but specs 01/03/05 all document
exit 3 (Runtime) for these — a contract CI/orchestration relies on. The hooks
runner now wraps hook-exec and template failures as Runtime, the deployer wraps
its extract/link/symlink/purge/release-dir failures, and emitError reports the
resolved code in the JSON error event instead of a hardcoded 1. cmderr re-exports
Wrap/Resolve. The specs already matched; only the code changed.Part of M19 (exit-code classification).
Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(transport) Download agent as a raw binary, not a tar.gz - (ec289ad) by @bchatard
goreleaser ships raw binaries (formats: [binary], asset
bifrost_{version}{os}{arch}), but the downloader requested a .tar.gz and
re-prefixed an already-v-prefixed version, so every agent auto-download 404'd
and only --agent-binary worked. downloadURL now targets the raw asset and
strips a leading v; downloadAgent caches the bytes directly (no gzip/tar).Part of M19 (agent binary download). ADR-0011 and spec 07 updated to match.
Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(transport) Shell-quote interpolated values in remote commands - (689e901) by @bchatard
Agent invocation strings interpolated env, app, release name, and the artifact
basename straight into a remote shell via session.Run, unquoted — they broke on
spaces and were injectable from semi-trusted filenames. A new ShellQuote helper
single-quote-escapes each value; it is now applied at every interpolation site in
client_deploy, client_activate, client_list, client_rollback, and staging's rm -rf
and chmod calls. An integration test proves a space/semicolon payload round-trips
literally over a real SSH shell without injecting.Part of M19 (quote remote command arguments).
Co-Authored-By:Claude Fable 5 noreply@anthropic.com
📚 Documentation
-
(tasks) Add M19 hardening and M20 cleanup milestones - (bdd04a4) by @bchatard
Record the findings from the full code/doc review as roadmap tasks. M19
covers the critical agent-download fix, command-injection hardening, agent
integrity verification, CI integration tests, the hook-output protocol, and
exit-code classification. M20 collects the minor cleanups (S1-S10).Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(tasks) Record the container-readiness fix under M19 - (03b248c) by @bchatard
The integration-test CI job (M19) exposed and led to fixing the SSH container
readiness race (commit e837a96). Record it on the roadmap rather than only in
session memory, per the project's roadmap discipline.Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(testing) Require container readiness to gate on a setup marker - (639c94d) by @bchatard
Record the forward-facing rule from the M19 container-readiness fix: SSH
integration containers must signal readiness via a setup-complete marker, not
wait.ForListeningPort (which the Docker port proxy can report open before the
startup script finishes). Complements the inline comment in ssh_container.go.Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
Reconcile specs and rules with shipped behaviour - (1ed87d6) by @bchatard
Fixes from the full review: spec 05 no longer claims interactive hooks are
unsupported in v0 (they prompt/skip); specs/README indexes specs 07 and 08; the
--config default in spec 03 and coding.md now states the real resolution chain;
spec 07's release list/activate/rollback agent invocations match the actual client
commands (--env/--app passed, activate uses --no-confirm); versions.md covers
M11-M19; and the .goreleaser.yml ADR reference is qualified as a forge ADR.Part of M19 (documentation reconciliation). Moving the working-doc artifacts out
of docs/ is deferred pending confirmation.Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
Move M18 working-doc artifacts to .claude/plans - (08d7b6e) by @bchatard
The dated hook-lifecycle plan and design doc were working artifacts cluttering
docs/ (the plan ~2,000 lines, the design doc unindexed in specs/README). Move
them to .claude/plans/ as m18-hook-lifecycle.md and m18-hook-lifecycle-design.md,
matching the existing m0/m2 plan artifacts and the descriptive-naming convention.
The durable links to the design notes (M18 roadmap entry, ADR-0012) are repointed;
docs/ now holds only specs, ADRs, tasks, and the sample config.Completes M19 (documentation reconciliation).
Co-Authored-By:Claude Fable 5 noreply@anthropic.com
🧪 Testing
-
(testutil) Wait for container setup to finish, not just the port - (e837a96) by @bchatard
wait.ForListeningPort('22/tcp') can return before the container's setup script
finishes: Docker's port proxy on Linux binds the mapped port early, so tests ran
container-side setup (e.g. 'chown deploy:deploy') before 'useradd deploy' had run,
failing with exit 1. macOS Docker networking hid this; the M19 CI integration job
exposed it on GitHub. The setup script now touches /tmp/.setup-complete after all
setup (just before exec sshd), and readiness waits on that marker instead — so the
deploy user and keys are guaranteed present before any test runs.Co-Authored-By:Claude Fable 5 noreply@anthropic.com
⚙️ Miscellaneous Tasks
-
Run the integration test suite in CI - (98d8254) by @bchatard
The reusable forge go-ci workflow runs go test ./... without -tags integration,
and the build job only compiled, so the entire testcontainers suite (real deploy,
SSH transport, multi-server) never ran in CI — which is how the broken agent
download shipped. A new integration job runs go test -tags integration ./... on a
Docker-enabled ubuntu runner. Verified locally: 238 tests pass.Part of M19 (run integration tests in CI).
Co-Authored-By:Claude Fable 5 noreply@anthropic.com
Commit Statistics
- 12 commit(s) contributed to the release.
- 1 day(s) passed between the first and last commit.
- 12 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.
v0.20.0
🚀 Features
-
(config) Update config init scaffold for 8-hook lifecycle - (2b7260e) by @bchatard
-
(hooks) Expand hook lifecycle to 8 symmetric pre/post stages - (3f298ae) by @bchatard
Renames pre_enable_release/post_enable_release to pre_activate/post_activate
to match the release activate/rollback verb, and adds pre_extract, post_link,
pre_purge, post_purge for full deploy pipeline coverage. Breaking change: old
hook names are rejected by strict YAML parsing with no alias.
🐛 Bug Fixes
🚜 Refactor
-
(config) Rename ServerConfig to Server - (9357cef) by @bchatard
ServerConfig was the only schema type with a redundant Config suffix
inside the config package; every other entity (Application, Environment,
Paths, Settings) is named bare.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
📚 Documentation
-
(adr) Record hook lifecycle granularity decision (ADR-0012) - (1b9faf7) by @bchatard
-
(claude) Document transport package and fix lint command name - (bdc57e4) by @bchatard
CLAUDE.md's project layout and tech stack were missing internal/transport
(SSH/SFTP agent model from ADR-0009/0011) and the adaouat/forge dependency.
Also fixes hk fix -S golangci-lint to the actual registered step name,
golangci_lint, in CLAUDE.md and workflow.md.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
-
(config) Add annotated sample .bifrost.yml - (3887416) by @bchatard
Documents every field in internal/config/schema.go with comments,
modeled on heraut's docs/heraut.sample.yml. Linked from docs/README.md.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
-
(plans) Record hook lifecycle granularity implementation plan - (fd32c1e) by @bchatard
All 15 tasks and their steps are marked complete, matching the merged
ADR-0012 implementation. -
(schema) Update bifrost.schema.json for 8-hook lifecycle - (685d2fe) by @bchatard
-
(specs) Add hook lifecycle redesign spec - (fa6df86) by @bchatard
Proposes replacing the 4 hook lifecycle points with 8 symmetric
pre/post pairs per deploy stage, renaming pre/post_enable_release to
pre/post_activate to align with the existingrelease activateverb.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
-
(specs) Update spec 02 for 8-hook lifecycle - (19f21ed) by @bchatard
-
(specs) Rewrite spec 05 hook lifecycle table for 8 hooks - (56f0d69) by @bchatard
-
(specs) Update specs 03 and 06 for 8-hook lifecycle - (9d56f37) by @bchatard
-
(tasks) Mark M18 hook lifecycle granularity complete - (5619cf4) by @bchatard
-
Update bifrost.sample.yml for 8-hook lifecycle - (30786d6) by @bchatard
🧪 Testing
-
(cmd) Cover all 8 hook lifecycle points and verify deploy ordering - (1cc766c) by @bchatard
-
(config) Assert old hook key names are rejected by strict YAML - (6711c1d) by @bchatard
Commit Statistics
- 17 commit(s) contributed to the release.
- 1 day(s) passed between the first and last commit.
- 17 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.
v0.19.1
🐛 Bug Fixes
-
(deps) Bump forge to v0.16.0 - (15c818c) by @bchatard
Pulls in forge's whatsnew rendering fixes: dropped glamour's
terminal-querying "auto" style (which fell back to raw markdown when
the terminal didn't answer), added $PAGER support, and fixed a
double-print bug when the pager exits non-zero.
Commit Statistics
- 1 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 1 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.
v0.19.0
🚀 Features
-
(config) Add JSON Schema and wire it into config init - (c96bc6f) by @bchatard
Add bifrost.schema.json (draft-07) describing the full v1 .bifrost.yml:
strategy, servers, paths, settings, variables, hooks, and environments
with applications. additionalProperties is false throughout to mirror the
loader's strict KnownFields decoding.config init now emits a '# yaml-language-server: $schema=' modeline as the
first line so editors with the YAML language server validate against the
schema. Tests cover the modeline and the schema's JSON validity; the schema
was verified against the testdata configs and the generated scaffold.M17:bifrost.schema.json + config init schema modeline. Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
📚 Documentation
-
(roadmap) Mark M17 server-resolution and staging-path tests done - (2baff8b) by @bchatard
Both tasks were already satisfied by tests written during their feature
milestones under the project's TDD rule:- server resolution → internal/config/merge_test.go (M12)
- staging dir path → internal/transport/staging_test.go (M13)
No new tests needed; marking [x] to reflect actual coverage.
Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(specs) Reconcile specs 01-03,07 with shipped implementation - (cc7ecaa) by @bchatard
- 01: current symlink documented as absolute target (matches SetCurrent
and the integration tests) - 02: fix stale hook lifecycle table (post_extract/pre_link replace the
obsolete pre_artifact entry) - 03: rewrite config section as show/check/init subcommands (M5), replace
the removed top-level init with release init, add --agent-binary and a
client-mode pointer to deploy/release commands - 07: document the BIFROST_KNOWN_HOSTS override for host-key verification
Spec 08 reviewed; already accurate.
M17:spec review and update. Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
- 01: current symlink documented as absolute target (matches SetCurrent
🧪 Testing
-
(cmd) Integration test for --agent-binary download bypass - (eee82d5) by @bchatard
Deploy over SSH with --agent-binary set and a deliberately unresolvable
version. If the flag were ignored, deployToServer would fall through to
ResolveAgentBinary and fail trying to download that tag; a successful
deploy proves the supplied binary was used and no download was attempted.M17:integration test for --agent-binary (no download). Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(cmd) Integration test for SSH auth failure exit code - (dba401c) by @bchatard
Deploy against a container offering a valid but unauthorized key (the
host key, absent from authorized_keys) with the agent fallback disabled.
Host verification passes, authentication is rejected, and the resulting
error must be an ExitError with code 3 (Runtime) naming the server.M17:integration test for SSH auth failure. Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(cmd) Integration test for unknown remote arch exit code - (9d31be2) by @bchatard
Replace the container's uname with one reporting Linux/i386 — an arch
absent from mapPlatform's table — and deploy without --agent-binary so
the download path runs platform detection first. The error must be an
ExitError with code 3 (Runtime) naming the server and the rejected arch.A waitForSSHReady probe gates the deploy: wait.ForListeningPort only
proves the port is open, leaving a window where sshd drops the handshake
with EOF, which would otherwise surface as a connect error instead.M17:integration test for unknown remote arch. Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(cmd) Integration test for staging cleanup on agent failure - (a7101b8) by @bchatard
A failing post_extract hook makes the remote agent exit non-zero after
it has created and extracted the release — a mid-deploy failure. The test
asserts the release dir exists (agent reached extraction), the deploy
returns the agent's non-zero exit, and the deferred staging cleanup left
no bifrost-* directory behind under the staging base.M17:integration test for cleanup on mid-deploy failure. Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(config) Cover flat config generator merge precedence - (d92beac) by @bchatard
Add precedence-through-the-generator tests for GenerateFlatConfig:
scalar override (env/app over global), variables precedence, shared
path concatenation across all three levels, and hook priority sorting.
The existing flatgen tests only exercised a single-level scenario.M17:flat config generator unit tests. Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
Commit Statistics
- 8 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 8 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.
v0.18.0
[0.18.0] - 2026-06-10
🚀 Features
-
(whatsnew) Embed CHANGELOG.md as the offline fallback - (8893019) by @bchatard
Adds a root package embedding CHANGELOG.md into a string (the embed must live
at the repo root to reach the file) and passes it to WhatsNewConfig.Changelog,
so whatsnew renders the bundled changelog when GitHub is unreachable and the
cache is cold (forge ADR-0012 tier D).Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
💼 Other
-
(deps) Bump forge to v0.15.0 - (8eeded6) by @bchatard
Brings WhatsNewConfig.Changelog (forge ADR-0012 tier D) for the embedded
changelog offline fallback.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
Commit Statistics
- 2 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 2 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.