fix(gitea-releases): restore the prerelease imperative to the create path
The retrofit left only a descriptive sentence on the loaded path — "Gitea never infers a prerelease from a -beta/-rc tag name" — and moved the imperative into references/conventions.md behind a trigger listing semver naming, release-notes sourcing and release-to-tag relationships. Draft and prerelease are not in that list, and "cut a v2.0.0-beta.1" is exactly the request where the caller does not raise the topic, so the rule was unreachable from the flow that needs it. Severity comes from the repair path: the MCP surface has create, get, get_latest, list and delete only — there is no update or edit tool. A release published without is_pre_release can only be corrected by delete_release plus a fresh create, and get_latest_release points consumers at the beta meanwhile. Neither SKILL.md nor call-signatures.md said so anywhere. The flags are now set explicitly on every create, the missing update tool and its delete-and-recreate consequence are stated in the body, and the semver pass-through rule stranded behind the same trigger is promoted alongside it. call-signatures.md now cites the deployed tool description as direct evidence that get_latest_release excludes drafts, while keeping the prerelease half hedged — that remains unconfirmed. Verified live against gitea-mcp v1.7.0, read-only calls. Refs #99
This commit is contained in:
@@ -18,7 +18,7 @@ metadata:
|
||||
## Gotchas
|
||||
|
||||
- **Deleting a release never deletes its tag.** A release is a metadata wrapper around a tag, so removing both takes two independent destructive calls. The reverse — whether deleting a tag deletes its release — is *unconfirmed*; verify with `list_releases`/`get_release` after `delete_tag` rather than assume it survives.
|
||||
- **`is_draft`/`is_pre_release` are booleans the caller sets — Gitea never infers a prerelease from a `-beta`/`-rc` tag name.** The response object names them `draft`/`prerelease`; passing `draft` as an input key is silently ignored, not rejected.
|
||||
- **Set `is_draft`/`is_pre_release` explicitly on every `create_release` — Gitea never infers a prerelease from a `-beta`/`-rc` tag name.** A tag named `v2.0.0-beta.1` publishes as a full release, and becomes the repo's latest, unless `is_pre_release: true` is passed in the same call. The response object names them `draft`/`prerelease`; passing `draft` as an input key is silently ignored, not rejected.
|
||||
- **`list_releases`/`list_tags` default `per_page` to 20**, where most other gitea-mcp list tools default to 30 — a caller assuming 30 under-counts the pages a full sweep needs.
|
||||
|
||||
## Dispatch table
|
||||
@@ -37,11 +37,13 @@ metadata:
|
||||
|
||||
`target` (on `create_release`/`create_tag`) is a commitish — a branch name, existing tag, or commit SHA — the point the new tag is cut from.
|
||||
|
||||
Pass a caller-supplied `tag_name` through verbatim. Semver with a `v` prefix is a tooling convention, not a Gitea constraint — the API accepts any string — so never validate or rewrite it.
|
||||
|
||||
## Workflow
|
||||
|
||||
- [ ] **Creating a release:** Call `create_release` with `tag_name`, `target`, and `title`. Gitea is assumed to create the tag from `target` when `tag_name` does not yet exist — plausible from the API shape, not confirmed in the research docs — so a separate `create_tag` is only needed to tag a commit without wrapping it in a release. Verify with `get_tag` afterward if the caller depends on it.
|
||||
- [ ] **Creating a release:** Call `create_release` with `tag_name`, `target`, `title`, and `is_draft`/`is_pre_release` set explicitly — never left to default. **There is no update or edit tool on this surface**: `create_release`, `get_release`, `get_latest_release`, `list_releases` and `delete_release` are the whole set. A release published with the wrong flag therefore has no non-destructive repair — the only fix is `delete_release` plus a fresh `create_release`. Gitea is assumed to create the tag from `target` when `tag_name` does not yet exist — plausible from the API shape, not confirmed in the research docs — so a separate `create_tag` is only needed to tag a commit without wrapping it in a release. Verify with `get_tag` afterward if the caller depends on it.
|
||||
- [ ] **Deleting a release:** `delete_release` takes the numeric `id` and never a `tag_name`; `delete_tag` is the mirror opposite and never takes an id. With only a tag name in hand, resolve the id through `list_releases` (paginating if needed) or `get_release` first.
|
||||
- [ ] **Deleting a tag along with its release:** Delete the release first, then call `delete_tag` — confirm both are intended before proceeding, since each is irreversible on its own.
|
||||
- [ ] **Listing every page:** Loop `page: 1, 2, 3...` until a response returns fewer than `per_page` entries. Nothing here auto-paginates.
|
||||
|
||||
If exact input params or response field shapes are needed, read `references/call-signatures.md`. If the caller raises semver tag naming, release-notes sourcing, or how a release relates to its tag, read `references/conventions.md`.
|
||||
If exact input params or response field shapes are needed, read `references/call-signatures.md`. If the caller raises semver tag naming, draft/prerelease semantics, release-notes sourcing, or how a release relates to its tag, read `references/conventions.md`.
|
||||
|
||||
Reference in New Issue
Block a user