Repository navigation
fix: stop the Git workflow getting stuck after a push or page reload - #37
Conversation
After Stack Manager pushed a commit, its private retained ref stayed on that commit. Once anyone else pushed on top of it, every later commit reported "remote changed" forever, and fetching could not clear it. A retained head that the remote already contains is published work, so the branch state now continues from the fetched head when that is newer, exactly as it does when no commit was ever retained. Unpushed retained commits keep blocking as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018E16JisaGNSCUUfrJpDmuZ
📝 WalkthroughWalkthroughGitMutations now checks commit ancestry when selecting a local head after fetching. The UI retains commit details when the local branch is ahead of the remote. Tests cover remote advancement, repository sync, a subsequent commit, and a successful push. ChangesRemote advancement handling
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to The changed workflow blocks a commit until the advanced remote is synced, then allows committing on top of it. No actionable merge-blocking risk remains. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The recovery change preserves the existing authorization and push safeguards. No new publishing bypass was identified in the reviewed flow, but broader security coverage and recovery after abrupt process interruption remain unverified. Retained concerns Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
The Push button for a kept local commit lived only in page state, so a reload or a visit to another tab lost it. Committing the same drafts again then failed as outdated (they are already in that commit), leaving no way to push from the UI. Workflow responses already carry the branch state. When it shows unpushed local commits and the remote has not moved, the Changes tab now offers Push for the local head again; the server still re-checks the retained commit and remote head before pushing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018E16JisaGNSCUUfrJpDmuZ
There was a problem hiding this comment.
🔇 Additional comments (1)
tests/e2e/changes-commit.spec.ts (1)
319-320: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.Route cleanup is skipped when an assertion fails.
page.unrouteruns only if every earlier assertion passes. Playwright creates a newpagefor each test, so a failure here does not leak routes into other tests. The cleanup is therefore redundant. Remove bothunroutecalls, or wrap the body intry/finallyif you keep them.
ℹ️ Review info
⚙️ Run configuration
- Configuration used: defaults
- Review profile: CHILL
- Plan: Advanced
- Run ID:
33c7d6cd-03e1-4e12-a97b-c400371b1608
📒 Files selected for processing (2)
src/ui/source/changes-view.tsxtests/e2e/changes-commit.spec.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.
Two dead ends found while preparing v0.5.0. In both, Stack Manager could no longer commit or push without someone getting into the container to fix it. Each is a separate commit with its own regression test.
1. Commits blocked forever after a pushed commit is built on elsewhere
After Stack Manager pushed a commit, the private retained ref (
refs/stack-manager/heads/<branch>) stayed on that commit. As soon as anyone else pushed on top of it (for example from a laptop), every later commit returnedremote_changed, and fetching could not clear it.Fix (
GitMutations.fetchState): a retained head that the remote already contains counts as published work. When the last fetched remote-tracking head is newer than that published head, the branch state continues from the fetched head. This is the same behaviour as when no commit was ever retained.ahead 0, behind 0).Test:
continues committing after a pushed commit is built upon elsewhere(integration, real Git server). It fails onmainwithexpected 'remote_changed' to be 'commit_succeeded'.2. A kept local commit could not be pushed after leaving the Changes tab
The Push button for a kept commit (after Commit, or after a failed push) lived only in React state. A reload or a visit to History lost it. Committing the same drafts again then failed with
draft_outdated, because they're already in that commit. So there was no way to push from the UI.Fix (
ChangesView.applyResult): workflow responses already include the branch state. When a commit attempt reports unpushed local commits (ahead > 0) and the remote hasn't moved (behind 0), the tab offers Push for the local head again. The server still re-checks the exact retained commit and remote head before pushing.Test: e2e
an unpushed commit from an earlier visit can still be pushed(mocked workflow responses; checks the push request body).Validation
pnpm check: format, lint, typecheck, 26 files / 348 tests pass.pnpm buildpasses.pnpm test:e2ewithE2E_GIT_REMOTE=https://github.com/docker/awesome-compose.git E2E_STACK_ROOT=nginx-golang: 33 passed, 9 skipped (mobile-only skips).User-facing docs for these behaviours are in the separate
docs: prepare v0.5.0 Git workflow releasePR. Please merge this PR first.🤖 Generated with Claude Code
https://claude.ai/code/session_018E16JisaGNSCUUfrJpDmuZ
Summary by CodeRabbit