Skip to content

Commit 3a27ca2

Browse files
authored
Feature-flagged support for JobContext.CheckRunId (#3811)
1 parent 282f7cd commit 3a27ca2

File tree

5 files changed

+152
-2
lines changed

5 files changed

+152
-2
lines changed

src/Runner.Common/Constants.cs

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public static class Features
163163
public static readonly string LogTemplateErrorsAsDebugMessages = "DistributedTask.LogTemplateErrorsAsDebugMessages";
164164
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
165165
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
166+
public static readonly string AddCheckRunIdToJobContext = "actions_add_check_run_id_to_job_context";
166167
}
167168

168169
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";

src/Runner.Worker/ExecutionContext.cs

+15-1
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,21 @@ public void InitializeJob(Pipelines.AgentJobRequestMessage message, Cancellation
862862

863863
ExpressionValues["secrets"] = Global.Variables.ToSecretsContext();
864864
ExpressionValues["runner"] = new RunnerContext();
865-
ExpressionValues["job"] = new JobContext();
865+
866+
Trace.Info("Initializing Job context");
867+
var jobContext = new JobContext();
868+
if (Global.Variables.GetBoolean(Constants.Runner.Features.AddCheckRunIdToJobContext) ?? false)
869+
{
870+
ExpressionValues.TryGetValue("job", out var jobDictionary);
871+
if (jobDictionary != null)
872+
{
873+
foreach (var pair in jobDictionary.AssertDictionary("job"))
874+
{
875+
jobContext[pair.Key] = pair.Value;
876+
}
877+
}
878+
}
879+
ExpressionValues["job"] = jobContext;
866880

867881
Trace.Info("Initialize GitHub context");
868882
var githubAccessToken = new StringContextData(Global.Variables.Get("system.github.token"));

src/Runner.Worker/JobContext.cs

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using GitHub.DistributedTask.Pipelines.ContextData;
1+
using GitHub.DistributedTask.Pipelines.ContextData;
22
using GitHub.Runner.Common.Util;
33
using GitHub.Runner.Common;
44

@@ -56,5 +56,31 @@ public DictionaryContextData Container
5656
}
5757
}
5858
}
59+
60+
public double? CheckRunId
61+
{
62+
get
63+
{
64+
if (this.TryGetValue("check_run_id", out var value) && value is NumberContextData number)
65+
{
66+
return number.Value;
67+
}
68+
else
69+
{
70+
return null;
71+
}
72+
}
73+
set
74+
{
75+
if (value.HasValue)
76+
{
77+
this["check_run_id"] = new NumberContextData(value.Value);
78+
}
79+
else
80+
{
81+
this["check_run_id"] = null;
82+
}
83+
}
84+
}
5985
}
6086
}

src/Test/L0/Worker/ExecutionContextL0.cs

+71
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,77 @@ public void ActionVariables_SecretsPrecedenceForDebugUsingVars()
11681168
}
11691169
}
11701170

