| name | pr-workflow-automation |
| description | Automated PR workflow with amendments and retry logic
When user asks to create a PR, merge changes, or needs PR management
|
PR Workflow Automation Agent
Branch & PR management in shepherdjerred/monorepo uses git-spice — every PR is a stacked PR. Load the git-spice-helper skill first (it's authoritative); create/update PRs with git-spice branch/stack submit — a single PR is a stack of one. The gh pr create and manual-git rebase examples below are the generic fallback for repos without git-spice.
This monorepo's CI is Buildkite, not GitHub Actions. buildkite/monorepo/pr + ci/merge-conflict run per PR — gh pr checks shows their pass/fail, but the gh run / GitHub Actions commands in the CI-monitoring material below don't apply here (use bk build view or the Buildkite web UI for logs instead). For this repo, the workflow is: verify locally (typecheck/test/lint for touched packages), push, create the PR, then handle review comments, merge conflicts, and Buildkite failures. The CI-monitoring material below is generic reference for repos that do have GitHub Actions CI.
Overview
This agent automates the complete pull request workflow: pushing changes, creating PRs, and (in repos that have CI) monitoring CI status and fixing failures through amendments and retries.
Core Workflow
When creating a PR, follow this automated workflow:
- Verify locally (typecheck/test/lint for the packages you touched)
- Push changes to remote branch
- Create pull request with GitHub CLI
- Monitor reviews and merge conflicts until ready for human review
- (Repos with CI only) Monitor CI status; on failure amend, force push, repeat
CLI Commands
Push and Create PR
git push -u origin $(git branch --show-current)
gh pr create --fill
gh pr create --title "feat: add new feature" --body "Description of changes"
gh pr create --draft --fill
gh pr create --fill-first
Monitor CI Status
gh pr checks
gh pr checks --watch
gh pr checks --json name,status,conclusion
gh run view <run-id>
gh run watch <run-id>
Get Latest Workflow Run
gh run list --branch $(git branch --show-current) --limit 1
gh run list --branch $(git branch --show-current) --limit 1 --json databaseId,status,conclusion
gh run list --workflow ci.yml --branch $(git branch --show-current) --limit 1
Amend and Force Push
git commit --amend --no-edit
git add .
git commit --amend --no-edit
git push --force-with-lease
git push -f
Complete PR Workflow Script
#!/bin/bash
set -euo pipefail
MAX_RETRIES=5
POLL_INTERVAL=30
BRANCH=$(git branch --show-current)
echo "Starting PR workflow for branch: $BRANCH"
echo "Pushing changes..."
git push -u origin "$BRANCH"
if ! gh pr view &>/dev/null; then
echo "Creating pull request..."
gh pr create --fill
else
echo "PR already exists, updating..."
fi
attempt=1
while [ $attempt -le $MAX_RETRIES ]; do
echo "Attempt $attempt/$MAX_RETRIES: Waiting for CI..."
sleep 10
while true; do
status=$(gh pr checks --json status,conclusion --jq '
if all(.status == "COMPLETED") then
if all(.conclusion == "SUCCESS") then "SUCCESS"
else "FAILURE"
end
else "PENDING"
end
')
echo "CI Status: $status"
if [ "$status" = "SUCCESS" ]; then
echo "✅ CI passed! PR is ready."
exit 0
elif [ "$status" = "FAILURE" ]; then
echo "❌ CI failed on attempt $attempt"
break
fi
sleep $POLL_INTERVAL
done
if [ $attempt -lt $MAX_RETRIES ]; then
echo "Attempting automatic fix..."
echo "Failure details:"
gh pr checks
echo ""
echo "CI failed. Please fix the issues, then press Enter to amend and retry..."
read -r
echo "Amending commit and retrying..."
git add -A
git commit --amend --no-edit
git push --force-with-lease
attempt=$((attempt + 1))
else
echo "❌ Max retries reached. Manual intervention required."
exit 1
fi
done
Advanced Patterns
Automatic Fix Detection
if gh pr checks --json name,conclusion --jq '.[] | select(.name == "lint" and .conclusion == "FAILURE")' | grep -q .; then
echo "Lint failures detected, running auto-fix..."
bun run lint:fix
git add -A
git commit --amend --no-edit
git push --force-with-lease
fi
if gh pr checks --json name,conclusion --jq '.[] | select(.name == "typecheck" and .conclusion == "FAILURE")' | grep -q .; then
echo "Type check failures detected"
fi
Wait for Specific Check
check_name="ci"
while true; do
status=$(gh pr checks --json name,status,conclusion --jq "
.[] | select(.name == \"$check_name\") |
if .status == \"COMPLETED\" then
.conclusion
else
\"PENDING\"
end
")
case $status in
SUCCESS)
echo "✅ $check_name passed"
break
;;
FAILURE)
echo "❌ $check_name failed"
exit 1
;;
PENDING|IN_PROGRESS)
echo "⏳ Waiting for $check_name..."
sleep 30
;;
esac
done
Get Failure Logs
failed_run=$(gh run list --branch $(git branch --show-current) \
--limit 1 --json databaseId,conclusion --jq \
'select(.conclusion == "FAILURE") | .databaseId')
if [ -n "$failed_run" ]; then
echo "Fetching logs for failed run: $failed_run"
gh run view "$failed_run" --log-failed
fi
Parallel Check Monitoring
checks=("lint" "typecheck" "test" "build")
for check in "${checks[@]}"; do
(
echo "Monitoring $check..."
gh run watch --workflow "$check.yml" --exit-status
) &
done
wait
echo "All checks completed"
Best Practices
1. Force Push Safety
git push --force-with-lease
if git fetch origin && git diff origin/$BRANCH --quiet; then
git push --force-with-lease
else
echo "⚠️ Remote branch has new commits. Pull first!"
exit 1
fi
2. Commit Message Preservation
git commit --amend --no-edit
git commit --amend -m "fix: address CI failures"
3. Clean Retry State
git status --porcelain | grep -q . && git add -A
git diff --cached --quiet || git commit --amend --no-edit
4. Timeout Protection
TIMEOUT=1800
START_TIME=$(date +%s)
while true; do
CURRENT_TIME=$(date +%s)
ELAPSED=$((CURRENT_TIME - START_TIME))
if [ $ELAPSED -gt $TIMEOUT ]; then
echo "⏰ Timeout: CI took longer than 30 minutes"
exit 1
fi
sleep 30
done
5. Retry Backoff
RETRY_DELAY=60
for attempt in $(seq 1 $MAX_RETRIES); do
if [ $attempt -lt $MAX_RETRIES ]; then
wait_time=$((RETRY_DELAY * attempt))
echo "Waiting ${wait_time}s before retry..."
sleep $wait_time
fi
done
Common Scenarios
Scenario 1: Lint Failures
if gh pr checks --json name,conclusion | jq -e '.[] | select(.name | contains("lint")) | select(.conclusion == "FAILURE")'; then
echo "Running lint fix..."
bun run lint:fix
git add -A
git commit --amend --no-edit
git push --force-with-lease
fi
Scenario 2: Test Failures
echo "❌ Tests failed. Common fixes:"
echo " 1. Run tests locally: bun test"
echo " 2. Check test output: gh run view --log"
echo " 3. Fix issues and amend: git commit --amend --no-edit"
echo " 4. Push: git push --force-with-lease"
Scenario 3: Build Failures
echo "❌ Build failed. Checking for common issues..."
if gh run view --log | grep -q "Cannot find module"; then
echo "Installing dependencies..."
bun install
git add bun.lockb
git commit --amend --no-edit
git push --force-with-lease
fi
Complete Example: Auto-Fixing PR
#!/bin/bash
set -euo pipefail
BRANCH=$(git branch --show-current)
MAX_RETRIES=3
if ! git diff --cached --quiet || ! git diff --quiet; then
git add -A
git commit || {
echo "Nothing to commit"
exit 0
}
fi
git push -u origin "$BRANCH"
gh pr view &>/dev/null || gh pr create --fill
for attempt in $(seq 1 $MAX_RETRIES); do
echo "=== Attempt $attempt/$MAX_RETRIES ==="
echo "Waiting for CI to start..."
sleep 15
gh pr checks --watch || true
failures=$(gh pr checks --json name,conclusion --jq '
[.[] | select(.conclusion == "FAILURE") | .name] | join(", ")
')
if [ -z "$failures" ]; then
echo "✅ All checks passed!"
exit 0
fi
echo "❌ Failed checks: $failures"
fixed=false
if echo "$failures" | grep -qi "lint"; then
echo "Auto-fixing lint issues..."
bun run lint:fix && fixed=true
fi
if echo "$failures" | grep -qi "format"; then
echo "Auto-fixing format issues..."
bun run format && fixed=true
fi
if $fixed && ! git diff --quiet; then
git add -A
git commit --amend --no-edit
git push --force-with-lease
echo "Pushed fixes, retrying..."
continue
fi
if [ $attempt -lt $MAX_RETRIES ]; then
echo ""
echo "Could not auto-fix. Please make changes and press Enter to retry..."
read -r
git add -A
git commit --amend --no-edit
git push --force-with-lease
fi
done
echo "❌ Max retries reached. Manual intervention required."
echo "View failures: gh pr checks"
exit 1
When to Ask for Help
Ask the user for clarification when:
- CI failures are not automatically fixable (type errors, test logic issues)
- Maximum retry attempts reached
- PR creation fails (authentication, permissions)
- Branch protection rules prevent force push
- Conflicts exist with base branch
- Custom CI workflows with non-standard check names