Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions GitHelperApp/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace GitHelperApp;
[Subcommand(typeof(SearchWorkItemsCommand))]
[Subcommand(typeof(CreateCustomPrCommand))]
[Subcommand(typeof(GetRepositoriesCommand))]
// [Subcommand(typeof(RunPipelinesCommand))]
[Subcommand(typeof(GetBuildsCommand))]
public sealed class Application
{
/// <summary>
Expand Down
68 changes: 68 additions & 0 deletions GitHelperApp/Commands/GetBuildsCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using GitHelperApp.Commands.Interfaces;
using GitHelperApp.Models;
using GitHelperApp.Services.Interfaces;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;

namespace GitHelperApp.Commands;

/// <summary>
/// Special command to process the builds and get latest build runs.
/// </summary>
public sealed class GetBuildsCommand : ICustomCommand
{
private readonly ILogger<GetBuildsCommand> _logger;
private readonly IPipelineService _pipelineService;
private readonly IOutputService _outputService;

[Option(CommandOptionType.SingleValue, Description = "Print to console", ShortName = "pc")]
private bool IsPrintToConsole { get; }

[Option(CommandOptionType.SingleValue, Description = "Print to file", ShortName = "pf")]
private bool IsPrintToFile { get; }

[Option(CommandOptionType.SingleValue, Description = "Branch", ShortName = "b")]
private string Branch { get; }

[Option(CommandOptionType.SingleValue, Description = "Environment", ShortName = "e")]
private string Environment { get; }

public GetBuildsCommand(ILogger<GetBuildsCommand> logger, IPipelineService pipelineService, IOutputService outputService)
{
_logger = logger;
_pipelineService = pipelineService;
_outputService = outputService;
}

public async Task OnExecuteAsync(CommandLineApplication command, IConsole console)
{
try
{
var (runId, directory) = _outputService.InitializeOutputBatch("GetBuilds");

// start pipelines
_logger.LogInformation("Start searching for builds...");

var settings = new PipelineRunSettings
{
Branch = Branch,
Environment = Environment
};

var buildResults = await _pipelineService.GetBuildDetailsAsync(settings);

_logger.LogInformation($"Builds processed: {buildResults.Count}");

// output the results
_logger.LogInformation("Output build run results...");

_outputService.OutputBuildDetailsResult(buildResults, runId, directory, IsPrintToConsole, IsPrintToFile);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occured while searching builds on Azure DevOps");

throw;
}
}
}
69 changes: 69 additions & 0 deletions GitHelperApp/Commands/RunPipelinesCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using GitHelperApp.Commands.Interfaces;
using GitHelperApp.Models;
using GitHelperApp.Services.Interfaces;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;

namespace GitHelperApp.Commands;

// TODO: implement this command later...

public sealed class RunPipelinesCommand : ICustomCommand
{
private readonly ILogger<RunPipelinesCommand> _logger;
private readonly IPipelineService _pipelineService;
private readonly IOutputService _outputService;

[Option(CommandOptionType.SingleValue, Description = "Print to console", ShortName = "pc")]
private bool IsPrintToConsole { get; }

[Option(CommandOptionType.SingleValue, Description = "Print to file", ShortName = "pf")]
private bool IsPrintToFile { get; }

[Option(CommandOptionType.SingleValue, Description = "Branch", ShortName = "b")]
private string Branch { get; }

[Option(CommandOptionType.SingleValue, Description = "Environment", ShortName = "e")]
private string Environment { get; }

[Option(CommandOptionType.SingleValue, Description = "Dry run", ShortName = "d")]
private bool DryRun { get; }

public RunPipelinesCommand(ILogger<RunPipelinesCommand> logger, IPipelineService pipelineService, IOutputService outputService)
{
_logger = logger;
_pipelineService = pipelineService;
_outputService = outputService;
}

public async Task OnExecuteAsync(CommandLineApplication command, IConsole console)
{
try
{
var (runId, directory) = _outputService.InitializeOutputBatch("RunPipelines");

// start pipelines
_logger.LogInformation("Start pipelines for repositories...");

var settings = new PipelineRunSettings
{
Branch = Branch,
Environment = Environment
};
var runResults = await _pipelineService.RunPipelineAsync(settings, DryRun);

_logger.LogInformation($"Pipelines processed: {runResults.Count}");

// output the results
_logger.LogInformation("Output pipelines run results...");

// TODO: implement the logic to print results
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occured while running pipelines on Azure DevOps");

throw;
}
}
}
2 changes: 2 additions & 0 deletions GitHelperApp/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public static IServiceCollection InitializeDependencies(this IServiceCollection
services.AddSingleton<IWorkItemsService, WorkItemsService>();
services.AddTransient<IRepositoryService, RepositoryService>();

services.AddSingleton<IPipelineService, PipelineService>();

// add content generators
services.AddSingleton<IContentGeneratorFactory, ContentGeneratorFactory>();

Expand Down
3 changes: 3 additions & 0 deletions GitHelperApp/Generators/FileNameGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public string CreateFileNameForWorkItems(string directory, string runId) =>
public string CreateFileNameForRepositories(string directory, string runId) =>
Path.Combine(_appConfig.OutputDirectory, directory, $"Repositories-{runId}.{GetExtension(_appConfig.OutputFormat)}");

public string CreateFileNameForBuildDetails(string directory, string runId) =>
Path.Combine(_appConfig.OutputDirectory, directory, $"Builds-{runId}.{GetExtension(_appConfig.OutputFormat)}");

private static string GetExtension(string format)
{
return format switch
Expand Down
1 change: 1 addition & 0 deletions GitHelperApp/Generators/Interfaces/IContentGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ public interface IContentGenerator
List<string> ProcessWorkItemsSearchResults(List<WorkItemSearchResult> witResults);
List<string> ProcessSummaryTableResult(List<ReleaseSummaryModel> aggregatedResult);
List<string> ProcessRepositoriesResult(List<RepositoryModel> repositoryModels);
IReadOnlyCollection<string> ProcessBuildDetailsResult(List<BuildDetails> buildResults);
}
1 change: 1 addition & 0 deletions GitHelperApp/Generators/Interfaces/IFileNameGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ public interface IFileNameGenerator
string CreateFileNameForPrIds(string directory, string runId);
string CreateFileNameForWorkItems(string directory, string runId);
string CreateFileNameForRepositories(string directory, string runId);
string CreateFileNameForBuildDetails(string directory, string runId);
}
6 changes: 6 additions & 0 deletions GitHelperApp/Generators/MarkdownContentGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,10 @@ public List<string> ProcessRepositoriesResult(List<RepositoryModel> repositoryMo

return lines;
}

public IReadOnlyCollection<string> ProcessBuildDetailsResult(List<BuildDetails> buildResults)
{
// TODO: no need to add the logic here because simple markdown file is not supported the tables
return Enumerable.Empty<string>().ToList();
}
}
41 changes: 37 additions & 4 deletions GitHelperApp/Generators/MarkdownTableContentGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,19 @@ public List<string> ProcessRepositoriesResult(List<RepositoryModel> repositoryMo
return lines;
}

