Skip to content

Commit b2b62d9

Browse files
committed
(#146) Add GitLab VCS Provider
This commit introduces a new GitLabProvider class, and implements the necessary methods to allow GRM to create release notes on GitLab. This is made possible by using the NGitLab library. A new option has been added to the base command, which allows settings of the --provider at the command line. The default value for this option is GitHub, so everything continues to work as it is expected to.
1 parent d5fd29d commit b2b62d9

File tree

9 files changed

+652
-6
lines changed

9 files changed

+652
-6
lines changed

src/GitReleaseManager.Cli/Program.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
using GitReleaseManager.Core.Commands;
99
using GitReleaseManager.Core.Configuration;
1010
using GitReleaseManager.Core.Helpers;
11+
using GitReleaseManager.Core.Model;
1112
using GitReleaseManager.Core.Options;
1213
using GitReleaseManager.Core.Provider;
1314
using GitReleaseManager.Core.ReleaseNotes;
1415
using GitReleaseManager.Core.Templates;
1516
using Microsoft.Extensions.DependencyInjection;
17+
using NGitLab;
1618
using Octokit;
1719
using Serilog;
1820

@@ -96,7 +98,6 @@ private static void RegisterServices(BaseSubOptions options)
9698
.AddSingleton<IFileSystem>(fileSystem)
9799
.AddSingleton<IReleaseNotesExporter, ReleaseNotesExporter>()
98100
.AddSingleton<IReleaseNotesBuilder, ReleaseNotesBuilder>()
99-
.AddSingleton<IVcsProvider, GitHubProvider>()
100101
.AddSingleton<IVcsService, VcsService>();
101102

102103
if (options is BaseVcsOptions vcsOptions)
@@ -106,9 +107,7 @@ private static void RegisterServices(BaseSubOptions options)
106107
throw new Exception("The token option is not defined");
107108
}
108109

109-
var gitHubClient = new GitHubClient(new ProductHeaderValue("GitReleaseManager")) { Credentials = new Credentials(vcsOptions.Token) };
110-
serviceCollection = serviceCollection
111-
.AddSingleton<IGitHubClient>(gitHubClient);
110+
RegisterVcsProvider(vcsOptions, serviceCollection);
112111
}
113112

114113
serviceCollection = serviceCollection
@@ -197,5 +196,25 @@ private static Task<int> ExecuteCommand<TOptions>(TOptions options)
197196

198197
private static void LogOptions(BaseSubOptions options)
199198
=> Log.Debug("{@Options}", options);
199+
200+
private static void RegisterVcsProvider(BaseVcsOptions vcsOptions, IServiceCollection serviceCollection)
201+
{
202+
Log.Information("Using {Provider} as VCS Provider", vcsOptions.Provider);
203+
if (vcsOptions.Provider == VcsProvider.GitLab)
204+
{
205+
var gitlabClient = new GitLabClient("https://gitlab.com", vcsOptions.Token);
206+
serviceCollection
207+
.AddSingleton<IVcsProvider, GitLabProvider>()
208+
.AddSingleton<IGitLabClient>(gitlabClient);
209+
}
210+
else
211+
{
212+
// default to Github
213+
var gitHubClient = new GitHubClient(new ProductHeaderValue("GitReleaseManager")) { Credentials = new Credentials(vcsOptions.Token) };
214+
serviceCollection
215+
.AddSingleton<IGitHubClient>(gitHubClient)
216+
.AddSingleton<IVcsProvider, GitHubProvider>();
217+
}
218+
}
200219
}
201220
}

src/GitReleaseManager.Core/Extensions/MilestoneExtensions.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using Octokit;
32
using Serilog;
43

