Bump version, and ensure new versions always released#3
Conversation
WalkthroughAdds a CI version-bump gate for PRs against main, bumps project version to 0.3.1, extends branch validation to attempt a shallow fetch of remote refs in CI, and adds tests to simulate git fetch/cat-file behavior and verify shallow-fetch logic. Changes
Sequence Diagram(s)sequenceDiagram
participant PR as "Pull Request (runner)"
participant CI as "CI job"
participant Local as "Local repo (workspace)"
participant Remote as "origin (remote)"
PR->>CI: trigger pull_request workflow
CI->>Local: read PR's pyproject.toml version
CI->>Remote: fetch main's pyproject.toml (from main branch)
CI-->>CI: compare versions
alt PR version == main version or missing
CI->>PR: emit error/warning and fail workflow
else PR version > main version
CI->>Local: proceed to tests
Local->>CI: run validate_branch
alt branch ref not present locally (e.g., origin/...)
CI->>Remote: git fetch --depth=1 <remote> <ref>
Remote-->>CI: fetch success/failure
alt fetch success
CI->>Local: recheck ref (git cat-file)
Local-->>CI: ref exists -> continue
else fetch failure
CI->>PR: print error and fail
end
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@squawk_alembic/hook.py`:
- Around line 158-165: The fetch call using subprocess.run(["git", "fetch",
"origin", remote_branch, "--depth=1"]) can succeed in CI shallow clones yet not
create refs/remotes/origin/<branch>; update the fetch invocation (the
subprocess.run call where remote_branch is used in hook.py) to use an explicit
refspec such as "refs/heads/{remote_branch}:refs/remotes/origin/{remote_branch}"
(or prefixed with + if forcing) as the fetch argument so the remote-tracking
branch is written locally while keeping --depth=1; keep the existing return
logic but ensure the subprocess.run args include that refspec string instead of
just remote_branch.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
squawk_alembic/hook.pytests/test_main.py
| if branch.startswith("origin/"): | ||
| remote_branch = branch.removeprefix("origin/") | ||
| fetch = subprocess.run( | ||
| ["git", "fetch", "origin", remote_branch, "--depth=1"], | ||
| capture_output=True, | ||
| ) | ||
| return False | ||
| return True | ||
| if fetch.returncode == 0: | ||
| return True |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify git fetch behavior with and without explicit refspec
# Test in a temporary directory to check if origin/<branch> is created
echo "Testing git fetch behavior..."
# Create a bare repo to act as remote
mkdir -p /tmp/test_remote
cd /tmp/test_remote
git init --bare
# Create a local repo and push a commit
mkdir -p /tmp/test_local
cd /tmp/test_local
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
echo "test" > file.txt
git add file.txt
git commit -m "initial"
git push origin main
# Create a shallow clone to simulate CI
mkdir -p /tmp/test_shallow
cd /tmp/test_shallow
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
# Test: fetch without explicit refspec
git fetch origin main --depth=1
echo "After 'git fetch origin main --depth=1':"
git rev-parse --verify origin/main 2>&1 || echo "origin/main NOT created"
# Also test with explicit refspec for comparison
rm -rf /tmp/test_shallow2
mkdir -p /tmp/test_shallow2
cd /tmp/test_shallow2
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
git fetch origin "main:refs/remotes/origin/main" --depth=1
echo "After 'git fetch origin main:refs/remotes/origin/main --depth=1':"
git rev-parse --verify origin/main 2>&1 || echo "origin/main NOT created"
# Cleanup
rm -rf /tmp/test_remote /tmp/test_local /tmp/test_shallow /tmp/test_shallow2Repository: kintsugi-tax/squawk-pre-commit
Length of output: 2934
🏁 Script executed:
#!/bin/bash
# Corrected test: verify git fetch behavior with matching branch names
echo "Testing git fetch behavior with correct branch name..."
# Create a bare repo to act as remote
mkdir -p /tmp/test_remote
cd /tmp/test_remote
git init --bare
# Create a local repo and push a commit
mkdir -p /tmp/test_local
cd /tmp/test_local
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
echo "test" > file.txt
git add file.txt
git commit -m "initial"
git push origin master
# Test 1: fetch without explicit refspec
echo "===== Test 1: git fetch origin master --depth=1 ====="
mkdir -p /tmp/test_shallow
cd /tmp/test_shallow
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
git fetch origin master --depth=1 2>&1
echo "Checking if origin/master was created:"
git rev-parse --verify origin/master 2>&1 && echo "✓ origin/master EXISTS" || echo "✗ origin/master NOT created"
echo ""
# Test 2: fetch with explicit refspec
echo "===== Test 2: git fetch origin master:refs/remotes/origin/master --depth=1 ====="
mkdir -p /tmp/test_shallow2
cd /tmp/test_shallow2
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
git fetch origin "master:refs/remotes/origin/master" --depth=1 2>&1
echo "Checking if origin/master was created:"
git rev-parse --verify origin/master 2>&1 && echo "✓ origin/master EXISTS" || echo "✗ origin/master NOT created"
# Cleanup
rm -rf /tmp/test_remote /tmp/test_local /tmp/test_shallow /tmp/test_shallow2Repository: kintsugi-tax/squawk-pre-commit
Length of output: 3078
🏁 Script executed:
#!/bin/bash
# Test with explicit verification of push and remote state
echo "Testing git fetch behavior..."
# Create a bare repo to act as remote
mkdir -p /tmp/test_remote
cd /tmp/test_remote
git init --bare
# Create a local repo and push a commit
mkdir -p /tmp/test_local
cd /tmp/test_local
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
echo "test" > file.txt
git add file.txt
git commit -m "initial"
git push origin master
push_status=$?
echo "Push exit code: $push_status"
# Verify push created ref on remote
echo "Refs on remote after push:"
cd /tmp/test_remote
git show-ref
# Test 1: fetch without explicit refspec
echo ""
echo "===== Test 1: git fetch origin master --depth=1 ====="
mkdir -p /tmp/test_shallow
cd /tmp/test_shallow
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
git fetch origin master --depth=1
fetch_exit=$?
echo "Fetch exit code: $fetch_exit"
echo "Checking if origin/master was created:"
if git rev-parse --verify origin/master 2>/dev/null; then
echo "✓ origin/master EXISTS"
else
echo "✗ origin/master NOT created"
fi
echo "Refs in repository:"
git show-ref
# Test 2: fetch with explicit refspec
echo ""
echo "===== Test 2: git fetch origin master:refs/remotes/origin/master --depth=1 ====="
mkdir -p /tmp/test_shallow2
cd /tmp/test_shallow2
git init
git config user.email "test@example.com"
git config user.name "Test User"
git remote add origin /tmp/test_remote
git fetch origin "master:refs/remotes/origin/master" --depth=1
fetch_exit=$?
echo "Fetch exit code: $fetch_exit"
echo "Checking if origin/master was created:"
if git rev-parse --verify origin/master 2>/dev/null; then
echo "✓ origin/master EXISTS"
else
echo "✗ origin/master NOT created"
fi
echo "Refs in repository:"
git show-ref
# Cleanup
rm -rf /tmp/test_remote /tmp/test_local /tmp/test_shallow /tmp/test_shallow2Repository: kintsugi-tax/squawk-pre-commit
Length of output: 3117
🏁 Script executed:
#!/bin/bash
# Examine the actual code and understand the context
cd /repo
cat -n squawk_alembic/hook.py | sed -n '130,175p'Repository: kintsugi-tax/squawk-pre-commit
Length of output: 1753
🌐 Web query:
git fetch shallow clone remote tracking branch refs/remotes behavior
💡 Result:
In a shallow clone (git clone --depth N ...), Git typically behaves differently for remote-tracking branches (refs/remotes/<remote>/...) because --depth implies --single-branch unless you add --no-single-branch. As a result, the clone is configured to fetch/update only one remote-tracking branch by default. [1]
What actually happens to refs/remotes/...
Normal (non–single-branch) clone
Your remote fetch refspec is usually:
+refs/heads/*:refs/remotes/origin/*
So git fetch origin updates all refs/remotes/origin/* remote-tracking branches. [2]
Shallow clone (default: single-branch)
Git writes a narrow refspec (only the cloned branch), e.g.:
+refs/heads/main:refs/remotes/origin/main
So git fetch origin will keep updating only refs/remotes/origin/main, and you may not even have other refs/remotes/origin/<branch> names locally to update. [1]
That’s why people often observe “git fetch doesn’t bring in other remotes/origin/* branches” in shallow clones: it’s mostly the configured refspec / single-branch mode, not a special rule about refs/remotes themselves. [1]
How to fetch other branches (while staying shallow)
Option A (best upfront): clone shallow but not single-branch
git clone --depth 1 --no-single-branch <url>This keeps history shallow but allows remote-tracking branches for multiple branches to be created/updated. [1]
Option B: fetch a specific extra branch by explicit refspec
git fetch --depth 1 origin otherbranch:refs/remotes/origin/otherbranchThis directly tells Git which refs/remotes/... name to update. [3]
Option C: change what the remote tracks (persistent)
Adjust the remote’s branch list / fetch refspec so future git fetch updates additional refs/remotes/origin/*. (Common approaches: git remote set-branches ... or editing remote.origin.fetch.) [4]
Shallow boundary caveat (.git/shallow)
When fetching in/into shallow history, some updates may require changing the shallow boundary; Git can refuse such updates unless you allow it (e.g. git fetch --update-shallow ...). [2]
Sources: git-clone docs on --depth implying --single-branch and how that limits future fetch updates [1]; git-fetch docs on refspecs, remote-tracking branches, and --update-shallow [2]; common refspec workaround examples [3]; discussion of changing tracked branches / refspec in shallow clones [4].
Use explicit refspec to ensure remote-tracking branch is created in shallow clones.
In shallow clones (common in CI), git fetch origin <branch> without an explicit refspec won't create refs/remotes/origin/<branch> because the narrow refspec only tracks the single cloned branch. The function returns True if fetch succeeds, but the ref may not exist locally afterward.
Use an explicit refspec to ensure the remote-tracking branch is created:
🔧 Proposed fix with explicit refspec
if branch.startswith("origin/"):
remote_branch = branch.removeprefix("origin/")
fetch = subprocess.run(
- ["git", "fetch", "origin", remote_branch, "--depth=1"],
+ ["git", "fetch", "origin", f"{remote_branch}:refs/remotes/origin/{remote_branch}", "--depth=1"],
capture_output=True,
)🧰 Tools
🪛 Ruff (0.15.2)
[error] 160-160: subprocess call: check for execution of untrusted input
(S603)
[error] 161-161: Starting a process with a partial executable path
(S607)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@squawk_alembic/hook.py` around lines 158 - 165, The fetch call using
subprocess.run(["git", "fetch", "origin", remote_branch, "--depth=1"]) can
succeed in CI shallow clones yet not create refs/remotes/origin/<branch>; update
the fetch invocation (the subprocess.run call where remote_branch is used in
hook.py) to use an explicit refspec such as
"refs/heads/{remote_branch}:refs/remotes/origin/{remote_branch}" (or prefixed
with + if forcing) as the fetch argument so the remote-tracking branch is
written locally while keeping --depth=1; keep the existing return logic but
ensure the subprocess.run args include that refspec string instead of just
remote_branch.
stephen-kintsugi
left a comment
There was a problem hiding this comment.
Shallow fetch fallback for CI shallow clones looks good. Tests cover the happy path, fetch failure, and non-origin branches correctly.
Summary by CodeRabbit
Chores
Bug Fixes
Tests