Files
HAL9000 f808abff86 chore(ci): fix pre-commit hook failures
Fix JSON syntax errors in .devcontainer/devcontainer.json (removed
invalid JS-style // comments) and .devcontainer/opencode.json (removed
90+ trailing commas). Apply auto-fixes for end-of-file and trailing
whitespace issues across 100+ files. Fix SIM105 ruff violations in
benchmarks/core_circuit_breaker_bench.py (use contextlib.suppress).

Note: The security fix from issue #7478 (validate_path startswith bypass)
was already delivered to master in commit e18ac5f2. This PR as currently
structured is non-atomic (35 commits across 10+ issues) and needs
significant restructure before merge. This commit only addresses the
CI/pre-commit failures.

ISSUES CLOSED: #7478
2026-06-14 09:51:14 -04:00
..

Pull Requests API Reference

Core Endpoints

List Pull Requests

GET /repos/{owner}/{repo}/pulls

Parameters:

Parameter Type Description
state string Filter by state: open, closed, all
sort string Sort by: oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority
milestone int Filter by milestone ID
labels string Comma-separated label IDs
poster string Filter by PR author (username)
page int Page number (1-based)
limit int Page size (default varies by server config)
# List open PRs
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls?state=open&limit=10"

# List closed PRs sorted by most recently updated
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls?state=closed&sort=recentupdate&page=1&limit=25"

# Filter by milestone and labels
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls?state=open&milestone=3&labels=5,12"

Create a Pull Request

POST /repos/{owner}/{repo}/pulls

CreatePullRequestOption:

Field Type Required Description
title string yes PR title
body string no PR description (markdown)
head string yes Source branch name
base string yes Target branch name
assignee string no Single assignee username
assignees array[string] no Multiple assignee usernames
labels array[int] no Label IDs to apply
milestone int no Milestone ID
due_date string no Due date (ISO 8601 format)
# Create a simple PR
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Add user authentication",
    "body": "## Summary\nImplements JWT-based auth.\n\nCloses #42",
    "head": "{head_branch}",
    "base": "{base_branch}"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls"

# Create a PR with assignees, labels, and milestone
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Refactor database layer",
    "body": "Switches from raw SQL to ORM queries.",
    "head": "{head_branch}",
    "base": "{base_branch}",
    "assignees": ["{assignee1}", "{assignee2}"],
    "labels": [1, 5, 8],
    "milestone": 2,
    "due_date": "2025-03-15T00:00:00Z"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls"

Get Pull Request Details

GET /repos/{owner}/{repo}/pulls/{index}
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}"

Update a Pull Request

PATCH /repos/{owner}/{repo}/pulls/{index}

Accepts the same fields as create (title, body, base, assignee, assignees, labels, milestone, due_date) plus:

Field Type Description
state string Change state: open or closed
allow_maintainer_edit boolean Allow maintainers to push to head
# Update title and body
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Add user authentication (v2)",
    "body": "Updated implementation using OAuth2."
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}"

# Close a PR
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"state": "closed"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}"

# Allow maintainer edits
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"allow_maintainer_edit": true}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}"

List Pinned Pull Requests

GET /repos/{owner}/{repo}/pulls/pinned
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/pinned"

Get PR Between Specific Branches

GET /repos/{owner}/{repo}/pulls/{base}/{head}

Returns the PR (if any) that merges head into base.

curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{base}/{head}"

Get Diff or Patch

GET /repos/{owner}/{repo}/pulls/{index}.diff
GET /repos/{owner}/{repo}/pulls/{index}.patch

Returns raw diff or patch format (plain text, not JSON).

# Get raw diff
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}.diff"

# Get patch format
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}.patch"

List PR Commits

GET /repos/{owner}/{repo}/pulls/{index}/commits
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/commits"

Update PR Branch (Server-Side Rebase/Merge)

POST /repos/{owner}/{repo}/pulls/{index}/update

Merges or rebases the base branch into the PR's head branch without needing a local clone. Only works when there are no conflicts.

Query Parameters:

Parameter Type Description
style string rebase or merge (default: merge)

Note: The style parameter is a query parameter per the Swagger spec. Some Forgejo versions also accept {"style": "rebase"} as a JSON body, but the canonical way is as a query parameter.

# Update PR branch by merging base into head (default)
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/update?style=merge"

# Update PR branch by rebasing onto base
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/update?style=rebase"

PullRequest Response Object

Key Fields