private IEnumerable<string> CreateRepositoriesTable(List<RepositoryModel> repositoryModels)
public IReadOnlyCollection<string> ProcessBuildDetailsResult(List<BuildDetails> buildResults)
{
var lines = new List<string>();

lines.Add($"# Build details (Count = {buildResults.Count})");
lines.AddRange(CreateBuildDetailsTable(buildResults));

return lines;
}

#region Helpers.

private static IEnumerable<string> CreateRepositoriesTable(List<RepositoryModel> repositoryModels)
{
return repositoryModels
.OrderBy(x => x.Name)
Expand All @@ -176,9 +188,7 @@ private IEnumerable<string> CreateRepositoriesTable(List<RepositoryModel> reposi
})
.ToMarkdownTable(new[] { "#", "Title" });
}

#region Helpers.


private static IEnumerable<string> CreatePullRequestList(List<PullRequestResult> prResults)
{
return prResults.Where(x => x.PullRequestId != 0)
Expand Down Expand Up @@ -242,6 +252,29 @@ private static IEnumerable<string> CreateSummaryTable(List<ReleaseSummaryModel>
})
.ToMarkdownTable(new[] { "#", "Repository", "Build Pipeline", "PR", "Work Items Count" });
}

private static IEnumerable<string> CreateBuildDetailsTable(List<BuildDetails> buildResults)
{
return buildResults
.Where(x => x != null)
.Select((x, index) => new
{
Index = index + 1,
Repo = $"[{x.RepositoryName}]({x.RepositoryUrl})",
x.Environment,
x.SourceBranch,
SourceLink = $"[{x.SourceVersion}]({x.SourceCommitLink})",
Link = x.Status == "None"
? $"[Pipeline]({x.BuildLink})"
: $"[Build ({x.Status})]({x.BuildLink})",
x.RequestedFor,
x.StartTime,
x.FinishTime,
CurrentLink = $"[{x.CurrentCommit}]({x.CurrentCommitLink})",
x.Message
})
.ToMarkdownTable(new[] { "#", "Repository", "Environment", "Branch", "Commit", "Build", "Requested For", "Start", "End", "Current Commit", "Status" });
}

