Merged PR 764381: Remove 'launchworkers' mode from AdoBuildRunner

It is not in use, and with worker stages being the recommended way to include workers there is no need to keep it around
This commit is contained in:
Marcelo Lynch 🧉 2024-02-02 22:39:17 +00:00
Родитель 39942469bb
Коммит 3a4df1af89
7 изменённых файлов: 11 добавлений и 239 удалений

Просмотреть файл

@ -81,16 +81,13 @@ namespace BuildXL.AdoBuildRunner.Build
return returnCode;
}
/// <summary>
/// Log the exit code as an error on the ADO console if it's non-zero, as informational otherwise
/// </summary>
private void LogExitCode(int returnCode)
{
if (returnCode != 0)
{
m_logger.Error(($"ExitCode: {returnCode}"));
}
else
{
m_logger.Info($"ExitCode: {returnCode}");
}
Action<string> logAction = returnCode != 0 ? m_logger.Error : m_logger.Info;
logAction.Invoke($"The BuildXL process completed with exit code {returnCode}");
}
}
}

Просмотреть файл

@ -1,84 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using AdoBuildRunner.Vsts;
using BuildXL.AdoBuildRunner.Vsts;
#nullable enable
namespace BuildXL.AdoBuildRunner.Build
{
/// <summary>
/// Queues a worker pipeline specifying
/// (1) user-provided parameters and
/// (2) the BuildXL build information in the form of triggerInfo
/// </summary>
public class WorkerQueuer
{
private readonly IApi m_api;
private readonly ILogger m_logger;
/// <nodoc />
public WorkerQueuer(ILogger logger, IApi api)
{
m_api = api;
m_logger = logger;
}
/// <summary>
/// Queue a build on the worker pipeline. We include any extra parameters provided by the user, and also a payload
/// for the worker in the form of triggerInfo key-value pairs
/// </summary>
/// <param name="pipelineId">The id of the pipeline that will be triggered</param>
/// <param name="args">Queueing parameters: either template parameters (/param:K=V) or queue-time variables (/var:K=V). Unrecognized options are ignored</param>
public Task QueueWorkerPipelineAsync(int pipelineId, string[] args)
{
// Parse the rest of the arguments looking for the extra parameters
// TODO: Better argument parsing. This is pretty awful but it should do for now:
// we just ignore malformed arguments and pay attention only to the ones of the form
// /param:K=V
var templateParams = new Dictionary<string, string>();
var queueTimeVars = new Dictionary<string, string>();
foreach (var arg in args)
{
const string ParamOpt = "/param:";
const string VarOpt = "/var:";
if (!TryExtractKeyValuePair(ParamOpt, arg, templateParams) && !TryExtractKeyValuePair(VarOpt, arg, queueTimeVars))
{
m_logger.Warning($"Ignoring unrecognized argument {arg}");
}
}
// Include information for the worker pipeline in the trigger info
var triggerInfo = new Dictionary<string, string>()
{
[Constants.TriggeringAdoBuildIdParameter] = m_api.BuildId,
};
var sourceBranch = Environment.GetEnvironmentVariable(Constants.SourceBranchVariableName)!;
var sourceVersion = Environment.GetEnvironmentVariable(Constants.SourceVersionVariableName)!;
return m_api.QueueBuildAsync(pipelineId, sourceBranch, sourceVersion, queueTimeVars, templateParams, triggerInfo);
}
private static bool TryExtractKeyValuePair(string optName, string arg, Dictionary<string, string> targetDict)
{
var trimmed = arg.Trim();
if (trimmed.StartsWith(optName))
{
var kvp = trimmed.Substring(optName.Length).Split("=", 2);
if (kvp.Length == 2)
{
targetDict[kvp[0]] = kvp[1];
return true;
}
}
return false;
}
}
}

Просмотреть файл

