Skip to content

fix: make aidevops update resilient — recover from stuck versions (#2288)#2289

Merged
marcusquinn merged 1 commit intomainfrom
bugfix/fix-update-version-stuck
Feb 25, 2026
Merged

fix: make aidevops update resilient — recover from stuck versions (#2288)#2289
marcusquinn merged 1 commit intomainfrom
bugfix/fix-update-version-stuck

Conversation

@marcusquinn
Copy link
Copy Markdown
Owner

Summary

Fixes #2288aidevops update stuck on old version (e.g. 2.125 while 2.128.3 is available).

Root Cause

cmd_update() uses git pull --ff-only origin main which fails permanently when:

  1. Dirty working tree — pre-PR#2287 versions of set_permissions() and update_scan_results_log() modified tracked files in the git repo, dirtying the working tree. --ff-only refuses to pull over dirty files.
  2. Chicken-and-egg — the fix for dirty trees (PR fix: prevent aidevops update from dirtying git working tree #2287) is in the newer version the user can't pull, so they're stuck forever.
  3. Diverged history / detached HEAD — if the local branch diverged or HEAD is detached, --ff-only fails with no recovery path.

The old code returned an error on --ff-only failure, leaving the user permanently stuck.

Fix (3 parts)

  1. Branch guard: Ensure local repo is on main before pulling (handles detached HEAD from tag checkouts or interrupted operations)
  2. Staged change cleanup: Extend PR fix: prevent aidevops update from dirtying git working tree #2287's cleanup to also handle staged changes (git diff --cached) not just unstaged
  3. Hard reset fallback: When --ff-only fails, fall back to git reset --hard origin/main instead of returning an error — the install repo at ~/Git/aidevops should always mirror origin/main exactly (matches setup.sh bootstrap behavior at line 401-405)

Also adds --tags to git fetch for version tag consistency.

Testing

  • All 629 tests pass (496 passed, 133 skipped, 0 failed) via test-smoke-help.sh
  • ShellCheck: zero violations
  • Bash syntax check: passes bash -n

Edge Cases Handled

Scenario Before After
Dirty working tree (unstaged) --ff-only fails, stuck Cleaned before pull
Dirty working tree (staged) --ff-only fails, stuck Unstaged + cleaned before pull
Diverged local history --ff-only fails, error returned Falls back to reset --hard origin/main
Detached HEAD git pull fails (no branch) Switches to main first
git rev-list fails after reset Crash under set -e Fallback to echo "0"

… detached HEAD

Fixes #2288 — aidevops update stuck on old version (e.g. 2.125 while 2.128.3 available).

Root cause: git pull --ff-only fails when the working tree is dirty or local
history has diverged, with no recovery path. Users on pre-PR#2287 versions
could not get the dirty-tree fix because the fix itself required a successful pull.

Three changes:
1. Ensure local repo is on main branch before pulling (handles detached HEAD)
2. Clean both staged and unstaged changes before pull (extends PR #2287 fix)
3. Fall back to git reset --hard origin/main when --ff-only fails, instead of
   returning an error — the install repo should always mirror origin/main exactly
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 25, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 13 minutes and 4 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between fa24d01 and 5d5e36d.

📒 Files selected for processing (1)
  • aidevops.sh
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/fix-update-version-stuck

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the resilience of the 'aidevops update' command by addressing common scenarios that could cause it to get stuck. It ensures that the update process can reliably recover from issues like dirty working trees, detached HEADs, or diverged local history, allowing users to consistently update to the latest version. The changes implement a more robust Git update mechanism, including proactive branch management, comprehensive cleanup of local changes, and a hard reset fallback, to maintain a clean and up-to-date local repository.

Highlights

  • Branch Guard: Added logic to ensure the local repository is on the 'main' branch before attempting an update, handling detached HEAD states and stale branches.
  • Staged Change Cleanup: Enhanced the working tree cleanup process to include both unstaged and staged changes, preventing 'git pull --ff-only' from being blocked by them.
  • Hard Reset Fallback: Implemented a fallback mechanism where if 'git pull --ff-only' fails, the repository is reset hard to 'origin/main', ensuring the local state always mirrors the remote.
  • Tag Fetching: Modified 'git fetch' to include '--tags', improving version consistency by fetching all tags from the remote.
  • Robust Commit Counting: Added error handling to 'git rev-list --count' to prevent script crashes if the command fails to determine commit differences.
Changelog
  • aidevops.sh
    • Introduced a check and automatic switch to the 'main' branch to handle detached HEAD scenarios and ensure proper pulling.
    • Expanded the working tree cleanup to include both unstaged and staged changes using 'git reset HEAD -- .' and 'git checkout -- .'.
    • Updated 'git fetch' to include the '--tags' option for better version tracking and consistency.
    • Implemented a fallback mechanism to 'git reset --hard origin/main' if 'git pull --ff-only' fails, making the update process more robust.
    • Added error handling to the 'git rev-list --count' command to prevent failures when determining commit differences.
    • Refactored the execution of 'setup.sh' and the final working tree cleanup to occur consistently after any update attempt, regardless of the Git pull outcome.
Activity
  • No specific activity (comments, reviews, etc.) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 71 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Wed Feb 25 15:41:52 UTC 2026: Code review monitoring started
Wed Feb 25 15:41:52 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 71

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 71
  • VULNERABILITIES: 0

Generated on: Wed Feb 25 15:41:54 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request significantly improves the resilience of the aidevops update command by handling cases where git pull --ff-only would previously fail, such as a dirty working tree or diverged history. The introduction of a branch guard, cleanup for staged files, and a git reset --hard fallback are excellent enhancements. My review focuses on a recurring pattern of suppressing stderr on git commands, which can hide important debugging information. All suggested changes align with the repository's rules, advocating for the removal of 2>/dev/null in favor of more targeted suppression (like --quiet) or allowing stderr to be visible, especially when || true or similar constructs are used to handle command failures gracefully.

current_branch=$(git branch --show-current 2>/dev/null || echo "")
if [[ "$current_branch" != "main" ]]; then
print_info "Switching to main branch..."
git checkout main --quiet 2>/dev/null || git checkout -b main origin/main --quiet 2>/dev/null || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Suppressing stderr with 2>/dev/null can hide important error messages if this command fails for reasons other than the branch not existing (e.g., repository corruption, permissions issues). The --quiet flag already handles standard output. It's better to let stderr be visible for debugging, especially since the || chain is designed to handle failures.

Suggested change
git checkout main --quiet 2>/dev/null || git checkout -b main origin/main --quiet 2>/dev/null || true
git checkout main --quiet || git checkout -b main origin/main --quiet || true
References
  1. When using git commands (like 'init', 'remote') in shell scripts, use the '-q' flag to suppress standard output instead of '2>/dev/null', ensuring that error messages on stderr remain visible for debugging.

# Handles both staged and unstaged changes.
# See: https://github.com/marcusquinn/aidevops/issues/2286
if ! git diff --quiet 2>/dev/null; then
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The git diff --quiet command should not produce output on stderr during normal operation. Suppressing stderr with 2>/dev/null is likely redundant and could mask underlying system errors or problems with the git installation. It's safer to remove the redirection to ensure all potential errors are visible for debugging.

Suggested change
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
if ! git diff --quiet || ! git diff --cached --quiet; then
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

if ! git diff --quiet 2>/dev/null; then
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
print_info "Cleaning up stale working tree changes..."
git reset HEAD -- . 2>/dev/null || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Suppressing stderr with 2>/dev/null can hide important error messages if git reset fails for unexpected reasons (e.g., file permissions, repository corruption). Since you're using || true to prevent script exit, it's better to allow error messages to be printed for easier debugging.

Suggested change
git reset HEAD -- . 2>/dev/null || true
git reset HEAD -- . || true
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
print_info "Cleaning up stale working tree changes..."
git reset HEAD -- . 2>/dev/null || true
git checkout -- . 2>/dev/null || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Suppressing stderr with 2>/dev/null can hide important error messages if git checkout fails for unexpected reasons (e.g., file permissions, repository corruption). Since you're using || true to prevent script exit, it's better to allow error messages to be printed for easier debugging.

Suggested change
git checkout -- . 2>/dev/null || true
git checkout -- . || true
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

# by aidevops and should always track origin/main exactly.
# See: https://github.com/marcusquinn/aidevops/issues/2288
print_warning "Fast-forward pull failed — resetting to origin/main..."
git reset --hard origin/main --quiet 2>/dev/null || {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This git reset --hard is a critical recovery step. Suppressing stderr with 2>/dev/null hides the reason for failure if the reset doesn't work, making it difficult to diagnose the problem. The error handling block will be more informative if the original error from git is visible.

Suggested change
git reset --hard origin/main --quiet 2>/dev/null || {
git reset --hard origin/main --quiet || {
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

# Print bounded summary of meaningful changes
if [[ "$old_hash" != "$new_hash" ]]; then
local total_commits
total_commits=$(git rev-list --count "$old_hash..$new_hash" 2>/dev/null || echo "0")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While the || echo "0" correctly prevents the script from exiting if git rev-list fails, suppressing stderr with 2>/dev/null hides the actual error message. This makes it harder to debug issues that aren't just an invalid commit range (e.g., a problem with git itself). It's better to let the error be visible.

Suggested change
total_commits=$(git rev-list --count "$old_hash..$new_hash" 2>/dev/null || echo "0")
total_commits=$(git rev-list --count "$old_hash..$new_hash" || echo "0")
References
  1. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.

# Safety net: discard any working tree changes setup.sh may have introduced
# (e.g. chmod on tracked scripts, scan results written to repo)
# See: https://github.com/marcusquinn/aidevops/issues/2286
git checkout -- . 2>/dev/null || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Suppressing stderr with 2>/dev/null on this final cleanup step can hide errors related to file permissions or other issues that might prevent git checkout from succeeding. Since || true is used to prevent script exit, allowing errors to be displayed would be more informative for debugging.

Suggested change
git checkout -- . 2>/dev/null || true
git checkout -- . || true
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

@augmentcode
Copy link
Copy Markdown

augmentcode bot commented Feb 25, 2026

🤖 Augment PR Summary

Summary: Improves aidevops update resilience when the local install repo can’t fast-forward to the latest origin/main (fixes #2288).

Key changes:

• Ensures the repo is on main before updating (handles detached HEAD / stale branches).

• Cleans both staged and unstaged working-tree changes prior to pulling.

• Fetches origin/main with --tags for version/tag consistency.

• If git pull --ff-only fails, falls back to git reset --hard origin/main and continues with setup.sh.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

current_branch=$(git branch --show-current 2>/dev/null || echo "")
if [[ "$current_branch" != "main" ]]; then
print_info "Switching to main branch..."
git checkout main --quiet 2>/dev/null || git checkout -b main origin/main --quiet 2>/dev/null || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git checkout ... || ... || true masks branch-switch failures, so cmd_update() may continue in a detached/incorrect branch state without any signal. Consider verifying that the checkout actually succeeded (or at least warning) so updates don’t silently rely on the later reset path.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

# Handles both staged and unstaged changes.
# See: https://github.com/marcusquinn/aidevops/issues/2286
if ! git diff --quiet 2>/dev/null; then
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cleanup detects staged/unstaged diffs, but it won’t catch untracked files that can still block git pull/git reset (e.g., “untracked working tree file would be overwritten”). If the goal is to fully “unstick” updates, it may be worth accounting for that class of failure too.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

# by aidevops and should always track origin/main exactly.
# See: https://github.com/marcusquinn/aidevops/issues/2288
print_warning "Fast-forward pull failed — resetting to origin/main..."
git reset --hard origin/main --quiet 2>/dev/null || {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because git reset --hard origin/main redirects stderr to /dev/null, the user won’t see the underlying reason when it fails (often the key clue for remediation). Surfacing the git error output in the failure path would make troubleshooting much easier.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@marcusquinn marcusquinn merged commit f1b2cb8 into main Feb 25, 2026
31 checks passed
@marcusquinn marcusquinn deleted the bugfix/fix-update-version-stuck branch March 3, 2026 03:23
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.

aidevops update not pulling latest version - stuck on 2.125 while 2.128.3 available

1 participant