Field Type Description
number int PR index number
title string PR title
body string PR description (markdown)
state string open or closed
draft boolean Whether this is a draft PR
mergeable boolean/null Whether the PR can be merged (null = not yet computed)
merged boolean Whether the PR has been merged
merged_at string/null Timestamp of merge (ISO 8601)
merged_by User/null User who performed the merge
base PRBranchInfo Target branch info
head PRBranchInfo Source branch info
additions int Total lines added
deletions int Total lines deleted
changed_files int Number of files changed
comments int Number of general comments
review_comments int Number of review/inline comments
labels array[Label] Applied labels
milestone Milestone Associated milestone
assignees array[User] Assigned users
requested_reviewers array[User] Users requested for review
requested_reviewers_teams array[Team] Teams requested for review
merge_base string Merge base commit SHA
merge_commit_sha string Merge commit SHA (if merged)
diff_url string URL to raw diff
patch_url string URL to patch format
allow_maintainer_edit boolean Whether maintainers can push to head branch
pin_order int Pin order (0 = not pinned)
flow string PR flow type

PRBranchInfo Fields

Field Type Description
label string Branch label (owner:branch)
ref string Branch name
sha string Current HEAD SHA of the branch
repo_id int Repository ID
repo Repository Full repository object

Checking PR Status

Check if a PR is a Draft

PR=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}")

IS_DRAFT=$(echo "$PR" | jq '.draft')
echo "Is draft: $IS_DRAFT"

Check if a PR Has Conflicts (Not Mergeable)

The mergeable field indicates whether the PR can be cleanly merged:

  • true - no conflicts, can merge
  • false - has conflicts, cannot merge
  • null - mergeability not yet computed (Forgejo computes this lazily)
MERGEABLE=$(echo "$PR" | jq '.mergeable')
if [ "$MERGEABLE" = "false" ]; then
  echo "PR has merge conflicts!"
elif [ "$MERGEABLE" = "null" ]; then
  echo "Mergeability not yet computed. Try again shortly."
else
  echo "PR is mergeable."
fi

Check if a PR is Stale (Base Branch Has Advanced)

A PR is "stale" when the base branch has new commits that are not in the PR's branch. Compare pr.base.sha (the base branch SHA at the time the PR object was generated) with the current HEAD of the base branch:

# Get the PR's recorded base SHA
PR_BASE_SHA=$(echo "$PR" | jq -r '.base.sha')

# Get the current HEAD of the base branch
BASE_BRANCH=$(echo "$PR" | jq -r '.base.ref')
CURRENT_BASE_SHA=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/branches/${BASE_BRANCH}" | jq -r '.commit.id')

if [ "$PR_BASE_SHA" != "$CURRENT_BASE_SHA" ]; then
  echo "PR is stale. Base branch has advanced."
  echo "PR base SHA:      $PR_BASE_SHA"
  echo "Current base SHA:  $CURRENT_BASE_SHA"

  # Optionally update the PR branch server-side
  curl -s -X POST \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/update?style=rebase"
else
  echo "PR is up to date with base branch."
fi

Combined Status Check

#!/bin/bash
# Full PR health check
OWNER="{owner}"
REPO="{repo}"
PR_INDEX="{index}"

PR=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/${OWNER}/${REPO}/pulls/${PR_INDEX}")

echo "PR #${PR_INDEX}: $(echo "$PR" | jq -r '.title')"
echo "State:     $(echo "$PR" | jq -r '.state')"
echo "Draft:     $(echo "$PR" | jq '.draft')"
echo "Merged:    $(echo "$PR" | jq '.merged')"
echo "Mergeable: $(echo "$PR" | jq '.mergeable')"
echo "Changes:   +$(echo "$PR" | jq '.additions') -$(echo "$PR" | jq '.deletions') in $(echo "$PR" | jq '.changed_files') files"
echo "Comments:  $(echo "$PR" | jq '.comments') general, $(echo "$PR" | jq '.review_comments') review"

# Check staleness
PR_BASE_SHA=$(echo "$PR" | jq -r '.base.sha')
BASE_BRANCH=$(echo "$PR" | jq -r '.base.ref')
CURRENT_BASE=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/${OWNER}/${REPO}/branches/${BASE_BRANCH}" | jq -r '.commit.id')

if [ "$PR_BASE_SHA" != "$CURRENT_BASE" ]; then
  echo "Status:    STALE (base branch has new commits)"
else
  echo "Status:    Up to date"
fi