guide · computers

Agents and the Deploy Gate: When They Push

How an agent runs the ABS deploy playbook end-to-end: three-SHA check, regression gate, rsync to webroot, CF cache purge, commit, github push, ship-ready for operator review.

July 14, 2026 · By Alastair Fraser

A friendly retro robot standing beside a 7-station assembly line where each station is labeled 3-SHA, BUILD, REGRESSION, RSYNC, PURGE, COMMIT, and SHIP-READY, with a small human figure sitting at a desk reviewing a clipboard at the SHIP-READY station while the robot points at them.

The deploy playbook in one sentence

The agent runs the same deploy chain the operator runs by hand: three-SHA check, build, regression suite, rsync to webroot, CF cache purge, commit, github push. Each step has a single failure mode the agent must surface.

When the agent runs the deploy itself (rather than handing it off), it gets the work done in 5-7 minutes without the operator sitting at the keyboard. The discipline is the same — the failure surfaces are the same.

Step 1: the three-SHA check

Before ANY deploy action:

LOCAL=$(git rev-parse HEAD)
ORIGN=$(git ls-remote origin refs/heads/main | cut -f1)
GITHUB=$(git ls-remote github refs/heads/main | cut -f1)
[ "$LOCAL" = "$ORIGN" ] && [ "$ORIGN" = "$GITHUB" ] && echo "OK" || { echo "MISMATCH"; exit 1; }

If the assertion fails, the deploy chain hard-fails. Don’t proceed.

The failure shapes:

  • local < origin — pull —ff-only.
  • local < github — push origin main.
  • origin < github — push origin main from a fresh local.
  • all distinct — investigate, reconcile, treat as a hard fail.

The agent runs this check at the start of every deploy. If it fails, the agent surfaces the mismatch to the operator.

Step 2: the build

cd /srv/abs-site
npm run build 2>&1 | tail -10

The build exits 0 on success. A non-zero exit is a hard fail. The agent captures the build log, surfaces the error pattern if any, and pauses.

Two persistent checkers in the build output:

  • InvalidContentEntryDataError — a guide frontmatter schema error. The agent re-reads the offending file, fixes, and rebuilds.
  • affiliate-link-tag — the link-rewrite pass. The agent confirms the count matches expectations; if the count drifted, the agent investigates.

Step 3: the regression suite

/opt/hermes/.venv/bin/python /opt/data/scripts/run_regression_suite.py

The regression suite runs “8” scripts; “7” are green today (“1” is paused due to a known issue). The agent surfaces the green/red tally, surfaces any new reds, and pauses on any new reds.

The agent doesn’t run the regression suite from a forked process; it inherits the operator’s environment. If the suite fails, the agent returns to fixing rather than proceeding to rsync.

Step 4: rsync to webroot

rsync -a --delete /srv/abs-site/dist/ /var/www/agenticbotsitter/

The --delete flag is what makes this a deploy, not a copy. The agent captures the rsync summary (files copied, files removed) and surfaces if the file count is way off (a sign of accidental deletion).

For sites that are not /var/www/agenticbotsitter/, the path is operator-specific. The agent should never rsync to a path the operator hasn’t approved.

Step 5: CF cache purge

CF_TOKEN="$CF_API_TOKEN" ZONE="$CF_ZONE_ID" \
/opt/hermes/.venv/bin/python /opt/data/scripts/refresh_abs_from_matrix.sh

The agent purges “12” URLs: the new guide, the new image, the new WebP, the relevant indexes, the homepage, the sitemap, the RSS, the bundle, the redirect rules, the CNAME, and the brand-new asset bundle if any.

The agent surfaces the purge confirmation per URL. A failed purge is not fatal (CF will re-serve stale-but-still-correct HTML), but a failed purge of a new URL means the new asset won’t show up — that’s a real problem.

Step 6: commit + push

git commit -m "post(guides): <slug1> <slug2> <slug3> (N cumulative today)" \
           -m "<commit body with operator-readable form per agent-discipline>"
git push origin main
git push github main

The agent runs the commit with the operator-readable form. Force-pushes are NEVER used unless the operator explicitly requests them after seeing the situation.

The agent confirms both pushes completed by checking git ls-remote post-push. If github is missing, the agent re-tries once; a second failure is a surface to the operator.

Step 7: the ship-ready moment

After all six steps complete, the agent surfaces:

SHIP-READY: <commit-sha>
local:    <local>  (matches)
origin:   <origin> (matches)
github:   <github> (matches)
dist:     <new guide count> guides built
live:     <new guide URL> HTTP 200
regression: 7/8 green

The operator reviews the ship-ready and either confirms (“shipped, next batch”) or redirects (“hold, fix X”). The agent never proceeds past this point without an explicit operator decision on irreversible work.

What the agent does NOT do during a deploy

  1. The agent doesn’t edit /var/www/agenticbotsitter/ directly. Always rsync from dist/.
  2. The agent doesn’t bypass the regression suite. Even when the change is small.
  3. The agent doesn’t force-push to GitHub without operator confirmation.
  4. The agent doesn’t run two deploys in parallel. Sequential is the rule.

What not to do

  • Don’t rsync with a misconfigured --delete. Test the rsync on a stale dest first if unsure.
  • Don’t push without testing the live URL. A force-push to GitHub is auditable; a force-rsync to webroot is not.
  • Don’t skip the ship-ready moment. The operator’s review is part of the loop.
  • Don’t deploy during peak traffic without first coordinating with the operator.

Verification checklist

#CheckWhen
”1”three-SHA matchBefore any deploy action
”2”Build exits 0After npm run build
”3”Regression suite stateBefore rsync
”4”Rsync summaryAfter rsync
”5”CF purge “12” URLsAfter rsync
”6”Commit + “2” pushesAfter purge
”7”Ship-ready surfaceOperator decision

Sources

Last verified: 2026-07-14 against Hermes v0.18.2 (2026.7.7.2). Live deploy chain verified against ABS webroot at /var/www/agenticbotsitter/.

Sources

#agent#deploy#gate#three-sha#rsync

Submit a take

Have a different read on this? Drop a comment below — your email isn't published, and I read every one. Nothing leaves the site until I approve it.

Your email address will not be published. Required fields are marked.