diff --git a/src/Runner.Worker/JobExtension.cs b/src/Runner.Worker/JobExtension.cs index b76fc7992bc..9a2c887f195 100644 --- a/src/Runner.Worker/JobExtension.cs +++ b/src/Runner.Worker/JobExtension.cs @@ -191,6 +191,13 @@ public async Task> InitializeJob(IExecutionContext jobContext, Pipel context.Output($"Runner is running behind proxy server '{HostContext.WebProxy.HttpsProxyAddress}' for all HTTPS requests."); } + // Signal to the user that the job is running with locked/pinned + // action dependencies (a lockfile is in effect). + if (message.ActionsDependencies != null && message.ActionsDependencies.Count > 0) + { + context.Output("Running with locked dependencies"); + } + // Prepare the workflow directory context.Output("Prepare workflow directory"); var directoryManager = HostContext.GetService(); diff --git a/src/Test/L0/Worker/JobExtensionL0.cs b/src/Test/L0/Worker/JobExtensionL0.cs index 45c64a411c7..2f2dd1db51b 100644 --- a/src/Test/L0/Worker/JobExtensionL0.cs +++ b/src/Test/L0/Worker/JobExtensionL0.cs @@ -199,6 +199,54 @@ public async Task JobExtensionBuildStepsList() } } + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public async Task JobExtensionOutputsLockedDependenciesWhenPresent() + { + using (TestHostContext hc = CreateTestContext()) + { + var consoleLines = new List(); + _jobServerQueue.Setup(x => x.QueueWebConsoleLine(It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((Guid _, string line, long? __) => consoleLines.Add(line)); + + _message.ActionsDependencies.Add("actions/checkout@v4:sha256-abc123"); + + var jobExtension = new JobExtension(); + jobExtension.Initialize(hc); + + _actionManager.Setup(x => x.PrepareActionsAsync(It.IsAny(), It.IsAny>(), It.IsAny())) + .Returns(Task.FromResult(new PrepareResult(new List(), new Dictionary()))); + + await jobExtension.InitializeJob(_jobEc, _message); + + Assert.Contains(consoleLines, line => line.Contains("Running with locked dependencies")); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public async Task JobExtensionDoesNotOutputLockedDependenciesWhenAbsent() + { + using (TestHostContext hc = CreateTestContext()) + { + var consoleLines = new List(); + _jobServerQueue.Setup(x => x.QueueWebConsoleLine(It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((Guid _, string line, long? __) => consoleLines.Add(line)); + + var jobExtension = new JobExtension(); + jobExtension.Initialize(hc); + + _actionManager.Setup(x => x.PrepareActionsAsync(It.IsAny(), It.IsAny>(), It.IsAny())) + .Returns(Task.FromResult(new PrepareResult(new List(), new Dictionary()))); + + await jobExtension.InitializeJob(_jobEc, _message); + + Assert.DoesNotContain(consoleLines, line => line.Contains("Running with locked dependencies")); + } + } + [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] @@ -292,15 +340,22 @@ public async Task InitializeJob_DoesNotLogCacheMode_WhenVariableAbsent() public async Task JobExtensionBuildFailsWithoutContainerIfRequired() { Environment.SetEnvironmentVariable(Constants.Variables.Actions.RequireJobContainer, "true"); - using (TestHostContext hc = CreateTestContext()) + try { - var jobExtension = new JobExtension(); - jobExtension.Initialize(hc); + using (TestHostContext hc = CreateTestContext()) + { + var jobExtension = new JobExtension(); + jobExtension.Initialize(hc); - _actionManager.Setup(x => x.PrepareActionsAsync(It.IsAny(), It.IsAny>(), It.IsAny())) - .Returns(Task.FromResult(new PrepareResult(new List() { new JobExtensionRunner(null, "", "prepare1", null), new JobExtensionRunner(null, "", "prepare2", null) }, new Dictionary()))); + _actionManager.Setup(x => x.PrepareActionsAsync(It.IsAny(), It.IsAny>(), It.IsAny())) + .Returns(Task.FromResult(new PrepareResult(new List() { new JobExtensionRunner(null, "", "prepare1", null), new JobExtensionRunner(null, "", "prepare2", null) }, new Dictionary()))); - await Assert.ThrowsAsync(() => jobExtension.InitializeJob(_jobEc, _message)); + await Assert.ThrowsAsync(() => jobExtension.InitializeJob(_jobEc, _message)); + } + } + finally + { + Environment.SetEnvironmentVariable(Constants.Variables.Actions.RequireJobContainer, null); } }