@ -20,33 +20,13 @@ namespace BuildXL.AdoBuildRunner
class Program
{
/// <summary>
/// The AdoBuildRunner supports two modes of operation (apart from a ping mode only used for debugging)
///
/// (1) launchworkers mode. This is used to trigger a distributed worker pipeline.
/// This mode is chosen if the first argument to the program is exactly "launchworkers".
/// It is important that this invocation is made from the same job that will run the build:
/// this is both because we communicate the agent's IP address at this stage and also calculate
/// the related session ID as a hash of job-specific values.
///
/// The command line should look like this:
/// AdoBuildRunner.exe launchworkers 12345 [/param:key1=value1 /var:key2=value2 ...]
/// Where:
/// 12345 is is the pipeline id that we are about to queue. This should always be the second argument.
/// After that, a number of /param or /var options can be passed. A /param option specifies a
/// template parameter, and a /var option a build variable, that we will send along with the build request.
/// All of these parameters should be settable at queue time or the build trigger will fail
///
/// (2) build mode.
/// If the first argument is neither "ping" or "launchworkers", the AdoBuildRunner will try to run
/// a BuildXL build.
/// To run a distributed build, the AdoBuildRunnerWorkerPipelineRole environment variable should
/// be set to either "Orchestrator" or "Worker". An unset or different value will result in a single-machine build.
/// To run a distributed build, the AdoBuildRunnerWorkerPipelineRole environment variable should
/// be set to either "Orchestrator" or "Worker". An unset or different value will result in a single-machine build.
///
/// All of the arguments passed to the AdoBuildRunner will be used as arguments for the BuildXL invocation.
/// For the orchestrator build, the /dynamicBuildWorkerSlots argument should be passed with the number of
/// remote workers that this build expects. The rest of the arguments for distributed builds are chosen
/// by the build runner (see <see cref="BuildExecutor"/>).
///
/// All of the arguments passed to the AdoBuildRunner will be used as arguments for the BuildXL invocation.
/// For the orchestrator build, the /dynamicBuildWorkerSlots argument should be passed with the number of
/// remote workers that this build expects. The rest of the arguments for distributed builds are chosen
/// by the build runner (see <see cref="BuildExecutor"/>).
/// </summary>
public static async Task<int> Main(string[] args)
{
@ -85,17 +65,6 @@ namespace BuildXL.AdoBuildRunner
var buildManager = new BuildManager(api, executor, buildContext, args, logger);
return await buildManager.BuildAsync(isOrchestrator: Environment.GetEnvironmentVariable(Constants.AdoBuildRunnerPipelineRole) == "Orchestrator");
}
else if (args[0] == "launchworkers")
{
if (args.Length < 2 || !int.TryParse(args[1], out var pipelineId))
{
throw new CoordinationException("launchworkers mode's first argument must be an integer representing the worker pipeline id");
}
var wq = new WorkerQueuer(logger, api);
await wq.QueueWorkerPipelineAsync(pipelineId, args.Skip(2).ToArray());
return 0;
}
else
{
logger.Info($"Trying to coordinate build for command: {string.Join(" ", args)}");

Просмотреть файл

@ -319,17 +319,6 @@ namespace BuildXL.AdoBuildRunner.Vsts
return null;
}
/// <inheritdoc />
public Task QueueBuildAsync(int pipelineId,
string sourceBranch,
string sourceVersion,
Dictionary<string, string>? parameters = null,
Dictionary<string, string>? templateParameters = null,
Dictionary<string, string>? triggerInfo = null)
{
return m_http.QueuePipelineAsync(pipelineId, sourceBranch, sourceVersion, parameters, templateParameters, triggerInfo);
}
[DoesNotReturn]
private void LogAndThrow(string error)
{

Просмотреть файл

@ -91,10 +91,5 @@ namespace BuildXL.AdoBuildRunner.Vsts
/// </summary>
/// <returns></returns>
Task PublishBuildInfo(BuildContext buildContext, BuildInfo buildInfo);
/// <summary>
/// Queue a build
/// </summary>
Task QueueBuildAsync(int pipelineId, string sourceBranch, string sourceVersion, Dictionary<string, string>? parameters = null, Dictionary<string, string>? templateParameters = null, Dictionary<string, string>? triggerInfo = null);
}
}

