// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Text.Json; using System.Threading.Tasks; using System.Xml; using EpicGames.Core; using Microsoft.Extensions.Logging; namespace AutomationTool.Tasks { /// /// Parameters for a Docker-Build task /// public class DockerPushTaskParameters { /// /// Repository /// [TaskParameter] public string Repository { get; set; } /// /// Source image to push /// [TaskParameter] public string Image { get; set; } /// /// Name of the target image /// [TaskParameter(Optional = true)] public string TargetImage { get; set; } /// /// Additional environment variables /// [TaskParameter(Optional = true)] public string Environment { get; set; } /// /// File to read environment from /// [TaskParameter(Optional = true)] public string EnvironmentFile { get; set; } /// /// Whether to login to AWS ECR /// [TaskParameter(Optional = true)] public bool AwsEcr { get; set; } /// /// Path to a json file for authentication to the repository for pushing. /// [TaskParameter(Optional = true)] public string RepositoryAuthFile { get; set; } } /// /// Spawns Docker and waits for it to complete. /// [TaskElement("Docker-Push", typeof(DockerPushTaskParameters))] public class DockerPushTask : SpawnTaskBase { readonly DockerPushTaskParameters _parameters; /// /// Construct a Docker task /// /// Parameters for the task public DockerPushTask(DockerPushTaskParameters parameters) { _parameters = parameters; } /// /// ExecuteAsync the task. /// /// Information about the current job /// Set of build products produced by this node. /// Mapping from tag names to the set of files they include public override async Task ExecuteAsync(JobContext job, HashSet buildProducts, Dictionary> tagNameToFileSet) { Logger.LogInformation("Pushing Docker image"); using (LogIndentScope scope = new LogIndentScope(" ")) { string exe = DockerTask.GetDockerExecutablePath(); Dictionary environment = ParseEnvVars(_parameters.Environment, _parameters.EnvironmentFile); if (_parameters.AwsEcr) { IProcessResult result = await SpawnTaskBase.ExecuteAsync("aws", "ecr get-login-password", envVars: environment, logOutput: false); await ExecuteAsync(exe, $"login {_parameters.Repository} --username AWS --password-stdin", input: result.Output); } if (!String.IsNullOrEmpty(_parameters.RepositoryAuthFile)) { string repositoryText = CommandUtils.ReadAllText(_parameters.RepositoryAuthFile); Dictionary authDict = JsonSerializer.Deserialize>(repositoryText); await ExecuteAsync(exe, $"login {_parameters.Repository} --username {authDict["Username"]} --password-stdin", input: authDict["Token"]); } string targetImage = _parameters.TargetImage ?? _parameters.Image; await ExecuteAsync(exe, $"tag {_parameters.Image} {_parameters.Repository}/{targetImage}", envVars: environment); await ExecuteAsync(exe, $"push {_parameters.Repository}/{targetImage}", envVars: environment); } } /// /// Output this task out to an XML writer. /// public override void Write(XmlWriter writer) { Write(writer, _parameters); } /// /// Find all the tags which are used as inputs to this task /// /// The tag names which are read by this task public override IEnumerable FindConsumedTagNames() { yield break; } /// /// Find all the tags which are modified by this task /// /// The tag names which are modified by this task public override IEnumerable FindProducedTagNames() { yield break; } } }