From 4c9d2d7751f011bd71fa1e31677634fea84ac938 Mon Sep 17 00:00:00 2001 From: Defame1297 Date: Mon, 17 Aug 2026 16:58:56 +0000 Subject: [PATCH 1/2] fix(gitea): correct which pull_request_write params apply on create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gitea-prs reference documented `milestone` as "settable on both "create" and "update"". It is not: `pull_request_write method: "create"` accepts the parameter, returns no error or warning, and discards it. Verified against the gitea-mcp v1.6.0 source rather than by observation alone. `createPullRequestFn` builds its `CreatePullRequestOption` from owner, repo, title, body, head, base, draft, labels and deadline only — so the drop is not limited to `milestone` as issue #104 supposed. `assignee`, `assignees`, `reviewers` and `team_reviewers` are discarded on create too, and `reviewers`/`team_reviewers` are discarded on "update" as well; they are only ever read by "add_reviewers" and "remove_reviewers". Two properties made the original error easy to make and hard to catch, so both are now written down next to the correction: `labels` sits beside `milestone`, reads identically, and does apply on create; and `issue_write method: "create"` honours `assignees` and `milestone`, so the asymmetry is specific to pull requests. While in the file, corrected the adjacent draft gotcha. It prescribed reconstructing the un-prefixed title by hand to un-draft a PR; `applyDraftPrefix` shows "update" with `draft: false` and no `title` fetches the stored title and strips the prefix server-side. Impact: documentation only, no behaviour change. Callers following the old text silently created PRs with no milestone, assignee or reviewer. Confined to references/pull-requests.md, so the ADR-0020 skill gates do not apply and gitea-prs needs no #99 retrofit first. Fixes: #104 Refs: #99 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01ETxbGFetkbJQBHsx442Brt --- .../gitea-prs/references/pull-requests.md | 25 +++++++++++++------ .../gitea-prs/references/pull-requests.md | 25 +++++++++++++------ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md b/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md index 93986e6..0650c67 100644 --- a/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md +++ b/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md @@ -41,7 +41,7 @@ List responses trim PRs down to summary fields — `head`/`base` are bare ref st - `"get_files"` returns the list of changed file objects. - `"get_status"` returns the combined commit status for the PR's head commit — CI result only, not review/approval state (see `references/merging.md`). -**Milestone gotcha:** because `pull_request_read` only ever returns a milestone title, never an ID, resolving "which milestone ID does this PR belong to" requires calling into `gitea-labels-milestones`' `milestone_read method: "list"` and matching by title. Do not attempt to infer or guess the ID. +**Milestone gotcha:** because `pull_request_read` only ever returns a milestone title, never an ID, resolving "which milestone ID does this PR belong to" requires calling into `gitea-labels-milestones`' `milestone_read method: "list"` and matching by title. Do not attempt to infer or guess the ID. This is the read-side milestone problem; for the separate write-side one, see the `"create"` drop Gotcha under `pull_request_write`. ## `pull_request_write` @@ -54,22 +54,31 @@ List responses trim PRs down to summary fields — `head`/`base` are bare ref st - `body` (string, required for `"create"`; optional for `"update"`) - `head` (string, required for `"create"`) — source branch; same-repo PRs use a bare branch name, cross-repo fork PRs use `"fork-owner:branch-name"` (see Gotcha) - `base` (string, required for `"create"`) — target branch -- `assignee` (string, optional) — single login -- `assignees` (array of strings, optional) — login names -- `milestone` (number, optional) — milestone ID, never a title; settable on both `"create"` and `"update"` +- `assignee` (string, optional) — single login; **`"update"` only** — silently dropped on `"create"` (see Gotcha) +- `assignees` (array of strings, optional) — login names; **`"update"` only** — silently dropped on `"create"` (see Gotcha) +- `milestone` (number, optional) — milestone ID, never a title; **`"update"` only** — silently dropped on `"create"` (see Gotcha) - `state` (string, optional, for `"update"`) — `"open"` | `"closed"` (no `"all"` — unlike issue state filters) - `allow_maintainer_edit` (boolean, optional, for `"update"`) - `labels` (array of numbers, optional) — label IDs, never names — resolve via `gitea-labels-milestones` first - `deadline` (string, optional) — ISO 8601 - `remove_deadline` (boolean, optional) -- `reviewers` (array of strings, optional) — login names; settable directly on `"create"`, or use `"add_reviewers"`/`"remove_reviewers"` to adjust reviewers on an already-open PR -- `team_reviewers` (array of strings, optional) — same as `reviewers`: settable on `"create"`, or via `"add_reviewers"`/`"remove_reviewers"` post-creation -- `draft` (boolean, optional, for `"create"`) — prepends `"WIP:"` to the title (see Gotcha) +- `reviewers` (array of strings, optional) — login names; **`"add_reviewers"`/`"remove_reviewers"` only** — silently dropped on both `"create"` and `"update"` (see Gotcha) +- `team_reviewers` (array of strings, optional) — same as `reviewers`: `"add_reviewers"`/`"remove_reviewers"` only +- `draft` (boolean, optional) — prepends `"WIP:"` to the title; honoured on both `"create"` and `"update"` (see Gotcha) Merge-specific parameters (`merge_style`, `delete_branch`, `force_merge`, `merge_when_checks_succeed`, `head_commit_id`, `message` as merge commit message) are covered in `references/merging.md`. +**`"create"` silently drops most optional parameters.** `"create"` reads only `owner`, `repo`, `title`, `body`, `head`, `base`, `draft`, `labels`, and `deadline`. Every other optional parameter — `assignee`, `assignees`, `milestone`, `reviewers`, `team_reviewers` — is accepted without error and discarded. There is no error, no warning, and nothing in the response distinguishing a dropped parameter from one that was never passed: the response simply omits the key. Setting any of them requires a second call after the PR exists — `"update"` for `assignee`/`assignees`/`milestone`, `"add_reviewers"` for `reviewers`/`team_reviewers`. + +Two things make this easy to miss: + +- **`labels` does apply on `"create"`.** It sits next to `milestone` in the parameter list and reads identically, so a caller who confirms the labels landed will reasonably assume the milestone did too. +- **`issue_write method: "create"` does honour `assignees` and `milestone`.** The asymmetry is specific to pull requests; experience with the issue write does not transfer. + +To verify a milestone actually applied, re-read the PR and check for the `milestone` key, or check that the milestone's `open_issues` count moved — the create response alone cannot tell you. + **Cross-repo head format:** `head` must be `"fork-owner:branch-name"` for a PR originating from a fork of the base repo. Passing a bare branch name causes Gitea to search for that branch in the base repo instead, and returns 422 when it isn't found there. -**Draft/WIP behavior:** `draft: true` on `"create"` is implemented by prepending `"WIP:"` to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call `"update"` with `title` set to the same text minus the `"WIP:"` prefix; there is no dedicated undraft method. +**Draft/WIP behavior:** `draft: true` on `"create"` is implemented by prepending `"WIP:"` to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call `"update"` with `draft: false` and no `title` — the server reads the PR's current title and strips the prefix itself, so you do not need to reconstruct the un-prefixed text. Passing `title` alongside `draft` applies the prefix rule to the title you passed rather than the stored one. **`update_branch`:** takes only `owner`, `repo`, `pull_number` — no other parameters. It merges the current base branch into the PR's head branch server-side, resolving a PR that Gitea reports as behind its base (analogous to GitHub's "Update branch" button). Use it when a PR shows `mergeable: false` or an out-of-date status due to base-branch drift rather than an actual conflict; if the head and base have truly diverged with conflicting changes, this call fails and the conflict must be resolved by pushing a merge/rebase to the head branch directly, outside this skill's scope. diff --git a/plugins/gitea/skills/gitea-prs/references/pull-requests.md b/plugins/gitea/skills/gitea-prs/references/pull-requests.md index 93986e6..0650c67 100644 --- a/plugins/gitea/skills/gitea-prs/references/pull-requests.md +++ b/plugins/gitea/skills/gitea-prs/references/pull-requests.md @@ -41,7 +41,7 @@ List responses trim PRs down to summary fields — `head`/`base` are bare ref st - `"get_files"` returns the list of changed file objects. - `"get_status"` returns the combined commit status for the PR's head commit — CI result only, not review/approval state (see `references/merging.md`). -**Milestone gotcha:** because `pull_request_read` only ever returns a milestone title, never an ID, resolving "which milestone ID does this PR belong to" requires calling into `gitea-labels-milestones`' `milestone_read method: "list"` and matching by title. Do not attempt to infer or guess the ID. +**Milestone gotcha:** because `pull_request_read` only ever returns a milestone title, never an ID, resolving "which milestone ID does this PR belong to" requires calling into `gitea-labels-milestones`' `milestone_read method: "list"` and matching by title. Do not attempt to infer or guess the ID. This is the read-side milestone problem; for the separate write-side one, see the `"create"` drop Gotcha under `pull_request_write`. ## `pull_request_write` @@ -54,22 +54,31 @@ List responses trim PRs down to summary fields — `head`/`base` are bare ref st - `body` (string, required for `"create"`; optional for `"update"`) - `head` (string, required for `"create"`) — source branch; same-repo PRs use a bare branch name, cross-repo fork PRs use `"fork-owner:branch-name"` (see Gotcha) - `base` (string, required for `"create"`) — target branch -- `assignee` (string, optional) — single login -- `assignees` (array of strings, optional) — login names -- `milestone` (number, optional) — milestone ID, never a title; settable on both `"create"` and `"update"` +- `assignee` (string, optional) — single login; **`"update"` only** — silently dropped on `"create"` (see Gotcha) +- `assignees` (array of strings, optional) — login names; **`"update"` only** — silently dropped on `"create"` (see Gotcha) +- `milestone` (number, optional) — milestone ID, never a title; **`"update"` only** — silently dropped on `"create"` (see Gotcha) - `state` (string, optional, for `"update"`) — `"open"` | `"closed"` (no `"all"` — unlike issue state filters) - `allow_maintainer_edit` (boolean, optional, for `"update"`) - `labels` (array of numbers, optional) — label IDs, never names — resolve via `gitea-labels-milestones` first - `deadline` (string, optional) — ISO 8601 - `remove_deadline` (boolean, optional) -- `reviewers` (array of strings, optional) — login names; settable directly on `"create"`, or use `"add_reviewers"`/`"remove_reviewers"` to adjust reviewers on an already-open PR -- `team_reviewers` (array of strings, optional) — same as `reviewers`: settable on `"create"`, or via `"add_reviewers"`/`"remove_reviewers"` post-creation -- `draft` (boolean, optional, for `"create"`) — prepends `"WIP:"` to the title (see Gotcha) +- `reviewers` (array of strings, optional) — login names; **`"add_reviewers"`/`"remove_reviewers"` only** — silently dropped on both `"create"` and `"update"` (see Gotcha) +- `team_reviewers` (array of strings, optional) — same as `reviewers`: `"add_reviewers"`/`"remove_reviewers"` only +- `draft` (boolean, optional) — prepends `"WIP:"` to the title; honoured on both `"create"` and `"update"` (see Gotcha) Merge-specific parameters (`merge_style`, `delete_branch`, `force_merge`, `merge_when_checks_succeed`, `head_commit_id`, `message` as merge commit message) are covered in `references/merging.md`. +**`"create"` silently drops most optional parameters.** `"create"` reads only `owner`, `repo`, `title`, `body`, `head`, `base`, `draft`, `labels`, and `deadline`. Every other optional parameter — `assignee`, `assignees`, `milestone`, `reviewers`, `team_reviewers` — is accepted without error and discarded. There is no error, no warning, and nothing in the response distinguishing a dropped parameter from one that was never passed: the response simply omits the key. Setting any of them requires a second call after the PR exists — `"update"` for `assignee`/`assignees`/`milestone`, `"add_reviewers"` for `reviewers`/`team_reviewers`. + +Two things make this easy to miss: + +- **`labels` does apply on `"create"`.** It sits next to `milestone` in the parameter list and reads identically, so a caller who confirms the labels landed will reasonably assume the milestone did too. +- **`issue_write method: "create"` does honour `assignees` and `milestone`.** The asymmetry is specific to pull requests; experience with the issue write does not transfer. + +To verify a milestone actually applied, re-read the PR and check for the `milestone` key, or check that the milestone's `open_issues` count moved — the create response alone cannot tell you. + **Cross-repo head format:** `head` must be `"fork-owner:branch-name"` for a PR originating from a fork of the base repo. Passing a bare branch name causes Gitea to search for that branch in the base repo instead, and returns 422 when it isn't found there. -**Draft/WIP behavior:** `draft: true` on `"create"` is implemented by prepending `"WIP:"` to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call `"update"` with `title` set to the same text minus the `"WIP:"` prefix; there is no dedicated undraft method. +**Draft/WIP behavior:** `draft: true` on `"create"` is implemented by prepending `"WIP:"` to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call `"update"` with `draft: false` and no `title` — the server reads the PR's current title and strips the prefix itself, so you do not need to reconstruct the un-prefixed text. Passing `title` alongside `draft` applies the prefix rule to the title you passed rather than the stored one. **`update_branch`:** takes only `owner`, `repo`, `pull_number` — no other parameters. It merges the current base branch into the PR's head branch server-side, resolving a PR that Gitea reports as behind its base (analogous to GitHub's "Update branch" button). Use it when a PR shows `mergeable: false` or an out-of-date status due to base-branch drift rather than an actual conflict; if the head and base have truly diverged with conflicting changes, this call fails and the conflict must be resolved by pushing a merge/rebase to the head branch directly, outside this skill's scope. -- 2.43.0 From 967d3ade255b4b967e5f31bbc157fce5ff586034 Mon Sep 17 00:00:00 2001 From: Defame1297 Date: Mon, 17 Aug 2026 17:29:06 +0000 Subject: [PATCH 2/2] fix(gitea): document the remaining create/update parameter asymmetries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the review of #106, which found four parameter claims the first pass left wrong or missing. All four verified against gitea-mcp v1.6.0 source before changing anything. `remove_deadline` is dropped on "create" like the others, but the new Gotcha enumerated a closed list that omitted it — so the paragraph contradicted its own opening sentence. The list is now open ("including") and the parameter carries the same "update" only marker as its neighbours. `base` is settable on "update": editPullRequestFn reads it and retargets the PR onto a different base branch. The file documented it as required for "create" and said nothing else, hiding a real capability. This one is under-claiming rather than over-claiming, but a file whose subject is which parameter applies to which method is the place to fix it. applyDraftPrefix strips two prefixes, `WIP:` and `[WIP]`, matched with strings.EqualFold, while only "WIP: " is ever added. The un-draft correction said "the prefix" singular, which understates what a caller can hand it. README.md bundled `reviewers` and `milestone` into "creating and updating". Capability prose rather than a parameter contract, so not strictly false, but it is the same conflation that produced the original bug and it is not behind any gate. Not addressed here: SKILL.md's description still advertises updating reviewers, its draft guidance still prescribes the manual workaround, and its milestone-resolution instruction carries no method qualifier — so an agent working from SKILL.md alone can still reach the failure mode. Those edits trip skill-size-check and the Vale prefilter, pulling in the ADR-0020 retrofit; tracked on #99 rather than done silently here. Refs: #104 Refs: #99 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01ETxbGFetkbJQBHsx442Brt --- plugins/gitea/.apm/skills/gitea-prs/README.md | 2 +- .../.apm/skills/gitea-prs/references/pull-requests.md | 8 ++++---- plugins/gitea/skills/gitea-prs/README.md | 2 +- .../gitea/skills/gitea-prs/references/pull-requests.md | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/gitea/.apm/skills/gitea-prs/README.md b/plugins/gitea/.apm/skills/gitea-prs/README.md index 3f6841e..7236390 100644 --- a/plugins/gitea/.apm/skills/gitea-prs/README.md +++ b/plugins/gitea/.apm/skills/gitea-prs/README.md @@ -4,7 +4,7 @@ List, read, create, update, merge, and review Gitea pull requests. ## What it does -This skill handles the pull request lifecycle within the Gitea integration suite — listing and reading PRs (details, diff, changed files, CI status, reviews), creating and updating them (title, body, reviewers, labels, milestone), closing/reopening, merging with a chosen strategy and post-merge branch cleanup, and the full code-review flow (create a review with inline comments, submit it, dismiss or delete it). It composes `gitea-labels-milestones` for label/milestone ID resolution rather than duplicating that logic, and defers to `gitea-issues` for anything that turns out to be an issue rather than a PR (they share one number space) and to `gitea-branches`/`gitea-files` for the underlying branch/file operations behind a PR. +This skill handles the pull request lifecycle within the Gitea integration suite — listing and reading PRs (details, diff, changed files, CI status, reviews), creating them (title, body, labels), updating them (title, body, assignees, labels, milestone), managing reviewers, closing/reopening, merging with a chosen strategy and post-merge branch cleanup, and the full code-review flow (create a review with inline comments, submit it, dismiss or delete it). It composes `gitea-labels-milestones` for label/milestone ID resolution rather than duplicating that logic, and defers to `gitea-issues` for anything that turns out to be an issue rather than a PR (they share one number space) and to `gitea-branches`/`gitea-files` for the underlying branch/file operations behind a PR. ## Usage diff --git a/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md b/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md index 0650c67..05084d4 100644 --- a/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md +++ b/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md @@ -53,7 +53,7 @@ List responses trim PRs down to summary fields — `head`/`base` are bare ref st - `title` (string, required for `"create"`; optional for `"update"`) - `body` (string, required for `"create"`; optional for `"update"`) - `head` (string, required for `"create"`) — source branch; same-repo PRs use a bare branch name, cross-repo fork PRs use `"fork-owner:branch-name"` (see Gotcha) -- `base` (string, required for `"create"`) — target branch +- `base` (string, required for `"create"`; optional for `"update"`) — target branch; passing it on `"update"` retargets an open PR onto a different base - `assignee` (string, optional) — single login; **`"update"` only** — silently dropped on `"create"` (see Gotcha) - `assignees` (array of strings, optional) — login names; **`"update"` only** — silently dropped on `"create"` (see Gotcha) - `milestone` (number, optional) — milestone ID, never a title; **`"update"` only** — silently dropped on `"create"` (see Gotcha) @@ -61,14 +61,14 @@ List responses trim PRs down to summary fields — `head`/`base` are bare ref st - `allow_maintainer_edit` (boolean, optional, for `"update"`) - `labels` (array of numbers, optional) — label IDs, never names — resolve via `gitea-labels-milestones` first - `deadline` (string, optional) — ISO 8601 -- `remove_deadline` (boolean, optional) +- `remove_deadline` (boolean, optional) — **`"update"` only** — silently dropped on `"create"` (harmless there, but it does not do anything) - `reviewers` (array of strings, optional) — login names; **`"add_reviewers"`/`"remove_reviewers"` only** — silently dropped on both `"create"` and `"update"` (see Gotcha) - `team_reviewers` (array of strings, optional) — same as `reviewers`: `"add_reviewers"`/`"remove_reviewers"` only - `draft` (boolean, optional) — prepends `"WIP:"` to the title; honoured on both `"create"` and `"update"` (see Gotcha) Merge-specific parameters (`merge_style`, `delete_branch`, `force_merge`, `merge_when_checks_succeed`, `head_commit_id`, `message` as merge commit message) are covered in `references/merging.md`. -**`"create"` silently drops most optional parameters.** `"create"` reads only `owner`, `repo`, `title`, `body`, `head`, `base`, `draft`, `labels`, and `deadline`. Every other optional parameter — `assignee`, `assignees`, `milestone`, `reviewers`, `team_reviewers` — is accepted without error and discarded. There is no error, no warning, and nothing in the response distinguishing a dropped parameter from one that was never passed: the response simply omits the key. Setting any of them requires a second call after the PR exists — `"update"` for `assignee`/`assignees`/`milestone`, `"add_reviewers"` for `reviewers`/`team_reviewers`. +**`"create"` silently drops most optional parameters.** `"create"` reads only `owner`, `repo`, `title`, `body`, `head`, `base`, `draft`, `labels`, and `deadline`. Every other optional parameter — including `assignee`, `assignees`, `milestone`, `reviewers`, `team_reviewers` and `remove_deadline` — is accepted without error and discarded. There is no error, no warning, and nothing in the response distinguishing a dropped parameter from one that was never passed: the response simply omits the key. Setting any of them requires a second call after the PR exists — `"update"` for `assignee`/`assignees`/`milestone`, `"add_reviewers"` for `reviewers`/`team_reviewers`. Two things make this easy to miss: @@ -79,6 +79,6 @@ To verify a milestone actually applied, re-read the PR and check for the `milest **Cross-repo head format:** `head` must be `"fork-owner:branch-name"` for a PR originating from a fork of the base repo. Passing a bare branch name causes Gitea to search for that branch in the base repo instead, and returns 422 when it isn't found there. -**Draft/WIP behavior:** `draft: true` on `"create"` is implemented by prepending `"WIP:"` to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call `"update"` with `draft: false` and no `title` — the server reads the PR's current title and strips the prefix itself, so you do not need to reconstruct the un-prefixed text. Passing `title` alongside `draft` applies the prefix rule to the title you passed rather than the stored one. +**Draft/WIP behavior:** `draft: true` on `"create"` is implemented by prepending `"WIP:"` to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call `"update"` with `draft: false` and no `title` — the server reads the PR's current title and strips the prefix itself, so you do not need to reconstruct the un-prefixed text. Two prefixes are recognised for stripping — `WIP:` and `[WIP]` — matched case-insensitively, even though only `"WIP: "` is ever added. Passing `title` alongside `draft` applies the prefix rule to the title you passed rather than the stored one. **`update_branch`:** takes only `owner`, `repo`, `pull_number` — no other parameters. It merges the current base branch into the PR's head branch server-side, resolving a PR that Gitea reports as behind its base (analogous to GitHub's "Update branch" button). Use it when a PR shows `mergeable: false` or an out-of-date status due to base-branch drift rather than an actual conflict; if the head and base have truly diverged with conflicting changes, this call fails and the conflict must be resolved by pushing a merge/rebase to the head branch directly, outside this skill's scope. diff --git a/plugins/gitea/skills/gitea-prs/README.md b/plugins/gitea/skills/gitea-prs/README.md index 3f6841e..7236390 100644 --- a/plugins/gitea/skills/gitea-prs/README.md +++ b/plugins/gitea/skills/gitea-prs/README.md @@ -4,7 +4,7 @@ List, read, create, update, merge, and review Gitea pull requests. ## What it does -This skill handles the pull request lifecycle within the Gitea integration suite — listing and reading PRs (details, diff, changed files, CI status, reviews), creating and updating them (title, body, reviewers, labels, milestone), closing/reopening, merging with a chosen strategy and post-merge branch cleanup, and the full code-review flow (create a review with inline comments, submit it, dismiss or delete it). It composes `gitea-labels-milestones` for label/milestone ID resolution rather than duplicating that logic, and defers to `gitea-issues` for anything that turns out to be an issue rather than a PR (they share one number space) and to `gitea-branches`/`gitea-files` for the underlying branch/file operations behind a PR. +This skill handles the pull request lifecycle within the Gitea integration suite — listing and reading PRs (details, diff, changed files, CI status, reviews), creating them (title, body, labels), updating them (title, body, assignees, labels, milestone), managing reviewers, closing/reopening, merging with a chosen strategy and post-merge branch cleanup, and the full code-review flow (create a review with inline comments, submit it, dismiss or delete it). It composes `gitea-labels-milestones` for label/milestone ID resolution rather than duplicating that logic, and defers to `gitea-issues` for anything that turns out to be an issue rather than a PR (they share one number space) and to `gitea-branches`/`gitea-files` for the underlying branch/file operations behind a PR. ## Usage diff --git a/plugins/gitea/skills/gitea-prs/references/pull-requests.md b/plugins/gitea/skills/gitea-prs/references/pull-requests.md index 0650c67..05084d4 100644 --- a/plugins/gitea/skills/gitea-prs/references/pull-requests.md +++ b/plugins/gitea/skills/gitea-prs/references/pull-requests.md @@ -53,7 +53,7 @@ List responses trim PRs down to summary fields — `head`/`base` are bare ref st - `title` (string, required for `"create"`; optional for `"update"`) - `body` (string, required for `"create"`; optional for `"update"`) - `head` (string, required for `"create"`) — source branch; same-repo PRs use a bare branch name, cross-repo fork PRs use `"fork-owner:branch-name"` (see Gotcha) -- `base` (string, required for `"create"`) — target branch +- `base` (string, required for `"create"`; optional for `"update"`) — target branch; passing it on `"update"` retargets an open PR onto a different base - `assignee` (string, optional) — single login; **`"update"` only** — silently dropped on `"create"` (see Gotcha) - `assignees` (array of strings, optional) — login names; **`"update"` only** — silently dropped on `"create"` (see Gotcha) - `milestone` (number, optional) — milestone ID, never a title; **`"update"` only** — silently dropped on `"create"` (see Gotcha) @@ -61,14 +61,14 @@ List responses trim PRs down to summary fields — `head`/`base` are bare ref st - `allow_maintainer_edit` (boolean, optional, for `"update"`) - `labels` (array of numbers, optional) — label IDs, never names — resolve via `gitea-labels-milestones` first - `deadline` (string, optional) — ISO 8601 -- `remove_deadline` (boolean, optional) +- `remove_deadline` (boolean, optional) — **`"update"` only** — silently dropped on `"create"` (harmless there, but it does not do anything) - `reviewers` (array of strings, optional) — login names; **`"add_reviewers"`/`"remove_reviewers"` only** — silently dropped on both `"create"` and `"update"` (see Gotcha) - `team_reviewers` (array of strings, optional) — same as `reviewers`: `"add_reviewers"`/`"remove_reviewers"` only - `draft` (boolean, optional) — prepends `"WIP:"` to the title; honoured on both `"create"` and `"update"` (see Gotcha) Merge-specific parameters (`merge_style`, `delete_branch`, `force_merge`, `merge_when_checks_succeed`, `head_commit_id`, `message` as merge commit message) are covered in `references/merging.md`. -**`"create"` silently drops most optional parameters.** `"create"` reads only `owner`, `repo`, `title`, `body`, `head`, `base`, `draft`, `labels`, and `deadline`. Every other optional parameter — `assignee`, `assignees`, `milestone`, `reviewers`, `team_reviewers` — is accepted without error and discarded. There is no error, no warning, and nothing in the response distinguishing a dropped parameter from one that was never passed: the response simply omits the key. Setting any of them requires a second call after the PR exists — `"update"` for `assignee`/`assignees`/`milestone`, `"add_reviewers"` for `reviewers`/`team_reviewers`. +**`"create"` silently drops most optional parameters.** `"create"` reads only `owner`, `repo`, `title`, `body`, `head`, `base`, `draft`, `labels`, and `deadline`. Every other optional parameter — including `assignee`, `assignees`, `milestone`, `reviewers`, `team_reviewers` and `remove_deadline` — is accepted without error and discarded. There is no error, no warning, and nothing in the response distinguishing a dropped parameter from one that was never passed: the response simply omits the key. Setting any of them requires a second call after the PR exists — `"update"` for `assignee`/`assignees`/`milestone`, `"add_reviewers"` for `reviewers`/`team_reviewers`. Two things make this easy to miss: @@ -79,6 +79,6 @@ To verify a milestone actually applied, re-read the PR and check for the `milest **Cross-repo head format:** `head` must be `"fork-owner:branch-name"` for a PR originating from a fork of the base repo. Passing a bare branch name causes Gitea to search for that branch in the base repo instead, and returns 422 when it isn't found there. -**Draft/WIP behavior:** `draft: true` on `"create"` is implemented by prepending `"WIP:"` to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call `"update"` with `draft: false` and no `title` — the server reads the PR's current title and strips the prefix itself, so you do not need to reconstruct the un-prefixed text. Passing `title` alongside `draft` applies the prefix rule to the title you passed rather than the stored one. +**Draft/WIP behavior:** `draft: true` on `"create"` is implemented by prepending `"WIP:"` to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call `"update"` with `draft: false` and no `title` — the server reads the PR's current title and strips the prefix itself, so you do not need to reconstruct the un-prefixed text. Two prefixes are recognised for stripping — `WIP:` and `[WIP]` — matched case-insensitively, even though only `"WIP: "` is ever added. Passing `title` alongside `draft` applies the prefix rule to the title you passed rather than the stored one. **`update_branch`:** takes only `owner`, `repo`, `pull_number` — no other parameters. It merges the current base branch into the PR's head branch server-side, resolving a PR that Gitea reports as behind its base (analogous to GitHub's "Update branch" button). Use it when a PR shows `mergeable: false` or an out-of-date status due to base-branch drift rather than an actual conflict; if the head and base have truly diverged with conflicting changes, this call fails and the conflict must be resolved by pushing a merge/rebase to the head branch directly, outside this skill's scope. -- 2.43.0