Skip to content

Add codavox deploy: the Code Manager deploy verb for OpenVox#11

Merged
miharp merged 1 commit into
mainfrom
feat/deploy-command
Jul 24, 2026
Merged

Add codavox deploy: the Code Manager deploy verb for OpenVox#11
miharp merged 1 commit into
mainfrom
feat/deploy-command

Conversation

@miharp

@miharp miharp commented Jul 24, 2026

Copy link
Copy Markdown
Owner

The one command ex-PE customers reach for is puppet-code deploy. codavox already had the whole distribution engine — staging, seal, pull, code_id, atomic swap — but no deploy verb: you ran r10k yourself, then signaled the publisher. This adds the familiar one-command flow.

codavox deploy

$ codavox deploy production --wait --staging /etc/puppetlabs/code-staging
production    deployed    a3f1c9e4b2d8    (commit 5f2e9c1)    serving

Runs r10k deploy environment <env>… --puppetfile into staging, seals each tree to report its code_id and the resolved control-repo commit, and signals the running publisher (SIGHUP via its pidfile) to reseal. --wait blocks until the publisher has materialized the new artifact — the same primary-side "deploy is live" completion Code Manager's --wait gives. r10k is discovered on PATH, then /opt/puppetlabs/puppet/bin/r10k, overridable with --r10k. --all, --no-modules, --json round it out.

Preserves the load-bearing invariant

Running r10k here does not re-resolve per compiler: r10k runs once, centrally, producing one resolved tree every compiler converges onto — exactly how Code Manager runs r10k once and distributes the result. The publisher stays a pure distributor with no control-repo credentials, a deliberate divergence from PE that keeps its trust boundary small.

Built as the seam, not a one-off

The orchestration lives in internal/deploy, not inline in the CLI, because the next front doors — a webhook receiver and a deploy API, so a control-repo push or CI job deploys like puppet-code — must funnel through one deploy path rather than reimplementing r10k invocation and the reseal trigger. The publisher now writes a pidfile (<state>/publish.pid) so the deploy can find and signal it.

Reseal trigger: SIGHUP via pidfile

deploy runs on the primary next to the publisher, so it signals locally — no new authenticated endpoint, no client cert. --wait is then a filesystem check for the materialized artifact. No publisher running: deploy still stages and reports code_ids but warns nothing serves them yet; --wait in that case is an error. (An HTTP trigger earns its keep only for off-box deploys, i.e. the webhook/API phase.)

Tests

  • internal/deploy against a fake r10k: reported code_id equals an independent seal, commit captured, --all lists staged envs, r10k non-zero surfaces as an error, missing/malformed pidfile rejected, explicit-missing-r10k rejected.
  • End-to-end (internal/agent): codavox deploy --wait against a live publisher signals it, blocks until serving, and a compiler then converges onto the new content.

Docs

New deploying.md; commands.md and README updated — the README gains a quickstart framed for Code Manager users (codavox deploy productionpuppet-code deploy production).

Verified: go test -race ./..., golangci-lint 0 issues, gofmt/vet clean, markdownlint 0 issues.

🤖 Generated with Claude Code

Ex-PE customers moving to OpenVox lose Code Manager, whose daily surface is one
command: puppet-code deploy. codavox had the whole distribution engine —
staging, seal, pull, code_id, atomic swap — but no deploy verb; you ran r10k
yourself and signaled the publisher. This adds the familiar one-command flow.

codavox deploy <env> | --all [--wait] runs r10k into staging, seals each tree
to report its code_id and the resolved commit, and signals the running
publisher (SIGHUP via its pidfile) to reseal. --wait blocks until the publisher
has materialized the new artifact, i.e. is serving it — the same primary-side
completion Code Manager's --wait gives. r10k is discovered on PATH, then the
OpenVox package path, overridable with --r10k.

This does not weaken the load-bearing invariant that codavox never re-resolves
per compiler: r10k runs once, centrally, producing one resolved tree every
compiler converges onto — exactly how Code Manager runs r10k once and
distributes the result. The publisher stays a pure distributor with no
control-repo credentials, a deliberate divergence from PE keeping its trust
boundary small.

The orchestration lives in internal/deploy, not inline in the CLI, because the
next front doors — a webhook receiver and a deploy API, so a control-repo push
or CI job deploys like puppet-code — must funnel through one deploy path rather
than reimplementing r10k invocation and the reseal trigger. The publisher now
writes a pidfile so the deploy can find and signal it.

Tests: internal/deploy against a fake r10k (code_id matches an independent
seal, commit captured, --all lists staged envs, r10k non-zero surfaces as an
error, pidfile missing/malformed rejected); and an end-to-end run where
codavox deploy --wait against a live publisher signals it, blocks until
serving, and a compiler then converges. README gains a quickstart framed for
Code Manager users.

Signed-off-by: Michael Harp <mike@mikeharp.com>
@miharp
miharp merged commit ad2e80f into main Jul 24, 2026
7 checks passed
@miharp
miharp deleted the feat/deploy-command branch July 24, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant