mirror of
https://github.com/actions/runner.git
synced 2026-07-03 11:06:08 +08:00
feat: expose effective Actions cache-mode to steps and job log
Export ACTIONS_CACHE_MODE env to node and container action steps when the actions_cache_mode job variable is present and non-empty, mirroring the existing ACTIONS_CACHE_SERVICE_V2 wiring. Also log the effective cache-mode at job start. When the variable is absent or empty, behavior is unchanged.
This commit is contained in:
@@ -239,6 +239,11 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
Environment["ACTIONS_RESULTS_URL"] = resultsUrl;
|
||||
}
|
||||
|
||||
if (ExecutionContext.Global.Variables.TryGetValue("actions_cache_mode", out var cacheMode) && !string.IsNullOrEmpty(cacheMode))
|
||||
{
|
||||
Environment["ACTIONS_CACHE_MODE"] = cacheMode;
|
||||
}
|
||||
|
||||
if (ExecutionContext.Global.Variables.GetBoolean(Constants.Runner.Features.SetOrchestrationIdEnvForActions) ?? false)
|
||||
{
|
||||
if (ExecutionContext.Global.Variables.TryGetValue(Constants.Variables.System.OrchestrationId, out var orchestrationId) && !string.IsNullOrEmpty(orchestrationId))
|
||||
|
||||
@@ -78,6 +78,11 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
Environment["ACTIONS_CACHE_SERVICE_V2"] = bool.TrueString;
|
||||
}
|
||||
|
||||
if (ExecutionContext.Global.Variables.TryGetValue("actions_cache_mode", out var cacheMode) && !string.IsNullOrEmpty(cacheMode))
|
||||
{
|
||||
Environment["ACTIONS_CACHE_MODE"] = cacheMode;
|
||||
}
|
||||
|
||||
if (ExecutionContext.Global.Variables.GetBoolean(Constants.Runner.Features.SetOrchestrationIdEnvForActions) ?? false)
|
||||
{
|
||||
if (ExecutionContext.Global.Variables.TryGetValue(Constants.Variables.System.OrchestrationId, out var orchestrationId) && !string.IsNullOrEmpty(orchestrationId))
|
||||
|
||||
@@ -171,6 +171,12 @@ namespace GitHub.Runner.Worker
|
||||
context.Output($"Secret source: {secretSource}");
|
||||
}
|
||||
|
||||
var cacheMode = jobContext.Global.Variables.Get("actions_cache_mode");
|
||||
if (!string.IsNullOrEmpty(cacheMode))
|
||||
{
|
||||
context.Output($"Actions cache-mode: {cacheMode}");
|
||||
}
|
||||
|
||||
var repoFullName = context.GetGitHubContext("repository");
|
||||
ArgUtil.NotNull(repoFullName, nameof(repoFullName));
|
||||
context.Debug($"Primary repository: {repoFullName}");
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.Actions.RunService.WebApi;
|
||||
using GitHub.DistributedTask.Pipelines;
|
||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Runner.Worker;
|
||||
@@ -85,5 +90,122 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
Assert.Equal("ubuntu:20.04", _stepTelemetry.Action);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
[InlineData("read")]
|
||||
[InlineData("none")]
|
||||
[InlineData("write")]
|
||||
[InlineData("write-only")]
|
||||
public async Task RunAsync_ExportsCacheModeEnv_WhenVariableSet(string mode)
|
||||
{
|
||||
using (TestHostContext hc = CreateTestContext())
|
||||
{
|
||||
var environment = await RunNodeScriptActionHandlerAsync(hc, new Dictionary<string, VariableValue>
|
||||
{
|
||||
{ "actions_cache_mode", mode }
|
||||
});
|
||||
|
||||
Assert.True(environment.TryGetValue("ACTIONS_CACHE_MODE", out var value));
|
||||
Assert.Equal(mode, value);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public async Task RunAsync_DoesNotExportCacheModeEnv_WhenVariableAbsent()
|
||||
{
|
||||
using (TestHostContext hc = CreateTestContext())
|
||||
{
|
||||
var environment = await RunNodeScriptActionHandlerAsync(hc, new Dictionary<string, VariableValue>());
|
||||
|
||||
Assert.False(environment.ContainsKey("ACTIONS_CACHE_MODE"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public async Task RunAsync_DoesNotExportCacheModeEnv_WhenVariableEmpty()
|
||||
{
|
||||
using (TestHostContext hc = CreateTestContext())
|
||||
{
|
||||
var environment = await RunNodeScriptActionHandlerAsync(hc, new Dictionary<string, VariableValue>
|
||||
{
|
||||
{ "actions_cache_mode", "" }
|
||||
});
|
||||
|
||||
Assert.False(environment.ContainsKey("ACTIONS_CACHE_MODE"));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Dictionary<string, string>> RunNodeScriptActionHandlerAsync(TestHostContext hc, IDictionary<string, VariableValue> variables)
|
||||
{
|
||||
var actionDirectory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Work), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(actionDirectory);
|
||||
var scriptFile = "main.js";
|
||||
File.WriteAllText(Path.Combine(actionDirectory, scriptFile), "// noop");
|
||||
|
||||
var serverVariables = new Variables(hc, variables);
|
||||
var endpoints = new List<ServiceEndpoint>
|
||||
{
|
||||
new ServiceEndpoint()
|
||||
{
|
||||
Name = WellKnownServiceEndpointNames.SystemVssConnection,
|
||||
Url = new Uri("https://pipelines.actions.githubusercontent.com"),
|
||||
Authorization = new EndpointAuthorization()
|
||||
{
|
||||
Scheme = "Test",
|
||||
Parameters = { { "AccessToken", "token" } }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_ec.Setup(x => x.Global).Returns(new GlobalContext()
|
||||
{
|
||||
Variables = serverVariables,
|
||||
Endpoints = endpoints,
|
||||
PrependPath = new List<string>(),
|
||||
EnvironmentVariables = new Dictionary<string, string>()
|
||||
});
|
||||
_ec.Setup(x => x.ExpressionValues).Returns(new DictionaryContextData());
|
||||
_ec.Setup(x => x.GetGitHubContext("workspace")).Returns(actionDirectory);
|
||||
_ec.Setup(x => x.GetMatchers()).Returns(new List<IssueMatcherConfig>());
|
||||
_ec.Setup(x => x.ForceCompleted).Returns(new TaskCompletionSource<int>().Task);
|
||||
_ec.Setup(x => x.CancellationToken).Returns(CancellationToken.None);
|
||||
|
||||
var stepHost = new Mock<IStepHost>();
|
||||
stepHost.Setup(x => x.DetermineNodeRuntimeVersion(It.IsAny<IExecutionContext>(), It.IsAny<string>())).ReturnsAsync("node20");
|
||||
stepHost.Setup(x => x.ResolvePathForStepHost(It.IsAny<IExecutionContext>(), It.IsAny<string>())).Returns((IExecutionContext ec, string path) => path);
|
||||
stepHost.Setup(x => x.ExecuteAsync(
|
||||
It.IsAny<IExecutionContext>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<IDictionary<string, string>>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<System.Text.Encoding>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<CancellationToken>())).ReturnsAsync(0);
|
||||
|
||||
var handler = new NodeScriptActionHandler();
|
||||
handler.Initialize(hc);
|
||||
handler.ExecutionContext = _ec.Object;
|
||||
handler.StepHost = stepHost.Object;
|
||||
handler.Environment = new Dictionary<string, string>();
|
||||
handler.Inputs = new Dictionary<string, string>();
|
||||
handler.RuntimeVariables = serverVariables;
|
||||
handler.ActionDirectory = actionDirectory;
|
||||
handler.Action = new RepositoryPathReference() { Name = "actions/checkout", Ref = "v2" };
|
||||
handler.Data = new NodeJSActionExecutionData() { Script = scriptFile, NodeVersion = "node20" };
|
||||
|
||||
await handler.RunAsync(ActionRunStage.Main);
|
||||
|
||||
return handler.Environment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user