又开发了一个优雅的小工具

在开源项目中,Issues是一个强大的功能,用于跟踪bug、功能请求和任务。然而,随着项目的发展,Issues可能会变得难以管理,特别是当你需要离线访问或进行深入分析时。

当然GitHub Issues除了上述功能以外,做在线笔记也非常的方便,它支持Markdown语法,还能打标签、分层等等,还天然的支持评论功能。由于我本人就非常热衷于使用Issue做笔记,但是问题就是在离线环境下无法使用,那么能不能把Issue作为离线Markdown文件下载到本地呢?

答案显然是可以的,也是我本次项目的主要功能之一。

issue2file是一个用Go语言编写的命令行工具,它可以将GitHub仓库中的Issues导出为本地Markdown文件,并提供多种强大的功能:

1)完整内容保留:保留Issue的标题、内容、标签、状态、创建时间等信息

2)评论支持:可选择性地下载Issue的所有评论

除此之外,我想了想能不能通过AI扩展一下?答案显然也是可以的,所以还补充了如下功能:

3)AI分析:集成AI功能,可以对Issues进行智能分析和总结

4)数据可视化:自动生成多种图表,包括Issue状态分布、标签分布和时间趋势等

项目介绍

还是先说一下使用方式吧,当然如果想要支持私有仓库和AI功能的话,需要拿到自己的Github Token和DeepSeek的API Token。

1)仓库地址

shell 复制代码
https://github.com/ibarryyan/issue2file

2)工具构建

shell 复制代码
go mod tidy 
go build 

3)使用方式

最简单的使用方式就是直接运行可执行文件,加上仓库链接作为参数,比如

shell 复制代码
./issue2file ibarryyan/golang-tips-100

如果想要拉取自己的私有仓库就要先生成一个自己的Github Token,然后使用命令行参数或者配置文件进行启动,详细说明可以参考:

shell 复制代码
https://github.com/ibarryyan/issue2file/blob/master/README.md

当然了,还有额外的参数能支持生成图表分析仓库的所有Issue,主要有Issue创建时间趋势、状态分析和标签分布等几个维度:

技术实现

issue2file采用模块化设计,主要包含以下几个核心组件:

1)配置管理:使用Viper库处理配置文件

2)GitHub API交互:使用go-github库获取Issues数据

3)Markdown生成:将Issue数据转换为Markdown格式

4)AI分析:集成AI能力对Issues进行分析

5)图表生成:使用go-echarts库生成数据可视化图表

关键技术点

1)配置管理

项目使用Viper库来处理配置,支持从配置文件中读取各种参数:

go 复制代码
func InitConfig() {
    viper.SetConfigName("config")
    viper.SetConfigType("conf")
    viper.AddConfigPath(".")

    if err := viper.ReadInConfig(); err != nil {
        log.Fatalf("Error reading config file: %s", err)
    }

    // 读取配置项
    Config.GitHubToken = viper.GetString("gitHubToken")
    Config.AIToken = viper.GetString("aiToken")
    Config.CommentEnable = viper.GetBool("commentEnable")
    Config.AIEnable = viper.GetBool("aiEnable")
    Config.ChartEnable = viper.GetBool("chartEnable")
    Config.OutputDir = viper.GetString("outputDir")
    Config.SummaryFile = viper.GetString("summaryFile")
}

2)GitHub API交互

使用go-github库与GitHub API进行交互,获取Issues数据:

go 复制代码
func FetchIssues(owner, repo string) ([]*github.Issue, error) {
    ctx := context.Background()
    ts := oauth2.StaticTokenSource(
        &oauth2.Token{AccessToken: Config.GitHubToken},
    )
    tc := oauth2.NewClient(ctx, ts)
    client := github.NewClient(tc)

    opt := &github.IssueListByRepoOptions{
        State:     "all",
        Sort:      "created",
        Direction: "desc",
        ListOptions: github.ListOptions{
            PerPage: 100,
        },
    }

    var allIssues []*github.Issue
    for {
        issues, resp, err := client.Issues.ListByRepo(ctx, owner, repo, opt)
        if err != nil {
            return nil, err
        }
        allIssues = append(allIssues, issues...)
        if resp.NextPage == 0 {
            break
        }
        opt.Page = resp.NextPage
    }

    return allIssues, nil
}

3)Markdown生成

将Issue数据转换为结构化的Markdown文件:

go 复制代码
func GenerateMarkdown(issue *github.Issue, comments []*github.IssueComment) string {
    var md strings.Builder

    // 添加标题
    md.WriteString(fmt.Sprintf("# %s\n\n", *issue.Title))

    // 添加元数据
    md.WriteString(fmt.Sprintf("- **Issue编号**: #%d\n", *issue.Number))
    md.WriteString(fmt.Sprintf("- **创建者**: %s\n", *issue.User.Login))
    md.WriteString(fmt.Sprintf("- **创建时间**: %s\n", issue.CreatedAt.Format("2006-01-02 15:04:05")))
    md.WriteString(fmt.Sprintf("- **状态**: %s\n", *issue.State))

    // 添加标签
    if len(issue.Labels) > 0 {
        md.WriteString("- **标签**: ")
        for i, label := range issue.Labels {
            if i > 0 {
                md.WriteString(", ")
            }
            md.WriteString(*label.Name)
        }
        md.WriteString("\n")
    }

    // 添加正文
    md.WriteString("\n## 内容\n\n")
    md.WriteString(*issue.Body)

    // 添加评论
    if len(comments) > 0 {
        md.WriteString("\n\n## 评论\n\n")
        for _, comment := range comments {
            md.WriteString(fmt.Sprintf("### %s 评论于 %s\n\n", *comment.User.Login, comment.CreatedAt.Format("2006-01-02 15:04:05")))
            md.WriteString(*comment.Body)
            md.WriteString("\n\n---\n\n")
        }
    }

    return md.String()
}

4)AI分析

集成AI能力,对Issues进行智能分析和总结:

go 复制代码
func AnalyzeIssues(issues []*github.Issue) (string, error) {
    if !Config.AIEnable || Config.AIToken == "" {
        return "", errors.New("AI analysis is disabled or token is not provided")
    }

    // 准备AI分析的输入数据
    var input strings.Builder
    input.WriteString("请分析以下GitHub Issues,并提供总结报告:\n\n")

    for _, issue := range issues {
        input.WriteString(fmt.Sprintf("Issue #%d: %s\n", *issue.Number, *issue.Title))
        input.WriteString(fmt.Sprintf("状态: %s\n", *issue.State))
        input.WriteString(fmt.Sprintf("创建时间: %s\n", issue.CreatedAt.Format("2006-01-02")))
        input.WriteString("标签: ")
        for i, label := range issue.Labels {
            if i > 0 {
                input.WriteString(", ")
            }
            input.WriteString(*label.Name)
        }
        input.WriteString("\n\n")

        // 限制内容长度,避免超出AI API的限制
        body := *issue.Body
        if len(body) > 500 {
            body = body[:500] + "..."
        }
        input.WriteString(body)
        input.WriteString("\n\n---\n\n")
    }

    // 调用AI API进行分析
    analysis, err := callAIAPI(input.String())
    if err != nil {
        return "", err
    }

    return analysis, nil
}

5)图表生成

使用go-echarts库生成数据可视化图表:

go 复制代码
func GenerateCharts(issues []*github.Issue, outputDir string) error {
    if !Config.ChartEnable {
        return nil
    }

    // 生成状态分布图
    if err := generateStatusChart(issues, outputDir); err != nil {
        return err
    }

    // 生成标签分布图
    if err := generateTagsChart(issues, outputDir); err != nil {
        return err
    }

    // 生成时间趋势图
    if err := generateTimeChart(issues, outputDir); err != nil {
        return err
    }

    return nil
}

全部代码目前已经开源,大家可以去Github上拉取~~

开源成果

issue2file项目在开源后的一周内就获得了29个star,这种积极的社区反馈不仅验证了项目的价值,也为未来的发展提供了动力。

在这里主要感谢@ruanyf老师在《科技爱好者周刊》中的推荐!

总结与规划

issue2file成功地实现了将GitHub Issues转换为本地Markdown文件的核心功能,并通过AI分析和数据可视化等特性提供了额外的价值。

基于社区反馈和项目愿景,未来的发展计划包括:

功能增强:

  • 添加增量更新功能,只下载新的或更新的Issues
  • 增强AI分析能力,提供更深入的洞察

用户体验改进:

  • 提供Web界面,使非技术用户也能轻松使用
  • 添加进度显示和更详细的日志
  • 完善文档和示例

如果你对这个项目感兴趣,欢迎访问GitHub仓库(https://github.com/ibarryyan/issue2file),给项目点个star,或者贡献代码!

相关推荐
system_error_x10 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
步行cgn12 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
码事漫谈13 小时前
AI 读你的提示词,其实很没耐心
后端
用户83562907805113 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我1234513 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒14 小时前
Java性能优化完全指南
前端·人工智能·后端
穆梓兰煊14 小时前
pgvector 0.8 评测:过滤向量检索的召回修复与边界
github
电子IT笔记14 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk5987814 小时前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端
雨中飘荡的记忆14 小时前
Claude Code 入门必会:@、!、Slash Commands,一篇讲清楚
人工智能·后端