Skip to content
17 changes: 17 additions & 0 deletions source/Calamari/ArgoCD/ArgoCDOutputVariablesWriter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Calamari.ArgoCD.Git;
using Calamari.ArgoCD.Models;
using Calamari.Common.Plumbing.Logging;
using Calamari.Kubernetes;
Expand All @@ -16,6 +18,21 @@ public ArgoCDOutputVariablesWriter(ILog log)
this.log = log;
}

public void WritePushResultOutput(
string applicationName,
int sourceIndex,
PushResult pushResult)
{
log.SetOutputVariableButDoNotAddToVariables(SpecialVariables.Git.Output.Applications(applicationName).Sources(sourceIndex).CommitSha, pushResult.ShortSha);

if (pushResult is PullRequestPushResult prResult)
{
log.SetOutputVariableButDoNotAddToVariables(SpecialVariables.Git.Output.Applications(applicationName).Sources(sourceIndex).PullRequestTitle, prResult.PullRequestTitle);
log.SetOutputVariableButDoNotAddToVariables(SpecialVariables.Git.Output.Applications(applicationName).Sources(sourceIndex).PullRequestUrl, prResult.PullRequestUri);
log.SetOutputVariableButDoNotAddToVariables(SpecialVariables.Git.Output.Applications(applicationName).Sources(sourceIndex).PullRequestNumber, prResult.PullRequestNumber.ToString(CultureInfo.InvariantCulture));
}
}

