Skip to content

Commit d57b88a

Browse files
authored
Request non-concurrent target workspace if engine is non-concurrent (#339)
This optimizes workspace allocation on GitLab when the engine being used doesn't support or allow concurrency. It also adds a new environment variable UET_USE_EXCLUSIVE_NODES_FOR_NONCONCURRENT_ENGINE which will request tags 'buildgraph-exclusive-windows' and 'buildgraph-exclusive-mac' (GitLab runners with this tag should be configured to only run one job at a time per node). This ensures that our concurrent GitLab runners don't idle waiting for an engine or target workspace to unlock due to non-concurrency.
1 parent f3cadbb commit d57b88a

File tree

3 files changed

+95
-30
lines changed

3 files changed

+95
-30
lines changed

UET/Redpoint.Uet.BuildPipeline.Executors.GitLab/GitLabBuildExecutor.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ protected override async Task ExecuteBuildServerSpecificPipelineAsync(
3434
BuildSpecification buildSpecification,
3535
BuildServerPipeline buildServerPipeline)
3636
{
37+
ArgumentNullException.ThrowIfNull(buildSpecification);
3738
ArgumentNullException.ThrowIfNull(buildServerPipeline);
3839

3940
if (string.IsNullOrWhiteSpace(_buildServerOutputFilePath))
@@ -67,11 +68,27 @@ protected override async Task ExecuteBuildServerSpecificPipelineAsync(
6768

6869
if (sourceJob.Agent.Platform == BuildServerJobPlatform.Windows)
6970
{
70-
job.Tags = new List<string> { "buildgraph-windows" };
71+
if (buildSpecification.Engine.IsNonConcurrent &&
72+
System.Environment.GetEnvironmentVariable("UET_USE_EXCLUSIVE_NODES_FOR_NONCONCURRENT_ENGINE") == "1")
73+
{
74+
job.Tags = new List<string> { "buildgraph-exclusive-windows" };
75+
}
76+
else
77+
{
78+
job.Tags = new List<string> { "buildgraph-windows" };
79+
}
7180
}
7281
else if (sourceJob.Agent.Platform == BuildServerJobPlatform.Mac)
7382
{
74-
job.Tags = new List<string> { "buildgraph-mac" };
83+
if (buildSpecification.Engine.IsNonConcurrent &&
84+
System.Environment.GetEnvironmentVariable("UET_USE_EXCLUSIVE_NODES_FOR_NONCONCURRENT_ENGINE") == "1")
85+
{
86+
job.Tags = new List<string> { "buildgraph-exclusive-mac" };
87+
}
88+
else
89+
{
90+
job.Tags = new List<string> { "buildgraph-mac" };
91+
}
7592
}
7693
else if (sourceJob.Agent.Platform == BuildServerJobPlatform.Meta)
7794
{

UET/Redpoint.Uet.BuildPipeline.Executors.GitLab/GitLabBuildNodeExecutor.cs

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Threading.Tasks;
1717
using Redpoint.Concurrency;
1818
using Redpoint.Uet.BuildPipeline.BuildGraph.PreBuild;
19+
using System.Collections.Specialized;
1920

2021
public class GitLabBuildNodeExecutor : IBuildNodeExecutor
2122
{
@@ -60,6 +61,42 @@ private class NodeNameExecutionState
6061
public string? NodeName;
6162
}
6263

64+
private async Task<IWorkspace> GetGitWorkspaceAsync(
65+
string repository,
66+
string commit,
67+
string branch,
68+
IReadOnlyList<string> nodeNames,
69+
BuildSpecification buildSpecification,
70+
CancellationToken cancellationToken)
71+
{
72+
NameValueCollection? queryString = null;
73+
if (buildSpecification.Engine.IsNonConcurrent)
74+
{
75+
_logger.LogInformation("Requesting non-concurrent Git workspace, because the engine is non-concurrent.");
76+
queryString = new NameValueCollection
77+
{
78+
{ "concurrent", "false" }
79+
};
80+
}
81+
82+
return await _workspaceProvider.GetWorkspaceAsync(
83+
new GitWorkspaceDescriptor
84+
{
85+
RepositoryUrl = repository,
86+
RepositoryCommitOrRef = commit,
87+
RepositoryBranchForReservationParameters = branch,
88+
AdditionalFolderLayers = Array.Empty<string>(),
89+
AdditionalFolderZips = Array.Empty<string>(),
90+
WorkspaceDisambiguators = nodeNames,
91+
ProjectFolderName = buildSpecification.ProjectFolderName,
92+
BuildType = GitWorkspaceDescriptorBuildType.Generic,
93+
WindowsSharedGitCachePath = null,
94+
MacSharedGitCachePath = null,
95+
QueryString = queryString,
96+
},
97+
cancellationToken).ConfigureAwait(false);
98+
}
99+
63100
public async Task<int> ExecuteBuildNodesAsync(
64101
BuildSpecification buildSpecification,
65102
BuildConfigDynamic<BuildConfigPluginDistribution, IPrepareProvider>[]? preparePlugin,
@@ -247,20 +284,12 @@ async Task<int> ExecuteNodesInWorkspaceAsync(
247284
_logger.LogTrace($"Executing build with engine build type of 'CurrentWorkspace', obtaining single workspace and using it as the engine directory as well.");
248285

249286
_logger.LogTrace($"Obtaining workspace for build.");
250-
await using ((await _workspaceProvider.GetWorkspaceAsync(
251-
new GitWorkspaceDescriptor
252-
{
253-
RepositoryUrl = repository,
254-
RepositoryCommitOrRef = commit,
255-
RepositoryBranchForReservationParameters = branch,
256-
AdditionalFolderLayers = Array.Empty<string>(),
257-
AdditionalFolderZips = Array.Empty<string>(),
258-
WorkspaceDisambiguators = nodeNames,
259-
ProjectFolderName = buildSpecification.ProjectFolderName,
260-
BuildType = GitWorkspaceDescriptorBuildType.Generic,
261-
WindowsSharedGitCachePath = null,
262-
MacSharedGitCachePath = null,
263-
},
287+
await using ((await GetGitWorkspaceAsync(
288+
repository,
289+
commit,
290+
branch,
291+
nodeNames,
292+
buildSpecification,
264293
cancellationToken).ConfigureAwait(false)).AsAsyncDisposable(out var targetWorkspace).ConfigureAwait(false))
265294
{
266295
_logger.LogTrace($"Calling ExecuteNodesInWorkspaceAsync inside allocated workspace.");
@@ -291,20 +320,12 @@ async Task<int> ExecuteNodesInWorkspaceAsync(
291320
_logger.LogTrace($"Executing build with engine build type of 'None', obtained engine workspace and obtaining target workspace separately.");
292321

293322
_logger.LogTrace($"Obtaining workspace for build.");
294-
await using ((await _workspaceProvider.GetWorkspaceAsync(
295-
new GitWorkspaceDescriptor
296-
{
297-
RepositoryUrl = repository,
298-
RepositoryCommitOrRef = commit,
299-
RepositoryBranchForReservationParameters = branch,
300-
AdditionalFolderLayers = Array.Empty<string>(),
301-
AdditionalFolderZips = Array.Empty<string>(),
302-
WorkspaceDisambiguators = nodeNames,
303-
ProjectFolderName = buildSpecification.ProjectFolderName,
304-
BuildType = GitWorkspaceDescriptorBuildType.Generic,
305-
WindowsSharedGitCachePath = null,
306-
MacSharedGitCachePath = null,
307-
},
323+
await using ((await GetGitWorkspaceAsync(
324+
repository,
325+
commit,
326+
branch,
327+
nodeNames,
328+
buildSpecification,
308329
cancellationToken).ConfigureAwait(false)).AsAsyncDisposable(out var targetWorkspace).ConfigureAwait(false))
309330
{
310331
_logger.LogTrace($"Calling ExecuteNodesInWorkspaceAsync inside allocated workspace.");

UET/Redpoint.Uet.BuildPipeline/Executors/BuildEngineSpecification.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,32 @@ public string ToReparsableString()
172172
throw new NotSupportedException();
173173
}
174174
}
175+
176+
public bool IsNonConcurrent
177+
{
178+
get
179+
{
180+
if (!string.IsNullOrWhiteSpace(_engineVersion))
181+
{
182+
return true;
183+
}
184+
185+
if (!string.IsNullOrWhiteSpace(_enginePath))
186+
{
187+
return true;
188+
}
189+
190+
if (!string.IsNullOrWhiteSpace(_gitUrl))
191+
{
192+
if (_queryString != null &&
193+
_queryString["concurrent"] == "false")
194+
{
195+
return true;
196+
}
197+
}
198+
199+
return false;
200+
}
201+
}
175202
}
176203
}

0 commit comments

Comments
 (0)