pr-workflow-automation

Automated PR workflow with CI monitoring, amendments, and retry logic When user asks to create a PR, merge changes, or needs CI-aware PR management

15 stars

Best use case

pr-workflow-automation is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Automated PR workflow with CI monitoring, amendments, and retry logic When user asks to create a PR, merge changes, or needs CI-aware PR management

Teams using pr-workflow-automation should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/pr-workflow-automation/SKILL.md --create-dirs "https://raw.githubusercontent.com/shepherdjerred/monorepo/main/packages/dotfiles/dot_agents/skills/pr-workflow-automation/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/pr-workflow-automation/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How pr-workflow-automation Compares

Feature / Agentpr-workflow-automationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Automated PR workflow with CI monitoring, amendments, and retry logic When user asks to create a PR, merge changes, or needs CI-aware PR management

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# PR Workflow Automation Agent

## Overview

This agent automates the complete pull request workflow: pushing changes, creating PRs, monitoring CI status, and automatically fixing failures through amendments and retries until CI passes.

## Core Workflow

When creating a PR, follow this automated workflow:

1. **Push changes** to remote branch
2. **Create pull request** with GitHub CLI
3. **Monitor CI status** by polling GitHub Actions
4. **On CI failure**: Amend commit, force push, repeat
5. **On CI success**: Report completion

## CLI Commands

### Push and Create PR

```bash
# Push current branch to remote
git push -u origin $(git branch --show-current)

# Create PR with gh CLI
gh pr create --fill

# Create PR with custom title and body
gh pr create --title "feat: add new feature" --body "Description of changes"

# Create draft PR
gh pr create --draft --fill

# Auto-fill from commits
gh pr create --fill-first
```

### Monitor CI Status

```bash
# Check PR status (shows all checks)
gh pr checks

# Watch checks in real-time
gh pr checks --watch

# Get check status as JSON
gh pr checks --json name,status,conclusion

# View specific workflow run
gh run view <run-id>

# Watch workflow run
gh run watch <run-id>
```

### Get Latest Workflow Run

```bash
# Get latest run for current PR
gh run list --branch $(git branch --show-current) --limit 1

# Get run ID and status
gh run list --branch $(git branch --show-current) --limit 1 --json databaseId,status,conclusion

# Filter by workflow
gh run list --workflow ci.yml --branch $(git branch --show-current) --limit 1
```

### Amend and Force Push

```bash
# Amend last commit (keep message)
git commit --amend --no-edit

# Amend with new changes
git add .
git commit --amend --no-edit

# Force push to update PR
git push --force-with-lease

# Force push (less safe)
git push -f
```

## Complete PR Workflow Script

```bash
#!/bin/bash
set -euo pipefail

# Configuration
MAX_RETRIES=5
POLL_INTERVAL=30  # seconds
BRANCH=$(git branch --show-current)

echo "Starting PR workflow for branch: $BRANCH"

# Step 1: Push branch
echo "Pushing changes..."
git push -u origin "$BRANCH"

# Step 2: Create PR (if doesn't exist)
if ! gh pr view &>/dev/null; then
  echo "Creating pull request..."
  gh pr create --fill
else
  echo "PR already exists, updating..."
fi

# Step 3: Monitor and retry loop
attempt=1
while [ $attempt -le $MAX_RETRIES ]; do
  echo "Attempt $attempt/$MAX_RETRIES: Waiting for CI..."

  # Wait for checks to start
  sleep 10

  # Poll for completion
  while true; do
    # Get check status
    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

    # Keep polling
    sleep $POLL_INTERVAL
  done

  # CI failed - attempt to fix
  if [ $attempt -lt $MAX_RETRIES ]; then
    echo "Attempting automatic fix..."

    # Get failure details
    echo "Failure details:"
    gh pr checks

    # This is where you'd implement automatic fixes
    # For now, we'll just ask the user
    echo ""
    echo "CI failed. Please fix the issues, then press Enter to amend and retry..."
    read -r

    # Amend and push
    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

```bash
# Check if linting fixes are needed
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

# Check if type errors exist
if gh pr checks --json name,conclusion --jq '.[] | select(.name == "typecheck" and .conclusion == "FAILURE")' | grep -q .; then
  echo "Type check failures detected"
  # Type errors usually need manual fixes
fi
```

### Wait for Specific Check

```bash
# Wait for specific workflow to complete
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

```bash
# Get failed job 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

```bash
# Monitor multiple checks simultaneously
checks=("lint" "typecheck" "test" "build")

for check in "${checks[@]}"; do
  (
    echo "Monitoring $check..."
    gh run watch --workflow "$check.yml" --exit-status
  ) &
done

# Wait for all background jobs
wait

echo "All checks completed"
```

## Integration with Dagger

For projects using Dagger CI:

```bash
# The workflow typically calls a single Dagger command
# Monitor the main CI workflow
gh run watch --workflow ci.yml --exit-status

# Or check specific Dagger job output
gh run view --log | grep "dagger call"
```

## Best Practices

### 1. Force Push Safety

```bash
# Always use --force-with-lease instead of -f
# This prevents overwriting changes you haven't seen
git push --force-with-lease

