feat: implements first version
This commit is contained in:
125
.gitignore
vendored
Normal file
125
.gitignore
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
|
||||
update-tag.sln.DotSettings.user
|
||||
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/dotnetcore,jetbrains+all,visualstudiocode
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=dotnetcore,jetbrains+all,visualstudiocode
|
||||
|
||||
### DotnetCore ###
|
||||
# .NET Core build folders
|
||||
bin/
|
||||
obj/
|
||||
|
||||
# Common node modules locations
|
||||
/node_modules
|
||||
/wwwroot/node_modules
|
||||
|
||||
### JetBrains+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### JetBrains+all Patch ###
|
||||
# Ignores the whole .idea folder and all .iml files
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
.idea/
|
||||
|
||||
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||
|
||||
*.iml
|
||||
modules.xml
|
||||
.idea/misc.xml
|
||||
*.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/dotnetcore,jetbrains+all,visualstudiocode
|
||||
106
src/Cli/AppRunner.cs
Normal file
106
src/Cli/AppRunner.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Application.Commands;
|
||||
using Application.Queries;
|
||||
using Cli.Models;
|
||||
using MediatR;
|
||||
using Spectre.Console;
|
||||
using Version = Application.Models.Version;
|
||||
|
||||
namespace Cli
|
||||
{
|
||||
public class AppRunner
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public AppRunner(IMediator mediator)
|
||||
{
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
public async Task Run(string repoPath)
|
||||
{
|
||||
// Check if git dir
|
||||
var services = new List<string>();
|
||||
try
|
||||
{
|
||||
services = await _mediator.Send(new GetServicesFromGitRepo.Query(repoPath));
|
||||
}
|
||||
catch (LibGit2Sharp.RepositoryNotFoundException)
|
||||
{
|
||||
AnsiConsole.Markup("[red]Error:[/] Unable to extract Versions. Are we running inside a git repository?\n\n");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
var chosenService = "";
|
||||
if (services.Count > 1)
|
||||
{
|
||||
chosenService = AnsiConsole.Prompt(
|
||||
new SelectionPrompt<string>()
|
||||
.Title("Which [green]service[/] is the new version for?")
|
||||
.PageSize(10)
|
||||
.MoreChoicesText("[grey](Move up and down to reveal more services)[/]")
|
||||
.AddChoices(services));
|
||||
}
|
||||
|
||||
|
||||
var versionInfo = await _mediator.Send(new GetVersionInformationFromRepo.Query(repoPath, chosenService));
|
||||
Selection selection;
|
||||
if (versionInfo != null)
|
||||
{
|
||||
selection = AnsiConsole.Prompt(
|
||||
new SelectionPrompt<Selection>()
|
||||
.Title($"Select new version. (Current version is [green]{versionInfo.CurrentVersion}[/])")
|
||||
.PageSize(10)
|
||||
.AddChoices(
|
||||
new Selection("rc ", versionInfo.NextMinorRcVersion),
|
||||
new Selection("patch", versionInfo.NextPatchVersion),
|
||||
new Selection("minor", versionInfo.NextMinorVersion),
|
||||
new Selection("major", versionInfo.NextMajorVersion)
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
selection = AnsiConsole.Prompt(
|
||||
new SelectionPrompt<Selection>()
|
||||
.Title("[red]Error evaluating version from newest tag.[/]\nAdd new version tag **AND** push to origin?)")
|
||||
.PageSize(10)
|
||||
.AddChoices(
|
||||
new Selection("yes", new Version(0, 1, 0)),
|
||||
new Selection("yes", new Version(0, 1, 0, 1)),
|
||||
new Selection("no", null)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (selection.Version == null)
|
||||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _mediator.Send(new AddTagToGitRepo.Command(repoPath, selection.Version.ToString()));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AnsiConsole.Markup("[red]Error:[/] Unable to write Tag to repository\n\n");
|
||||
AnsiConsole.WriteException(ex);
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _mediator.Send(new PushCommitsToRemote.Command(repoPath));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AnsiConsole.Markup("[red]Error:[/] Tag was written but unable to push to remote\n\n");
|
||||
AnsiConsole.WriteException(ex);
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/Cli/Cli.csproj
Normal file
24
src/Cli/Cli.csproj
Normal file
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>Cli</RootNamespace>
|
||||
<PackAsTool>true</PackAsTool>
|
||||
<ToolCommandName>update-tag</ToolCommandName>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
|
||||
<PackageReference Include="Spectre.Console" Version="0.42.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\Core.csproj" />
|
||||
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
13
src/Cli/DependencyInjection.cs
Normal file
13
src/Cli/DependencyInjection.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Cli
|
||||
{
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddCli(this IServiceCollection services)
|
||||
{
|
||||
return services
|
||||
.AddTransient<AppRunner>();
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/Cli/Extensions/Semver.cs
Normal file
21
src/Cli/Extensions/Semver.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Semver;
|
||||
|
||||
namespace Cli.Extensions
|
||||
{
|
||||
public static class SemverParser
|
||||
{
|
||||
public static bool TryParse(string version, out SemVersion semverVersion)
|
||||
{
|
||||
try
|
||||
{
|
||||
semverVersion = SemVersion.Parse(version.TrimStart('v').TrimStart('V'));
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
semverVersion = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/Cli/Models/Selection.cs
Normal file
21
src/Cli/Models/Selection.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Application.Models;
|
||||
|
||||
namespace Cli.Models
|
||||
{
|
||||
public class Selection
|
||||
{
|
||||
public Selection(string title, Version version)
|
||||
{
|
||||
Title = title;
|
||||
Version = version;
|
||||
}
|
||||
|
||||
private string Title { get; }
|
||||
public Version Version { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Version == null ? Title : $"{Title}\t [green]{Version}[/]";
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/Cli/Program.cs
Normal file
39
src/Cli/Program.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Application;
|
||||
using Infrastructure;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Cli
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
using var host = CreateHostBuilder()
|
||||
.Build();
|
||||
|
||||
var appRunner = host
|
||||
.Services
|
||||
.CreateScope()
|
||||
.ServiceProvider
|
||||
.GetRequiredService<AppRunner>();
|
||||
|
||||
await appRunner.Run(args.FirstOrDefault() ?? Environment.CurrentDirectory);
|
||||
}
|
||||
|
||||
private static IHostBuilder CreateHostBuilder()
|
||||
{
|
||||
return Host.CreateDefaultBuilder()
|
||||
.ConfigureServices(
|
||||
(_, services) =>
|
||||
services
|
||||
.AddCli()
|
||||
.AddInfrastructure()
|
||||
.AddCore()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/Core/Commands/AddTagToGitRepo.cs
Normal file
34
src/Core/Commands/AddTagToGitRepo.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Application.Interfaces;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Commands
|
||||
{
|
||||
public class AddTagToGitRepo : RequestHandler<AddTagToGitRepo.Command>
|
||||
{
|
||||
private readonly IGitRepoWriteService _gitRepoWriteService;
|
||||
|
||||
public AddTagToGitRepo(IGitRepoWriteService gitRepoWriteService)
|
||||
{
|
||||
_gitRepoWriteService = gitRepoWriteService;
|
||||
}
|
||||
|
||||
public class Command : IRequest
|
||||
{
|
||||
public string RepoPath { get; }
|
||||
public string Tag { get; }
|
||||
|
||||
|
||||
public Command(string repoPath, string tag)
|
||||
{
|
||||
RepoPath = repoPath;
|
||||
Tag = tag;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void Handle(Command request)
|
||||
{
|
||||
_gitRepoWriteService.AddTag(request.RepoPath, request.Tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/Core/Commands/PushCommitsToRemote.cs
Normal file
31
src/Core/Commands/PushCommitsToRemote.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Application.Interfaces;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Commands
|
||||
{
|
||||
public class PushCommitsToRemote : RequestHandler<PushCommitsToRemote.Command>
|
||||
{
|
||||
private readonly IGitRepoWriteService _gitRepoWriteService;
|
||||
|
||||
public PushCommitsToRemote(IGitRepoWriteService gitRepoWriteService)
|
||||
{
|
||||
_gitRepoWriteService = gitRepoWriteService;
|
||||
}
|
||||
|
||||
public class Command : IRequest
|
||||
{
|
||||
public string RepoPath { get; }
|
||||
|
||||
public Command(string repoPath)
|
||||
{
|
||||
RepoPath = repoPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void Handle(Command request)
|
||||
{
|
||||
_gitRepoWriteService.Push(request.RepoPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/Core/Core.csproj
Normal file
14
src/Core/Core.csproj
Normal file
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>Application</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="9.0.0" />
|
||||
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
14
src/Core/DependencyInjection.cs
Normal file
14
src/Core/DependencyInjection.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Application
|
||||
{
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddCore(this IServiceCollection services)
|
||||
{
|
||||
return services
|
||||
.AddMediatR(typeof(DependencyInjection));
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/Core/Interfaces/IGitRepoReadService.cs
Normal file
10
src/Core/Interfaces/IGitRepoReadService.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Application.Models;
|
||||
|
||||
namespace Application.Interfaces
|
||||
{
|
||||
public interface IGitRepoReadService
|
||||
{
|
||||
public IEnumerable<Version> GetAllVersions(string repoPath);
|
||||
}
|
||||
}
|
||||
8
src/Core/Interfaces/IGitRepoWriteService.cs
Normal file
8
src/Core/Interfaces/IGitRepoWriteService.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Application.Interfaces
|
||||
{
|
||||
public interface IGitRepoWriteService
|
||||
{
|
||||
void AddTag(string repoPath, string tag);
|
||||
void Push(string repoPath);
|
||||
}
|
||||
}
|
||||
136
src/Core/Models/Version.cs
Normal file
136
src/Core/Models/Version.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Application.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct:
|
||||
/// "Major.Minor.Patch-Rc+Service"
|
||||
///
|
||||
/// Example:
|
||||
/// "0.1.4-RC.4+ErpNext"
|
||||
/// </summary>
|
||||
public class Version
|
||||
{
|
||||
public Version(int major, int minor, int patch)
|
||||
{
|
||||
Major = major;
|
||||
Minor = minor;
|
||||
Patch = patch;
|
||||
}
|
||||
|
||||
public Version(int major, int minor, int patch, int rc)
|
||||
{
|
||||
Major = major;
|
||||
Minor = minor;
|
||||
Patch = patch;
|
||||
Rc = rc;
|
||||
}
|
||||
|
||||
public Version(int major, int minor, int patch, string rc, string service)
|
||||
{
|
||||
Major = major;
|
||||
Minor = minor;
|
||||
Patch = patch;
|
||||
Rc = ExtractNumberFromRcString(rc);
|
||||
Service = service ?? "";
|
||||
}
|
||||
|
||||
private static int? ExtractNumberFromRcString(string rc)
|
||||
{
|
||||
var resultString = Regex.Match(rc, @"\d+").Value;
|
||||
return int.TryParse(resultString, out var rcNumber) ? rcNumber : null;
|
||||
}
|
||||
|
||||
|
||||
public int Major { get; private set; }
|
||||
public int Minor { get; private set; }
|
||||
public int Patch { get; private set; }
|
||||
public int? Rc { get; private set; }
|
||||
public string Service { get; }
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(Major);
|
||||
sb.Append('.');
|
||||
sb.Append(Minor);
|
||||
sb.Append('.');
|
||||
sb.Append(Patch);
|
||||
|
||||
if (Rc != null)
|
||||
{
|
||||
sb.Append('-');
|
||||
sb.Append("RC.");
|
||||
sb.Append(Rc);
|
||||
}
|
||||
|
||||
if (Service != null && Service.Length > 0)
|
||||
{
|
||||
sb.Append('+');
|
||||
sb.Append(Service);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public Version NextMajor()
|
||||
{
|
||||
var nextVersion = new Version(Major, Minor, Patch, Rc.ToString(), Service);
|
||||
nextVersion.BumpMajor();
|
||||
return nextVersion;
|
||||
}
|
||||
|
||||
public Version NextMinor()
|
||||
{
|
||||
var nextVersion = new Version(Major, Minor, Patch, Rc.ToString(), Service);
|
||||
nextVersion.BumpMinor();
|
||||
return nextVersion;
|
||||
}
|
||||
|
||||
public Version NextPatch()
|
||||
{
|
||||
var nextVersion = new Version(Major, Minor, Patch, Rc.ToString(), Service);
|
||||
nextVersion.BumpPatch();
|
||||
return nextVersion;
|
||||
}
|
||||
|
||||
public Version NextRc()
|
||||
{
|
||||
var nextVersion = new Version(Major, Minor, Patch, Rc.ToString(), Service);
|
||||
nextVersion.BumpRc();
|
||||
return nextVersion;
|
||||
}
|
||||
|
||||
public void BumpMajor()
|
||||
{
|
||||
Major++;
|
||||
Minor = 0;
|
||||
Patch = 0;
|
||||
Rc = null;
|
||||
}
|
||||
|
||||
public void BumpMinor()
|
||||
{
|
||||
Minor++;
|
||||
Patch = 0;
|
||||
Rc = null;
|
||||
}
|
||||
|
||||
public void BumpPatch()
|
||||
{
|
||||
Patch++;
|
||||
Rc = null;
|
||||
}
|
||||
|
||||
public void BumpRc()
|
||||
{
|
||||
if (Rc == null)
|
||||
{
|
||||
BumpMinor();
|
||||
}
|
||||
Rc = Rc == null ? 0 : Rc + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/Core/Models/VersionInformation.cs
Normal file
20
src/Core/Models/VersionInformation.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace Application.Models
|
||||
{
|
||||
public class VersionInformation
|
||||
{
|
||||
public VersionInformation(Version currentVersion)
|
||||
{
|
||||
CurrentVersion = currentVersion;
|
||||
NextMajorVersion = currentVersion.NextMajor();
|
||||
NextMinorVersion = currentVersion.NextMinor();
|
||||
NextPatchVersion = currentVersion.NextPatch();
|
||||
NextMinorRcVersion = currentVersion.NextRc();
|
||||
}
|
||||
|
||||
public Version CurrentVersion { get; }
|
||||
public Version NextMajorVersion { get; }
|
||||
public Version NextMinorVersion { get; }
|
||||
public Version NextPatchVersion { get; }
|
||||
public Version NextMinorRcVersion { get; }
|
||||
}
|
||||
}
|
||||
37
src/Core/Queries/GetServicesFromGitRepo.cs
Normal file
37
src/Core/Queries/GetServicesFromGitRepo.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Application.Interfaces;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Queries
|
||||
{
|
||||
public class GetServicesFromGitRepo : RequestHandler<GetServicesFromGitRepo.Query, List<string>>
|
||||
{
|
||||
public class Query : IRequest<List<string>>
|
||||
{
|
||||
public Query(string repositoryPath)
|
||||
{
|
||||
RepositoryPath = repositoryPath;
|
||||
}
|
||||
|
||||
public string RepositoryPath { get; }
|
||||
}
|
||||
|
||||
private readonly IGitRepoReadService _gitRepoReadService;
|
||||
|
||||
public GetServicesFromGitRepo(IGitRepoReadService gitRepoReadService)
|
||||
{
|
||||
_gitRepoReadService = gitRepoReadService;
|
||||
}
|
||||
|
||||
protected override List<string> Handle(Query request)
|
||||
{
|
||||
return _gitRepoReadService
|
||||
.GetAllVersions(request.RepositoryPath)
|
||||
.Select(v => v.Service)
|
||||
.Distinct()
|
||||
.OrderBy(v => v)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
51
src/Core/Queries/GetVersionInformationFromRepo.cs
Normal file
51
src/Core/Queries/GetVersionInformationFromRepo.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Application.Interfaces;
|
||||
using Application.Models;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Queries
|
||||
{
|
||||
public class GetVersionInformationFromRepo : RequestHandler<GetVersionInformationFromRepo.Query, VersionInformation>
|
||||
{
|
||||
public class Query : IRequest<VersionInformation>
|
||||
{
|
||||
public Query(string repositoryPath, string onlyForService = "")
|
||||
{
|
||||
RepositoryPath = repositoryPath;
|
||||
OnlyForService = onlyForService;
|
||||
}
|
||||
|
||||
public string RepositoryPath { get; }
|
||||
public string OnlyForService { get; }
|
||||
}
|
||||
|
||||
private readonly IGitRepoReadService _gitRepoReadService;
|
||||
|
||||
public GetVersionInformationFromRepo(IGitRepoReadService gitRepoReadService)
|
||||
{
|
||||
_gitRepoReadService = gitRepoReadService;
|
||||
}
|
||||
|
||||
protected override VersionInformation Handle(Query request)
|
||||
{
|
||||
var versions = _gitRepoReadService
|
||||
.GetAllVersions(request.RepositoryPath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.OnlyForService))
|
||||
{
|
||||
versions = versions
|
||||
.Where(v => v.Service.Equals(request.OnlyForService, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
var currentVersion = versions
|
||||
.OrderByDescending(v => v.Major)
|
||||
.ThenByDescending(v => v.Minor)
|
||||
.ThenByDescending(v => v.Patch)
|
||||
.ThenByDescending(v => v.Rc)
|
||||
.FirstOrDefault();
|
||||
|
||||
return currentVersion == null ? null : new VersionInformation(currentVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
7
src/Domain/Domain.csproj
Normal file
7
src/Domain/Domain.csproj
Normal file
@@ -0,0 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
16
src/Infrastructure/DependencyInjection.cs
Normal file
16
src/Infrastructure/DependencyInjection.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Application.Interfaces;
|
||||
using Infrastructure.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Infrastructure
|
||||
{
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
|
||||
{
|
||||
return services
|
||||
.AddSingleton<IGitRepoReadService, GitRepoReadService>()
|
||||
.AddSingleton<IGitRepoWriteService, GitRepoWriteService>();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/Infrastructure/Infrastructure.csproj
Normal file
17
src/Infrastructure/Infrastructure.csproj
Normal file
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LibGit2Sharp" Version="0.26.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="semver" Version="2.0.6" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
37
src/Infrastructure/Services/GitRepoReadService.cs
Normal file
37
src/Infrastructure/Services/GitRepoReadService.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using Application.Interfaces;
|
||||
using LibGit2Sharp;
|
||||
using Semver;
|
||||
using Version = Application.Models.Version;
|
||||
|
||||
namespace Infrastructure.Services
|
||||
{
|
||||
public class GitRepoReadService : IGitRepoReadService
|
||||
{
|
||||
public IEnumerable<Version> GetAllVersions(string repoPath)
|
||||
{
|
||||
using var repo = new Repository(repoPath);
|
||||
foreach (var tag in repo.Tags)
|
||||
{
|
||||
if (TryParse(tag.FriendlyName, out var semver))
|
||||
{
|
||||
yield return new Version(semver.Major, semver.Minor, semver.Patch, semver.Prerelease, semver.Build);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryParse(string version, out SemVersion semverVersion)
|
||||
{
|
||||
try
|
||||
{
|
||||
semverVersion = SemVersion.Parse(version.TrimStart('v').TrimStart('V'));
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
semverVersion = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/Infrastructure/Services/GitRepoWriteService.cs
Normal file
20
src/Infrastructure/Services/GitRepoWriteService.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Application.Interfaces;
|
||||
using LibGit2Sharp;
|
||||
|
||||
namespace Infrastructure.Services
|
||||
{
|
||||
public class GitRepoWriteService : IGitRepoWriteService
|
||||
{
|
||||
public void AddTag(string repoPath, string tag)
|
||||
{
|
||||
using var repo = new Repository(repoPath);
|
||||
repo.ApplyTag(tag);
|
||||
}
|
||||
|
||||
public void Push(string repoPath)
|
||||
{
|
||||
using var repo = new Repository(repoPath);
|
||||
repo.Network.Push(repo.Head);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
tests/update-tag.tests/VersionTests.cs
Normal file
65
tests/update-tag.tests/VersionTests.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Xunit;
|
||||
using Version = Application.Models.Version;
|
||||
|
||||
namespace UpdateTag.Tests
|
||||
{
|
||||
public class VersionTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(1, 0, 0, "", "", "2.0.0")]
|
||||
[InlineData(1, 1, 0, "", "", "2.0.0")]
|
||||
[InlineData(1, 1, 1, "", "", "2.0.0")]
|
||||
[InlineData(1, 1, 1, "RC.4", "", "2.0.0")]
|
||||
[InlineData(1, 1, 1, "RC.4", "ErpNext", "2.0.0+ErpNext")]
|
||||
public void BumpMajor(int major, int minor, int patch, string rc, string service, string expected)
|
||||
|
||||
{
|
||||
var version = new Version(major, minor, patch, rc, service);
|
||||
version.BumpMajor();
|
||||
Assert.Equal(expected, version.ToString());
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, 0, 0, "", "", "1.1.0")]
|
||||
[InlineData(1, 1, 0, "", "", "1.2.0")]
|
||||
[InlineData(1, 1, 1, "", "", "1.2.0")]
|
||||
[InlineData(1, 1, 1, "RC.4", "", "1.2.0")]
|
||||
[InlineData(1, 1, 1, "RC.4", "ErpNext", "1.2.0+ErpNext")]
|
||||
public void BumpMinor(int major, int minor, int patch, string rc, string service, string expected)
|
||||
|
||||
{
|
||||
var version = new Version(major, minor, patch, rc, service);
|
||||
version.BumpMinor();
|
||||
Assert.Equal(expected, version.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, 0, 0, "", "", "1.0.1")]
|
||||
[InlineData(1, 1, 0, "", "", "1.1.1")]
|
||||
[InlineData(1, 1, 1, "", "", "1.1.2")]
|
||||
[InlineData(1, 1, 1, "RC.4", "", "1.1.2")]
|
||||
[InlineData(1, 1, 1, "RC.4", "ErpNext", "1.1.2+ErpNext")]
|
||||
public void BumpPatch(int major, int minor, int patch, string rc, string service, string expected)
|
||||
|
||||
{
|
||||
var version = new Version(major, minor, patch, rc, service);
|
||||
version.BumpPatch();
|
||||
Assert.Equal(expected, version.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, 0, 0, "", "", "1.1.0-RC.0")]
|
||||
[InlineData(1, 1, 0, "", "", "1.2.0-RC.0")]
|
||||
[InlineData(1, 1, 1, "", "", "1.2.0-RC.0")]
|
||||
[InlineData(1, 1, 1, "RC.4", "", "1.1.1-RC.5")]
|
||||
[InlineData(1, 1, 1, "RC.4", "ErpNext", "1.1.1-RC.5+ErpNext")]
|
||||
public void BumpRc(int major, int minor, int patch, string rc, string service, string expected)
|
||||
|
||||
{
|
||||
var version = new Version(major, minor, patch, rc, service);
|
||||
version.BumpRc();
|
||||
Assert.Equal(expected, version.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
27
tests/update-tag.tests/update-tag.tests.csproj
Normal file
27
tests/update-tag.tests/update-tag.tests.csproj
Normal file
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>UpdateTag.Tests</RootNamespace>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.0.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Core\Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
86
update-tag.sln
Normal file
86
update-tag.sln
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30114.105
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{50940826-54B4-446A-B27A-8B4693F4697A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cli", "src\Cli\Cli.csproj", "{91DAAA93-C852-4E09-AA5A-64B9D02C448D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{476F6D7F-1C9D-49EE-ACD1-49C13721D930}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "update-tag.tests", "tests\update-tag.tests\update-tag.tests.csproj", "{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{35A56961-3C0B-466E-8CE8-FF0660EED834}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "src\Core\Core.csproj", "{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Release|x64.Build.0 = Release|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{91DAAA93-C852-4E09-AA5A-64B9D02C448D} = {50940826-54B4-446A-B27A-8B4693F4697A}
|
||||
{8C8A5F65-5D2C-45D2-85A4-B0EF38E6D65B} = {476F6D7F-1C9D-49EE-ACD1-49C13721D930}
|
||||
{35A56961-3C0B-466E-8CE8-FF0660EED834} = {50940826-54B4-446A-B27A-8B4693F4697A}
|
||||
{7C947404-498C-40F4-A9AA-8ABCBAFD2DB6} = {50940826-54B4-446A-B27A-8B4693F4697A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Reference in New Issue
Block a user