统计 Github 2021 贡献过的开源项目

统计一下 2021 贡献过的开源项目

Intro

新的一年的开始了,有很多总结和回顾还没有做,今天就盘点一下贡献过的开源项目吧~

起初想着手动地通过 Github Dashboard 来统计

b010c2a84e205009dfe30347b434bd70.png

但是感觉有些麻烦,还得一个个地复制标题链接等,好麻烦,于是就想是不是可以写一个简单的小程序通过 Github 的 API 来统计呢,答案是肯定的,可以参考后面的示例代码

Contributions

过去一年的贡献如下,一共提了 81 个 PR 其中有 43 个是自己维护的开源项目的 PR,已从下面的 PR 中移除

统计结果来自 Github 的 API:https://api.github.com/search/issues?page=1&q=author%3Aweihanli+type%3Apr+is:merged+merged:%3E=2021-01-01

  • davidfowl/DotNetCodingPatterns

    • enhancement on Caching singletons sample code https://github.com/davidfowl/DotNetCodingPatterns/pull/11

  • domaindrivendev/Swashbuckle.AspNetCore

    • Enhancement for SwaggerUIMiddleware https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/2214

  • dotnet/aspnetcore

    • Fix http logging log typo https://github.com/dotnet/aspnetcore/pull/36871

    • Update 10_bug_report.md https://github.com/dotnet/aspnetcore/pull/36922

  • dotnet/core

    • Update for .NET 6 release https://github.com/dotnet/core/pull/6892

  • dotnet/dotnet-monitor

    • update windows build script https://github.com/dotnet/dotnet-monitor/pull/40

  • dotnet/format

    • Remove unnecessary config https://github.com/dotnet/format/pull/1486

  • dotnet/issue-labeler

    • use generic host https://github.com/dotnet/issue-labeler/pull/15

  • dotnet/maui

    • Update MauiAppBuilder.cs https://github.com/dotnet/maui/pull/3445

  • dotnet/runtime

    • Update ConfigurationManager https://github.com/dotnet/runtime/pull/59600

  • dotnet/sdk

    • Add self contained short flag https://github.com/dotnet/sdk/pull/19681

    • Use null-coalescing assignment operator https://github.com/dotnet/sdk/pull/20678

  • dotnetcore/CAP

    • make OperateResult._errors readonly https://github.com/dotnetcore/CAP/pull/869

    • fix typo in comment https://github.com/dotnetcore/CAP/pull/870

    • Use KeyExistsAsync for exists check https://github.com/dotnetcore/CAP/pull/1004

  • dotnetcore/FastGithub

    • Fix build for .NET 6 with the latest SDK and some warning and typo https://github.com/dotnetcore/FastGithub/pull/26

    • Remove unnecessary config https://github.com/dotnetcore/FastGithub/pull/84

  • EdiWang/Moonglade

    • Common.props enhancement https://github.com/EdiWang/Moonglade/pull/566

  • IEvangelist/blazorators

    • Github CodeSpaces support https://github.com/IEvangelist/blazorators/pull/3

    • Refine the generator https://github.com/IEvangelist/blazorators/pull/6

    • Apply file-scoped namespace style and skip none partial classes https://github.com/IEvangelist/blazorators/pull/7

  • IEvangelist/pwned-client

    • Remove IsExternalInit https://github.com/IEvangelist/pwned-client/pull/6

  • kubernetes-client/csharp

    • Update TokenFileAuth https://github.com/kubernetes-client/csharp/pull/631

    • Expose kube config default location https://github.com/kubernetes-client/csharp/pull/635

    • Makes realFileSystem readonly https://github.com/kubernetes-client/csharp/pull/655

    • AddRange extension enhancement https://github.com/kubernetes-client/csharp/pull/771

  • LemonSharp/Admin.FrontEnd

    • Add Github CI support https://github.com/LemonSharp/Admin.FrontEnd/pull/2

    • Add dotnet-monitor https://github.com/LemonSharp/Admin.FrontEnd/pull/4

  • LemonSharp/User

    • Publish event when user register success https://github.com/LemonSharp/User/pull/1

  • LemonSharp/VaccinationCore

    • Implement AppointmentQueries/VaccinationQueries https://github.com/LemonSharp/VaccinationCore/pull/1

  • LemonSharp/VaccinationSite

    • Feat/add appointment api https://github.com/LemonSharp/VaccinationSite/pull/1

    • Add GetSiteInfoById API https://github.com/LemonSharp/VaccinationSite/pull/2

    • Add dotnet-monitor sidecar https://github.com/LemonSharp/VaccinationSite/pull/3

    • Enable swagger on production https://github.com/LemonSharp/VaccinationSite/pull/4

  • microsoft/reverse-proxy

    • Fix typo https://github.com/microsoft/reverse-proxy/pull/1245

    • Use WaitAsync https://github.com/microsoft/reverse-proxy/pull/1306

  • night-moon-studio/NatashaPad

    • Update to .NET 6 https://github.com/night-moon-studio/NatashaPad/pull/10

  • pengweiqhca/Xunit.DependencyInjection

    • Add Github Actions CI https://github.com/pengweiqhca/Xunit.DependencyInjection/pull/55

    • Update template https://github.com/pengweiqhca/Xunit.DependencyInjection/pull/59

  • StackExchange/StackExchange.Redis

    • Add support for GETDEL command https://github.com/StackExchange/StackExchange.Redis/pull/1840

    • Makes StreamEntry constructor public https://github.com/StackExchange/StackExchange.Redis/pull/1923

  • Tyrrrz/CliWrap

    • Remove unused dependencies https://github.com/Tyrrrz/CliWrap/pull/132

  • ua-parser/uap-csharp

    • Update target framework for netstandard2.0 https://github.com/ua-parser/uap-csharp/pull/65

