{“content”:”---\nname: github-pr-workflow\ndescription: 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.\nversion: 1.1.0\nauthor: Hermes Agent\nlicense: MIT\nmetadata:\n hermes:\n tags: [GitHub, Pull-Requests, CI/CD, Git, Automation, Merge]\n related_skills: [github-auth, github-code-review]\n---\n\n# GitHub Pull Request Workflow\n\nComplete guide for managing the PR lifecycle. Each section shows the gh way first, then the git + curl fallback for machines without gh.\n\n## Prerequisites\n\n- Authenticated with GitHub (see github-auth skill)\n- Inside a git repository with a GitHub remote\n\n### Quick Auth Detection\n\nbash\n# Determine which method to use throughout this workflow\nif command -v gh &>/dev/null && gh auth status &>/dev/null; then\n AUTH=\"gh\"\nelse\n AUTH=\"git\"\n # Ensure we have a token for API calls\n if [ -z \"$GITHUB_TOKEN\" ]; then\n if [ -f ~/.hermes/.env ] && grep -q \"^GITHUB_TOKEN=\" ~/.hermes/.env; then\n GITHUB_TOKEN=$(grep \"^GITHUB_TOKEN=\" ~/.hermes/.env | head -1 | cut -d= -f2 | tr -d '\\n\\r')\n elif grep -q \"github.com\" ~/.git-credentials 2>/dev/null; then\n GITHUB_TOKEN=$(grep \"github.com\" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]*:\\([^@]*\\)@.*|\\1|')\n fi\n fi\nfi\necho \"Using: $AUTH\"\n\n\n### Extracting Owner/Repo from the Git Remote\n\nMany curl commands need owner/repo. Extract it from the git remote:\n\nbash\n# Works for both HTTPS and SSH remote URLs\nREMOTE_URL=$(git remote get-url origin)\nOWNER_REPO=$(echo \"$REMOTE_URL\" | sed -E 's|.*github\\.com[:/]||; s|\\.git$||')\nOWNER=$(echo \"$OWNER_REPO\" | cut -d/ -f1)\nREPO=$(echo \"$OWNER_REPO\" | cut -d/ -f2)\necho \"Owner: $OWNER, Repo: $REPO\"\n\n\n---\n\n## 1. Branch Creation\n\nThis part is pure git — identical either way:\n\nbash\n# Make sure you're up to date\ngit fetch origin\ngit checkout main && git pull origin main\n\n# Create and switch to a new branch\ngit checkout -b feat/add-user-authentication\n\n\nBranch naming conventions:\n- feat/description — new features\n- fix/description — bug fixes\n- refactor/description — code restructuring\n- docs/description — documentation\n- ci/description — CI/CD changes\n\n## 2. Making Commits\n\nUse the agent’s file tools (write_file, patch) to make changes, then commit:\n\nbash\n# Stage specific files\ngit add src/auth.py src/models/user.py tests/test_auth.py\n\n# Commit with a conventional commit message\ngit commit -m \"feat: add JWT-based user authentication\n\n- Add login/register endpoints\n- Add User model with password hashing\n- Add auth middleware for protected routes\n- Add unit tests for auth flow\"\n\n\nCommit message format (Conventional Commits):\n\ntype(scope): short description\n\nLonger explanation if needed. Wrap at 72 characters.\n\n\nTypes: feat, fix, refactor, docs, test, ci, chore, perf\n\n## 3. Pushing and Creating a PR\n\n### Push the Branch (same either way)\n\nbash\ngit push -u origin HEAD\n\n\n### Create the PR\n\nWith gh:\n\nbash\ngh pr create \\\n --title \"feat: add JWT-based user authentication\" \\\n --body \"## Summary\n- Adds login and register API endpoints\n- JWT token generation and validation\n\n## Test Plan\n- [ ] Unit tests pass\n\nCloses #42\"\n\n\nOptions: --draft, --reviewer user1,user2, --label \"enhancement\", --base develop\n\nWith git + curl:\n\nbash\nBRANCH=$(git branch --show-current)\n\ncurl -s -X POST \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n -H \"Accept: application/vnd.github.v3+json\" \\\n https://api.github.com/repos/$OWNER/$REPO/pulls \\\n -d \"{\n \\\"title\\\": \\\"feat: add JWT-based user authentication\\\",\n \\\"body\\\": \\\"## Summary\\nAdds login and register API endpoints.\\n\\nCloses #42\\\",\n \\\"head\\\": \\\"$BRANCH\\\",\n \\\"base\\\": \\\"main\\\"\n }\"\n\n\nThe response JSON includes the PR number — save it for later commands.\n\nTo create as a draft, add \"draft\": true to the JSON body.\n\n## 4. Monitoring CI Status\n\n### Check CI Status\n\nWith gh:\n\nbash\n# One-shot check\ngh pr checks\n\n# Watch until all checks finish (polls every 10s)\ngh pr checks --watch\n\n\nWith git + curl:\n\nbash\n# Get the latest commit SHA on the current branch\nSHA=$(git rev-parse HEAD)\n\n# Query the combined status\ncurl -s \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status \\\n | python3 -c \"\nimport sys, json\ndata = json.load(sys.stdin)\nprint(f\\\"Overall: {data['state']}\\\")\nfor s in data.get('statuses', []):\n print(f\\\" {s['context']}: {s['state']} - {s.get('description', '')}\\\")\"\n\n# Also check GitHub Actions check runs (separate endpoint)\ncurl -s \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/check-runs \\\n | python3 -c \"\nimport sys, json\ndata = json.load(sys.stdin)\nfor cr in data.get('check_runs', []):\n print(f\\\" {cr['name']}: {cr['status']} / {cr['conclusion'] or 'pending'}\\\")\"\n\n\n### Poll Until Complete (git + curl)\n\nbash\n# Simple polling loop — check every 30 seconds, up to 10 minutes\nSHA=$(git rev-parse HEAD)\nfor i in $(seq 1 20); do\n STATUS=$(curl -s \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status \\\n | python3 -c \"import sys,json; print(json.load(sys.stdin)['state'])\")\n echo \"Check $i: $STATUS\"\n if [ \"$STATUS\" = \"success\" ] || [ \"$STATUS\" = \"failure\" ] || [ \"$STATUS\" = \"error\" ]; then\n break\n fi\n sleep 30\ndone\n\n\n## 5. Auto-Fixing CI Failures\n\nWhen CI fails, diagnose and fix. This loop works with either auth method.\n\n### Step 1: Get Failure Details\n\nWith gh:\n\nbash\n# List recent workflow runs on this branch\ngh run list --branch $(git branch --show-current) --limit 5\n\n# View failed logs\ngh run view <RUN_ID> --log-failed\n\n\nWith git + curl:\n\nbash\nBRANCH=$(git branch --show-current)\n\n# List workflow runs on this branch\ncurl -s \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n \"https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$BRANCH&per_page=5\" \\\n | python3 -c \"\nimport sys, json\nruns = json.load(sys.stdin)['workflow_runs']\nfor r in runs:\n print(f\\\"Run {r['id']}: {r['name']} - {r['conclusion'] or r['status']}\\\")\"\n\n# Get failed job logs (download as zip, extract, read)\nRUN_ID=<run_id>\ncurl -s -L \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/logs \\\n -o /tmp/ci-logs.zip\ncd /tmp && unzip -o ci-logs.zip -d ci-logs && cat ci-logs/*.txt\n\n\n### Step 2: Fix and Push\n\nAfter identifying the issue, use file tools (patch, write_file) to fix it:\n\nbash\ngit add <fixed_files>\ngit commit -m \"fix: resolve CI failure in <check_name>\"\ngit push\n\n\n### Step 3: Verify\n\nRe-check CI status using the commands from Section 4 above.\n\n### Auto-Fix Loop Pattern\n\nWhen asked to auto-fix CI, follow this loop:\n\n1. Check CI status → identify failures\n2. Read failure logs → understand the error\n3. Use read_file + patch/write_file → fix the code\n4. git add . && git commit -m \"fix: ...\" && git push\n5. Wait for CI → re-check status\n6. Repeat if still failing (up to 3 attempts, then ask the user)\n\n## 6. Merging\n\nWith gh:\n\nbash\n# Squash merge + delete branch (cleanest for feature branches)\ngh pr merge --squash --delete-branch\n\n# Enable auto-merge (merges when all checks pass)\ngh pr merge --auto --squash --delete-branch\n\n\nWith git + curl:\n\nbash\nPR_NUMBER=<number>\n\n# Merge the PR via API (squash)\ncurl -s -X PUT \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/merge \\\n -d \"{\n \\\"merge_method\\\": \\\"squash\\\",\n \\\"commit_title\\\": \\\"feat: add user authentication (#$PR_NUMBER)\\\"\n }\"\n\n# Delete the remote branch after merge\nBRANCH=$(git branch --show-current)\ngit push origin --delete $BRANCH\n\n# Switch back to main locally\ngit checkout main && git pull origin main\ngit branch -d $BRANCH\n\n\nMerge methods: \"merge\" (merge commit), \"squash\", \"rebase\"\n\n### Enable Auto-Merge (curl)\n\nbash\n# Auto-merge requires the repo to have it enabled in settings.\n# This uses the GraphQL API since REST doesn't support auto-merge.\nPR_NODE_ID=$(curl -s \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \\\n | python3 -c \"import sys,json; print(json.load(sys.stdin)['node_id'])\")\n\ncurl -s -X POST \\\n -H \"Authorization: token $GITHUB_TOKEN\" \\\n https://api.github.com/graphql \\\n -d \"{\\\"query\\\": \\\"mutation { enablePullRequestAutoMerge(input: {pullRequestId: \\\\\\\"$PR_NODE_ID\\\\\\\", mergeMethod: SQUASH}) { clientMutationId } }\\\"}\"\n\n\n## 7. Complete Workflow Example\n\nbash\n# 1. Start from clean main\ngit checkout main && git pull origin main\n\n# 2. Branch\ngit checkout -b fix/login-redirect-bug\n\n# 3. (Agent makes code changes with file tools)\n\n# 4. Commit\ngit add src/auth/login.py tests/test_login.py\ngit commit -m \"fix: correct redirect URL after login\n\nPreserves the ?next= parameter instead of always redirecting to /dashboard.\"\n\n# 5. Push\ngit push -u origin HEAD\n\n# 6. Create PR (picks gh or curl based on what's available)\n# ... (see Section 3)\n\n# 7. Monitor CI (see Section 4)\n\n# 8. Merge when green (see Section 6)\n\n\n## Useful PR Commands Reference\n\n| Action | gh | git + curl |\n|--------|-----|-----------|\n| 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\" |\n| View PR diff | gh pr diff | git diff main...HEAD (local) or curl -H \"Accept: application/vnd.github.diff\" ... |\n| Add comment | gh pr comment N --body \"...\" | curl -X POST .../issues/N/comments -d '{\"body\":\"...\"}' |\n| Request review | gh pr edit N --add-reviewer user | curl -X POST .../pulls/N/requested_reviewers -d '{\"reviewers\":[\"user\"]}' |\n| Close PR | gh pr close N | curl -X PATCH .../pulls/N -d '{\"state\":\"closed\"}' |\n| Check out someone’s PR | gh pr checkout N | git fetch origin pull/N/head:pr-N && git checkout pr-N |\n”}