1171+
[Fact]
1172+
[Trait("Level", "L0")]
1173+
[Trait("Category", "Worker")]
1174+
public void InitializeJob_HydratesJobContextWithCheckRunId()
1175+
{
1176+
using (TestHostContext hc = CreateTestContext())
1177+
{
1178+
// Arrange: Create a job request message and make sure the feature flag is enabled
1179+
var variables = new Dictionary<string, VariableValue>()
1180+
{
1181+
[Constants.Runner.Features.AddCheckRunIdToJobContext] = new VariableValue("true"),
1182+
};
1183+
var jobRequest = new Pipelines.AgentJobRequestMessage(new TaskOrchestrationPlanReference(), new TimelineReference(), Guid.NewGuid(), "some job name", "some job name", null, null, null, variables, new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null, null, null);
1184+
var pagingLogger = new Moq.Mock<IPagingLogger>();
1185+
var jobServerQueue = new Moq.Mock<IJobServerQueue>();
1186+
hc.EnqueueInstance(pagingLogger.Object);
1187+
hc.SetSingleton(jobServerQueue.Object);
1188+
var ec = new Runner.Worker.ExecutionContext();
1189+
ec.Initialize(hc);
1190+
1191+
// Arrange: Add check_run_id to the job context
1192+
var jobContext = new Pipelines.ContextData.DictionaryContextData();
1193+
jobContext["check_run_id"] = new NumberContextData(123456);
1194+
jobRequest.ContextData["job"] = jobContext;
1195+
jobRequest.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();
1196+
1197+
// Act
1198+
ec.InitializeJob(jobRequest, CancellationToken.None);
1199+
1200+
// Assert
1201+
Assert.NotNull(ec.JobContext);
1202+
Assert.Equal(123456, ec.JobContext.CheckRunId);
1203+
}
1204+
}
1205+
1206+
// TODO: this test can be deleted when `AddCheckRunIdToJobContext` is fully rolled out
1207+
[Fact]
1208+
[Trait("Level", "L0")]
1209+
[Trait("Category", "Worker")]
1210+
public void InitializeJob_HydratesJobContextWithCheckRunId_FeatureFlagDisabled()
1211+
{
1212+
using (TestHostContext hc = CreateTestContext())
1213+
{
1214+
// Arrange: Create a job request message and make sure the feature flag is disabled
1215+
var variables = new Dictionary<string, VariableValue>()
1216+
{
1217+
[Constants.Runner.Features.AddCheckRunIdToJobContext] = new VariableValue("false"),
1218+
};
1219+
var jobRequest = new Pipelines.AgentJobRequestMessage(new TaskOrchestrationPlanReference(), new TimelineReference(), Guid.NewGuid(), "some job name", "some job name", null, null, null, variables, new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null, null, null);
1220+
var pagingLogger = new Moq.Mock<IPagingLogger>();
1221+
var jobServerQueue = new Moq.Mock<IJobServerQueue>();
1222+
hc.EnqueueInstance(pagingLogger.Object);
1223+
hc.SetSingleton(jobServerQueue.Object);
1224+
var ec = new Runner.Worker.ExecutionContext();
1225+
ec.Initialize(hc);
1226+
1227+
// Arrange: Add check_run_id to the job context
1228+
var jobContext = new Pipelines.ContextData.DictionaryContextData();
1229+
jobContext["check_run_id"] = new NumberContextData(123456);
1230+
jobRequest.ContextData["job"] = jobContext;
1231+
jobRequest.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();
1232+
1233+
// Act
1234+
ec.InitializeJob(jobRequest, CancellationToken.None);
1235+
1236+
// Assert
1237+
Assert.NotNull(ec.JobContext);
1238+
Assert.Null(ec.JobContext.CheckRunId); // with the feature flag disabled we should not have added a CheckRunId to the JobContext
1239+
}
1240+
}
1241+
11711242
private bool ExpressionValuesAssertEqual(DictionaryContextData expect, DictionaryContextData actual)
11721243
{
11731244
foreach (var key in expect.Keys.ToList())

src/Test/L0/Worker/JobContextL0.cs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using GitHub.DistributedTask.Pipelines.ContextData;
3+
using GitHub.Runner.Worker;
4+
using Xunit;
5+
6+
namespace GitHub.Runner.Common.Tests.Worker
7+
{
8+
public class JobContextL0
9+
{
10+
[Fact]
11+
public void CheckRunId_SetAndGet_WorksCorrectly()
12+
{
13+
var ctx = new JobContext();
14+
ctx.CheckRunId = 12345;
15+
Assert.Equal(12345, ctx.CheckRunId);
16+
Assert.True(ctx.TryGetValue("check_run_id", out var value));
17+
Assert.IsType<NumberContextData>(value);
18+
Assert.Equal(12345, ((NumberContextData)value).Value);
19+
}
20+
21+
[Fact]
22+
public void CheckRunId_NotSet_ReturnsNull()
23+
{
24+
var ctx = new JobContext();
25+
Assert.Null(ctx.CheckRunId);
26+
Assert.False(ctx.TryGetValue("check_run_id", out var value));
27+
}
28+
29+
[Fact]
30+
public void CheckRunId_SetNull_RemovesKey()
31+
{
32+
var ctx = new JobContext();
33+
ctx.CheckRunId = 12345;
34+
ctx.CheckRunId = null;
35+
Assert.Null(ctx.CheckRunId);
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)