feat(deploy): hermes-agent autodeploy unit + timer (DAN-2730) - #189
Merged
Conversation
Companion to hermes-gateway.service: a oneshot systemd unit + timer that fast-forwards a hermes-agent checkout to its tracked branch and restarts the gateway ONLY when the checkout moved. Idempotent and quiet — exits 0 without touching the gateway when already current. The restart deliberately lives in a systemd/launchd path, not hermes cron: the cron lifecycle_guard blocks jobs from restarting the gateway they run under. Parameterized via env (repo dir, branch, restart unit, systemctl scope, optional venv sync + Slack webhook) so one script serves both a system-level (User=hermes) and a rootless user-level deploy. Safety: refuses a dirty tree, fast-forward only (never force past a diverged/force-pushed history), flock against overlapping timer fires, and runs the venv sync only when uv.lock/pyproject/requirements changed. Core paths (no-op / ff+restart / dirty / diverged) verified against a scratch repo with stubbed systemctl. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MW1vwtetBTLSMJcBYp9r1C
dizhaky
marked this pull request as ready for review
August 13, 2026 15:31
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This was referenced Aug 13, 2026
github-actions Bot
pushed a commit
that referenced
this pull request
Aug 17, 2026
Resolves Dependabot alert #189 (GHSA-2v37-7h3g-55p8 / CVE-2026-67213). nanoid before 3.3.18 can loop indefinitely when customAlphabet or customRandom is called with size=0, causing a denial-of-service. nanoid is a transitive dependency via postcss in the website/ Docusaurus sub-project; not directly imported in any source file. Updates both the overrides entry and the lockfile resolution.
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.
What does this PR do?
Adds a systemd autodeploy companion to
hermes-gateway.service: a oneshot unit + timer that fast-forwards a hermes-agent checkout to its tracked branch and restarts the gateway only when the checkout actually moved. Idempotent and quiet — when already current it exits 0 without touching the gateway or emitting an alert.Motivation: merges to
maincurrently don't reach a running gateway until someone manually pulls and restarts (this is exactly what happened deploying #188 to a live host). The restart deliberately lives in a systemd/launchd path, nothermes cron— the cronlifecycle_guardblocks jobs from restarting the gateway they run under.Related Issue
Fixes DAN-2730.
Type of Change
Changes Made
deploy/hermes-agent-autodeploy.sh— the deploy script. Parameterized via env (HERMES_REPO_DIR,HERMES_BRANCH,HERMES_RESTART_UNIT,HERMES_SYSTEMCTL_ARGS, optionalHERMES_VENV_SYNC,SLACK_WEBHOOK_URL,HERMES_ALERT_LABEL) so one script serves both a system-level (User=hermes) and a rootlesssystemctl --userdeploy.deploy/hermes-agent-autodeploy.service—Type=oneshot;StartLimit*correctly in[Unit]; hardening mirrorshermes-gateway.service; install docs for both system- and user-level in the header.deploy/hermes-agent-autodeploy.timer—OnBootSec=5min,OnUnitActiveSec=15min,Persistent=true,RandomizedDelaySec=90.Safety properties: refuses a dirty working tree; fast-forward only (never advances past a diverged/force-pushed history — surfaces for manual resolution);
flockagainst overlapping timer fires; runs the venv sync only whenuv.lock/pyproject.toml/requirements.txtchanged across the fast-forward; a failed venv sync aborts before the restart so a half-updated gateway never starts. Alerts post one line to Slack whenSLACK_WEBHOOK_URLis set and always mirror to the journal; alert failures never abort the deploy result.How to Test
Verified the four control-flow paths against a scratch git repo with a stubbed
systemctl:Also
bash -nclean;systemd-analyze verifypasses except for the expected "ExecStart not present" on a host where the script isn't installed to/usr/local/bin.Checklist
Code
feat(deploy): ...)Documentation & Housekeeping
cli-config.yaml.example— N/A (no config keys)AGENTS.md— N/A (deploy artifact, no core/agent behavior change)🤖 Generated with Claude Code
https://claude.ai/code/session_01MW1vwtetBTLSMJcBYp9r1C
Generated by Claude Code