forked from Gitlink/gitlink-cli
Improve onboard template: per-issue content-aware welcome comments
- fetchIssueDetail now gets both subject and description
- renderComment substitutes {subject}, {description}, {number}, {login}
- defaultTemplate includes issue summary for targeted guidance
- dry-run preview shows the full rendered comment
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0ed9dcabfc
commit
be837d4f8e
|
|
@ -25,7 +25,7 @@ func Shortcuts() []*common.Shortcut {
|
|||
Flags: []common.Flag{
|
||||
{Name: "issues", Short: "i", Usage: "Comma-separated issue numbers (e.g. 1,3,7)"},
|
||||
{Name: "tag", Short: "t", Usage: "Tag name to match (comma-separated)", Default: "good first issue,help wanted"},
|
||||
{Name: "template", Usage: "Custom welcome message template (use {login} for @mention)"},
|
||||
{Name: "template", Usage: "Custom welcome message template ({login}, {number}, {subject}, {description})"},
|
||||
},
|
||||
DryRun: true,
|
||||
DryRunHint: dryRunHint,
|
||||
|
|
@ -96,11 +96,11 @@ func runWelcomeByIssueNumbers(ctx *common.RuntimeContext, issueArg string) error
|
|||
|
||||
var issues []issueInfo
|
||||
for _, num := range issueNums {
|
||||
subject, err := fetchIssueSubject(ctx, num)
|
||||
info, err := fetchIssueDetail(ctx, num)
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取 issue #%d 失败: %w", num, err)
|
||||
}
|
||||
issues = append(issues, issueInfo{number: num, subject: subject})
|
||||
issues = append(issues, info)
|
||||
}
|
||||
|
||||
return processIssues(ctx, issues)
|
||||
|
|
@ -127,18 +127,20 @@ func parseIssueNumbers(s string) ([]int, error) {
|
|||
return nums, nil
|
||||
}
|
||||
|
||||
// fetchIssueSubject fetches a single issue's subject by number.
|
||||
func fetchIssueSubject(ctx *common.RuntimeContext, issueNumber int) (string, error) {
|
||||
// fetchIssueDetail fetches a single issue's subject and description by number.
|
||||
func fetchIssueDetail(ctx *common.RuntimeContext, issueNumber int) (issueInfo, error) {
|
||||
path := fmt.Sprintf("/v1/%s/%s/issues/%d", ctx.Owner, ctx.Repo, issueNumber)
|
||||
env, err := ctx.CallAPIWithQuery("GET", path, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return issueInfo{}, err
|
||||
}
|
||||
data, _ := env.Data.(map[string]interface{})
|
||||
if subj := getString(data, "subject"); subj != "" {
|
||||
return subj, nil
|
||||
subj := getString(data, "subject")
|
||||
if subj == "" {
|
||||
subj = fmt.Sprintf("issue #%d", issueNumber)
|
||||
}
|
||||
return fmt.Sprintf("issue #%d", issueNumber), nil
|
||||
desc := getString(data, "description")
|
||||
return issueInfo{number: issueNumber, subject: subj, description: desc}, nil
|
||||
}
|
||||
|
||||
// processIssues handles the common issue processing loop used by both
|
||||
|
|
@ -146,7 +148,7 @@ func fetchIssueSubject(ctx *common.RuntimeContext, issueNumber int) (string, err
|
|||
func processIssues(ctx *common.RuntimeContext, issues []issueInfo) error {
|
||||
tmpl := ctx.Arg("template")
|
||||
if tmpl == "" {
|
||||
tmpl = defaultTemplate(ctx.Owner, ctx.Repo)
|
||||
tmpl = ""
|
||||
}
|
||||
|
||||
type result struct {
|
||||
|
|
@ -162,7 +164,11 @@ func processIssues(ctx *common.RuntimeContext, issues []issueInfo) error {
|
|||
continue
|
||||
}
|
||||
|
||||
// Render per-issue message with issue-specific variables.
|
||||
body := renderComment(ctx, issue, tmpl)
|
||||
|
||||
if ctx.IsDryRun() {
|
||||
fmt.Printf("\n--- 预览 #%d \"%s\" ---\n%s\n---\n", issue.number, issue.subject, body)
|
||||
proceed, err := common.ConfirmAction(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -173,7 +179,7 @@ func processIssues(ctx *common.RuntimeContext, issues []issueInfo) error {
|
|||
}
|
||||
}
|
||||
|
||||
if err := addComment(ctx, issue.number, tmpl); err != nil {
|
||||
if err := addComment(ctx, issue.number, body); err != nil {
|
||||
results = append(results, result{issue.number, "error", err.Error()})
|
||||
} else {
|
||||
results = append(results, result{issue.number, "added", fmt.Sprintf("#%d \"%s\" — 已添加引导评论", issue.number, issue.subject)})
|
||||
|
|
@ -247,8 +253,9 @@ func tagNamesList(tags map[string]int) []string {
|
|||
}
|
||||
|
||||
type issueInfo struct {
|
||||
number int
|
||||
subject string
|
||||
number int
|
||||
subject string
|
||||
description string
|
||||
}
|
||||
|
||||
func fetchTaggedIssues(ctx *common.RuntimeContext, tagIDs []string) ([]issueInfo, error) {
|
||||
|
|
@ -313,30 +320,55 @@ func hasWelcomeComment(ctx *common.RuntimeContext, issueNumber int) bool {
|
|||
}
|
||||
|
||||
func addComment(ctx *common.RuntimeContext, issueNumber int, body string) error {
|
||||
body = strings.ReplaceAll(body, "{login}", ctx.Owner)
|
||||
path := fmt.Sprintf("/v1/%s/%s/issues/%d/journals", ctx.Owner, ctx.Repo, issueNumber)
|
||||
payload := map[string]interface{}{"notes": marker + "\n\n" + body}
|
||||
_, err := ctx.CallAPI("POST", path, payload)
|
||||
return err
|
||||
}
|
||||
|
||||
// defaultTemplate returns the default onboarding message.
|
||||
func defaultTemplate(owner, repo string) string {
|
||||
// renderComment renders the comment body for a specific issue.
|
||||
// It uses the --template if provided, otherwise generates an issue-aware default.
|
||||
func renderComment(ctx *common.RuntimeContext, issue issueInfo, customTmpl string) string {
|
||||
tmpl := customTmpl
|
||||
if tmpl == "" {
|
||||
tmpl = defaultTemplate(ctx.Owner, ctx.Repo, issue)
|
||||
}
|
||||
body := strings.NewReplacer(
|
||||
"{login}", ctx.Owner,
|
||||
"{number}", strconv.Itoa(issue.number),
|
||||
"{subject}", issue.subject,
|
||||
"{description}", issue.description,
|
||||
).Replace(tmpl)
|
||||
return body
|
||||
}
|
||||
|
||||
// defaultTemplate returns an issue-aware onboarding message.
|
||||
func defaultTemplate(owner, repo string, issue issueInfo) string {
|
||||
summary := issue.subject
|
||||
if len(issue.description) > 200 {
|
||||
summary = issue.description[:200] + "..."
|
||||
} else if issue.description != "" {
|
||||
summary = issue.description
|
||||
}
|
||||
return fmt.Sprintf(`## 欢迎贡献!:wave:
|
||||
|
||||
感谢你对 [%s/%s](https://www.gitlink.org.cn/%s/%s) 的关注。这个 issue 适合新手参与,以下是快速上手指南:
|
||||
感谢你对 [%s/%s](https://www.gitlink.org.cn/%s/%s) 的关注。
|
||||
|
||||
### 参与步骤
|
||||
### :bulb: 关于本 Issue:{subject}
|
||||
|
||||
%s
|
||||
|
||||
### :rocket: 参与步骤
|
||||
1. **Fork 仓库** 并克隆到本地
|
||||
2. 创建新分支:` + "`git checkout -b fix/issue-{number}`" + `
|
||||
3. 修改代码并提交
|
||||
3. 参照上方 issue 描述修改代码
|
||||
4. 推送到你的 Fork 后创建 Pull Request
|
||||
|
||||
### 注意事项
|
||||
### :memo: 注意事项
|
||||
- 请先阅读 [CONTRIBUTING.md](https://www.gitlink.org.cn/%s/%s/src/master/CONTRIBUTING.md)(如有)
|
||||
- 如遇到问题,欢迎在 issue 评论区留言
|
||||
- 如有疑问,欢迎在评论区留言讨论
|
||||
|
||||
期待你的 PR!`, owner, repo, owner, repo, owner, repo)
|
||||
期待你的 PR!`, owner, repo, owner, repo, summary, owner, repo)
|
||||
}
|
||||
|
||||
func getString(m map[string]interface{}, key string) string {
|
||||
|
|
|
|||
Loading…
Reference in New Issue