54
namespace GitReleaseManager.Core.Extensions
@@ -8,7 +7,30 @@ public static class MilestoneExtensions
87
{
98
public static readonly ILogger _logger = Log.ForContext(typeof(MilestoneExtensions));
109

11-
public static Version Version(this Milestone ver)
10+
public static Version Version(this Octokit.Milestone ver)
11+
{
12+
if (ver is null)
13+
{
14+
throw new ArgumentNullException(nameof(ver));
15+
}
16+
17+
var nameWithoutPrerelease = ver.Title.Split('-')[0];
18+
if (nameWithoutPrerelease.StartsWith("v", StringComparison.OrdinalIgnoreCase))
19+
{
20+
_logger.Debug("Removing version prefix from {Name}", ver.Title);
21+
nameWithoutPrerelease = nameWithoutPrerelease.Remove(0, 1);
22+
}
23+
24+
if (!System.Version.TryParse(nameWithoutPrerelease, out Version parsedVersion))
25+
{
26+
_logger.Warning("No valid version was found on {Title}", ver.Title);
27+
return new Version(0, 0);
28+
}
29+
30+
return parsedVersion;
31+
}
32+
33+
public static Version Version(this NGitLab.Models.Milestone ver)
1234
{
1335
if (ver is null)
1436
{

src/GitReleaseManager.Core/GitReleaseManager.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2424
<PrivateAssets>all</PrivateAssets>
2525
</PackageReference>
26+
<PackageReference Include="NGitLab" Version="6.39.0" />
2627
<PackageReference Include="Octokit" Version="7.1.0" />
2728
<PackageReference Include="Scriban" Version="5.7.0" />
2829
<PackageReference Include="seriloganalyzer" Version="0.15.0" />
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
namespace GitReleaseManager.Core.MappingProfiles
2+
{
3+
using System;
4+
using AutoMapper;
5+
using GitReleaseManager.Core.Extensions;
6+
7+
public class GitLabProfile : Profile
8+
{
9+
public GitLabProfile()
10+
{
11+
CreateMap<NGitLab.Models.Milestone, Model.Milestone>()
12+
.ForMember(dest => dest.PublicNumber, act => act.MapFrom(src => src.Iid))
13+
.ForMember(dest => dest.InternalNumber, act => act.MapFrom(src => src.Id))
14+
.AfterMap((src, dest) => dest.Version = src.Version());
15+
CreateMap<NGitLab.Models.ReleaseInfo, Model.Release>()
16+
.ForMember(dest => dest.Draft, act => act.MapFrom(src => src.ReleasedAt > DateTime.UtcNow))
17+
.ForMember(dest => dest.Body, act => act.MapFrom(src => src.Description))
18+
.ForMember(dest => dest.Assets, act => act.MapFrom(src => src.Assets.Links))
19+
.ReverseMap();
20+
CreateMap<NGitLab.Models.ReleaseLink, Model.ReleaseAsset>().ReverseMap();
21+
CreateMap<NGitLab.Models.Issue, Model.Issue>()
22+
.ForMember(dest => dest.InternalNumber, act => act.MapFrom(src => src.Id))
23+
.ForMember(dest => dest.PublicNumber, act => act.MapFrom(src => src.IssueId))
24+
.ForMember(dest => dest.HtmlUrl, act => act.MapFrom(src => src.WebUrl))
25+
.ForMember(dest => dest.IsPullRequest, act => act.MapFrom(src => false))
26+
.ReverseMap();
27+
CreateMap<NGitLab.Models.MergeRequest, Model.Issue>()
28+
.ForMember(dest => dest.InternalNumber, act => act.MapFrom(src => src.Id))
29+
.ForMember(dest => dest.PublicNumber, act => act.MapFrom(src => src.Iid))
30+
.ForMember(dest => dest.HtmlUrl, act => act.MapFrom(src => src.WebUrl))
31+
.ForMember(dest => dest.IsPullRequest, act => act.MapFrom(src => true))
32+
.ReverseMap();
33+
CreateMap<string, Model.Label>().ForMember(dest => dest.Name, act => act.MapFrom(src => src));
34+
CreateMap<Model.Release, NGitLab.Models.ReleaseCreate>()
35+
.ForMember(dest => dest.Description, act => act.MapFrom(src => src.Body))
36+
.ForMember(dest => dest.Ref, act => act.MapFrom(src => src.TargetCommitish))
37+
.ForMember(dest => dest.Milestones, act => act.MapFrom(src => new string[] { src.TagName }))
38+
.ForMember(dest => dest.ReleasedAt, act => act.MapFrom(src => src.Draft ? DateTime.UtcNow.AddYears(1) : DateTime.UtcNow))
39+
.ForMember(dest => dest.Assets, act => act.Ignore())
40+
.ReverseMap();
41+
CreateMap<NGitLab.Models.ProjectIssueNote, Model.IssueComment>()
42+
.ForMember(dest => dest.Id, act => act.MapFrom(src => src.NoteId))
43+
.ReverseMap();
44+
CreateMap<NGitLab.Models.MergeRequestComment, Model.IssueComment>()
45+
.ReverseMap();
46+
}
47+
}
48+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace GitReleaseManager.Core.Model
2+
{
3+
public enum VcsProvider
4+
{
5+
GitHub = 0,
6+
GitLab = 1,
7+
}
8+
}

src/GitReleaseManager.Core/Options/BaseVcsSubOptions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CommandLine;
22
using Destructurama.Attributed;
3+
using GitReleaseManager.Core.Model;
34

45
namespace GitReleaseManager.Core.Options
56
{
@@ -14,5 +15,8 @@ public abstract class BaseVcsOptions : BaseSubOptions
1415

1516
[Option('r', "repository", HelpText = "The name of the repository.", Required = true)]
1617
public string RepositoryName { get; set; }
18+
19+
[Option("provider", HelpText = "Version Control System provider", Default = VcsProvider.GitHub)]
20+
public VcsProvider Provider { get; set; }
1721
}
1822
}

0 commit comments

Comments
 (0)