Skip to content

Commit ae09a9d

Browse files
authored
Fix composite post-step marker display names (#4267)
1 parent 7650fc4 commit ae09a9d

2 files changed

Lines changed: 72 additions & 1 deletion

File tree

src/Runner.Worker/Handlers/CompositeActionHandler.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,14 @@ private async Task RunStepsAsync(List<IStep> embeddedSteps, ActionRunStage stage
312312
// Emit start marker after full context setup so display name expressions resolve correctly
313313
if (emitCompositeMarkers)
314314
{
315-
step.TryUpdateDisplayName(out _);
315+
try
316+
{
317+
step.EvaluateDisplayName(step.ExecutionContext.ExpressionValues, step.ExecutionContext, out _);
318+
}
319+
catch (Exception ex)
320+
{
321+
Trace.Warning("Caught exception while evaluating embedded step display name. {0}", ex);
322+
}
316323
ExecutionContext.Output($"##[start-action display={EscapeProperty(SanitizeDisplayName(step.DisplayName))};id={EscapeProperty(markerId)}]");
317324
stepStopwatch = Stopwatch.StartNew();
318325
}

src/Test/L0/Worker/Handlers/CompositeActionHandlerL0.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Runtime.CompilerServices;
4+
using GitHub.DistributedTask.Pipelines;
5+
using GitHub.DistributedTask.Pipelines.ContextData;
46
using GitHub.DistributedTask.WebApi;
57
using GitHub.Runner.Common.Util;
68
using GitHub.Runner.Sdk;
79
using GitHub.Runner.Worker;
810
using GitHub.Runner.Worker.Handlers;
911
using Moq;
12+
using Newtonsoft.Json.Linq;
1013
using Xunit;
1114
using DTWebApi = GitHub.DistributedTask.WebApi;
15+
using Pipelines = GitHub.DistributedTask.Pipelines;
1216

1317
namespace GitHub.Runner.Common.Tests.Worker.Handlers
1418
{
@@ -250,6 +254,66 @@ public void MarkerFormat_ContinueOnError()
250254
Assert.Equal("##[end-action id=failing-step;outcome=failure;conclusion=success;duration_ms=500]", marker);
251255
}
252256

257+
[Fact]
258+
[Trait("Level", "L0")]
259+
[Trait("Category", "Worker")]
260+
public void PostStepMarker_UsesEvaluatedDisplayName()
261+
{
262+
// Arrange: create an ActionRunner with a RepositoryPathReference (simulating actions/cache@v4)
263+
// and Stage = Post. Verify that EvaluateDisplayName produces the correct display name
264+
// so the composite marker emits "Run actions/cache@v4" instead of the fallback "run".
265+
var hc = new TestHostContext(this, nameof(PostStepMarker_UsesEvaluatedDisplayName));
266+
var actionManifestLegacy = new ActionManifestManagerLegacy();
267+
actionManifestLegacy.Initialize(hc);
268+
hc.SetSingleton<IActionManifestManagerLegacy>(actionManifestLegacy);
269+
var actionManifestNew = new ActionManifestManager();
270+
actionManifestNew.Initialize(hc);
271+
hc.SetSingleton<IActionManifestManager>(actionManifestNew);
272+
var actionManifestManager = new ActionManifestManagerWrapper();
273+
actionManifestManager.Initialize(hc);
274+
hc.SetSingleton<IActionManifestManagerWrapper>(actionManifestManager);
275+
276+
var ec = new Mock<IExecutionContext>();
277+
var contextData = new DictionaryContextData();
278+
var githubContext = new GitHubContext();
279+
githubContext.Add("event", JToken.Parse("{\"foo\":\"bar\"}").ToPipelineContextData());
280+
contextData.Add("github", githubContext);
281+
#if OS_WINDOWS
282+
contextData["env"] = new DictionaryContextData();
283+
#else
284+
contextData["env"] = new CaseSensitiveDictionaryContextData();
285+
#endif
286+
ec.Setup(x => x.Global).Returns(new GlobalContext());
287+
ec.Setup(x => x.ExpressionValues).Returns(contextData);
288+
ec.Setup(x => x.ExpressionFunctions).Returns(new List<GitHub.DistributedTask.Expressions2.IFunctionInfo>());
289+
ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()));
290+
ec.Object.Global.Variables = new Variables(hc, new Dictionary<string, VariableValue>());
291+
292+
var actionRunner = new ActionRunner();
293+
actionRunner.Initialize(hc);
294+
actionRunner.ExecutionContext = ec.Object;
295+
actionRunner.Stage = ActionRunStage.Post;
296+
actionRunner.Action = new Pipelines.ActionStep()
297+
{
298+
Name = "cache",
299+
Id = Guid.NewGuid(),
300+
Reference = new Pipelines.RepositoryPathReference()
301+
{
302+
Name = "actions/cache",
303+
Ref = "v4"
304+
}
305+
};
306+
307+
// Act: call EvaluateDisplayName directly, which is what CompositeActionHandler now does
308+
// for embedded steps (including Post stage) instead of TryUpdateDisplayName.
309+
var result = actionRunner.EvaluateDisplayName(contextData, ec.Object, out bool updated);
310+
311+
// Assert: display name should be "Run actions/cache@v4", not the fallback "run"
312+
Assert.True(result);
313+
Assert.True(updated);
314+
Assert.Equal("Run actions/cache@v4", actionRunner.DisplayName);
315+
}
316+
253317
// Helper methods that call the real production code
254318
private static string EscapeProperty(string value) =>
255319
CompositeActionHandler.EscapeProperty(value);

0 commit comments

Comments
 (0)