希望接下来的一年能够有更多更高质量的开源贡献~

很多开源项目的贡献很简单并不会很复杂,大家也可以尽可能的贡献一些自己的力量来让 .NET 社区的开源项目越来越好~

Sample

上面的统计结果来自上面提到的 API

- author 用户名
- type=pr 返回 PR
- is:merged 过滤合并的 PR
- merged: 根据 PR 合并时间过滤
- page: 当前页码,默认是 1, 用来分页

0f6910014c31d491b28cebe9a0db71b3.png

Github API result

上面的返回结果中的 html_url 对应的就是对应 PR 的 HTML 页面地址, title/body 对应 PR 的标题和描述信息,created_atclosed_at 分别对应 PR 的创建和合并时间

写了一个简单的小程序来统计结果,示例代码如下:

using System.Net.Http.Json;
using System.Text.Json.Nodes;
using WeihanLi.Extensions;

const int pageCount = 30;
const string userName = "weihanli";
const string urlFormat =
    $"search/issues?page={{0}}&q=author%3A{userName}+type%3Apr+is:merged+merged:%3E=2021-01-01";

var prList = new List<GithubPRModel>();
var itemsCount = 0;
var pageNum = 1;

using var httpClient = new HttpClient()
{
    BaseAddress = new Uri("https://api.github.com/")
};
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api#user-agent-required
httpClient.DefaultRequestHeaders
    .TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36");

do
{
    var url = urlFormat.FormatWith(pageNum.ToString());
    using var response = await httpClient.GetAsync(url);
    var responseText = await response.Content.ReadAsStringAsync();
    var responseObj = JsonNode.Parse(responseText);
    ArgumentNullException.ThrowIfNull(responseObj);
    var items = responseObj["items"]?.AsArray();
    ArgumentNullException.ThrowIfNull(items);
    itemsCount = items.Count;

    foreach (var item in items)
    {
        prList.Add(new GithubPRModel()
        {
            Title = item["title"]?.GetValue<string>(),
            Body = item["body"]?.GetValue<string>(),
            Url = item["html_url"]?.GetValue<string>(),
            CreatedAt = item["created_at"]?.GetValue<DateTimeOffset>(),
            ClosedAt = item["closed_at"]?.GetValue<DateTimeOffset>()
        });
    }

    pageNum++;
} while (itemsCount == pageCount);

var totalCount = prList.Count;
prList.RemoveAll(x => userName.Equals(x.UserName, StringComparison.OrdinalIgnoreCase));
var excludedCount = prList.Count;
Console.WriteLine($"Total:{totalCount}, excludedCount: {excludedCount}");

Console.WriteLine("Completed");
Console.ReadLine();

internal class GithubPRModel
{
    private string _url;
    public string Title { get; set; }
    public string Body { get; set; }
    public DateTimeOffset? CreatedAt { get; set; }
    public DateTimeOffset? ClosedAt { get; set; }

    public string Url
    {
        get => _url;
        set
        {
            _url = value;
            if (!string.IsNullOrEmpty(_url))
            {
                var index = _url.IndexOf("/pull/", StringComparison.OrdinalIgnoreCase);
                RepoUrl = _url[..index];
                RepoName = RepoUrl.Replace("https://github.com/", "");
                UserName = RepoName[..RepoName.IndexOf('/')];
            }
        }
    }

    public string UserName { get; private set; }

    public string RepoName { get; private set; }

    public string RepoUrl { get; private set; }
}

上面的结果就是用这个示例中的代码生成的,为了方便也可以改造一下上面的代码直接生成 Markdown 内容,上面的贡献内容就是下面这段生成 markdown 的代码生成出来的,你也可以根据自己需要进行一些定制

var mdContent = prList.GroupBy(g => new
{
  g.RepoName,
  g.RepoUrl
})
.OrderBy(g => g.Key.RepoName)
.Select(g => $@"- [{g.Key.RepoName}]({g.Key.RepoUrl})
{g.OrderBy(x => x.CreatedAt).Select(x => $"  - {x.Title} <{x.Url}>").StringJoin(Environment.NewLine)}
")
.StringJoin(Environment.NewLine);

await File.WriteAllTextAsync("result.md", mdContent);

StringJoin 是一个基于 string.Join 的扩展方法

More

上面的示例中有一个需要注意的地方就是 UserAgent 请求头的配置,如果不配置,Github 就会返回一个 403 

40b4198db7a8317ffade435f45e32d81.png

可以参考 Github 文档 https://docs.github.com/en/rest/overview/resources-in-the-rest-api#user-agent-required

另外还有一些可以优化的地方,比如说可以使用 System.Text.JsonGetFromJsonAsync 方法来简化 http response JSON 反序列化

另外可以考虑使用 Github 提供的客户端,因为我的需求比较简单所以直接调了这个 API,也可以考虑使用 Github 客户端 octokit

References

  • https://api.github.com/search/issues?page=1&q=state%3Aclosed+author%3Aweihanli+type%3Apr+is:merged+merged:%3E=2021-01-01

  • https://docs.github.com/en/rest/overview/resources-in-the-rest-api#user-agent-required

  • https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests#search-based-on-the-state-of-an-issue-or-pull-request

  • https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests#search-by-author

  • https://stackoverflow.com/questions/17412809/how-to-get-my-pull-requests-from-github-api

  • https://github.com/WeihanLi/SamplesInPractice/blob/master/GithubAPISample/Program.cs

  • https://github.com/octokit/octokit.net

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值