# Even safer: check if remote has changed
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

```bash
# When amending, preserve the commit message
git commit --amend --no-edit

# If you need to update the message during retry
git commit --amend -m "fix: address CI failures"
```

### 3. Clean Retry State

```bash
# Before each retry, ensure clean state
git status --porcelain | grep -q . && git add -A
git diff --cached --quiet || git commit --amend --no-edit
```

### 4. Timeout Protection

```bash
# Set maximum wait time for CI
TIMEOUT=1800  # 30 minutes
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

  # Check status...
  sleep 30
done
```

### 5. Retry Backoff

```bash
# Increase wait time between retries
RETRY_DELAY=60
for attempt in $(seq 1 $MAX_RETRIES); do
  # ... check CI ...

  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

```bash
# Detect lint failure
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

```bash
# Test failures usually need manual fix
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

```bash
# Build failures
echo "❌ Build failed. Checking for common issues..."

# Check if dependencies need updating
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

```bash
#!/bin/bash
# pr-auto-fix.sh - Complete PR workflow with auto-fixes

set -euo pipefail

BRANCH=$(git branch --show-current)
MAX_RETRIES=3

# Ensure we have changes
if ! git diff --cached --quiet || ! git diff --quiet; then
  git add -A
  git commit || {
    echo "Nothing to commit"
    exit 0
  }
fi

# Push and create PR
git push -u origin "$BRANCH"
gh pr view &>/dev/null || gh pr create --fill

# Retry loop
for attempt in $(seq 1 $MAX_RETRIES); do
  echo "=== Attempt $attempt/$MAX_RETRIES ==="

  # Wait for checks to start
  echo "Waiting for CI to start..."
  sleep 15

  # Monitor until completion
  gh pr checks --watch || true

  # Get final status
  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"

  # Attempt auto-fixes
  fixed=false

  # Auto-fix lint
  if echo "$failures" | grep -qi "lint"; then
    echo "Auto-fixing lint issues..."
    bun run lint:fix && fixed=true
  fi

  # Auto-fix formatting
  if echo "$failures" | grep -qi "format"; then
    echo "Auto-fixing format issues..."
    bun run format && fixed=true
  fi

  # If we made fixes, commit and retry
  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

  # Manual intervention needed
  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

Related Skills

worktree-workflow

15
from shepherdjerred/monorepo

Git worktree workflow for isolated feature development and PR creation When user starts new work, needs to switch contexts, or wants parallel development

dissociated-clone-workflow

15
from shepherdjerred/monorepo

Fully isolated clones via `git clone --shared --dissociate` for parallel feature development without shared stash/reflog When user starts new work, needs isolated checkouts, wants parallel development, asks for worktree alternatives, or hits stash/reflog collisions across worktrees

toolkit-recall

15
from shepherdjerred/monorepo

Search past decisions, prior research, conversation history, monorepo docs, and fetched web pages. Use toolkit recall search to find context from previous work, and toolkit fetch to save web pages for future search.

zod-patterns

15
from shepherdjerred/monorepo

Zod schema validation, type-safe development, and strict TypeScript patterns. When user works with Zod, validates data, creates schemas, handles form validation, mentions z.object/z.string patterns, needs runtime validation, type-safe code, or strict TypeScript configuration.

zellij-helper

15
from shepherdjerred/monorepo

Zellij terminal multiplexer for session management, layouts, and pane operations When user mentions Zellij, terminal multiplexer, zellij commands, sessions, panes, layouts, or tabs

vite-react-helper

15
from shepherdjerred/monorepo

Vite + React for fast modern web development - build config, HMR, hooks, state management, and performance patterns When user works with Vite, React, creates components, manages state, uses hooks, or configures Vite builds

version-management

15
from shepherdjerred/monorepo

Use when asking about version management, Renovate annotations, versions.ts patterns, or pinning image/chart versions.

typst-authoring

15
from shepherdjerred/monorepo

This skill should be used when the user asks to "write Typst", "create a Typst document", "format in Typst", "convert to Typst", "Typst syntax", "Typst template", "Typst math", "Typst table", or works with .typ files. Provides comprehensive Typst markup, scripting, math, layout, and styling reference for authoring documents. Also use proactively when generating .typ output files (e.g., in deep-research reports).

typescript-helper

15
from shepherdjerred/monorepo

TypeScript development guidance for type systems and tooling When user works with .ts or .tsx files, mentions TypeScript, or encounters type errors

torvalds-deployment

15
from shepherdjerred/monorepo

Use when asking about adding services, createXxxDeployment patterns, or homelab deployment conventions. Services use per-namespace charts.

terraform-helper

15
from shepherdjerred/monorepo

Terraform and OpenTofu infrastructure as code - HCL, providers, modules, state management, and CLI operations When user works with .tf files, mentions Terraform, OpenTofu, tofu, HCL, infrastructure as code, or tf commands

terminal-concepts

15
from shepherdjerred/monorepo

Comprehensive guide for building CLI and TUI applications - terminal internals, design principles, and battle-tested patterns When building CLI/TUI apps, implementing argument parsing, handling terminal input/output, escape codes, buffering, signals, or asking about terminal development concepts