// Copyright Epic Games, Inc. All Rights Reserved. using System.Collections.Generic; using System.Threading.Tasks; using System.Xml; using EpicGames.Core; using Microsoft.Extensions.Logging; using UnrealBuildBase; namespace AutomationTool.Tasks { /// /// Parameters for a DotNet task /// public class DotNetTaskParameters { /// /// Docker command line arguments /// [TaskParameter(Optional = true)] public string Arguments { get; set; } /// /// Base directory for running the command /// [TaskParameter(Optional = true)] public string BaseDir { get; set; } /// /// Environment variables to set /// [TaskParameter(Optional = true)] public string Environment { get; set; } /// /// File to read environment variables from /// [TaskParameter(Optional = true)] public string EnvironmentFile { get; set; } /// /// The minimum exit code, which is treated as an error. /// [TaskParameter(Optional = true)] public int ErrorLevel { get; set; } = 1; /// /// Override path to dotnet executable /// [TaskParameter(Optional = true)] public FileReference DotNetPath { get; set; } } /// /// Spawns Docker and waits for it to complete. /// [TaskElement("DotNet", typeof(DotNetTaskParameters))] public class DotNetTask : SpawnTaskBase { readonly DotNetTaskParameters _parameters; /// /// Construct a Docker task /// /// Parameters for the task public DotNetTask(DotNetTaskParameters 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) { FileReference dotNetFile = _parameters.DotNetPath == null ? Unreal.DotnetPath : _parameters.DotNetPath; if (!FileReference.Exists(dotNetFile)) { throw new AutomationException("DotNet is missing from {0}", dotNetFile); } IProcessResult result = await ExecuteAsync(dotNetFile.FullName, _parameters.Arguments, workingDir: _parameters.BaseDir, envVars: ParseEnvVars(_parameters.Environment, _parameters.EnvironmentFile)); if (result.ExitCode < 0 || result.ExitCode >= _parameters.ErrorLevel) { Logger.LogError(KnownLogEvents.ExitCode, "Docker terminated with an exit code indicating an error ({ExitCode})", result.ExitCode); throw new AutomationException("Docker terminated with an exit code indicating an error ({0})", result.ExitCode) { OutputFormat = AutomationExceptionOutputFormat.Silent }; } } /// /// 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; } } public static partial class StandardTasks { /// /// Runs a command using dotnet. /// /// Command-line arguments. /// Base directory for running the command. /// Environment variables to set. /// File to read environment variables from. /// The minimum exit code, which is treated as an error. /// Override path to dotnet executable. public static async Task DotNetAsync(string arguments = null, DirectoryReference baseDir = null, string environment = null, FileReference environmentFile = null, int errorLevel = 1, FileReference dotNetPath = null) { DotNetTaskParameters parameters = new DotNetTaskParameters(); parameters.Arguments = arguments; parameters.BaseDir = baseDir?.FullName; parameters.Environment = environment; parameters.EnvironmentFile = environmentFile?.FullName; parameters.ErrorLevel = errorLevel; parameters.DotNetPath = dotNetPath; await ExecuteAsync(new DotNetTask(parameters)); } } }