|
10 | 10 | using System.Net.Http;
|
11 | 11 | using System.Threading.Tasks;
|
12 | 12 | using Microsoft.DotNet.ImageBuilder.Models.Image;
|
| 13 | +using Microsoft.DotNet.ImageBuilder.Services; |
13 | 14 | using Microsoft.DotNet.ImageBuilder.ViewModel;
|
14 | 15 | using Microsoft.DotNet.VersionTools.Automation.GitHubApi;
|
| 16 | +using Microsoft.TeamFoundation.SourceControl.WebApi; |
| 17 | +using Microsoft.VisualStudio.Services.Common; |
15 | 18 |
|
| 19 | +#nullable enable |
16 | 20 | namespace Microsoft.DotNet.ImageBuilder.Commands
|
17 | 21 | {
|
18 | 22 | [Export(typeof(ICommand))]
|
19 | 23 | public class PublishImageInfoCommand : ManifestCommand<PublishImageInfoOptions>
|
20 | 24 | {
|
21 | 25 | private readonly IGitHubClientFactory _gitHubClientFactory;
|
22 | 26 | private readonly ILoggerService _loggerService;
|
| 27 | + private readonly IAzdoGitHttpClientFactory _azdoGitHttpClientFactory; |
23 | 28 | private readonly HttpClient _httpClient;
|
| 29 | + private const string CommitMessage = "Merging Docker image info updates from build"; |
24 | 30 |
|
25 | 31 | [ImportingConstructor]
|
26 |
| - public PublishImageInfoCommand(IGitHubClientFactory gitHubClientFactory, ILoggerService loggerService, IHttpClientProvider httpClientFactory) |
| 32 | + public PublishImageInfoCommand(IGitHubClientFactory gitHubClientFactory, ILoggerService loggerService, IHttpClientProvider httpClientProvider, |
| 33 | + IAzdoGitHttpClientFactory azdoGitHttpClientFactory) |
27 | 34 | {
|
28 |
| - if (httpClientFactory is null) |
| 35 | + if (httpClientProvider is null) |
29 | 36 | {
|
30 |
| - throw new ArgumentNullException(nameof(httpClientFactory)); |
| 37 | + throw new ArgumentNullException(nameof(httpClientProvider)); |
31 | 38 | }
|
32 | 39 |
|
33 | 40 | _gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
|
34 | 41 | _loggerService = loggerService ?? throw new ArgumentNullException(nameof(loggerService));
|
| 42 | + _azdoGitHttpClientFactory = azdoGitHttpClientFactory ?? throw new ArgumentNullException(nameof(azdoGitHttpClientFactory)); |
35 | 43 |
|
36 |
| - _httpClient = httpClientFactory.GetClient(); |
| 44 | + _httpClient = httpClientProvider.GetClient(); |
37 | 45 | }
|
38 | 46 |
|
39 | 47 | public override async Task ExecuteAsync()
|
40 | 48 | {
|
41 | 49 | Uri imageInfoPathIdentifier = GitHelper.GetBlobUrl(Options.GitOptions);
|
42 |
| - GitObject imageInfoGitObject = await GetUpdatedImageInfoGitObjectAsync(); |
43 | 50 |
|
44 |
| - if (imageInfoGitObject is null) |
| 51 | + string? imageInfoContent = await GetUpdatedImageInfoAsync(); |
| 52 | + |
| 53 | + if (imageInfoContent is null) |
45 | 54 | {
|
46 | 55 | _loggerService.WriteMessage($"No changes to the '{imageInfoPathIdentifier}' file were needed.");
|
47 | 56 | return;
|
48 | 57 | }
|
49 | 58 |
|
50 | 59 | _loggerService.WriteMessage(
|
51 | 60 | $"The '{imageInfoPathIdentifier}' file has been updated with the following content:" +
|
52 |
| - Environment.NewLine + imageInfoGitObject.Content + Environment.NewLine); |
| 61 | + Environment.NewLine + imageInfoContent + Environment.NewLine); |
53 | 62 |
|
54 | 63 | if (!Options.IsDryRun)
|
55 | 64 | {
|
56 |
| - using IGitHubClient gitHubClient = _gitHubClientFactory.GetClient(Options.GitOptions.ToGitHubAuth(), Options.IsDryRun); |
57 |
| - await GitHelper.ExecuteGitOperationsWithRetryAsync(async () => |
58 |
| - { |
59 |
| - GitReference gitRef = await GitHelper.PushChangesAsync( |
60 |
| - gitHubClient, Options, "Merging image info updates from build.", |
61 |
| - branch => Task.FromResult<IEnumerable<GitObject>>(new GitObject[] { imageInfoGitObject })); |
62 |
| - |
63 |
| - Uri commitUrl = GitHelper.GetCommitUrl(Options.GitOptions, gitRef.Object.Sha); |
64 |
| - _loggerService.WriteMessage($"The '{imageInfoPathIdentifier}' file was updated ({commitUrl})."); |
65 |
| - }); |
| 65 | + await UpdateGitHubAsync(imageInfoContent, imageInfoPathIdentifier); |
| 66 | + await UpdateAzdoAsync(imageInfoContent, imageInfoPathIdentifier); |
66 | 67 | }
|
67 | 68 | }
|
68 | 69 |
|
69 |
| - private async Task<GitObject> GetUpdatedImageInfoGitObjectAsync() |
| 70 | + private async Task UpdateAzdoAsync(string imageInfoContent, Uri imageInfoPathIdentifier) |
| 71 | + { |
| 72 | + (Uri baseUrl, VssCredentials credentials) = Options.AzdoOptions.GetConnectionDetails(); |
| 73 | + |
| 74 | + using IAzdoGitHttpClient gitHttpClient = _azdoGitHttpClientFactory.GetClient(baseUrl, credentials); |
| 75 | + |
| 76 | + GitRepository repo = (await gitHttpClient.GetRepositoriesAsync()) |
| 77 | + .First(repo => repo.Name == Options.AzdoOptions.Repo); |
| 78 | + GitRef branchRef = (await gitHttpClient.GetBranchRefsAsync(repo.Id)) |
| 79 | + .First(branch => branch.Name == $"refs/heads/{Options.AzdoOptions.Branch}"); |
| 80 | + |
| 81 | + GitPush push = await gitHttpClient.PushChangesAsync(CommitMessage, repo.Id, branchRef, new Dictionary<string, string> |
| 82 | + { |
| 83 | + { Options.AzdoOptions.Path, imageInfoContent } |
| 84 | + }); |
| 85 | + |
| 86 | + TeamFoundation.SourceControl.WebApi.GitCommit commit = |
| 87 | + await gitHttpClient.GetCommitAsync(push.Commits.First().CommitId, repo.Id); |
| 88 | + |
| 89 | + _loggerService.WriteMessage($"The '{imageInfoPathIdentifier}' file was updated ({commit.RemoteUrl})."); |
| 90 | + } |
| 91 | + |
| 92 | + private async Task UpdateGitHubAsync(string imageInfoContent, Uri imageInfoPathIdentifier) |
| 93 | + { |
| 94 | + IGitHubClient gitHubClient = _gitHubClientFactory.GetClient(Options.GitOptions.ToGitHubAuth(), Options.IsDryRun); |
| 95 | + await GitHelper.ExecuteGitOperationsWithRetryAsync(async () => |
| 96 | + { |
| 97 | + VersionTools.Automation.GitHubApi.GitObject imageInfoGitObject = new VersionTools.Automation.GitHubApi.GitObject |
| 98 | + { |
| 99 | + Path = Options.GitOptions.Path, |
| 100 | + Type = VersionTools.Automation.GitHubApi.GitObject.TypeBlob, |
| 101 | + Mode = VersionTools.Automation.GitHubApi.GitObject.ModeFile, |
| 102 | + Content = imageInfoContent |
| 103 | + }; |
| 104 | + |
| 105 | + GitReference gitRef = await GitHelper.PushChangesAsync( |
| 106 | + gitHubClient, Options, CommitMessage, |
| 107 | + branch => Task.FromResult<IEnumerable<VersionTools.Automation.GitHubApi.GitObject>>( |
| 108 | + new VersionTools.Automation.GitHubApi.GitObject[] { imageInfoGitObject })); |
| 109 | + |
| 110 | + Uri commitUrl = GitHelper.GetCommitUrl(Options.GitOptions, gitRef.Object.Sha); |
| 111 | + _loggerService.WriteMessage($"The '{imageInfoPathIdentifier}' file was updated ({commitUrl})."); |
| 112 | + }); |
| 113 | + } |
| 114 | + |
| 115 | + private async Task<string?> GetUpdatedImageInfoAsync() |
70 | 116 | {
|
71 | 117 | ImageArtifactDetails srcImageArtifactDetails = ImageInfoHelper.LoadFromFile(Options.ImageInfoPath, Manifest);
|
72 | 118 |
|
@@ -106,13 +152,7 @@ private async Task<GitObject> GetUpdatedImageInfoGitObjectAsync()
|
106 | 152 |
|
107 | 153 | if (originalTargetImageInfoContents != newTargetImageInfoContents)
|
108 | 154 | {
|
109 |
| - return new GitObject |
110 |
| - { |
111 |
| - Path = Options.GitOptions.Path, |
112 |
| - Type = GitObject.TypeBlob, |
113 |
| - Mode = GitObject.ModeFile, |
114 |
| - Content = newTargetImageInfoContents |
115 |
| - }; |
| 155 | + return newTargetImageInfoContents; |
116 | 156 | }
|
117 | 157 | else
|
118 | 158 | {
|
@@ -178,3 +218,4 @@ private void RemoveOutOfDateContent(ImageArtifactDetails imageArtifactDetails)
|
178 | 218 | }
|
179 | 219 | }
|
180 | 220 | }
|
| 221 | +#nullable disable |
0 commit comments