public void WriteImageUpdateOutput(IEnumerable<string> gateways,
IEnumerable<string> gitRepos,
IReadOnlyCollection<(ApplicationName ApplicationName, int TotalSourceCount, int MatchingSourceCount)> totalApplicationsWithSourceCounts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class UpdateArgoCDAppImagesInstallConvention : IInstallConvention
readonly IArgoCDApplicationManifestParser argoCdApplicationManifestParser;
readonly IGitVendorAgnosticApiAdapterFactory gitVendorAgnosticApiAdapterFactory;
readonly IClock clock;
readonly ArgoCDOutputVariablesWriter outputVariablesWriter;

public UpdateArgoCDAppImagesInstallConvention(ILog log,
ICalamariFileSystem fileSystem,
Expand All @@ -48,10 +49,12 @@ public UpdateArgoCDAppImagesInstallConvention(ILog log,
this.argoCdApplicationManifestParser = argoCdApplicationManifestParser;
this.gitVendorAgnosticApiAdapterFactory = gitVendorAgnosticApiAdapterFactory;
this.clock = clock;
outputVariablesWriter = new ArgoCDOutputVariablesWriter(log);
}

public void Install(RunningDeployment deployment)
{

log.Verbose("Executing Update Argo CD Application Images");
var deploymentConfig = deploymentConfigFactory.CreateUpdateImageConfig(deployment);

Expand Down Expand Up @@ -80,8 +83,7 @@ public void Install(RunningDeployment deployment)
var newImagesWritten = updatedApplications.SelectMany(r => r.UpdatedImages).ToHashSet();

var gatewayIds = argoProperties.Applications.Select(a => a.GatewayId).ToHashSet();
var outputWriter = new ArgoCDOutputVariablesWriter(log);
outputWriter.WriteImageUpdateOutput(gatewayIds,
outputVariablesWriter.WriteImageUpdateOutput(gatewayIds,
gitReposUpdated,
totalApplicationsWithSourceCounts,
updatedApplicationsWithSources,
Expand Down Expand Up @@ -171,7 +173,8 @@ HashSet<string> ProcessSource(ApplicationSourceWithMetadata sourceWithMetadata,
deploymentConfig,
sourceWithMetadata,
defaultRegistry)
: ProcessDirectory(gitCredentials,
: ProcessDirectory(applicationFromYaml,
gitCredentials,
repositoryFactory,
deploymentConfig,
sourceWithMetadata,
Expand All @@ -188,7 +191,8 @@ HashSet<string> ProcessSource(ApplicationSourceWithMetadata sourceWithMetadata,
}
case SourceType.Kustomize:
{
return ProcessKustomize(gitCredentials,
return ProcessKustomize(applicationFromYaml,
gitCredentials,
repositoryFactory,
deploymentConfig,
sourceWithMetadata,
Expand All @@ -205,11 +209,12 @@ HashSet<string> ProcessSource(ApplicationSourceWithMetadata sourceWithMetadata,
}

/// <returns>Images that were updated</returns>
HashSet<string> ProcessKustomize(Dictionary<string, GitCredentialDto> gitCredentials,
RepositoryFactory repositoryFactory,
UpdateArgoCDAppDeploymentConfig deploymentConfig,
ApplicationSourceWithMetadata sourceWithMetadata,
string defaultRegistry)
HashSet<string> ProcessKustomize(Application applicationFromYaml,
Dictionary<string, GitCredentialDto> gitCredentials,
RepositoryFactory repositoryFactory,
UpdateArgoCDAppDeploymentConfig deploymentConfig,
ApplicationSourceWithMetadata sourceWithMetadata,
string defaultRegistry)
{
var applicationSource = sourceWithMetadata.Source;

Expand All @@ -226,14 +231,15 @@ HashSet<string> ProcessKustomize(Dictionary<string, GitCredentialDto> gitCredent
var (updatedFiles, updatedImages) = UpdateKustomizeYaml(repository.WorkingDirectory, applicationSource.Path!, defaultRegistry, deploymentConfig.ImageReferences);
if (updatedImages.Count > 0)
{
var didPush = PushToRemote(repository,
var pushResult = PushToRemote(repository,
GitReference.CreateFromString(applicationSource.TargetRevision),
deploymentConfig.CommitParameters,
updatedFiles,
updatedImages);

if (didPush)
if (pushResult is not null)
{
outputVariablesWriter.WritePushResultOutput(applicationFromYaml.Metadata.Name, sourceWithMetadata.Index, pushResult);
return updatedImages;
}
}
Expand Down Expand Up @@ -263,20 +269,23 @@ HashSet<string> ProcessRef(Application applicationFromYaml,
LogHelmSourceConfigurationProblems(helmTargetsForRefSource.Problems);

using var repository = CreateRepository(gitCredentials, applicationSource, repositoryFactory);
var updatedImages = ProcessHelmUpdateTargets(repository,
var updatedImages = ProcessHelmUpdateTargets(
applicationFromYaml,
repository,
deploymentConfig,
applicationSource,
sourceWithMetadata,
helmTargetsForRefSource.Targets);

return updatedImages;
}

/// <returns>Images that were updated</returns>
HashSet<string> ProcessDirectory(Dictionary<string, GitCredentialDto> gitCredentials,
RepositoryFactory repositoryFactory,
UpdateArgoCDAppDeploymentConfig deploymentConfig,
ApplicationSourceWithMetadata sourceWithMetadata,
string defaultRegistry)
HashSet<string> ProcessDirectory(Application applicationFromYaml,
Dictionary<string, GitCredentialDto> gitCredentials,
RepositoryFactory repositoryFactory,
UpdateArgoCDAppDeploymentConfig deploymentConfig,
ApplicationSourceWithMetadata sourceWithMetadata,
string defaultRegistry)
{
var applicationSource = sourceWithMetadata.Source;
if (applicationSource.Path == null)
Expand All @@ -292,13 +301,19 @@ HashSet<string> ProcessDirectory(Dictionary<string, GitCredentialDto> gitCredent
var (updatedFiles, updatedImages) = UpdateKubernetesYaml(repository.WorkingDirectory, applicationSource.Path!, defaultRegistry, deploymentConfig.ImageReferences);
if (updatedImages.Count > 0)
{
var didPush = PushToRemote(repository,
var pushResult = PushToRemote(repository,
GitReference.CreateFromString(applicationSource.TargetRevision),
deploymentConfig.CommitParameters,
updatedFiles,
updatedImages);

return didPush ? updatedImages : new HashSet<string>();
if (pushResult is not null)
{
outputVariablesWriter.WritePushResultOutput(applicationFromYaml.Metadata.Name, sourceWithMetadata.Index, pushResult);
return updatedImages;
}

return [];
}
}
return new HashSet<string>();
Expand Down Expand Up @@ -345,16 +360,18 @@ HashSet<string> ProcessHelm(Application applicationFromYaml,

LogHelmSourceConfigurationProblems(valueFileProblems);

return ProcessHelmUpdateTargets(repository,
return ProcessHelmUpdateTargets(applicationFromYaml,
repository,
deploymentConfig,
applicationSource,
sourceWithMetadata,
valuesFilesToUpdate);
}

/// <returns>Images that were updated</returns>
HashSet<string> ProcessHelmUpdateTargets(RepositoryWrapper repository,
HashSet<string> ProcessHelmUpdateTargets(Application applicationFromYaml,
RepositoryWrapper repository,
UpdateArgoCDAppDeploymentConfig deploymentConfig,
ApplicationSource source,
ApplicationSourceWithMetadata sourceWithMetadata,
IReadOnlyCollection<HelmValuesFileImageUpdateTarget> targets)
{
var results = targets.Select(t => UpdateHelmImageValues(repository.WorkingDirectory,
Expand All @@ -366,14 +383,15 @@ HashSet<string> ProcessHelmUpdateTargets(RepositoryWrapper repository,
var updatedImages = results.SelectMany(r => r.ImagesUpdated).ToHashSet();
if (updatedImages.Count > 0)
{
var didPush = PushToRemote(repository,
GitReference.CreateFromString(source.TargetRevision),
var pushResult = PushToRemote(repository,
GitReference.CreateFromString(sourceWithMetadata.Source.TargetRevision),
deploymentConfig.CommitParameters,
results.Where(r => r.ImagesUpdated.Any()).Select(r => r.RelativeFilepath).ToHashSet(),
updatedImages);

if (didPush)
if (pushResult is not null)
{
outputVariablesWriter.WritePushResultOutput(applicationFromYaml.Metadata.Name, sourceWithMetadata.Index, pushResult);
return updatedImages;
}
}
Expand Down Expand Up @@ -546,11 +564,11 @@ HelmRefUpdatedResult UpdateHelmImageValues(string rootPath,
return new HelmRefUpdatedResult(new HashSet<string>(), Path.Combine(target.Path, target.FileName));
}

bool PushToRemote(RepositoryWrapper repository,
GitReference branchName,
GitCommitParameters commitParameters,
HashSet<string> updatedFiles,
HashSet<string> updatedImages)
PushResult? PushToRemote(RepositoryWrapper repository,
GitReference branchName,
GitCommitParameters commitParameters,
HashSet<string> updatedFiles,
HashSet<string> updatedImages)
{
log.Info("Staging files in repository");
repository.StageFiles(updatedFiles.ToArray());
Expand All @@ -559,18 +577,16 @@ bool PushToRemote(RepositoryWrapper repository,

log.Info("Commiting changes");
if (!repository.CommitChanges(commitParameters.Summary, commitDescription))
return false;
return null;

log.Verbose("Pushing to remote");
repository.PushChanges(commitParameters.RequiresPr,
return repository.PushChanges(commitParameters.RequiresPr,
commitParameters.Summary,
commitDescription,
branchName,
CancellationToken.None)
.GetAwaiter()
.GetResult();

return true;
}

//NOTE: rootPath needs to include the subfolder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class UpdateArgoCDApplicationManifestsInstallConvention : IInstallConvent
readonly IArgoCDManifestsFileMatcher argoCDManifestsFileMatcher;
readonly IGitVendorAgnosticApiAdapterFactory gitVendorAgnosticApiAdapterFactory;
readonly IClock clock;
readonly ArgoCDOutputVariablesWriter outputVariablesWriter;

public UpdateArgoCDApplicationManifestsInstallConvention(ICalamariFileSystem fileSystem,
string packageSubfolder,
Expand All @@ -50,6 +51,7 @@ public UpdateArgoCDApplicationManifestsInstallConvention(ICalamariFileSystem fil
this.gitVendorAgnosticApiAdapterFactory = gitVendorAgnosticApiAdapterFactory;
this.clock = clock;
this.packageSubfolder = packageSubfolder;
outputVariablesWriter = new ArgoCDOutputVariablesWriter(log);
}

public void Install(RunningDeployment deployment)
Expand Down Expand Up @@ -81,12 +83,11 @@ public void Install(RunningDeployment deployment)
var updatedApplicationsWithSources = applicationResults.Where(r => r.UpdatedSourceCount > 0).Select(r => (r.ApplicationName, r.UpdatedSourceCount)).ToList();

var gatewayIds = argoProperties.Applications.Select(a => a.GatewayId).ToHashSet();
var outputWriter = new ArgoCDOutputVariablesWriter(log);
outputWriter.WriteManifestUpdateOutput(gatewayIds,
gitReposUpdated,
totalApplicationsWithSourceCounts,
updatedApplicationsWithSources
);
outputVariablesWriter.WriteManifestUpdateOutput(gatewayIds,
gitReposUpdated,
totalApplicationsWithSourceCounts,
updatedApplicationsWithSources
);

}

Expand Down Expand Up @@ -200,14 +201,19 @@ bool ProcessSource(DeploymentScope deploymentScope,
if (repository.CommitChanges(deploymentConfig.CommitParameters.Summary, deploymentConfig.CommitParameters.Description))
{
log.Info("Changes were commited, pushing to remote");
repository.PushChanges(deploymentConfig.CommitParameters.RequiresPr,
var pushResult = repository.PushChanges(deploymentConfig.CommitParameters.RequiresPr,
deploymentConfig.CommitParameters.Summary,
deploymentConfig.CommitParameters.Description,
targetBranch,
CancellationToken.None)
.GetAwaiter()
.GetResult();

if (pushResult is not null)
{
outputVariablesWriter.WritePushResultOutput(applicationFromYaml.Metadata.Name, sourceWithMetadata.Index, pushResult);
}

return true;
}

Expand Down
Loading