diff --git a/shortcuts/issue/issue.go b/shortcuts/issue/issue.go index 9eb4ca3..13b3252 100644 --- a/shortcuts/issue/issue.go +++ b/shortcuts/issue/issue.go @@ -9,6 +9,11 @@ import ( "github.com/gitlink-org/gitlink-cli/shortcuts/common" ) +// v1RepoPath returns the v1 API path prefix: /v1/{owner}/{repo} +func v1RepoPath(ctx *common.RuntimeContext) string { + return fmt.Sprintf("/v1/%s/%s", ctx.Owner, ctx.Repo) +} + type existingIssue struct { Subject string Description string @@ -34,7 +39,7 @@ func Shortcuts() []*common.Shortcut { if s := ctx.Arg("state"); s != "" { q.Set("state", s) } - env, err := ctx.CallAPIWithQuery("GET", ctx.RepoPath()+"/issues", q) + env, err := ctx.CallAPIWithQuery("GET", v1RepoPath(ctx)+"/issues", q) if err != nil { return err } @@ -61,8 +66,9 @@ func Shortcuts() []*common.Shortcut { } body := map[string]interface{}{ "subject": title, + "status_id": 1, // 1 = open (required by v1 API) + "priority_id": 2, // 2 = normal "done_ratio": 0, - "priority_id": 2, } if desc := ctx.Arg("body"); desc != "" { body["description"] = desc @@ -73,7 +79,7 @@ func Shortcuts() []*common.Shortcut { if m := ctx.Arg("milestone"); m != "" { body["fixed_version_id"] = m } - env, err := ctx.CallAPI("POST", ctx.RepoPath()+"/issues", body) + env, err := ctx.CallAPI("POST", v1RepoPath(ctx)+"/issues", body) if err != nil { return err } @@ -84,17 +90,17 @@ func Shortcuts() []*common.Shortcut { Name: "view", Description: "View issue details", Flags: []common.Flag{ - {Name: "id", Short: "i", Usage: "Issue ID or number", Required: true}, + {Name: "number", Short: "n", Usage: "Issue number (as shown in the web URL)", Required: true}, }, Run: func(ctx *common.RuntimeContext) error { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - id, err := ctx.RequireArg("id") + number, err := ctx.RequireArg("number") if err != nil { return err } - env, err := ctx.CallAPI("GET", fmt.Sprintf("%s/issues/%s", ctx.RepoPath(), id), nil) + env, err := ctx.CallAPI("GET", fmt.Sprintf("%s/issues/%s", v1RepoPath(ctx), number), nil) if err != nil { return err } @@ -105,17 +111,17 @@ func Shortcuts() []*common.Shortcut { Name: "close", Description: "Close an issue", Flags: []common.Flag{ - {Name: "id", Short: "i", Usage: "Issue ID", Required: true}, + {Name: "number", Short: "n", Usage: "Issue number (as shown in the web URL)", Required: true}, }, Run: func(ctx *common.RuntimeContext) error { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - id, err := ctx.RequireArg("id") + number, err := ctx.RequireArg("number") if err != nil { return err } - current, err := fetchExistingIssue(ctx, id) + current, err := fetchExistingIssue(ctx, number) if err != nil { return err } @@ -125,7 +131,7 @@ func Shortcuts() []*common.Shortcut { "description": current.Description, "status_id": 5, // 5 = closed } - env, err := ctx.CallAPI("PUT", fmt.Sprintf("%s/issues/%s", ctx.RepoPath(), id), body) + env, err := ctx.CallAPI("PATCH", fmt.Sprintf("%s/issues/%s", v1RepoPath(ctx), number), body) if err != nil { return err } @@ -136,7 +142,7 @@ func Shortcuts() []*common.Shortcut { Name: "update", Description: "Update an issue", Flags: []common.Flag{ - {Name: "id", Short: "i", Usage: "Issue ID", Required: true}, + {Name: "number", Short: "n", Usage: "Issue number (as shown in the web URL)", Required: true}, {Name: "title", Short: "t", Usage: "New title"}, {Name: "body", Short: "b", Usage: "New description"}, {Name: "state", Short: "s", Usage: "New state: open, closed, or numeric status_id"}, @@ -145,7 +151,7 @@ func Shortcuts() []*common.Shortcut { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - id, err := ctx.RequireArg("id") + number, err := ctx.RequireArg("number") if err != nil { return err } @@ -156,7 +162,7 @@ func Shortcuts() []*common.Shortcut { return fmt.Errorf("at least one of --title, --body, or --state is required") } - current, err := fetchExistingIssue(ctx, id) + current, err := fetchExistingIssue(ctx, number) if err != nil { return err } @@ -178,7 +184,7 @@ func Shortcuts() []*common.Shortcut { } body["status_id"] = statusID } - env, err := ctx.CallAPI("PUT", fmt.Sprintf("%s/issues/%s", ctx.RepoPath(), id), body) + env, err := ctx.CallAPI("PATCH", fmt.Sprintf("%s/issues/%s", v1RepoPath(ctx), number), body) if err != nil { return err } @@ -189,14 +195,14 @@ func Shortcuts() []*common.Shortcut { Name: "comment", Description: "Add a comment to an issue", Flags: []common.Flag{ - {Name: "id", Short: "i", Usage: "Issue ID", Required: true}, + {Name: "number", Short: "n", Usage: "Issue number (as shown in the web URL)", Required: true}, {Name: "body", Short: "b", Usage: "Comment body", Required: true}, }, Run: func(ctx *common.RuntimeContext) error { if err := ctx.ResolveOwnerRepo(); err != nil { return err } - id, err := ctx.RequireArg("id") + number, err := ctx.RequireArg("number") if err != nil { return err } @@ -205,9 +211,9 @@ func Shortcuts() []*common.Shortcut { return err } payload := map[string]interface{}{ - "content": body, + "notes": body, } - env, err := ctx.CallAPI("POST", fmt.Sprintf("/issues/%s/journals", id), payload) + env, err := ctx.CallAPI("POST", fmt.Sprintf("%s/issues/%s/journals", v1RepoPath(ctx), number), payload) if err != nil { return err } @@ -217,8 +223,8 @@ func Shortcuts() []*common.Shortcut { } } -func fetchExistingIssue(ctx *common.RuntimeContext, id string) (*existingIssue, error) { - getEnv, err := ctx.CallAPI("GET", fmt.Sprintf("%s/issues/%s", ctx.RepoPath(), id), nil) +func fetchExistingIssue(ctx *common.RuntimeContext, number string) (*existingIssue, error) { + getEnv, err := ctx.CallAPI("GET", fmt.Sprintf("%s/issues/%s", v1RepoPath(ctx), number), nil) if err != nil { return nil, err } diff --git a/skills/gitlink-issue/SKILL.md b/skills/gitlink-issue/SKILL.md index 0e16d10..9a11def 100644 --- a/skills/gitlink-issue/SKILL.md +++ b/skills/gitlink-issue/SKILL.md @@ -1,6 +1,6 @@ --- name: gitlink-issue -version: 1.0.0 +version: 2.0.0 description: "Issue 管理:创建、查看、更新、关闭 Issue,添加评论。当用户需要操作 GitLink Issue 时触发。" metadata: requires: @@ -36,36 +36,34 @@ gitlink-cli issue +list --owner Gitlink --repo forgeplus --state open # 创建 Issue gitlink-cli issue +create --owner myuser --repo myrepo --title "Bug: 登录失败" --body "复现步骤:..." -# 查看 Issue 详情 -gitlink-cli issue +view --owner Gitlink --repo forgeplus --id 123 +# 查看 Issue 详情(使用网页可见的 Issue 编号) +gitlink-cli issue +view --owner Gitlink --repo forgeplus --number 4 # 更新 Issue -gitlink-cli issue +update --id 123 --title "新标题" --body "更新描述" +gitlink-cli issue +update --number 4 --title "新标题" --body "更新描述" # 关闭 Issue -gitlink-cli issue +close --id 123 +gitlink-cli issue +close --number 4 # 添加评论 -gitlink-cli issue +comment --id 123 --body "已修复,请验证" +gitlink-cli issue +comment --number 4 --body "已修复,请验证" ``` ## Raw API 补充 ```bash -# 获取 Issue 评论列表 -gitlink-cli api GET /issues/:issue_id/journals +# 获取 Issue 评论列表(使用 v1 API,按 issue number 查询) +gitlink-cli api GET /v1/:owner/:repo/issues/:number/journals -# 批量更新 Issue +# 批量更新 Issue(仍使用旧版 API,需传数据库 ID) gitlink-cli api POST /:owner/:repo/issues/series_update --body '{"ids":[1,2,3],"status_id":"closed"}' - -# Issue 认领 -gitlink-cli api POST /issues/:issue_id/claims ``` ## GitLink Issue 字段映射 | gitlink-cli 参数 | GitLink API 字段 | 说明 | |------------------|-----------------|------| +| `--number` / `-n` | `project_issues_index` | Issue 编号(网页 URL 中的序号) | | `--title` | `subject` | Issue 标题 | | `--body` | `description` | Issue 描述 | | `--assignee` | `assigned_to_id` | 指派人 ID | @@ -74,7 +72,8 @@ gitlink-cli api POST /issues/:issue_id/claims ## API 注意事项 -- **创建 Issue 时必须包含 `done_ratio: 0`**,否则数据库报错(CLI 已自动处理) +- **Issue 编号(`--number`)是网页 URL 中看到的序号**(如 `issues/4` 中的 `4`),不是数据库内部 ID +- Issue 操作使用 v1 API(`/api/v1/`),支持按 Issue 编号查询和操作 +- **创建 Issue 时 CLI 会自动设置 `status_id: 1`(开启)和 `priority_id: 2`(正常)** - **更新/关闭 Issue 时必须保留当前 `subject` 和 `description`**,即使只修改状态(CLI 会先读取当前 Issue 并自动带回) -- 使用 Raw API 操作 Issue 时需先 `GET issue`,再把当前 `subject`、`description` 与要修改的字段一起提交,避免清空描述 -- Issue 评论路径为 `/issues/:id/journals`(不带 owner/repo 前缀) +- v1 API 写操作必须使用 `access_token`(非 `token`)认证,CLI 已自动处理 diff --git a/skills/gitlink-issue/references/gitlink-issue-close.md b/skills/gitlink-issue/references/gitlink-issue-close.md index 9f70067..10a8d93 100644 --- a/skills/gitlink-issue/references/gitlink-issue-close.md +++ b/skills/gitlink-issue/references/gitlink-issue-close.md @@ -7,15 +7,15 @@ Close an issue. Automatically fetches the current issue subject and description, ## 命令 ```bash -# Close issue #42 -gitlink-cli issue +close -i 42 +# Close issue #4 +gitlink-cli issue +close -n 4 ``` ## 参数 | 参数 | 必填 | 说明 | |------|------|------| -| `--id, -i` | **是** | Issue ID | +| `--number, -n` | **是** | Issue 编号(网页 URL 中的序号) | | `--owner` | 否 | 仓库所有者(自动从 git remote 解析) | | `--repo` | 否 | 仓库名称(自动从 git remote 解析) | | `--format` | 否 | 输出格式: `json`/`table`/`yaml` | @@ -27,18 +27,18 @@ The command performs two API calls: 1. **Fetch** the issue to get the current `subject` and `description`: ``` - GET /{owner}/{repo}/issues/{id} + GET /v1/{owner}/{repo}/issues/{number} ``` 2. **Update** the issue with `status_id=5`, preserving the current description: ``` - PUT /{owner}/{repo}/issues/{id} + PATCH /v1/{owner}/{repo}/issues/{number} Body: { "subject": , "description": , "status_id": 5 } ``` ## Workflow -1. **Confirm** with the user which issue to close (by ID). -2. **Execute** `gitlink-cli issue +close -i {id}`. +1. **Confirm** with the user which issue to close (by number). +2. **Execute** `gitlink-cli issue +close -n {number}`. 3. **Report** that the issue has been closed successfully. > [!CAUTION] diff --git a/skills/gitlink-issue/references/gitlink-issue-comment.md b/skills/gitlink-issue/references/gitlink-issue-comment.md index eccc947..9a568c3 100644 --- a/skills/gitlink-issue/references/gitlink-issue-comment.md +++ b/skills/gitlink-issue/references/gitlink-issue-comment.md @@ -7,11 +7,11 @@ Add a comment to an existing issue. ## 命令 ```bash -# Add a comment to issue #42 -gitlink-cli issue +comment -i 42 -b "This has been fixed in commit abc123" +# Add a comment to issue #4 +gitlink-cli issue +comment -n 4 -b "This has been fixed in commit abc123" # Add a multi-line comment -gitlink-cli issue +comment -i 42 -b "Investigation results: +gitlink-cli issue +comment -n 4 -b "Investigation results: - Root cause: null pointer in auth module - Fix: add nil check before dereference" ``` @@ -20,8 +20,8 @@ gitlink-cli issue +comment -i 42 -b "Investigation results: | 参数 | 必填 | 说明 | |------|------|------| -| `--id, -i` | **是** | Issue ID | -| `--body, -b` | **是** | 评论内容(映射为 API 字段 `content`) | +| `--number, -n` | **是** | Issue 编号(网页 URL 中的序号) | +| `--body, -b` | **是** | 评论内容(映射为 v1 API 字段 `notes`) | | `--owner` | 否 | 仓库所有者(自动从 git remote 解析) | | `--repo` | 否 | 仓库名称(自动从 git remote 解析) | | `--format` | 否 | 输出格式: `json`/`table`/`yaml` | @@ -30,14 +30,14 @@ gitlink-cli issue +comment -i 42 -b "Investigation results: ## API ``` -POST /issues/{id}/journals -Body: { "content": body } +POST /v1/{owner}/{repo}/issues/{number}/journals +Body: { "notes": body } ``` ## Workflow 1. **Confirm** the comment content with the user before posting. -2. **Execute** `gitlink-cli issue +comment -i {id} -b "..."`. +2. **Execute** `gitlink-cli issue +comment -n {number} -b "..."`. 3. **Report** that the comment was added successfully. > [!CAUTION] diff --git a/skills/gitlink-issue/references/gitlink-issue-create.md b/skills/gitlink-issue/references/gitlink-issue-create.md index a53b528..9966cfc 100644 --- a/skills/gitlink-issue/references/gitlink-issue-create.md +++ b/skills/gitlink-issue/references/gitlink-issue-create.md @@ -2,7 +2,7 @@ > **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../../gitlink-shared/SKILL.md) 了解认证、全局参数和安全规则。 -Create a new issue in the current repository. The `done_ratio` field is automatically set to `0`. +Create a new issue in the current repository. Uses the v1 API which requires `status_id` and `priority_id` — the CLI automatically sets defaults (`status_id: 1` = open, `priority_id: 2` = normal). ## 命令 @@ -34,15 +34,15 @@ gitlink-cli issue +create -t "Fix CI pipeline" -b "Flaky tests" -a user123 -m 5 ## API ``` -POST /{owner}/{repo}/issues -Body: { "subject": title, "done_ratio": 0, "description": body, ... } +POST /v1/{owner}/{repo}/issues +Body: { "subject": title, "status_id": 1, "priority_id": 2, "done_ratio": 0, "description": body, ... } ``` ## Workflow 1. **Confirm** the issue title (and optional body) with the user before creating. 2. **Execute** `gitlink-cli issue +create -t "..." -b "..."`. -3. **Report** the created issue ID and URL to the user. +3. **Report** the created issue number and URL to the user. > [!CAUTION] > This is a **Write Operation** -- confirm user intent before executing. diff --git a/skills/gitlink-issue/references/gitlink-issue-list.md b/skills/gitlink-issue/references/gitlink-issue-list.md index f891356..a4d11d4 100644 --- a/skills/gitlink-issue/references/gitlink-issue-list.md +++ b/skills/gitlink-issue/references/gitlink-issue-list.md @@ -2,7 +2,7 @@ > **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../../gitlink-shared/SKILL.md) 了解认证、全局参数和安全规则。 -List issues for the current repository, with optional state filter and pagination. +List issues for the current repository, with optional state filter and pagination. Uses the v1 API which returns `project_issues_index` (the issue number visible in the web URL). ## 命令 @@ -35,9 +35,23 @@ gitlink-cli issue +list --format json ## API ``` -GET /{owner}/{repo}/issues?state={state}&page={page}&limit={limit} +GET /v1/{owner}/{repo}/issues?state={state}&page={page}&limit={limit} ``` +## 返回字段(v1) + +每个 Issue 包含以下关键字段: + +| 字段 | 说明 | +|------|------| +| `project_issues_index` | Issue 编号(网页 URL 中的序号) | +| `id` | 数据库内部 ID | +| `subject` | 标题 | +| `status_name` / `status_id` | 状态名 / 状态 ID | +| `author.login` | 作者 | +| `assigners` | 负责人列表 | +| `created_at` / `updated_at` | 创建 / 更新时间 | + ## References - [gitlink-issue](../SKILL.md) diff --git a/skills/gitlink-issue/references/gitlink-issue-update.md b/skills/gitlink-issue/references/gitlink-issue-update.md index 12c5df7..5687b10 100644 --- a/skills/gitlink-issue/references/gitlink-issue-update.md +++ b/skills/gitlink-issue/references/gitlink-issue-update.md @@ -10,20 +10,20 @@ The shortcut reads the current issue first and preserves existing `subject` and ```bash # Update issue title -gitlink-cli issue +update -i 42 -t "New title" +gitlink-cli issue +update -n 4 -t "New title" # Update issue description -gitlink-cli issue +update -i 42 -b "Updated description" +gitlink-cli issue +update -n 4 -b "Updated description" # Update both title and state -gitlink-cli issue +update -i 42 -t "Revised title" -s closed +gitlink-cli issue +update -n 4 -t "Revised title" -s closed ``` ## 参数 | 参数 | 必填 | 说明 | |------|------|------| -| `--id, -i` | **是** | Issue ID | +| `--number, -n` | **是** | Issue 编号(网页 URL 中的序号) | | `--title, -t` | 否 | 新标题(映射为 API 字段 `subject`) | | `--body, -b` | 否 | 新描述(映射为 API 字段 `description`) | | `--state, -s` | 否 | 新状态: `open`、`closed`,或数字状态 ID(映射为 API 字段 `status_id`;open=1,closed=5) | @@ -35,14 +35,14 @@ gitlink-cli issue +update -i 42 -t "Revised title" -s closed ## API ``` -PUT /{owner}/{repo}/issues/{id} +PATCH /v1/{owner}/{repo}/issues/{number} Body: { "subject": current_or_new_title, "description": current_or_new_body, "status_id": state } ``` ## Workflow 1. **Confirm** the fields to update and their new values with the user. -2. **Execute** `gitlink-cli issue +update -i {id} -t "..." -b "..."`. +2. **Execute** `gitlink-cli issue +update -n {number} -t "..." -b "..."`. 3. **Report** the updated issue details to the user. When using Raw API instead of the shortcut, fetch the issue first and include the current `subject` and `description` in the update payload. diff --git a/skills/gitlink-issue/references/gitlink-issue-view.md b/skills/gitlink-issue/references/gitlink-issue-view.md index c292f74..6f243d3 100644 --- a/skills/gitlink-issue/references/gitlink-issue-view.md +++ b/skills/gitlink-issue/references/gitlink-issue-view.md @@ -2,23 +2,23 @@ > **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../../gitlink-shared/SKILL.md) 了解认证、全局参数和安全规则。 -View details of a specific issue by its ID. +View details of a specific issue by its number (as shown in the web URL). ## 命令 ```bash -# View issue #42 -gitlink-cli issue +view -i 42 +# View issue #4 +gitlink-cli issue +view -n 4 # View issue with JSON output -gitlink-cli issue +view -i 42 --format json +gitlink-cli issue +view -n 4 --format json ``` ## 参数 | 参数 | 必填 | 说明 | |------|------|------| -| `--id, -i` | **是** | Issue ID 或编号 | +| `--number, -n` | **是** | Issue 编号(网页 URL 中的序号,如 `issues/4` 中的 `4`) | | `--owner` | 否 | 仓库所有者(自动从 git remote 解析) | | `--repo` | 否 | 仓库名称(自动从 git remote 解析) | | `--format` | 否 | 输出格式: `json`/`table`/`yaml` | @@ -27,7 +27,7 @@ gitlink-cli issue +view -i 42 --format json ## API ``` -GET /{owner}/{repo}/issues/{id} +GET /v1/{owner}/{repo}/issues/{number} ``` ## References