feat: write a release manifest, stop apps removed from the desired set - #154
Merged
Conversation
Every release now gets a manifest.json at its root: schema_version, release timestamp, resolved app_refs/env_refs (the actual tag resolve.py pulled, never @latest), and the desired apps list. No secrets, no target identifier - whoever's reading it already knows which host they're on. resolve.download_ref now returns (path, resolved_ref) instead of just path, so build_release/resolve_app_envs can capture what was actually resolved, not just what was requested. deploy_to_host reads the previous release's manifest.json off current before switching it, diffs its apps against the new desired set, and docker compose downs anything no longer wanted - using current's own path so that app's last-known compose file/.env are still there. This works even though the new release's own tree also still contains that app's compose file (build_release always copies the whole catalog, not just a target's desired subset) - using the old release avoids depending on that incidentally, and keeps the stop grounded in the last environment that app actually ran with. release_name moves from being generated once per host inside deploy_to_host to once per deploy in main() - keeps a multi-host target's manifest.json identical across every host of the same logical deploy, and deploy_to_host takes it as a parameter now. Closes #109 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This was referenced Aug 24, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements #109. Design was worked out in the issue's comment thread first (final manifest shape landed on there, deliberately smaller than the original proposal - no
targetfield,releasestays a timestamp not a semver tag, ref entries are resolved not requested).manifest.jsonat its root:schema_version,releasetimestamp, resolvedapp_refs/env_refs(the actual tag pulled, never@latest), and the sortedappslist. No secrets.resolve.download_refnow returns(path, resolved_ref)instead of justpath, so callers can capture what was actually resolved.deploy_to_hostreads the previous release'smanifest.jsonoffcurrentbefore switching it, diffs against the new desired app set, anddocker compose downs anything no longer wanted - using the oldcurrentpath (last-known compose file/.envstill intact there) rather than depending on the new release tree also happening to still contain that app's files (which it does, sincebuild_releasecopies the whole catalog every time, but the old path is the more directly-correct source for "stop what was actually running").release_namemoved from per-host (generated fresh insidedeploy_to_hostfor every host in a multi-host target) to once per deploy inmain(), so a multi-host target's manifest is identical across all its hosts for the same logical deploy.Test plan
deploy/tests/+encrypt-env/tests/+load-yaml-matrix/tests/(70 tests, new manifest/orphan-stop tests added) passmanifest.jsonand (once an app is actually removed from a target) correctly stops it