Просмотреть файл

@ -44,59 +44,6 @@ namespace BuildXL.AdoBuildRunner.Vsts
m_logger = logger;
}
/// <summary>
/// Queue a build - see https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/queue?view=azure-devops-rest-7.1
/// The pipeline is assumed to be in the same project and organization that the one running this build
/// </summary>
/// <param name="pipelineId">The pipeline id to queue</param>
/// <param name="parameters">These correspond to variables that can be set at queue time</param>
/// <param name="templateParameters">These correspond to template parameters that can be set at queue time</param>
/// <param name="sourceBranch">Source branch for the triggered build</param>
/// <param name="sourceVersion">Source verson for the triggered build</param>
/// <param name="triggerInfo">Arbitrary key-value pairs that will be available in the triggered build data. Use this for payloads</param>
public async Task QueuePipelineAsync(int pipelineId,
string sourceBranch,
string sourceVersion, Dictionary<string, string>? parameters,
Dictionary<string, string>? templateParameters,
Dictionary<string, string>? triggerInfo)
{
const string Endpoint = $"build/builds";
var payload = new QueueBuildRequest
{
Definition = new QueueBuildDefinition() { Id = pipelineId },
Parameters = parameters == null ? null : System.Text.Json.JsonSerializer.Serialize(parameters),
TemplateParameters = templateParameters,
TriggerInfo = triggerInfo,
SourceBranch = sourceBranch,
SourceVersion = sourceVersion
};
try
{
var vstsUri = GetVstsCollectionUri();
var uri = $"{vstsUri}{GetProject()}/_apis/{Endpoint}?api-version=7.1-preview.7";
m_logger?.Info($"[QueuePipelineAsync] Queuing build: {Environment.NewLine}{Newtonsoft.Json.JsonConvert.SerializeObject(payload)}");
var res = await Client.PostAsJsonAsync(uri, payload);
if (!res.IsSuccessStatusCode)
{
var responseStr = await res.Content.ReadAsStringAsync();
throw new Exception($"QueuePipelineAsync failed: {responseStr}");
}
else
{
var build = await res.Content.ReadFromJsonAsync<BuildData>(s_jsonSerializerOptions);
m_logger?.Info($"[QueuePipelineAsync] Queued build: {build?.Links.Web.Href}");
}
}
catch (Exception ex)
{
throw new CoordinationException(ex);
}
}
/// <summary>
/// Extracts the trigger info from the build information. We use this to communicate information from
/// the triggering orchestrator to the worker pipeline.
@ -127,7 +74,6 @@ namespace BuildXL.AdoBuildRunner.Vsts
}
}
private HttpClient GetClient()
{
var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });

Просмотреть файл

@ -7,47 +7,7 @@ using System.Text.Json.Serialization;
namespace BuildXL.AdoBuildRunner.Vsts
{
#region Data objects for HTTP requests, to be serialized to and from JSON
/// <nodoc />
[DataContract]
public class QueueBuildRequest
{
/// <nodoc />
[DataMember]
public QueueBuildDefinition Definition { get; set; }
/// <nodoc />
[DataMember]
public string Parameters { get; set; }
/// <nodoc />
[DataMember]
public Dictionary<string, string> TemplateParameters { get; set; }
/// <nodoc />
[DataMember]
public Dictionary<string, string> TriggerInfo { get; set; }
/// <nodoc />
[DataMember]
public string SourceBranch { get; set; }
/// <nodoc />
[DataMember]
public string SourceVersion { get; set; }
}
/// <nodoc />
[DataContract]
public class QueueBuildDefinition
{
/// <nodoc />
[DataMember]
public int Id { get; set; }
}
/// <nodoc />
[DataContract]
public class AdoLink