layered-soul/skills/forgejo-operations/references/api-merge-pattern.md
Sam & Claude 4d8ce07fa7 docs: apply Prettier to current markdown (Sam & Codex)
Normalize markdown formatting after the latest main updates.\n\nChecks: python3 scripts/layered_soul.py validate .; npx --yes prettier@3 --check '**/*.md'; git diff --check.
2026-06-14 01:48:32 +02:00

2 KiB

Forgejo API — Create and Merge PRs via curl

Pattern for automated PR creation and merge when branch protection blocks direct push.

Prerequisites

  • API token with repository:write scope
  • Token stored as FORGEJO_API_TOKEN in ~/.hermes/.env (mode 0600)

Create and merge a PR

source ~/.hermes/.env 2>/dev/null
API="https://code.smilepowered.org/api/v1/repos/<owner>/<repo>"

# Create PR
PR=$(curl -s -X POST \
  -H "Authorization: token $FORGEJO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"...","head":"<branch>","base":"main","body":"..."}' \
  "$API/pulls")
NUM=$(echo "$PR" | python3 -c "import sys,json; print(json.load(sys.stdin).get('number',''))")

# Merge
curl -s -X POST \
  -H "Authorization: token $FORGEJO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"Do":"merge","delete_branch_after_merge":true}' \
  "$API/pulls/$NUM/merge" > /dev/null

# Verify
curl -s -H "Authorization: token $FORGEJO_API_TOKEN" "$API/pulls/$NUM" | \
  python3 -c "import sys,json; d=json.load(sys.stdin); print(f'PR #{d[\"number\"]}: merged={d[\"merged\"]}')"

Token scopes needed

Scope For
repository:write Create PRs, merge PRs
organization:write Adjust branch protection rules
read:user Verify token identity (optional)

Pitfalls

  • Merge field capitalization: Forgejo merge endpoint requires "Do":"merge" (capital D). Lowercase "do" may return HTTP 422 [Do]: Required. Use "Do":"merge" and verify with a follow-up GET on the PR — HTTP 200 + empty body = merged.
  • The merge endpoint returns empty body on success (not JSON). Check PR state after merging by fetching GET /pulls/{id}.
  • Forgejo API base is https://<host>/api/v1, not /api.
  • Direct push to protected branches still blocked even with token — use PR creation + merge workflow.
  • Token must be the full hash, not truncated.