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.
56 lines
2 KiB
Markdown
56 lines
2 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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.
|