mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6aa01fabc | ||
|
|
3615fb6923 | ||
|
|
f61dcad5bb | ||
|
|
62d568674c | ||
|
|
07c00f6a8a | ||
|
|
05b84297b7 | ||
|
|
04679b56a9 | ||
|
|
d2ca24fa43 | ||
|
|
abdaacfa6e | ||
|
|
53fd7161e2 | ||
|
|
ce68f3b167 | ||
|
|
e2c7329292 | ||
|
|
22a9d89772 | ||
|
|
3851acd0cf | ||
|
|
aab4aca8f7 |
@@ -2,12 +2,10 @@
|
||||
|
||||
## Bugs
|
||||
|
||||
- Send Path when resolving actions so we can correctly validate Policy for Composite Actions (#1250)
|
||||
- Fixed an issue where GHES runners fail to download public docker images (#1199)
|
||||
|
||||
## Misc
|
||||
|
||||
- Allows flags instead of parameters when configuring the runner (#1220)
|
||||
|
||||
## Windows x64
|
||||
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.280.2
|
||||
2.281.0
|
||||
|
||||
@@ -90,6 +90,8 @@ namespace GitHub.Runner.Common
|
||||
this.SecretMasker.AddValueEncoder(ValueEncoders.UriDataEscape);
|
||||
this.SecretMasker.AddValueEncoder(ValueEncoders.XmlDataEscape);
|
||||
this.SecretMasker.AddValueEncoder(ValueEncoders.TrimDoubleQuotes);
|
||||
this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPreAmpersandEscape);
|
||||
this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPostAmpersandEscape);
|
||||
|
||||
// Create the trace manager.
|
||||
if (string.IsNullOrEmpty(logFile))
|
||||
|
||||
@@ -117,6 +117,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
try
|
||||
{
|
||||
// Determine the service deployment type based on connection data. (Hosted/OnPremises)
|
||||
// Hosted usually means github.com or localhost, while OnPremises means GHES or GHAE
|
||||
runnerSettings.IsHostedServer = runnerSettings.GitHubUrl == null || UrlUtil.IsHostedServer(new UriBuilder(runnerSettings.GitHubUrl));
|
||||
|
||||
// Warn if the Actions server url and GHES server url has different Host
|
||||
|
||||
@@ -494,7 +494,8 @@ namespace GitHub.Runner.Worker
|
||||
private void UpdateRegistryAuthForGitHubToken(IExecutionContext executionContext, ContainerInfo container)
|
||||
{
|
||||
var registryIsTokenCompatible = container.RegistryServer.Equals("ghcr.io", StringComparison.OrdinalIgnoreCase) || container.RegistryServer.Equals("containers.pkg.github.com", StringComparison.OrdinalIgnoreCase);
|
||||
if (!registryIsTokenCompatible)
|
||||
var isFallbackTokenFromHostedGithub = HostContext.GetService<IConfigurationStore>().GetSettings().IsHostedServer;
|
||||
if (!registryIsTokenCompatible || !isFallbackTokenFromHostedGithub)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -295,99 +295,108 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
CancellationTokenRegistration? jobCancelRegister = null;
|
||||
try
|
||||
{
|
||||
// Register job cancellation call back only if job cancellation token not been fire before each step run
|
||||
if (!ExecutionContext.Root.CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
// Test the condition again. The job was canceled after the condition was originally evaluated.
|
||||
jobCancelRegister = ExecutionContext.Root.CancellationToken.Register(() =>
|
||||
{
|
||||
// Mark job as cancelled
|
||||
ExecutionContext.Root.Result = TaskResult.Canceled;
|
||||
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
||||
|
||||
step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
|
||||
var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
|
||||
var conditionReTestResult = false;
|
||||
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
|
||||
{
|
||||
step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown.");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter);
|
||||
var condition = new BasicExpressionToken(null, null, null, step.Condition);
|
||||
conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Cancel the step since we get exception while re-evaluate step condition
|
||||
Trace.Info("Caught exception from expression when re-test condition on job cancellation.");
|
||||
step.ExecutionContext.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!conditionReTestResult)
|
||||
{
|
||||
// Cancel the step
|
||||
Trace.Info("Cancel current running step.");
|
||||
step.ExecutionContext.CancelToken();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ExecutionContext.Root.Result != TaskResult.Canceled)
|
||||
{
|
||||
// Mark job as cancelled
|
||||
ExecutionContext.Root.Result = TaskResult.Canceled;
|
||||
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
||||
}
|
||||
}
|
||||
// Evaluate condition
|
||||
step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'");
|
||||
var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext);
|
||||
var conditionResult = false;
|
||||
var conditionEvaluateError = default(Exception);
|
||||
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
|
||||
{
|
||||
step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown.");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter);
|
||||
var condition = new BasicExpressionToken(null, null, null, step.Condition);
|
||||
conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.Info("Caught exception from expression.");
|
||||
Trace.Error(ex);
|
||||
conditionEvaluateError = ex;
|
||||
}
|
||||
}
|
||||
if (!conditionResult && conditionEvaluateError == null)
|
||||
{
|
||||
// Condition is false
|
||||
Trace.Info("Skipping step due to condition evaluation.");
|
||||
step.ExecutionContext.Result = TaskResult.Skipped;
|
||||
continue;
|
||||
}
|
||||
else if (conditionEvaluateError != null)
|
||||
{
|
||||
// Condition error
|
||||
step.ExecutionContext.Error(conditionEvaluateError);
|
||||
step.ExecutionContext.Result = TaskResult.Failed;
|
||||
ExecutionContext.Result = TaskResult.Failed;
|
||||
break;
|
||||
}
|
||||
else
|
||||
// For main steps just run the action
|
||||
if (stage == ActionRunStage.Main)
|
||||
{
|
||||
await RunStepAsync(step);
|
||||
}
|
||||
// We need to evaluate conditions for pre/post steps
|
||||
else
|
||||
{
|
||||
// Register job cancellation call back only if job cancellation token not been fire before each step run
|
||||
if (!ExecutionContext.Root.CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
// Test the condition again. The job was canceled after the condition was originally evaluated.
|
||||
jobCancelRegister = ExecutionContext.Root.CancellationToken.Register(() =>
|
||||
{
|
||||
// Mark job as cancelled
|
||||
ExecutionContext.Root.Result = TaskResult.Canceled;
|
||||
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
||||
|
||||
step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
|
||||
var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
|
||||
var conditionReTestResult = false;
|
||||
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
|
||||
{
|
||||
step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown.");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter);
|
||||
var condition = new BasicExpressionToken(null, null, null, step.Condition);
|
||||
conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Cancel the step since we get exception while re-evaluate step condition
|
||||
Trace.Info("Caught exception from expression when re-test condition on job cancellation.");
|
||||
step.ExecutionContext.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!conditionReTestResult)
|
||||
{
|
||||
// Cancel the step
|
||||
Trace.Info("Cancel current running step.");
|
||||
step.ExecutionContext.CancelToken();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ExecutionContext.Root.Result != TaskResult.Canceled)
|
||||
{
|
||||
// Mark job as cancelled
|
||||
ExecutionContext.Root.Result = TaskResult.Canceled;
|
||||
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
||||
}
|
||||
}
|
||||
// Evaluate condition
|
||||
step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'");
|
||||
var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext);
|
||||
var conditionResult = false;
|
||||
var conditionEvaluateError = default(Exception);
|
||||
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
|
||||
{
|
||||
step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown.");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter);
|
||||
var condition = new BasicExpressionToken(null, null, null, step.Condition);
|
||||
conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.Info("Caught exception from expression.");
|
||||
Trace.Error(ex);
|
||||
conditionEvaluateError = ex;
|
||||
}
|
||||
}
|
||||
if (!conditionResult && conditionEvaluateError == null)
|
||||
{
|
||||
// Condition is false
|
||||
Trace.Info("Skipping step due to condition evaluation.");
|
||||
step.ExecutionContext.Result = TaskResult.Skipped;
|
||||
continue;
|
||||
}
|
||||
else if (conditionEvaluateError != null)
|
||||
{
|
||||
// Condition error
|
||||
step.ExecutionContext.Error(conditionEvaluateError);
|
||||
step.ExecutionContext.Result = TaskResult.Failed;
|
||||
ExecutionContext.Result = TaskResult.Failed;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
await RunStepAsync(step);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -217,6 +217,7 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
if (systemConnection.Data.TryGetValue("GenerateIdTokenUrl", out var generateIdTokenUrl) && !string.IsNullOrEmpty(generateIdTokenUrl))
|
||||
{
|
||||
Environment["ACTIONS_ID_TOKEN_REQUEST_URL"] = generateIdTokenUrl;
|
||||
Environment["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
|
||||
}
|
||||
|
||||
foreach (var variable in this.Environment)
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
if (systemConnection.Data.TryGetValue("GenerateIdTokenUrl", out var generateIdTokenUrl) && !string.IsNullOrEmpty(generateIdTokenUrl))
|
||||
{
|
||||
Environment["ACTIONS_ID_TOKEN_REQUEST_URL"] = generateIdTokenUrl;
|
||||
Environment["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
|
||||
}
|
||||
|
||||
// Resolve the target script.
|
||||
|
||||
@@ -147,7 +147,8 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
// Add Telemetry to JobContext to send with JobCompleteMessage
|
||||
if (stage == ActionRunStage.Main)
|
||||
{
|
||||
var telemetry = new ActionsStepTelemetry {
|
||||
var telemetry = new ActionsStepTelemetry
|
||||
{
|
||||
IsEmbedded = ExecutionContext.IsEmbedded,
|
||||
Type = "run",
|
||||
};
|
||||
@@ -276,6 +277,13 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
fileName = node12;
|
||||
}
|
||||
#endif
|
||||
var systemConnection = ExecutionContext.Global.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||
if (systemConnection.Data.TryGetValue("GenerateIdTokenUrl", out var generateIdTokenUrl) && !string.IsNullOrEmpty(generateIdTokenUrl))
|
||||
{
|
||||
Environment["ACTIONS_ID_TOKEN_REQUEST_URL"] = generateIdTokenUrl;
|
||||
Environment["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
|
||||
}
|
||||
|
||||
ExecutionContext.Debug($"{fileName} {arguments}");
|
||||
|
||||
using (var stdoutManager = new OutputManager(ExecutionContext, ActionCommandManager))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.ComponentModel;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GitHub.DistributedTask.Logging
|
||||
@@ -80,6 +81,65 @@ namespace GitHub.DistributedTask.Logging
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
public static String PowerShellPreAmpersandEscape(String value)
|
||||
{
|
||||
// if the secret is passed to PS as a command and it causes an error, sections of it can be surrounded by color codes
|
||||
// or printed individually.
|
||||
|
||||
// The secret secretpart1&secretpart2&secretpart3 would be split into 2 sections:
|
||||
// 'secretpart1&secretpart2&' and 'secretpart3'. This method masks for the first section.
|
||||
|
||||
// The secret secretpart1&+secretpart2&secretpart3 would be split into 2 sections:
|
||||
// 'secretpart1&+' and (no 's') 'ecretpart2&secretpart3'. This method masks for the first section.
|
||||
|
||||
var trimmed = string.Empty;
|
||||
if (!string.IsNullOrEmpty(value) && value.Contains("&"))
|
||||
{
|
||||
var secretSection = string.Empty;
|
||||
if (value.Contains("&+"))
|
||||
{
|
||||
secretSection = value.Substring(0, value.IndexOf("&+") + "&+".Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
secretSection = value.Substring(0, value.LastIndexOf("&") + "&".Length);
|
||||
}
|
||||
|
||||
// Don't mask short secrets
|
||||
if (secretSection.Length >= 6)
|
||||
{
|
||||
trimmed = secretSection;
|
||||
}
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
public static String PowerShellPostAmpersandEscape(String value)
|
||||
{
|
||||
var trimmed = string.Empty;
|
||||
if (!string.IsNullOrEmpty(value) && value.Contains("&"))
|
||||
{
|
||||
var secretSection = string.Empty;
|
||||
if (value.Contains("&+"))
|
||||
{
|
||||
// +1 to skip the letter that got colored
|
||||
secretSection = value.Substring(value.IndexOf("&+") + "&+".Length + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
secretSection = value.Substring(value.LastIndexOf("&") + "&".Length);
|
||||
}
|
||||
|
||||
if (secretSection.Length >= 6)
|
||||
{
|
||||
trimmed = secretSection;
|
||||
}
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
private static string Base64StringEscapeShift(String value, int shift)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(value);
|
||||
|
||||
@@ -112,6 +112,36 @@ namespace GitHub.Runner.Common.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("secret&secret&secret", "secret&secret&\x0033[96msecret\x0033[0m", "***\x0033[96m***\x0033[0m")]
|
||||
[InlineData("secret&secret+secret", "secret&\x0033[96msecret+secret\x0033[0m", "***\x0033[96m***\x0033[0m")]
|
||||
[InlineData("secret+secret&secret", "secret+secret&\x0033[96msecret\x0033[0m", "***\x0033[96m***\x0033[0m")]
|
||||
[InlineData("secret&secret&+secretsecret", "secret&secret&+\x0033[96ms\x0033[0mecretsecret", "***\x0033[96ms\x0033[0m***")]
|
||||
[InlineData("secret&+secret&secret", "secret&+\x0033[96ms\x0033[0mecret&secret", "***\x0033[96ms\x0033[0m***")]
|
||||
[InlineData("secret&+secret&+secret", "secret&+\x0033[96ms\x0033[0mecret&+secret", "***\x0033[96ms\x0033[0m***")]
|
||||
[InlineData("secret&+secret&secret&+secret", "secret&+\x0033[96ms\x0033[0mecret&secret&+secret", "***\x0033[96ms\x0033[0m***")]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void SecretSectionMasking(string secret, string rawOutput, string maskedOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Arrange.
|
||||
Setup();
|
||||
|
||||
// Act.
|
||||
_hc.SecretMasker.AddValue(secret);
|
||||
|
||||
// Assert.
|
||||
Assert.Equal(maskedOutput, _hc.SecretMasker.MaskSecrets(rawOutput));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.280.2
|
||||
2.281.0
|
||||
|
||||
Reference in New Issue
Block a user