Add forgejo_list_milestones tool #21

Closed
opened 2026-08-18 02:34:19 +00:00 by david · 1 comment
Owner

Summary

Add a listMilestones() function to src/milestones.ts and register a forgejo_list_milestones tool, so milestones can be browsed/filtered (id lookup for use in forgejo_issue_create/forgejo_pr_create's milestone param, which currently accepts ids only with no way to discover them).

Background

Depends on: #20 (Add forgejo_milestone_create tool) (needs the ForgejoMilestone interface, milestonePath() helper, and src/milestones.ts file scaffolding from that issue).

This extension's forgejo_issue_search/forgejo_pr_search tools already establish the pattern for filterable list/search tools: query params state, page, limit built into a URLSearchParams, GET request, array response. forgejo_list_milestones follows the same shape but for milestones, adding a name filter too (supported natively by the Forgejo API).

Implementation Details

Confirmed Forgejo/Gitea API v1 contract:

GET /repos/{owner}/{repo}/milestones (operationId issueGetMilestonesList)

Query params: state? (open/closed/all, default open), name? (filter by milestone name), page?, limit?.

Response (200): Milestone[] (see ForgejoMilestone interface from the create-milestone issue).

Files to change:

  1. src/milestones.ts:

    • Add ListMilestonesOptions interface: { state?: "open" | "closed" | "all"; name?: string; page?: number; limit?: number }.
    • Add listMilestones(target: ForgejoTarget, options: ListMilestonesOptions): Promise<Result<ForgejoMilestone[], ApiError>> — build a URLSearchParams from the options (mirroring searchIssues() in src/issues.ts), GET via forgejoApiCall.
  2. src/index.ts:

    • Import listMilestones from ./milestones.
    • Register forgejo_list_milestones tool:
      • label: "List Milestones"
      • promptSnippet: "List Forgejo milestones"
      • promptGuidelines: e.g. ["Run forgejo_list_milestones before passing a milestone id to forgejo_issue_create or forgejo_pr_create."]
      • parameters: Type.Object({ ...targetOverrides, state: Type.Optional(Type.Union([Type.Literal("open"), Type.Literal("closed"), Type.Literal("all")])), name: Type.Optional(Type.String(...)), page: Type.Optional(Type.Integer({ minimum: 1 })), limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 100 })) })
      • execute: resolve target, call listMilestones, return a text listing (id — title (state)) plus structured details.milestones, matching the style of forgejo_list_labels/forgejo_issue_search.
  3. tests/milestones.test.ts: add unit tests for listMilestones() — verify query string construction (all filter combinations), GET method, and success/error propagation.

  4. Tool-registration tests: add coverage for forgejo_list_milestones — schema shape, execute() with/without filters, empty-list text ("No milestones..." style, matching forgejo_list_labels's "No labels in this repository.").

Acceptance Criteria

  • listMilestones() exists in src/milestones.ts, builds the correct query string for state/name/page/limit, and returns Result<ForgejoMilestone[], ApiError>.
  • forgejo_list_milestones tool is registered with all four filters optional, plus targetOverrides.
  • Output text lists each milestone's id, title, and state; details includes the full milestone array and a count.
  • Empty results produce a clear "no milestones" message rather than an empty/blank response.
  • Unit tests cover listMilestones() (all filter combinations) and the tool registration/execution path.
  • npm test and npm run check pass with no regressions.

Test Plan

  1. Run npm test — new tests for listMilestones() and forgejo_list_milestones pass; full suite green.
  2. Run npm run check — lint/typecheck passes.
  3. Manual smoke test: after creating a milestone via forgejo_milestone_create, call forgejo_list_milestones state="open" and confirm it appears with the correct id; call with state="all" after closing it and confirm it still appears.
## Summary Add a `listMilestones()` function to `src/milestones.ts` and register a `forgejo_list_milestones` tool, so milestones can be browsed/filtered (id lookup for use in `forgejo_issue_create`/`forgejo_pr_create`'s `milestone` param, which currently accepts ids only with no way to discover them). ## Background **Depends on:** #20 (Add forgejo_milestone_create tool) (needs the `ForgejoMilestone` interface, `milestonePath()` helper, and `src/milestones.ts` file scaffolding from that issue). This extension's `forgejo_issue_search`/`forgejo_pr_search` tools already establish the pattern for filterable list/search tools: query params `state`, `page`, `limit` built into a `URLSearchParams`, GET request, array response. `forgejo_list_milestones` follows the same shape but for milestones, adding a `name` filter too (supported natively by the Forgejo API). ## Implementation Details **Confirmed Forgejo/Gitea API v1 contract:** `GET /repos/{owner}/{repo}/milestones` (operationId `issueGetMilestonesList`) Query params: `state?` (`open`/`closed`/`all`, default `open`), `name?` (filter by milestone name), `page?`, `limit?`. Response (`200`): `Milestone[]` (see `ForgejoMilestone` interface from the create-milestone issue). **Files to change:** 1. `src/milestones.ts`: - Add `ListMilestonesOptions` interface: `{ state?: "open" | "closed" | "all"; name?: string; page?: number; limit?: number }`. - Add `listMilestones(target: ForgejoTarget, options: ListMilestonesOptions): Promise<Result<ForgejoMilestone[], ApiError>>` — build a `URLSearchParams` from the options (mirroring `searchIssues()` in `src/issues.ts`), GET via `forgejoApiCall`. 2. `src/index.ts`: - Import `listMilestones` from `./milestones`. - Register `forgejo_list_milestones` tool: - `label`: "List Milestones" - `promptSnippet`: "List Forgejo milestones" - `promptGuidelines`: e.g. `["Run forgejo_list_milestones before passing a milestone id to forgejo_issue_create or forgejo_pr_create."]` - `parameters`: `Type.Object({ ...targetOverrides, state: Type.Optional(Type.Union([Type.Literal("open"), Type.Literal("closed"), Type.Literal("all")])), name: Type.Optional(Type.String(...)), page: Type.Optional(Type.Integer({ minimum: 1 })), limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 100 })) })` - `execute`: resolve target, call `listMilestones`, return a text listing (`id — title (state)`) plus structured `details.milestones`, matching the style of `forgejo_list_labels`/`forgejo_issue_search`. 3. `tests/milestones.test.ts`: add unit tests for `listMilestones()` — verify query string construction (all filter combinations), GET method, and success/error propagation. 4. Tool-registration tests: add coverage for `forgejo_list_milestones` — schema shape, execute() with/without filters, empty-list text ("No milestones..." style, matching `forgejo_list_labels`'s "No labels in this repository."). ## Acceptance Criteria - [ ] `listMilestones()` exists in `src/milestones.ts`, builds the correct query string for `state`/`name`/`page`/`limit`, and returns `Result<ForgejoMilestone[], ApiError>`. - [ ] `forgejo_list_milestones` tool is registered with all four filters optional, plus `targetOverrides`. - [ ] Output text lists each milestone's id, title, and state; `details` includes the full milestone array and a `count`. - [ ] Empty results produce a clear "no milestones" message rather than an empty/blank response. - [ ] Unit tests cover `listMilestones()` (all filter combinations) and the tool registration/execution path. - [ ] `npm test` and `npm run check` pass with no regressions. ## Test Plan 1. Run `npm test` — new tests for `listMilestones()` and `forgejo_list_milestones` pass; full suite green. 2. Run `npm run check` — lint/typecheck passes. 3. Manual smoke test: after creating a milestone via `forgejo_milestone_create`, call `forgejo_list_milestones state="open"` and confirm it appears with the correct id; call with `state="all"` after closing it and confirm it still appears.
david closed this issue 2026-08-18 08:02:41 +00:00
Author
Owner

pi-loop opened and merged a pull request for this issue: #35

pi-loop opened and merged a pull request for this issue: https://git.excelera.net/david/pi-extensions-and-skills/pulls/35
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
david/pi-extensions-and-skills#21
No description provided.