fix(update): fork updates that pull upstream code now run the full post-update path (#73108, salvage #73679) - #92769
Merged
Merged
Conversation
On a fork, `hermes update` compares HEAD against origin/main, and only then syncs the fork from upstream — inside the `commit_count == 0` branch, which returns immediately afterwards. So an update that pulls hundreds of commits from upstream prints "Already up to date!" and skips everything the post-update path does, including the dependency sync and the gateway restart. Observed on a fork-based deployment: 1654 commits pulled, "Already up to date!", and the launchd gateway left running. It then held pre-update modules in memory while lazily importing post-update ones, and failed later with an AttributeError for a method that plainly exists on disk — a mixed runtime that looks nothing like an update problem. Correlating every run in update.log, a restart happened on exactly the runs that pulled upstream *without* also claiming to be up to date, and never once they started co-occurring. Decide before the branch: capture HEAD, sync, and if HEAD moved, set commit_count from the range so the normal post-update path runs. The pull that follows is a no-op (the sync updates origin too); reaching the restart is the point. commit_count is floored at 1 — HEAD moving *is* the update, so a failed or zero count query must not send us back down the early return. steps still being skipped afterwards. Refs #73108
… the reload proof point The salvaged test drove the FULL post-update pipeline against the real dev box: real fleet probes read live gateways as STALE (exit 1) and the restart phase tripped the live-system guard on a real gateway PID. Pin empty fleet/gateway discovery and make _reload_updated_runtime_modules (the proof the post-update path ran — the bug returned before it) abort the pipeline. Sabotage-verified: disabling the hoisted sync fails the test.
Collaborator
Author
|
Live E2E (zero mocks) added to the validation record: built a real fork topology in /tmp — bare upstream 3 commits ahead, bare origin in sync with local, local checkout with both remotes. Confirmed the trigger state ( |
This was referenced Aug 23, 2026
This was referenced Aug 23, 2026
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
A fork's
hermes updatethat pulls hundreds of upstream commits no longer prints "Already up to date!" and skips everything — the upstream sync now runs BEFORE the no-update decision, so a HEAD-moving sync flows through the full post-update path: dependency sync, gateway restart, and the fleet version matrix (#73108's remaining leg; salvage of #73679 by @francip).Root cause:
_sync_with_upstream_if_neededlived INSIDE thecommit_count == 0branch, which returns immediately after — an update that pulled real code verified nothing (and on fork installs, bypassed the Phase-1 fleet matrix entirely).Changes
hermes_cli/update_cmd.py(@francip): hoist the fork sync above the no-update decision; if HEAD moved across the sync, setcommit_countfrom the moved range (min 1) so the normal update path runs. Reconciled with the shallow-repo commit-count block and the parked-branch stash handling that landed since his branch.tests/hermes_cli/test_cmd_update.py(@francip + ours): his regression test, hardened for host isolation — pinned fleet/gateway discovery (real dev-box gateways read STALE / trip the live-system guard) and the pipeline aborts at_reload_updated_runtime_modules, the exact proof point the bug never reached.Validation
test_cmd_update.pyCloses the fork leg of #73108; part of the Phase-1 completion pass on #91277 (the matrix now runs on fork updates too).
Infographic