Skill v1.1.0
currentAutomated scan100/100description: Full pull request lifecycle — create branches, commit changes, open PRs, monitor CI status, auto-fix failures, and merge. Works with gh CLI or falls back to git + GitHub REST API via curl. version: 1.1.0 license: MIT metadata: catalog: tags:
- GitHub
- Pull-Requests
- CI/CD
- Git
- Automation
- Merge
related_skills:
- github-auth
- github-code-review
Kheish Compatibility
This skill is repo-local and stays inactive until explicitly activated.
When the original instructions refer to legacy tool names, use these Kheish mappings:
terminal=>bashweb_extract=>web_fetch, plusweb_searchwhen discovery is neededsearch_files=>grep_searchandglob_searchbrowser_*tools require a browser-capable surfaced tool or MCP; if none is available, use the closest available surface and say so explicitly
When the instructions mention local helper files, resolve them from ${KHEISH_SKILL_DIR}.
GitHub Pull Request Workflow
Complete guide for managing the PR lifecycle. Each section shows the gh way first, then the git + curl fallback for machines without gh.
Prerequisites
- Authenticated with GitHub (see
github-authskill) - Inside a git repository with a GitHub remote
Quick Auth Detection
# Determine which method to use throughout this workflowif command -v gh &>/dev/null && gh auth status &>/dev/null; thenAUTH="gh"elif [ -n "$GITHUB_TOKEN" ]; thenAUTH="curl"elseAUTH="none"fi[ "$AUTH" = "none" ] && echo "Run 'gh auth login' or export GITHUB_TOKEN before PR API calls" && exit 1echo "Using: $AUTH"
Extracting Owner/Repo from the Git Remote
Many curl commands need owner/repo. Extract it from the git remote:
# Works for both HTTPS and SSH remote URLsREMOTE_URL=$(git remote get-url origin)OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github\.com[:/]||; s|\.git$||')OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1)REPO=$(echo "$OWNER_REPO" | cut -d/ -f2)echo "Owner: $OWNER, Repo: $REPO"
1. Branch Creation
This part is pure git — identical either way:
# Make sure you're up to dategit fetch origingit checkout main && git pull origin main# Create and switch to a new branchgit checkout -b feat/add-user-authentication
Branch naming conventions:
feat/description— new featuresfix/description— bug fixesrefactor/description— code restructuringdocs/description— documentationci/description— CI/CD changes
2. Making Commits
Use the agent's file tools (write_file, patch) to make changes, then commit:
# Stage specific filesgit add src/auth.py src/models/user.py tests/test_auth.py# Commit with a conventional commit messagegit commit -m "feat: add JWT-based user authentication- Add login/register endpoints- Add User model with password hashing- Add auth middleware for protected routes- Add unit tests for auth flow"
Commit message format (Conventional Commits):
type(scope): short descriptionLonger explanation if needed. Wrap at 72 characters.
Types: feat, fix, refactor, docs, test, ci, chore, perf
3. Pushing and Creating a PR
Push the Branch (same either way)
git push -u origin HEAD
Create the PR
With gh:
gh pr create \--title "feat: add JWT-based user authentication" \--body "## Summary- Adds login and register API endpoints- JWT token generation and validation## Test Plan- [ ] Unit tests passCloses #42"
Options: --draft, --reviewer user1,user2, --label "enhancement", --base develop
With git + curl:
BRANCH=$(git branch --show-current)curl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \-H "Accept: application/vnd.github.v3+json" \https://api.github.com/repos/$OWNER/$REPO/pulls \-d "{\"title\": \"feat: add JWT-based user authentication\",\"body\": \"## Summary\nAdds login and register API endpoints.\n\nCloses #42\",\"head\": \"$BRANCH\",\"base\": \"main\"}"
The response JSON includes the PR number — save it for later commands.
To create as a draft, add "draft": true to the JSON body.
4. Monitoring CI Status
Check CI Status
With gh:
# One-shot checkgh pr checks# Watch until all checks finish (polls every 10s)gh pr checks --watch
With git + curl:
# Get the latest commit SHA on the current branchSHA=$(git rev-parse HEAD)# Query the combined statuscurl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status \| python3 -c "import sys, jsondata = json.load(sys.stdin)print(f\"Overall: {data['state']}\")for s in data.get('statuses', []):print(f\" {s['context']}: {s['state']} - {s.get('description', '')}\")"# Also check GitHub Actions check runs (separate endpoint)curl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/check-runs \| python3 -c "import sys, jsondata = json.load(sys.stdin)for cr in data.get('check_runs', []):print(f\" {cr['name']}: {cr['status']} / {cr['conclusion'] or 'pending'}\")"
Poll Until Complete (git + curl)
# Simple polling loop — check every 30 seconds, up to 10 minutesSHA=$(git rev-parse HEAD)for i in $(seq 1 20); doSTATUS=$(curl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status \| python3 -c "import sys,json; print(json.load(sys.stdin)['state'])")echo "Check $i: $STATUS"if [ "$STATUS" = "success" ] || [ "$STATUS" = "failure" ] || [ "$STATUS" = "error" ]; thenbreakfisleep 30done
5. Auto-Fixing CI Failures
When CI fails, diagnose and fix. This loop works with either auth method.
Step 1: Get Failure Details
With gh:
# List recent workflow runs on this branchgh run list --branch $(git branch --show-current) --limit 5# View failed logsgh run view <RUN_ID> --log-failed
With git + curl:
BRANCH=$(git branch --show-current)# List workflow runs on this branchcurl -s \-H "Authorization: token $GITHUB_TOKEN" \"https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$BRANCH&per_page=5" \| python3 -c "import sys, jsonruns = json.load(sys.stdin)['workflow_runs']for r in runs:print(f\"Run {r['id']}: {r['name']} - {r['conclusion'] or r['status']}\")"# Get failed job logs (download as zip, extract, read)RUN_ID=<run_id>curl -s -L \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/logs \-o /tmp/ci-logs.zipcd /tmp && unzip -o ci-logs.zip -d ci-logs && cat ci-logs/*.txt
Step 2: Fix and Push
After identifying the issue, use file tools (patch, write_file) to fix it:
git add <fixed_files>git commit -m "fix: resolve CI failure in <check_name>"git push
Step 3: Verify
Re-check CI status using the commands from Section 4 above.
Auto-Fix Loop Pattern
When asked to auto-fix CI, follow this loop:
- Check CI status → identify failures
- Read failure logs → understand the error
- Use
read_file+patch/write_file→ fix the code git add . && git commit -m "fix: ..." && git push- Wait for CI → re-check status
- Repeat if still failing (up to 3 attempts, then ask the user)
6. Merging
With gh:
# Squash merge + delete branch (cleanest for feature branches)gh pr merge --squash --delete-branch# Enable auto-merge (merges when all checks pass)gh pr merge --auto --squash --delete-branch
With git + curl:
PR_NUMBER=<number># Merge the PR via API (squash)curl -s -X PUT \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/merge \-d "{\"merge_method\": \"squash\",\"commit_title\": \"feat: add user authentication (#$PR_NUMBER)\"}"# Delete the remote branch after mergeBRANCH=$(git branch --show-current)git push origin --delete $BRANCH# Switch back to main locallygit checkout main && git pull origin maingit branch -d $BRANCH
Merge methods: "merge" (merge commit), "squash", "rebase"
Enable Auto-Merge (curl)
# Auto-merge requires the repo to have it enabled in settings.# This uses the GraphQL API since REST doesn't support auto-merge.PR_NODE_ID=$(curl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \| python3 -c "import sys,json; print(json.load(sys.stdin)['node_id'])")curl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/graphql \-d "{\"query\": \"mutation { enablePullRequestAutoMerge(input: {pullRequestId: \\\"$PR_NODE_ID\\\", mergeMethod: SQUASH}) { clientMutationId } }\"}"
7. Complete Workflow Example
# 1. Start from clean maingit checkout main && git pull origin main# 2. Branchgit checkout -b fix/login-redirect-bug# 3. (Agent makes code changes with file tools)# 4. Commitgit add src/auth/login.py tests/test_login.pygit commit -m "fix: correct redirect URL after loginPreserves the ?next= parameter instead of always redirecting to /dashboard."# 5. Pushgit push -u origin HEAD# 6. Create PR (picks gh or curl based on what's available)# ... (see Section 3)# 7. Monitor CI (see Section 4)# 8. Merge when green (see Section 6)
Useful PR Commands Reference
| Action | gh | git + curl | |
|---|---|---|---|
| List my PRs | gh pr list --author @me | curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$OWNER/$REPO/pulls?state=open" | |
| View PR diff | gh pr diff | git diff main...HEAD (local) or curl -H "Accept: application/vnd.github.diff" ... | |
| Add comment | gh pr comment N --body "..." | curl -X POST .../issues/N/comments -d '{"body":"..."}' | |
| Request review | gh pr edit N --add-reviewer user | curl -X POST .../pulls/N/requested_reviewers -d '{"reviewers":["user"]}' | |
| Close PR | gh pr close N | curl -X PATCH .../pulls/N -d '{"state":"closed"}' | |
| Check out someone's PR | gh pr checkout N | git fetch origin pull/N/head:pr-N && git checkout pr-N |