#endregion
}
6 changes: 6 additions & 0 deletions GitHelperApp/Generators/TextFileContentGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,10 @@ public List<string> ProcessRepositoriesResult(List<RepositoryModel> repositoryMo

return lines;
}

public IReadOnlyCollection<string> ProcessBuildDetailsResult(List<BuildDetails> buildResults)
{
// TODO: no need to add the logic here because text file is not supported the tables
return Enumerable.Empty<string>().ToList();
}
}
9 changes: 6 additions & 3 deletions GitHelperApp/GitHelperApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="4.0.2" />
<PackageReference Include="McMaster.Extensions.Hosting.CommandLine" Version="4.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="16.170.0" />
<PackageReference Include="Microsoft.VisualStudio.Services.InteractiveClient" Version="16.170.0" />
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="19.212.0-preview" />
<PackageReference Include="Microsoft.VisualStudio.Services.InteractiveClient" Version="19.212.0-preview" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
Expand Down Expand Up @@ -55,6 +55,9 @@
<None Update="appsettings.MR.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.DD.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
14 changes: 14 additions & 0 deletions GitHelperApp/GitHelperApp/appsettings.DD.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"RepositoriesConfig": {
"DefaultSourceBranch": "dev",
"DefaultDestinationBranch": "release",
"DefaultTeamProject": "MSG",
"Repositories": [
{
"Name": "user-account-service",
"Path": "C:\\Projects\\Matrix\\user-account-service",
"PipelineId": 1012
}
]
}
}
10 changes: 10 additions & 0 deletions GitHelperApp/Helpers/GitBranchHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,14 @@ public static class GitBranchHelper
{
public static string GetRefName(string branchName) => $"origin/{branchName}";
public static string GetRefNameForAzure(string branchName) => $"refs/heads/{branchName}";

/// <summary>
/// Remove the branch ref header - 'refs/heads/'.
/// </summary>
/// <param name="refBranchName">Branch name with full ref from the Azure DevOps.</param>
/// <returns>Returns the branch name without ref name.</returns>
public static string RemoveRefName(string refBranchName)
{
return refBranchName.AsSpan(11).ToString();
}
}
23 changes: 23 additions & 0 deletions GitHelperApp/Models/BuildDetails.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace GitHelperApp.Models;

public sealed class BuildDetails
{
public string RepositoryName { get; set; }
public string RepositoryUrl { get; set; }
public int BuildId { get; set; }
public string RequestedFor { get; set; }
public DateTime FinishTime { get; set; }
public DateTime StartTime { get; set; }
public string Status { get; set; }
public string SourceBranch { get; set; }
public string SourceVersion { get; set; }
public string SourceCommitLink { get; set; }

public string Environment { get; set; }

public string BuildLink { get; set; }

public string CurrentCommit { get; set; }
public string CurrentCommitLink { get; set; }
public string Message { get; set; }
}
8 changes: 8 additions & 0 deletions GitHelperApp/Models/PipelineResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace GitHelperApp.Models;

public sealed class PipelineResult
{
public string Name { get; set; }
public string Url { get; set; }
public int Id { get; set; }
}
10 changes: 10 additions & 0 deletions GitHelperApp/Models/PipelineRunSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace GitHelperApp.Models;

/// <summary>
/// Settings to run the pipeline from specific branch to the specific environment.
/// </summary>
public sealed class PipelineRunSettings
{
public string Branch { get; set; }
public string Environment { get; set; }
}
Loading