mirror of
https://github.com/actions/runner.git
synced 2025-12-10 04:06:57 +00:00
Compare commits
8 Commits
v2.321.0
...
releases/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f840647b3 | ||
|
|
e2fbd1dc95 | ||
|
|
8d6acf2a7f | ||
|
|
6b3b42a840 | ||
|
|
826f58682e | ||
|
|
2eefff4b69 | ||
|
|
8456f7667d | ||
|
|
7f092c96db |
@@ -1,9 +1,10 @@
|
||||
## Features
|
||||
- Runner support for GHES Alpha (#381 #386 #390 #393 $401)
|
||||
- Allow secrets context in Container.env (#388)
|
||||
- Better telemetry tracing for self-hosted runner. (#405)
|
||||
- Launch middle man process on macOS to workaround SIP limit (#416)
|
||||
- Added support for custom labels (#414, #425)
|
||||
- support 'pre' execution for actions. (#389)
|
||||
## Bugs
|
||||
- Raise warning when volume mount root. (#413)
|
||||
- Fix typo (#394)
|
||||
- ArgumentNullException: Value cannot be null, for anonymous volume mounts (#426)
|
||||
## Misc
|
||||
- N/A
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.164.0
|
||||
2.169.1
|
||||
|
||||
13
src/Misc/layoutbin/macos-run-invoker.js
Normal file
13
src/Misc/layoutbin/macos-run-invoker.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const { spawn } = require('child_process');
|
||||
// argv[0] = node
|
||||
// argv[1] = macos-run-invoker.js
|
||||
var shell = process.argv[2];
|
||||
var args = process.argv.slice(3);
|
||||
console.log(`::debug::macos-run-invoker: ${shell}`);
|
||||
console.log(`::debug::macos-run-invoker: ${JSON.stringify(args)}`);
|
||||
var launch = spawn(shell, args, { stdio: 'inherit' });
|
||||
launch.on('exit', function (code) {
|
||||
if (code !== 0) {
|
||||
process.exit(code);
|
||||
}
|
||||
});
|
||||
@@ -87,6 +87,7 @@ namespace GitHub.Runner.Common
|
||||
public static class Args
|
||||
{
|
||||
public static readonly string Auth = "auth";
|
||||
public static readonly string Labels = "labels";
|
||||
public static readonly string MonitorSocketAddress = "monitorsocketaddress";
|
||||
public static readonly string Name = "name";
|
||||
public static readonly string Pool = "pool";
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace GitHub.Runner.Common
|
||||
CancellationToken RunnerShutdownToken { get; }
|
||||
ShutdownReason RunnerShutdownReason { get; }
|
||||
ISecretMasker SecretMasker { get; }
|
||||
ProductInfoHeaderValue UserAgent { get; }
|
||||
List<ProductInfoHeaderValue> UserAgents { get; }
|
||||
RunnerWebProxy WebProxy { get; }
|
||||
string GetDirectory(WellKnownDirectory directory);
|
||||
string GetConfigFile(WellKnownConfigFile configFile);
|
||||
@@ -54,7 +54,7 @@ namespace GitHub.Runner.Common
|
||||
private readonly ConcurrentDictionary<Type, object> _serviceInstances = new ConcurrentDictionary<Type, object>();
|
||||
private readonly ConcurrentDictionary<Type, Type> _serviceTypes = new ConcurrentDictionary<Type, Type>();
|
||||
private readonly ISecretMasker _secretMasker = new SecretMasker();
|
||||
private readonly ProductInfoHeaderValue _userAgent = new ProductInfoHeaderValue($"GitHubActionsRunner-{BuildConstants.RunnerPackage.PackageName}", BuildConstants.RunnerPackage.Version);
|
||||
private readonly List<ProductInfoHeaderValue> _userAgents = new List<ProductInfoHeaderValue>() { new ProductInfoHeaderValue($"GitHubActionsRunner-{BuildConstants.RunnerPackage.PackageName}", BuildConstants.RunnerPackage.Version) };
|
||||
private CancellationTokenSource _runnerShutdownTokenSource = new CancellationTokenSource();
|
||||
private object _perfLock = new object();
|
||||
private Tracing _trace;
|
||||
@@ -72,7 +72,7 @@ namespace GitHub.Runner.Common
|
||||
public CancellationToken RunnerShutdownToken => _runnerShutdownTokenSource.Token;
|
||||
public ShutdownReason RunnerShutdownReason { get; private set; }
|
||||
public ISecretMasker SecretMasker => _secretMasker;
|
||||
public ProductInfoHeaderValue UserAgent => _userAgent;
|
||||
public List<ProductInfoHeaderValue> UserAgents => _userAgents;
|
||||
public RunnerWebProxy WebProxy => _webProxy;
|
||||
public HostContext(string hostType, string logFile = null)
|
||||
{
|
||||
@@ -189,6 +189,17 @@ namespace GitHub.Runner.Common
|
||||
{
|
||||
_trace.Info($"No proxy settings were found based on environmental variables (http_proxy/https_proxy/HTTP_PROXY/HTTPS_PROXY)");
|
||||
}
|
||||
|
||||
var credFile = GetConfigFile(WellKnownConfigFile.Credentials);
|
||||
if (File.Exists(credFile))
|
||||
{
|
||||
var credData = IOUtil.LoadObject<CredentialData>(credFile);
|
||||
if (credData != null &&
|
||||
credData.Data.TryGetValue("clientId", out var clientId))
|
||||
{
|
||||
_userAgents.Add(new ProductInfoHeaderValue($"RunnerId", clientId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetDirectory(WellKnownDirectory directory)
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace GitHub.Runner.Common
|
||||
|
||||
// job request
|
||||
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
|
||||
Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, CancellationToken cancellationToken);
|
||||
Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId, CancellationToken cancellationToken);
|
||||
Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken);
|
||||
|
||||
// agent package
|
||||
@@ -300,10 +300,10 @@ namespace GitHub.Runner.Common
|
||||
// JobRequest
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
public Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
CheckConnection(RunnerConnectionType.JobRequest);
|
||||
return _requestTaskAgentClient.RenewAgentRequestAsync(poolId, requestId, lockToken, cancellationToken: cancellationToken);
|
||||
return _requestTaskAgentClient.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId: orchestrationId, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace GitHub.Runner.Listener
|
||||
private readonly string[] validArgs =
|
||||
{
|
||||
Constants.Runner.CommandLine.Args.Auth,
|
||||
Constants.Runner.CommandLine.Args.Labels,
|
||||
Constants.Runner.CommandLine.Args.MonitorSocketAddress,
|
||||
Constants.Runner.CommandLine.Args.Name,
|
||||
Constants.Runner.CommandLine.Args.Pool,
|
||||
@@ -249,6 +250,24 @@ namespace GitHub.Runner.Listener
|
||||
return GetArg(Constants.Runner.CommandLine.Args.StartupType);
|
||||
}
|
||||
|
||||
public ISet<string> GetLabels()
|
||||
{
|
||||
var labelSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
string labels = GetArgOrPrompt(
|
||||
name: Constants.Runner.CommandLine.Args.Labels,
|
||||
description: $"This runner will have the following labels: 'self-hosted', '{VarUtil.OS}', '{VarUtil.OSArchitecture}' \nEnter any additional labels (ex. label-1,label-2):",
|
||||
defaultValue: string.Empty,
|
||||
validator: Validators.LabelsValidator,
|
||||
isOptional: true);
|
||||
|
||||
if (!string.IsNullOrEmpty(labels))
|
||||
{
|
||||
labelSet = labels.Split(',').Where(x => !string.IsNullOrEmpty(x)).ToHashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return labelSet;
|
||||
}
|
||||
|
||||
//
|
||||
// Private helpers.
|
||||
//
|
||||
@@ -280,7 +299,8 @@ namespace GitHub.Runner.Listener
|
||||
string name,
|
||||
string description,
|
||||
string defaultValue,
|
||||
Func<string, bool> validator)
|
||||
Func<string, bool> validator,
|
||||
bool isOptional = false)
|
||||
{
|
||||
// Check for the arg in the command line parser.
|
||||
ArgUtil.NotNull(validator, nameof(validator));
|
||||
@@ -311,7 +331,8 @@ namespace GitHub.Runner.Listener
|
||||
secret: Constants.Runner.CommandLine.Args.Secrets.Any(x => string.Equals(x, name, StringComparison.OrdinalIgnoreCase)),
|
||||
defaultValue: defaultValue,
|
||||
validator: validator,
|
||||
unattended: Unattended);
|
||||
unattended: Unattended,
|
||||
isOptional: isOptional);
|
||||
}
|
||||
|
||||
private string GetEnvArg(string name)
|
||||
|
||||
@@ -166,6 +166,9 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
|
||||
_term.WriteLine();
|
||||
|
||||
var userLabels = command.GetLabels();
|
||||
_term.WriteLine();
|
||||
|
||||
var agents = await _runnerServer.GetAgentsAsync(runnerSettings.PoolId, runnerSettings.AgentName);
|
||||
Trace.Verbose("Returns {0} agents", agents.Count);
|
||||
agent = agents.FirstOrDefault();
|
||||
@@ -175,7 +178,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
if (command.GetReplace())
|
||||
{
|
||||
// Update existing agent with new PublicKey, agent version.
|
||||
agent = UpdateExistingAgent(agent, publicKey);
|
||||
agent = UpdateExistingAgent(agent, publicKey, userLabels);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -198,7 +201,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
else
|
||||
{
|
||||
// Create a new agent.
|
||||
agent = CreateNewAgent(runnerSettings.AgentName, publicKey);
|
||||
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -448,7 +451,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
}
|
||||
|
||||
|
||||
private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey)
|
||||
private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey, ISet<string> userLabels)
|
||||
{
|
||||
ArgUtil.NotNull(agent, nameof(agent));
|
||||
agent.Authorization = new TaskAgentAuthorization
|
||||
@@ -456,18 +459,25 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
PublicKey = new TaskAgentPublicKey(publicKey.Exponent, publicKey.Modulus),
|
||||
};
|
||||
|
||||
// update - update instead of delete so we don't lose labels etc...
|
||||
// update should replace the existing labels
|
||||
agent.Version = BuildConstants.RunnerPackage.Version;
|
||||
agent.OSDescription = RuntimeInformation.OSDescription;
|
||||
|
||||
agent.Labels.Clear();
|
||||
|
||||
agent.Labels.Add("self-hosted");
|
||||
agent.Labels.Add(VarUtil.OS);
|
||||
agent.Labels.Add(VarUtil.OSArchitecture);
|
||||
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
|
||||
agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
|
||||
agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
|
||||
|
||||
foreach (var userLabel in userLabels)
|
||||
{
|
||||
agent.Labels.Add(new AgentLabel(userLabel, LabelType.User));
|
||||
}
|
||||
|
||||
return agent;
|
||||
}
|
||||
|
||||
private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey)
|
||||
private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels)
|
||||
{
|
||||
TaskAgent agent = new TaskAgent(agentName)
|
||||
{
|
||||
@@ -480,9 +490,14 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
OSDescription = RuntimeInformation.OSDescription,
|
||||
};
|
||||
|
||||
agent.Labels.Add("self-hosted");
|
||||
agent.Labels.Add(VarUtil.OS);
|
||||
agent.Labels.Add(VarUtil.OSArchitecture);
|
||||
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
|
||||
agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
|
||||
agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
|
||||
|
||||
foreach (var userLabel in userLabels)
|
||||
{
|
||||
agent.Labels.Add(new AgentLabel(userLabel, LabelType.User));
|
||||
}
|
||||
|
||||
return agent;
|
||||
}
|
||||
@@ -511,7 +526,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
using (var httpClient = new HttpClient(httpClientHandler))
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("RemoteAuth", githubToken);
|
||||
httpClient.DefaultRequestHeaders.UserAgent.Add(HostContext.UserAgent);
|
||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||
|
||||
var bodyObject = new Dictionary<string, string>()
|
||||
{
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
bool secret,
|
||||
string defaultValue,
|
||||
Func<String, bool> validator,
|
||||
bool unattended);
|
||||
bool unattended,
|
||||
bool isOptional = false);
|
||||
}
|
||||
|
||||
public sealed class PromptManager : RunnerService, IPromptManager
|
||||
@@ -56,7 +57,8 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
bool secret,
|
||||
string defaultValue,
|
||||
Func<string, bool> validator,
|
||||
bool unattended)
|
||||
bool unattended,
|
||||
bool isOptional = false)
|
||||
{
|
||||
Trace.Info(nameof(ReadValue));
|
||||
ArgUtil.NotNull(validator, nameof(validator));
|
||||
@@ -70,6 +72,10 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
else if (isOptional)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Otherwise throw.
|
||||
throw new Exception($"Invalid configuration provided for {argName}. Terminating unattended configuration.");
|
||||
@@ -85,18 +91,28 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
{
|
||||
_terminal.Write($"[press Enter for {defaultValue}] ");
|
||||
}
|
||||
else if (isOptional){
|
||||
_terminal.Write($"[press Enter to skip] ");
|
||||
}
|
||||
|
||||
// Read and trim the value.
|
||||
value = secret ? _terminal.ReadSecret() : _terminal.ReadLine();
|
||||
value = value?.Trim() ?? string.Empty;
|
||||
|
||||
// Return the default if not specified.
|
||||
if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(defaultValue))
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
Trace.Info($"Falling back to the default: '{defaultValue}'");
|
||||
return defaultValue;
|
||||
if (!string.IsNullOrEmpty(defaultValue))
|
||||
{
|
||||
Trace.Info($"Falling back to the default: '{defaultValue}'");
|
||||
return defaultValue;
|
||||
}
|
||||
else if (isOptional)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return the value if it is not empty and it is valid.
|
||||
// Otherwise try the loop again.
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Security.Principal;
|
||||
|
||||
@@ -46,6 +47,21 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
string.Equals(value, "N", StringComparison.CurrentCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool LabelsValidator(string labels)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(labels))
|
||||
{
|
||||
var labelSet = labels.Split(',').Where(x => !string.IsNullOrEmpty(x)).ToHashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (labelSet.Any(x => x.Length > 256))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool NonEmptyValidator(string value)
|
||||
{
|
||||
return !string.IsNullOrEmpty(value);
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Linq;
|
||||
using GitHub.Services.Common;
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.WebApi.Jwt;
|
||||
|
||||
namespace GitHub.Runner.Listener
|
||||
{
|
||||
@@ -86,15 +87,30 @@ namespace GitHub.Runner.Listener
|
||||
}
|
||||
}
|
||||
|
||||
var orchestrationId = string.Empty;
|
||||
var systemConnection = jobRequestMessage.Resources.Endpoints.SingleOrDefault(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||
if (systemConnection?.Authorization != null &&
|
||||
systemConnection.Authorization.Parameters.TryGetValue("AccessToken", out var accessToken) &&
|
||||
!string.IsNullOrEmpty(accessToken))
|
||||
{
|
||||
var jwt = JsonWebToken.Create(accessToken);
|
||||
var claims = jwt.ExtractClaims();
|
||||
orchestrationId = claims.FirstOrDefault(x => string.Equals(x.Type, "orchid", StringComparison.OrdinalIgnoreCase))?.Value;
|
||||
if (!string.IsNullOrEmpty(orchestrationId))
|
||||
{
|
||||
Trace.Info($"Pull OrchestrationId {orchestrationId} from JWT claims");
|
||||
}
|
||||
}
|
||||
|
||||
WorkerDispatcher newDispatch = new WorkerDispatcher(jobRequestMessage.JobId, jobRequestMessage.RequestId);
|
||||
if (runOnce)
|
||||
{
|
||||
Trace.Info("Start dispatcher for one time used runner.");
|
||||
newDispatch.WorkerDispatch = RunOnceAsync(jobRequestMessage, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
|
||||
newDispatch.WorkerDispatch = RunOnceAsync(jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
|
||||
}
|
||||
else
|
||||
{
|
||||
newDispatch.WorkerDispatch = RunAsync(jobRequestMessage, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
|
||||
newDispatch.WorkerDispatch = RunAsync(jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
|
||||
}
|
||||
|
||||
_jobInfos.TryAdd(newDispatch.JobId, newDispatch);
|
||||
@@ -284,11 +300,11 @@ namespace GitHub.Runner.Listener
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunOnceAsync(Pipelines.AgentJobRequestMessage message, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
|
||||
private async Task RunOnceAsync(Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await RunAsync(message, previousJobDispatch, jobRequestCancellationToken, workerCancelTimeoutKillToken);
|
||||
await RunAsync(message, orchestrationId, previousJobDispatch, jobRequestCancellationToken, workerCancelTimeoutKillToken);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -297,7 +313,7 @@ namespace GitHub.Runner.Listener
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunAsync(Pipelines.AgentJobRequestMessage message, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
|
||||
private async Task RunAsync(Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
|
||||
{
|
||||
Busy = true;
|
||||
try
|
||||
@@ -328,7 +344,7 @@ namespace GitHub.Runner.Listener
|
||||
|
||||
// start renew job request
|
||||
Trace.Info($"Start renew job request {requestId} for job {message.JobId}.");
|
||||
Task renewJobRequest = RenewJobRequestAsync(_poolId, requestId, lockToken, firstJobRequestRenewed, lockRenewalTokenSource.Token);
|
||||
Task renewJobRequest = RenewJobRequestAsync(_poolId, requestId, lockToken, orchestrationId, firstJobRequestRenewed, lockRenewalTokenSource.Token);
|
||||
|
||||
// wait till first renew succeed or job request is canceled
|
||||
// not even start worker if the first renew fail
|
||||
@@ -607,7 +623,7 @@ namespace GitHub.Runner.Listener
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RenewJobRequestAsync(int poolId, long requestId, Guid lockToken, TaskCompletionSource<int> firstJobRequestRenewed, CancellationToken token)
|
||||
public async Task RenewJobRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId, TaskCompletionSource<int> firstJobRequestRenewed, CancellationToken token)
|
||||
{
|
||||
var runnerServer = HostContext.GetService<IRunnerServer>();
|
||||
TaskAgentJobRequest request = null;
|
||||
@@ -620,7 +636,7 @@ namespace GitHub.Runner.Listener
|
||||
{
|
||||
try
|
||||
{
|
||||
request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, token);
|
||||
request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token);
|
||||
|
||||
Trace.Info($"Successfully renew job request {requestId}, job is valid till {request.LockedUntil.Value}");
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace GitHub.Runner.Listener
|
||||
{
|
||||
try
|
||||
{
|
||||
VssUtil.InitializeVssClientSettings(HostContext.UserAgent, HostContext.WebProxy);
|
||||
VssUtil.InitializeVssClientSettings(HostContext.UserAgents, HostContext.WebProxy);
|
||||
|
||||
_inConfigStage = true;
|
||||
_completedCommand.Reset();
|
||||
|
||||
@@ -14,10 +14,10 @@ namespace GitHub.Runner.Sdk
|
||||
{
|
||||
public static class VssUtil
|
||||
{
|
||||
public static void InitializeVssClientSettings(ProductInfoHeaderValue additionalUserAgent, IWebProxy proxy)
|
||||
public static void InitializeVssClientSettings(List<ProductInfoHeaderValue> additionalUserAgents, IWebProxy proxy)
|
||||
{
|
||||
var headerValues = new List<ProductInfoHeaderValue>();
|
||||
headerValues.Add(additionalUserAgent);
|
||||
headerValues.AddRange(additionalUserAgents);
|
||||
headerValues.Add(new ProductInfoHeaderValue($"({RuntimeInformation.OSDescription.Trim()})"));
|
||||
|
||||
if (VssClientHttpRequestSettings.Default.UserAgent != null && VssClientHttpRequestSettings.Default.UserAgent.Count > 0)
|
||||
|
||||
@@ -21,11 +21,24 @@ using PipelineTemplateConstants = GitHub.DistributedTask.Pipelines.ObjectTemplat
|
||||
|
||||
namespace GitHub.Runner.Worker
|
||||
{
|
||||
public class PrepareResult
|
||||
{
|
||||
public PrepareResult(List<JobExtensionRunner> containerSetupSteps, Dictionary<Guid, IActionRunner> preStepTracker)
|
||||
{
|
||||
this.ContainerSetupSteps = containerSetupSteps;
|
||||
this.PreStepTracker = preStepTracker;
|
||||
}
|
||||
|
||||
public List<JobExtensionRunner> ContainerSetupSteps { get; set; }
|
||||
|
||||
public Dictionary<Guid, IActionRunner> PreStepTracker { get; set; }
|
||||
}
|
||||
|
||||
[ServiceLocator(Default = typeof(ActionManager))]
|
||||
public interface IActionManager : IRunnerService
|
||||
{
|
||||
Dictionary<Guid, ContainerInfo> CachedActionContainers { get; }
|
||||
Task<List<JobExtensionRunner>> PrepareActionsAsync(IExecutionContext executionContext, IEnumerable<Pipelines.JobStep> steps);
|
||||
Task<PrepareResult> PrepareActionsAsync(IExecutionContext executionContext, IEnumerable<Pipelines.JobStep> steps);
|
||||
Definition LoadAction(IExecutionContext executionContext, Pipelines.ActionStep action);
|
||||
}
|
||||
|
||||
@@ -39,7 +52,7 @@ namespace GitHub.Runner.Worker
|
||||
private readonly Dictionary<Guid, ContainerInfo> _cachedActionContainers = new Dictionary<Guid, ContainerInfo>();
|
||||
|
||||
public Dictionary<Guid, ContainerInfo> CachedActionContainers => _cachedActionContainers;
|
||||
public async Task<List<JobExtensionRunner>> PrepareActionsAsync(IExecutionContext executionContext, IEnumerable<Pipelines.JobStep> steps)
|
||||
public async Task<PrepareResult> PrepareActionsAsync(IExecutionContext executionContext, IEnumerable<Pipelines.JobStep> steps)
|
||||
{
|
||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||
ArgUtil.NotNull(steps, nameof(steps));
|
||||
@@ -49,6 +62,7 @@ namespace GitHub.Runner.Worker
|
||||
Dictionary<string, List<Guid>> imagesToBuild = new Dictionary<string, List<Guid>>(StringComparer.OrdinalIgnoreCase);
|
||||
Dictionary<string, ActionContainer> imagesToBuildInfo = new Dictionary<string, ActionContainer>(StringComparer.OrdinalIgnoreCase);
|
||||
List<JobExtensionRunner> containerSetupSteps = new List<JobExtensionRunner>();
|
||||
Dictionary<Guid, IActionRunner> preStepTracker = new Dictionary<Guid, IActionRunner>();
|
||||
IEnumerable<Pipelines.ActionStep> actions = steps.OfType<Pipelines.ActionStep>();
|
||||
|
||||
// TODO: Deprecate the PREVIEW_ACTION_TOKEN
|
||||
@@ -117,6 +131,22 @@ namespace GitHub.Runner.Worker
|
||||
imagesToBuildInfo[setupInfo.ActionRepository] = setupInfo;
|
||||
}
|
||||
}
|
||||
|
||||
var repoAction = action.Reference as Pipelines.RepositoryPathReference;
|
||||
if (repoAction.RepositoryType != Pipelines.PipelineConstants.SelfAlias)
|
||||
{
|
||||
var definition = LoadAction(executionContext, action);
|
||||
if (definition.Data.Execution.HasPre)
|
||||
{
|
||||
var actionRunner = HostContext.CreateService<IActionRunner>();
|
||||
actionRunner.Action = action;
|
||||
actionRunner.Stage = ActionRunStage.Pre;
|
||||
actionRunner.Condition = definition.Data.Execution.InitCondition;
|
||||
|
||||
Trace.Info($"Add 'pre' execution for {action.Id}");
|
||||
preStepTracker[action.Id] = actionRunner;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +183,7 @@ namespace GitHub.Runner.Worker
|
||||
}
|
||||
#endif
|
||||
|
||||
return containerSetupSteps;
|
||||
return new PrepareResult(containerSetupSteps, preStepTracker);
|
||||
}
|
||||
|
||||
public Definition LoadAction(IExecutionContext executionContext, Pipelines.ActionStep action)
|
||||
@@ -245,14 +275,19 @@ namespace GitHub.Runner.Worker
|
||||
Trace.Info($"Action container env: {StringUtil.ConvertToJson(containerAction.Environment)}.");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(containerAction.Pre))
|
||||
{
|
||||
Trace.Info($"Action container pre entrypoint: {containerAction.Pre}.");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(containerAction.EntryPoint))
|
||||
{
|
||||
Trace.Info($"Action container entrypoint: {containerAction.EntryPoint}.");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(containerAction.Cleanup))
|
||||
if (!string.IsNullOrEmpty(containerAction.Post))
|
||||
{
|
||||
Trace.Info($"Action container cleanup entrypoint: {containerAction.Cleanup}.");
|
||||
Trace.Info($"Action container post entrypoint: {containerAction.Post}.");
|
||||
}
|
||||
|
||||
if (CachedActionContainers.TryGetValue(action.Id, out var container))
|
||||
@@ -264,8 +299,9 @@ namespace GitHub.Runner.Worker
|
||||
else if (definition.Data.Execution.ExecutionType == ActionExecutionType.NodeJS)
|
||||
{
|
||||
var nodeAction = definition.Data.Execution as NodeJSActionExecutionData;
|
||||
Trace.Info($"Action pre node.js file: {nodeAction.Pre ?? "N/A"}.");
|
||||
Trace.Info($"Action node.js file: {nodeAction.Script}.");
|
||||
Trace.Info($"Action cleanup node.js file: {nodeAction.Cleanup ?? "N/A"}.");
|
||||
Trace.Info($"Action post node.js file: {nodeAction.Post ?? "N/A"}.");
|
||||
}
|
||||
else if (definition.Data.Execution.ExecutionType == ActionExecutionType.Plugin)
|
||||
{
|
||||
@@ -281,7 +317,7 @@ namespace GitHub.Runner.Worker
|
||||
|
||||
if (!string.IsNullOrEmpty(plugin.PostPluginTypeName))
|
||||
{
|
||||
pluginAction.Cleanup = plugin.PostPluginTypeName;
|
||||
pluginAction.Post = plugin.PostPluginTypeName;
|
||||
Trace.Info($"Action cleanup plugin: {plugin.PluginTypeName}.");
|
||||
}
|
||||
}
|
||||
@@ -534,7 +570,7 @@ namespace GitHub.Runner.Worker
|
||||
// Intentionally empty. Temporary for GHES alpha release, download from dotcom unauthenticated.
|
||||
}
|
||||
|
||||
httpClient.DefaultRequestHeaders.UserAgent.Add(HostContext.UserAgent);
|
||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||
using (var result = await httpClient.GetStreamAsync(archiveLink))
|
||||
{
|
||||
await result.CopyToAsync(fs, _defaultCopyBufferSize, actionDownloadCancellation.Token);
|
||||
@@ -788,7 +824,8 @@ namespace GitHub.Runner.Worker
|
||||
{
|
||||
public override ActionExecutionType ExecutionType => ActionExecutionType.Container;
|
||||
|
||||
public override bool HasCleanup => !string.IsNullOrEmpty(Cleanup);
|
||||
public override bool HasPre => !string.IsNullOrEmpty(Pre);
|
||||
public override bool HasPost => !string.IsNullOrEmpty(Post);
|
||||
|
||||
public string Image { get; set; }
|
||||
|
||||
@@ -798,51 +835,66 @@ namespace GitHub.Runner.Worker
|
||||
|
||||
public MappingToken Environment { get; set; }
|
||||
|
||||
public string Cleanup { get; set; }
|
||||
public string Pre { get; set; }
|
||||
|
||||
public string Post { get; set; }
|
||||
}
|
||||
|
||||
public sealed class NodeJSActionExecutionData : ActionExecutionData
|
||||
{
|
||||
public override ActionExecutionType ExecutionType => ActionExecutionType.NodeJS;
|
||||
|
||||
public override bool HasCleanup => !string.IsNullOrEmpty(Cleanup);
|
||||
public override bool HasPre => !string.IsNullOrEmpty(Pre);
|
||||
public override bool HasPost => !string.IsNullOrEmpty(Post);
|
||||
|
||||
public string Script { get; set; }
|
||||
|
||||
public string Cleanup { get; set; }
|
||||
public string Pre { get; set; }
|
||||
|
||||
public string Post { get; set; }
|
||||
}
|
||||
|
||||
public sealed class PluginActionExecutionData : ActionExecutionData
|
||||
{
|
||||
public override ActionExecutionType ExecutionType => ActionExecutionType.Plugin;
|
||||
|
||||
public override bool HasCleanup => !string.IsNullOrEmpty(Cleanup);
|
||||
public override bool HasPre => false;
|
||||
|
||||
public override bool HasPost => !string.IsNullOrEmpty(Post);
|
||||
|
||||
public string Plugin { get; set; }
|
||||
|
||||
public string Cleanup { get; set; }
|
||||
public string Post { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ScriptActionExecutionData : ActionExecutionData
|
||||
{
|
||||
public override ActionExecutionType ExecutionType => ActionExecutionType.Script;
|
||||
|
||||
public override bool HasCleanup => false;
|
||||
public override bool HasPre => false;
|
||||
public override bool HasPost => false;
|
||||
}
|
||||
|
||||
public abstract class ActionExecutionData
|
||||
{
|
||||
private string _initCondition = $"{Constants.Expressions.Always}()";
|
||||
private string _cleanupCondition = $"{Constants.Expressions.Always}()";
|
||||
|
||||
public abstract ActionExecutionType ExecutionType { get; }
|
||||
|
||||
public abstract bool HasCleanup { get; }
|
||||
public abstract bool HasPre { get; }
|
||||
public abstract bool HasPost { get; }
|
||||
|
||||
public string CleanupCondition
|
||||
{
|
||||
get { return _cleanupCondition; }
|
||||
set { _cleanupCondition = value; }
|
||||
}
|
||||
|
||||
public string InitCondition
|
||||
{
|
||||
get { return _initCondition; }
|
||||
set { _initCondition = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public class ContainerSetupInfo
|
||||
|
||||
@@ -305,6 +305,9 @@ namespace GitHub.Runner.Worker
|
||||
var envToken = default(MappingToken);
|
||||
var mainToken = default(StringToken);
|
||||
var pluginToken = default(StringToken);
|
||||
var preToken = default(StringToken);
|
||||
var preEntrypointToken = default(StringToken);
|
||||
var preIfToken = default(StringToken);
|
||||
var postToken = default(StringToken);
|
||||
var postEntrypointToken = default(StringToken);
|
||||
var postIfToken = default(StringToken);
|
||||
@@ -343,6 +346,15 @@ namespace GitHub.Runner.Worker
|
||||
case "post-if":
|
||||
postIfToken = run.Value.AssertString("post-if");
|
||||
break;
|
||||
case "pre":
|
||||
preToken = run.Value.AssertString("pre");
|
||||
break;
|
||||
case "pre-entrypoint":
|
||||
preEntrypointToken = run.Value.AssertString("pre-entrypoint");
|
||||
break;
|
||||
case "pre-if":
|
||||
preIfToken = run.Value.AssertString("pre-if");
|
||||
break;
|
||||
default:
|
||||
Trace.Info($"Ignore run property {runsKey}.");
|
||||
break;
|
||||
@@ -365,7 +377,9 @@ namespace GitHub.Runner.Worker
|
||||
Arguments = argsToken,
|
||||
EntryPoint = entrypointToken?.Value,
|
||||
Environment = envToken,
|
||||
Cleanup = postEntrypointToken?.Value,
|
||||
Pre = preEntrypointToken?.Value,
|
||||
InitCondition = preIfToken?.Value ?? "always()",
|
||||
Post = postEntrypointToken?.Value,
|
||||
CleanupCondition = postIfToken?.Value ?? "always()"
|
||||
};
|
||||
}
|
||||
@@ -374,14 +388,16 @@ namespace GitHub.Runner.Worker
|
||||
{
|
||||
if (string.IsNullOrEmpty(mainToken?.Value))
|
||||
{
|
||||
throw new ArgumentNullException($"Entry javascript fils is not provided.");
|
||||
throw new ArgumentNullException($"Entry javascript file is not provided.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return new NodeJSActionExecutionData()
|
||||
{
|
||||
Script = mainToken.Value,
|
||||
Cleanup = postToken?.Value,
|
||||
Pre = preToken?.Value,
|
||||
InitCondition = preIfToken?.Value ?? "always()",
|
||||
Post = postToken?.Value,
|
||||
CleanupCondition = postIfToken?.Value ?? "always()"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace GitHub.Runner.Worker
|
||||
{
|
||||
public enum ActionRunStage
|
||||
{
|
||||
Pre,
|
||||
Main,
|
||||
Post,
|
||||
}
|
||||
@@ -81,20 +82,18 @@ namespace GitHub.Runner.Worker
|
||||
ActionExecutionData handlerData = definition.Data?.Execution;
|
||||
ArgUtil.NotNull(handlerData, nameof(handlerData));
|
||||
|
||||
if (handlerData.HasPre &&
|
||||
Action.Reference is Pipelines.RepositoryPathReference repoAction &&
|
||||
string.Equals(repoAction.RepositoryType, Pipelines.PipelineConstants.SelfAlias, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ExecutionContext.Warning($"`pre` execution is not supported for local action from '{repoAction.Path}'");
|
||||
}
|
||||
|
||||
// The action has post cleanup defined.
|
||||
// we need to create timeline record for them and add them to the step list that StepRunner is using
|
||||
if (handlerData.HasCleanup && Stage == ActionRunStage.Main)
|
||||
if (handlerData.HasPost && (Stage == ActionRunStage.Pre || Stage == ActionRunStage.Main))
|
||||
{
|
||||
string postDisplayName = null;
|
||||
if (this.DisplayName.StartsWith(PipelineTemplateConstants.RunDisplayPrefix))
|
||||
{
|
||||
postDisplayName = $"Post {this.DisplayName.Substring(PipelineTemplateConstants.RunDisplayPrefix.Length)}";
|
||||
}
|
||||
else
|
||||
{
|
||||
postDisplayName = $"Post {this.DisplayName}";
|
||||
}
|
||||
|
||||
string postDisplayName = $"Post {this.DisplayName}";
|
||||
var repositoryReference = Action.Reference as RepositoryPathReference;
|
||||
var pathString = string.IsNullOrEmpty(repositoryReference.Path) ? string.Empty : $"/{repositoryReference.Path}";
|
||||
var repoString = string.IsNullOrEmpty(repositoryReference.Ref) ? $"{repositoryReference.Name}{pathString}" :
|
||||
@@ -108,7 +107,7 @@ namespace GitHub.Runner.Worker
|
||||
actionRunner.Condition = handlerData.CleanupCondition;
|
||||
actionRunner.DisplayName = postDisplayName;
|
||||
|
||||
ExecutionContext.RegisterPostJobStep($"{actionRunner.Action.Name}_post", actionRunner);
|
||||
ExecutionContext.RegisterPostJobStep(actionRunner);
|
||||
}
|
||||
|
||||
IStepHost stepHost = HostContext.CreateService<IDefaultStepHost>();
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace GitHub.Runner.Worker
|
||||
data: data);
|
||||
|
||||
executionContext.Debug($"Register post job cleanup for stopping/deleting containers.");
|
||||
executionContext.RegisterPostJobStep(nameof(StopContainersAsync), postJobStep);
|
||||
executionContext.RegisterPostJobStep(postJobStep);
|
||||
|
||||
// Check whether we are inside a container.
|
||||
// Our container feature requires to map working directory from host to the container.
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace GitHub.Runner.Worker
|
||||
|
||||
// others
|
||||
void ForceTaskComplete();
|
||||
void RegisterPostJobStep(string refName, IStep step);
|
||||
void RegisterPostJobStep(IStep step);
|
||||
}
|
||||
|
||||
public sealed class ExecutionContext : RunnerService, IExecutionContext
|
||||
@@ -161,6 +161,9 @@ namespace GitHub.Runner.Worker
|
||||
// Only job level ExecutionContext has PostJobSteps
|
||||
public Stack<IStep> PostJobSteps { get; private set; }
|
||||
|
||||
// Only job level ExecutionContext has StepsWithPostRegistered
|
||||
public HashSet<Guid> StepsWithPostRegistered { get; private set; }
|
||||
|
||||
public bool EchoOnActionCommand { get; set; }
|
||||
|
||||
|
||||
@@ -248,9 +251,15 @@ namespace GitHub.Runner.Worker
|
||||
});
|
||||
}
|
||||
|
||||
public void RegisterPostJobStep(string refName, IStep step)
|
||||
public void RegisterPostJobStep(IStep step)
|
||||
{
|
||||
step.ExecutionContext = Root.CreatePostChild(step.DisplayName, refName, IntraActionState);
|
||||
if (step is IActionRunner actionRunner && !Root.StepsWithPostRegistered.Add(actionRunner.Action.Id))
|
||||
{
|
||||
Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to post step stack.");
|
||||
return;
|
||||
}
|
||||
|
||||
step.ExecutionContext = Root.CreatePostChild(step.DisplayName, IntraActionState);
|
||||
Root.PostJobSteps.Push(step);
|
||||
}
|
||||
|
||||
@@ -647,6 +656,9 @@ namespace GitHub.Runner.Worker
|
||||
// PostJobSteps for job ExecutionContext
|
||||
PostJobSteps = new Stack<IStep>();
|
||||
|
||||
// StepsWithPostRegistered for job ExecutionContext
|
||||
StepsWithPostRegistered = new HashSet<Guid>();
|
||||
|
||||
// Job timeline record.
|
||||
InitializeTimelineRecord(
|
||||
timelineId: message.Timeline.Id,
|
||||
@@ -847,7 +859,7 @@ namespace GitHub.Runner.Worker
|
||||
}
|
||||
}
|
||||
|
||||
private IExecutionContext CreatePostChild(string displayName, string refName, Dictionary<string, string> intraActionState)
|
||||
private IExecutionContext CreatePostChild(string displayName, Dictionary<string, string> intraActionState)
|
||||
{
|
||||
if (!_expandedForPostJob)
|
||||
{
|
||||
@@ -856,7 +868,8 @@ namespace GitHub.Runner.Worker
|
||||
_childTimelineRecordOrder = _childTimelineRecordOrder * 2;
|
||||
}
|
||||
|
||||
return CreateChild(Guid.NewGuid(), displayName, refName, null, null, intraActionState, _childTimelineRecordOrder - Root.PostJobSteps.Count);
|
||||
var newGuid = Guid.NewGuid();
|
||||
return CreateChild(newGuid, displayName, newGuid.ToString("N"), null, null, intraActionState, _childTimelineRecordOrder - Root.PostJobSteps.Count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,9 +82,13 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
container.ContainerEntryPoint = Inputs.GetValueOrDefault("entryPoint");
|
||||
}
|
||||
}
|
||||
else if (stage == ActionRunStage.Pre)
|
||||
{
|
||||
container.ContainerEntryPoint = Data.Pre;
|
||||
}
|
||||
else if (stage == ActionRunStage.Post)
|
||||
{
|
||||
container.ContainerEntryPoint = Data.Cleanup;
|
||||
container.ContainerEntryPoint = Data.Post;
|
||||
}
|
||||
|
||||
// create inputs context for template evaluation
|
||||
|
||||
@@ -60,9 +60,13 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
{
|
||||
target = Data.Script;
|
||||
}
|
||||
else if (stage == ActionRunStage.Pre)
|
||||
{
|
||||
target = Data.Pre;
|
||||
}
|
||||
else if (stage == ActionRunStage.Post)
|
||||
{
|
||||
target = Data.Cleanup;
|
||||
target = Data.Post;
|
||||
}
|
||||
|
||||
ArgUtil.NotNullOrEmpty(target, nameof(target));
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
}
|
||||
else if (stage == ActionRunStage.Post)
|
||||
{
|
||||
plugin = Data.Cleanup;
|
||||
plugin = Data.Post;
|
||||
}
|
||||
|
||||
ArgUtil.NotNullOrEmpty(plugin, nameof(plugin));
|
||||
|
||||
@@ -259,6 +259,16 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
|
||||
// dump out the command
|
||||
var fileName = isContainerStepHost ? shellCommand : commandPath;
|
||||
#if OS_OSX
|
||||
if (Environment.ContainsKey("DYLD_INSERT_LIBRARIES")) // We don't check `isContainerStepHost` because we don't support container on macOS
|
||||
{
|
||||
// launch `node macOSRunInvoker.js shell args` instead of `shell args` to avoid macOS SIP remove `DYLD_INSERT_LIBRARIES` when launch process
|
||||
string node12 = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}");
|
||||
string macOSRunInvoker = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "macos-run-invoker.js");
|
||||
arguments = $"\"{macOSRunInvoker.Replace("\"", "\\\"")}\" \"{fileName.Replace("\"", "\\\"")}\" {arguments}";
|
||||
fileName = node12;
|
||||
}
|
||||
#endif
|
||||
ExecutionContext.Debug($"{fileName} {arguments}");
|
||||
|
||||
using (var stdoutManager = new OutputManager(ExecutionContext, ActionCommandManager))
|
||||
|
||||
@@ -110,9 +110,9 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
|
||||
// try to resolve path inside container if the request path is part of the mount volume
|
||||
#if OS_WINDOWS
|
||||
if (Container.MountVolumes.Exists(x => path.StartsWith(x.SourceVolumePath, StringComparison.OrdinalIgnoreCase)))
|
||||
if (Container.MountVolumes.Exists(x => !string.IsNullOrEmpty(x.SourceVolumePath) && path.StartsWith(x.SourceVolumePath, StringComparison.OrdinalIgnoreCase)))
|
||||
#else
|
||||
if (Container.MountVolumes.Exists(x => path.StartsWith(x.SourceVolumePath)))
|
||||
if (Container.MountVolumes.Exists(x => !string.IsNullOrEmpty(x.SourceVolumePath) && path.StartsWith(x.SourceVolumePath)))
|
||||
#endif
|
||||
{
|
||||
return Container.TranslateToContainerPath(path);
|
||||
|
||||
@@ -197,8 +197,8 @@ namespace GitHub.Runner.Worker
|
||||
// Download actions not already in the cache
|
||||
Trace.Info("Downloading actions");
|
||||
var actionManager = HostContext.GetService<IActionManager>();
|
||||
var prepareSteps = await actionManager.PrepareActionsAsync(context, message.Steps);
|
||||
preJobSteps.AddRange(prepareSteps);
|
||||
var prepareResult = await actionManager.PrepareActionsAsync(context, message.Steps);
|
||||
preJobSteps.AddRange(prepareResult.ContainerSetupSteps);
|
||||
|
||||
// Add start-container steps, record and stop-container steps
|
||||
if (jobContext.Container != null || jobContext.ServiceContainers.Count > 0)
|
||||
@@ -239,9 +239,23 @@ namespace GitHub.Runner.Worker
|
||||
|
||||
actionRunner.TryEvaluateDisplayName(contextData, context);
|
||||
jobSteps.Add(actionRunner);
|
||||
|
||||
if (prepareResult.PreStepTracker.TryGetValue(step.Id, out var preStep))
|
||||
{
|
||||
Trace.Info($"Adding pre-{action.DisplayName}.");
|
||||
preStep.TryEvaluateDisplayName(contextData, context);
|
||||
preStep.DisplayName = $"Pre {preStep.DisplayName}";
|
||||
preJobSteps.Add(preStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var intraActionStates = new Dictionary<Guid, Dictionary<string, string>>();
|
||||
foreach (var preStep in prepareResult.PreStepTracker)
|
||||
{
|
||||
intraActionStates[preStep.Key] = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
// Create execution context for pre-job steps
|
||||
foreach (var step in preJobSteps)
|
||||
{
|
||||
@@ -252,6 +266,12 @@ namespace GitHub.Runner.Worker
|
||||
Guid stepId = Guid.NewGuid();
|
||||
extensionStep.ExecutionContext = jobContext.CreateChild(stepId, extensionStep.DisplayName, null, null, stepId.ToString("N"));
|
||||
}
|
||||
else if (step is IActionRunner actionStep)
|
||||
{
|
||||
ArgUtil.NotNull(actionStep, step.DisplayName);
|
||||
Guid stepId = Guid.NewGuid();
|
||||
actionStep.ExecutionContext = jobContext.CreateChild(stepId, actionStep.DisplayName, stepId.ToString("N"), null, null, intraActionStates[actionStep.Action.Id]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create execution context for job steps
|
||||
@@ -260,7 +280,8 @@ namespace GitHub.Runner.Worker
|
||||
if (step is IActionRunner actionStep)
|
||||
{
|
||||
ArgUtil.NotNull(actionStep, step.DisplayName);
|
||||
actionStep.ExecutionContext = jobContext.CreateChild(actionStep.Action.Id, actionStep.DisplayName, actionStep.Action.Name, actionStep.Action.ScopeName, actionStep.Action.ContextName);
|
||||
intraActionStates.TryGetValue(actionStep.Action.Id, out var intraActionState);
|
||||
actionStep.ExecutionContext = jobContext.CreateChild(actionStep.Action.Id, actionStep.DisplayName, actionStep.Action.Name, actionStep.Action.ScopeName, actionStep.Action.ContextName, intraActionState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace GitHub.Runner.Worker
|
||||
// Validate args.
|
||||
ArgUtil.NotNullOrEmpty(pipeIn, nameof(pipeIn));
|
||||
ArgUtil.NotNullOrEmpty(pipeOut, nameof(pipeOut));
|
||||
VssUtil.InitializeVssClientSettings(HostContext.UserAgent, HostContext.WebProxy);
|
||||
VssUtil.InitializeVssClientSettings(HostContext.UserAgents, HostContext.WebProxy);
|
||||
var jobRunner = HostContext.CreateService<IJobRunner>();
|
||||
|
||||
using (var channel = HostContext.CreateService<IProcessChannel>())
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
"entrypoint": "non-empty-string",
|
||||
"args": "container-runs-args",
|
||||
"env": "container-runs-env",
|
||||
"pre-entrypoint": "non-empty-string",
|
||||
"pre-if": "non-empty-string",
|
||||
"post-entrypoint": "non-empty-string",
|
||||
"post-if": "non-empty-string"
|
||||
}
|
||||
@@ -67,6 +69,8 @@
|
||||
"properties": {
|
||||
"using": "non-empty-string",
|
||||
"main": "non-empty-string",
|
||||
"pre": "non-empty-string",
|
||||
"pre-if": "non-empty-string",
|
||||
"post": "non-empty-string",
|
||||
"post-if": "non-empty-string"
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace GitHub.DistributedTask.WebApi
|
||||
httpMethod,
|
||||
locationId,
|
||||
routeValues: routeValues,
|
||||
version: new ApiResourceVersion(5.1, 1),
|
||||
version: new ApiResourceVersion(6.0, 2),
|
||||
userState: userState,
|
||||
cancellationToken: cancellationToken,
|
||||
content: content);
|
||||
@@ -109,7 +109,7 @@ namespace GitHub.DistributedTask.WebApi
|
||||
httpMethod,
|
||||
locationId,
|
||||
routeValues: routeValues,
|
||||
version: new ApiResourceVersion(5.1, 1),
|
||||
version: new ApiResourceVersion(6.0, 2),
|
||||
userState: userState,
|
||||
cancellationToken: cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
@@ -164,7 +164,7 @@ namespace GitHub.DistributedTask.WebApi
|
||||
httpMethod,
|
||||
locationId,
|
||||
routeValues: routeValues,
|
||||
version: new ApiResourceVersion(5.1, 1),
|
||||
version: new ApiResourceVersion(6.0, 2),
|
||||
queryParameters: queryParams,
|
||||
userState: userState,
|
||||
cancellationToken: cancellationToken);
|
||||
@@ -227,7 +227,7 @@ namespace GitHub.DistributedTask.WebApi
|
||||
httpMethod,
|
||||
locationId,
|
||||
routeValues: routeValues,
|
||||
version: new ApiResourceVersion(5.1, 1),
|
||||
version: new ApiResourceVersion(6.0, 2),
|
||||
queryParameters: queryParams,
|
||||
userState: userState,
|
||||
cancellationToken: cancellationToken);
|
||||
@@ -257,7 +257,7 @@ namespace GitHub.DistributedTask.WebApi
|
||||
httpMethod,
|
||||
locationId,
|
||||
routeValues: routeValues,
|
||||
version: new ApiResourceVersion(5.1, 1),
|
||||
version: new ApiResourceVersion(6.0, 2),
|
||||
userState: userState,
|
||||
cancellationToken: cancellationToken,
|
||||
content: content);
|
||||
@@ -287,7 +287,7 @@ namespace GitHub.DistributedTask.WebApi
|
||||
httpMethod,
|
||||
locationId,
|
||||
routeValues: routeValues,
|
||||
version: new ApiResourceVersion(5.1, 1),
|
||||
version: new ApiResourceVersion(6.0, 2),
|
||||
userState: userState,
|
||||
cancellationToken: cancellationToken,
|
||||
content: content);
|
||||
|
||||
59
src/Sdk/DTWebApi/WebApi/AgentLabel.cs
Normal file
59
src/Sdk/DTWebApi/WebApi/AgentLabel.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GitHub.DistributedTask.WebApi
|
||||
{
|
||||
[DataContract]
|
||||
public class AgentLabel
|
||||
{
|
||||
[JsonConstructor]
|
||||
public AgentLabel()
|
||||
{
|
||||
}
|
||||
|
||||
public AgentLabel(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Type = LabelType.System;
|
||||
}
|
||||
|
||||
public AgentLabel(string name, LabelType type)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Type = type;
|
||||
}
|
||||
|
||||
private AgentLabel(AgentLabel labelToBeCloned)
|
||||
{
|
||||
this.Id = labelToBeCloned.Id;
|
||||
this.Name = labelToBeCloned.Name;
|
||||
this.Type = labelToBeCloned.Type;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public int Id
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public LabelType Type
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public AgentLabel Clone()
|
||||
{
|
||||
return new AgentLabel(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/Sdk/DTWebApi/WebApi/LabelType.cs
Normal file
14
src/Sdk/DTWebApi/WebApi/LabelType.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace GitHub.DistributedTask.WebApi
|
||||
{
|
||||
[DataContract]
|
||||
public enum LabelType
|
||||
{
|
||||
[EnumMember]
|
||||
System = 0,
|
||||
|
||||
[EnumMember]
|
||||
User = 1
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace GitHub.DistributedTask.WebApi
|
||||
|
||||
if (agentToBeCloned.m_labels != null && agentToBeCloned.m_labels.Count > 0)
|
||||
{
|
||||
m_labels = new HashSet<string>(agentToBeCloned.m_labels, StringComparer.OrdinalIgnoreCase);
|
||||
m_labels = new HashSet<AgentLabel>(agentToBeCloned.m_labels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,13 +118,13 @@ namespace GitHub.DistributedTask.WebApi
|
||||
/// <summary>
|
||||
/// The labels of the runner
|
||||
/// </summary>
|
||||
public ISet<string> Labels
|
||||
public ISet<AgentLabel> Labels
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_labels == null)
|
||||
{
|
||||
m_labels = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
m_labels = new HashSet<AgentLabel>();
|
||||
}
|
||||
return m_labels;
|
||||
}
|
||||
@@ -164,6 +164,6 @@ namespace GitHub.DistributedTask.WebApi
|
||||
private PropertiesCollection m_properties;
|
||||
|
||||
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Labels")]
|
||||
private HashSet<string> m_labels;
|
||||
private HashSet<AgentLabel> m_labels;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ namespace GitHub.DistributedTask.WebApi
|
||||
Int64 requestId,
|
||||
Guid lockToken,
|
||||
DateTime? expiresOn = null,
|
||||
string orchestrationId = null,
|
||||
Object userState = null,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
@@ -104,7 +105,30 @@ namespace GitHub.DistributedTask.WebApi
|
||||
LockedUntil = expiresOn,
|
||||
};
|
||||
|
||||
return UpdateAgentRequestAsync(poolId, requestId, lockToken, request, userState, cancellationToken);
|
||||
var additionalHeaders = new Dictionary<string, string>();
|
||||
if (!string.IsNullOrEmpty(orchestrationId))
|
||||
{
|
||||
additionalHeaders["X-VSS-OrchestrationId"] = orchestrationId;
|
||||
}
|
||||
|
||||
HttpMethod httpMethod = new HttpMethod("PATCH");
|
||||
Guid locationId = new Guid("fc825784-c92a-4299-9221-998a02d1b54f");
|
||||
object routeValues = new { poolId = poolId, requestId = requestId };
|
||||
HttpContent content = new ObjectContent<TaskAgentJobRequest>(request, new VssJsonMediaTypeFormatter(true));
|
||||
|
||||
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
|
||||
queryParams.Add("lockToken", lockToken.ToString());
|
||||
|
||||
return SendAsync<TaskAgentJobRequest>(
|
||||
httpMethod,
|
||||
additionalHeaders,
|
||||
locationId,
|
||||
routeValues: routeValues,
|
||||
version: new ApiResourceVersion(5.1, 1),
|
||||
queryParameters: queryParams,
|
||||
userState: userState,
|
||||
cancellationToken: cancellationToken,
|
||||
content: content);
|
||||
}
|
||||
|
||||
public Task<TaskAgent> ReplaceAgentAsync(
|
||||
@@ -171,5 +195,5 @@ namespace GitHub.DistributedTask.WebApi
|
||||
}
|
||||
|
||||
private readonly ApiResourceVersion m_currentApiVersion = new ApiResourceVersion(3.0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace GitHub.Services.WebApi.Jwt
|
||||
return ret;
|
||||
}
|
||||
|
||||
internal static IEnumerable<Claim> ExtractClaims(this JsonWebToken token)
|
||||
public static IEnumerable<Claim> ExtractClaims(this JsonWebToken token)
|
||||
{
|
||||
ArgumentUtility.CheckForNull(token, nameof(token));
|
||||
|
||||
|
||||
@@ -317,7 +317,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
false, // secret
|
||||
Environment.MachineName, // defaultValue
|
||||
Validators.NonEmptyValidator, // validator
|
||||
true)) // unattended
|
||||
true, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some runner");
|
||||
|
||||
// Act.
|
||||
@@ -344,7 +345,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
false, // secret
|
||||
Environment.MachineName, // defaultValue
|
||||
Validators.NonEmptyValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some runner");
|
||||
|
||||
// Act.
|
||||
@@ -371,7 +373,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
false, // secret
|
||||
"some default auth", // defaultValue
|
||||
Validators.AuthSchemeValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some auth");
|
||||
|
||||
// Act.
|
||||
@@ -398,7 +401,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
true, // secret
|
||||
string.Empty, // defaultValue
|
||||
Validators.NonEmptyValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some token");
|
||||
|
||||
// Act.
|
||||
@@ -475,7 +479,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
true, // secret
|
||||
string.Empty, // defaultValue
|
||||
Validators.NonEmptyValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some token");
|
||||
|
||||
// Act.
|
||||
@@ -502,7 +507,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
true, // secret
|
||||
string.Empty, // defaultValue
|
||||
Validators.NonEmptyValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some token");
|
||||
|
||||
// Act.
|
||||
@@ -529,7 +535,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
false, // secret
|
||||
string.Empty, // defaultValue
|
||||
Validators.ServerUrlValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some url");
|
||||
|
||||
// Act.
|
||||
@@ -556,7 +563,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
false, // secret
|
||||
"some default account", // defaultValue
|
||||
Validators.NTAccountValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some windows logon account");
|
||||
|
||||
// Act.
|
||||
@@ -584,7 +592,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
true, // secret
|
||||
string.Empty, // defaultValue
|
||||
Validators.NonEmptyValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some windows logon password");
|
||||
|
||||
// Act.
|
||||
@@ -611,7 +620,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
false, // secret
|
||||
"_work", // defaultValue
|
||||
Validators.NonEmptyValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some work");
|
||||
|
||||
// Act.
|
||||
@@ -640,7 +650,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
false, // secret
|
||||
string.Empty, // defaultValue
|
||||
Validators.ServerUrlValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some url");
|
||||
|
||||
// Act.
|
||||
@@ -669,7 +680,8 @@ namespace GitHub.Runner.Common.Tests
|
||||
false, // secret
|
||||
string.Empty, // defaultValue
|
||||
Validators.ServerUrlValidator, // validator
|
||||
false)) // unattended
|
||||
false, // unattended
|
||||
false)) // isOptional
|
||||
.Returns("some url");
|
||||
|
||||
// Act.
|
||||
|
||||
@@ -145,6 +145,8 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
||||
IConfigurationManager configManager = new ConfigurationManager();
|
||||
configManager.Initialize(tc);
|
||||
|
||||
var userLabels = "userlabel1,userlabel2";
|
||||
|
||||
trace.Info("Preparing command line arguments");
|
||||
var command = new CommandSettings(
|
||||
tc,
|
||||
@@ -156,7 +158,8 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
||||
"--pool", _expectedPoolName,
|
||||
"--work", _expectedWorkFolder,
|
||||
"--auth", _expectedAuthType,
|
||||
"--token", _expectedToken
|
||||
"--token", _expectedToken,
|
||||
"--labels", userLabels
|
||||
});
|
||||
trace.Info("Constructed.");
|
||||
_store.Setup(x => x.IsConfigured()).Returns(false);
|
||||
@@ -178,7 +181,10 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
||||
// validate GetAgentPoolsAsync gets called twice with automation pool type
|
||||
_runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2));
|
||||
|
||||
_runnerServer.Verify(x => x.AddAgentAsync(It.IsAny<int>(), It.Is<TaskAgent>(a => a.Labels.Contains("self-hosted") && a.Labels.Contains(VarUtil.OS) && a.Labels.Contains(VarUtil.OSArchitecture))), Times.Once);
|
||||
var expectedLabels = new List<string>() { "self-hosted", VarUtil.OS, VarUtil.OSArchitecture};
|
||||
expectedLabels.AddRange(userLabels.Split(",").ToList());
|
||||
|
||||
_runnerServer.Verify(x => x.AddAgentAsync(It.IsAny<int>(), It.Is<TaskAgent>(a => a.Labels.Select(x => x.Name).ToHashSet().SetEquals(expectedLabels))), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
Assert.NotNull(sessionIdProperty);
|
||||
sessionIdProperty.SetValue(request, DateTime.UtcNow.AddMinutes(5));
|
||||
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<TaskAgentJobRequest>(request));
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<TaskAgentJobRequest>(request));
|
||||
|
||||
_runnerServer.Setup(x => x.FinishAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<DateTime>(), It.IsAny<TaskResult>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<TaskAgentJobRequest>(new TaskAgentJobRequest()));
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
||||
_configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1 });
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() =>
|
||||
{
|
||||
count++;
|
||||
@@ -139,10 +139,10 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
var jobDispatcher = new JobDispatcher();
|
||||
jobDispatcher.Initialize(hc);
|
||||
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
|
||||
Assert.True(firstJobRequestRenewed.Task.IsCompletedSuccessfully);
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()), Times.Exactly(5));
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(5));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
||||
_configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1 });
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() =>
|
||||
{
|
||||
count++;
|
||||
@@ -197,11 +197,11 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
var jobDispatcher = new JobDispatcher();
|
||||
jobDispatcher.Initialize(hc);
|
||||
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
|
||||
Assert.True(firstJobRequestRenewed.Task.IsCompletedSuccessfully, "First renew should succeed.");
|
||||
Assert.False(cancellationTokenSource.IsCancellationRequested);
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()), Times.Exactly(5));
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(5));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
||||
_configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1 });
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() =>
|
||||
{
|
||||
count++;
|
||||
@@ -256,11 +256,11 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
var jobDispatcher = new JobDispatcher();
|
||||
jobDispatcher.Initialize(hc);
|
||||
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
|
||||
Assert.True(firstJobRequestRenewed.Task.IsCompletedSuccessfully, "First renew should succeed.");
|
||||
Assert.False(cancellationTokenSource.IsCancellationRequested);
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()), Times.Exactly(5));
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(5));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
||||
_configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1 });
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() =>
|
||||
{
|
||||
count++;
|
||||
@@ -315,11 +315,11 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
var jobDispatcher = new JobDispatcher();
|
||||
jobDispatcher.Initialize(hc);
|
||||
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
|
||||
Assert.True(firstJobRequestRenewed.Task.IsCompletedSuccessfully, "First renew should succeed.");
|
||||
Assert.True(cancellationTokenSource.IsCancellationRequested);
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()), Times.Exactly(8));
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(8));
|
||||
_runnerServer.Verify(x => x.RefreshConnectionAsync(RunnerConnectionType.JobRequest, It.IsAny<TimeSpan>()), Times.Exactly(3));
|
||||
_runnerServer.Verify(x => x.SetConnectionTimeout(RunnerConnectionType.JobRequest, It.IsAny<TimeSpan>()), Times.Once);
|
||||
}
|
||||
@@ -349,7 +349,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
||||
_configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1 });
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() =>
|
||||
{
|
||||
count++;
|
||||
@@ -372,11 +372,11 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
var jobDispatcher = new JobDispatcher();
|
||||
jobDispatcher.Initialize(hc);
|
||||
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
|
||||
Assert.False(firstJobRequestRenewed.Task.IsCompletedSuccessfully, "First renew should failed.");
|
||||
Assert.False(cancellationTokenSource.IsCancellationRequested);
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()), Times.Exactly(6));
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(6));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,7 +404,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
||||
_configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1 });
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() =>
|
||||
{
|
||||
count++;
|
||||
@@ -436,11 +436,11 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
var jobDispatcher = new JobDispatcher();
|
||||
jobDispatcher.Initialize(hc);
|
||||
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
||||
|
||||
Assert.True(firstJobRequestRenewed.Task.IsCompletedSuccessfully, "First renew should succeed.");
|
||||
Assert.False(cancellationTokenSource.IsCancellationRequested);
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()), Times.Exactly(5));
|
||||
_runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(5));
|
||||
_runnerServer.Verify(x => x.RefreshConnectionAsync(RunnerConnectionType.JobRequest, It.IsAny<TimeSpan>()), Times.Exactly(3));
|
||||
_runnerServer.Verify(x => x.SetConnectionTimeout(RunnerConnectionType.JobRequest, It.IsAny<TimeSpan>()), Times.Never);
|
||||
}
|
||||
@@ -481,7 +481,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
Assert.NotNull(sessionIdProperty);
|
||||
sessionIdProperty.SetValue(request, DateTime.UtcNow.AddMinutes(5));
|
||||
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<TaskAgentJobRequest>(request));
|
||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<TaskAgentJobRequest>(request));
|
||||
|
||||
_runnerServer.Setup(x => x.FinishAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<DateTime>(), It.IsAny<TaskResult>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<TaskAgentJobRequest>(new TaskAgentJobRequest()));
|
||||
|
||||
|
||||
@@ -660,7 +660,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
||||
_settings.AgentId))
|
||||
.Returns(async () =>
|
||||
{
|
||||
await Task.Delay(10);
|
||||
await Task.Delay(100);
|
||||
return "https://t.server";
|
||||
});
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace GitHub.Runner.Common.Tests
|
||||
}
|
||||
}
|
||||
|
||||
public ProductInfoHeaderValue UserAgent => new ProductInfoHeaderValue("L0Test", "0.0");
|
||||
public List<ProductInfoHeaderValue> UserAgents => new List<ProductInfoHeaderValue>() { new ProductInfoHeaderValue("L0Test", "0.0") };
|
||||
|
||||
public RunnerWebProxy WebProxy => new RunnerWebProxy();
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
};
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
//Assert
|
||||
Assert.Equal(actionId, (steps[0].Data as ContainerSetupInfo).StepIds[0]);
|
||||
@@ -217,7 +217,7 @@ runs:
|
||||
};
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
Assert.True(steps.Count == 0);
|
||||
}
|
||||
@@ -256,7 +256,7 @@ runs:
|
||||
var actionDir = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "TingluoHuang", "runner_L0", "repositoryactionwithdockerfile");
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
Assert.Equal(actionId, (steps[0].Data as ContainerSetupInfo).StepIds[0]);
|
||||
Assert.Equal(actionDir, (steps[0].Data as ContainerSetupInfo).Container.WorkingDirectory);
|
||||
Assert.Equal(Path.Combine(actionDir, "Dockerfile"), (steps[0].Data as ContainerSetupInfo).Container.Dockerfile);
|
||||
@@ -296,7 +296,7 @@ runs:
|
||||
var actionDir = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "TingluoHuang", "runner_L0", "repositoryactionwithdockerfileinrelativepath");
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
Assert.Equal(actionId, (steps[0].Data as ContainerSetupInfo).StepIds[0]);
|
||||
Assert.Equal(actionDir, (steps[0].Data as ContainerSetupInfo).Container.WorkingDirectory);
|
||||
@@ -335,7 +335,7 @@ runs:
|
||||
|
||||
var actionDir = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "TingluoHuang", "runner_L0", "repositoryactionwithdockerfileinrelativepath");
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
Assert.Equal(actionId, (steps[0].Data as ContainerSetupInfo).StepIds[0]);
|
||||
Assert.Equal(actionDir, (steps[0].Data as ContainerSetupInfo).Container.WorkingDirectory);
|
||||
@@ -375,7 +375,7 @@ runs:
|
||||
var actionDir = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "TingluoHuang", "runner_L0", "RepositoryActionWithActionfile_DockerfileRelativePath");
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
Assert.Equal(actionId, (steps[0].Data as ContainerSetupInfo).StepIds[0]);
|
||||
Assert.Equal(actionDir, (steps[0].Data as ContainerSetupInfo).Container.WorkingDirectory);
|
||||
@@ -415,7 +415,7 @@ runs:
|
||||
var actionDir = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "TingluoHuang", "runner_L0", "RepositoryActionWithActionfile_DockerHubImage");
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
Assert.Equal(actionId, (steps[0].Data as ContainerSetupInfo).StepIds[0]);
|
||||
Assert.Equal("ubuntu:18.04", (steps[0].Data as ContainerSetupInfo).Container.Image);
|
||||
@@ -454,7 +454,7 @@ runs:
|
||||
var actionDir = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "TingluoHuang", "runner_L0", "RepositoryActionWithActionYamlFile_DockerHubImage");
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
Assert.Equal((steps[0].Data as ContainerSetupInfo).StepIds[0], actionId);
|
||||
Assert.Equal("ubuntu:18.04", (steps[0].Data as ContainerSetupInfo).Container.Image);
|
||||
@@ -493,7 +493,7 @@ runs:
|
||||
var actionDir = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "TingluoHuang", "runner_L0", "repositoryactionwithactionfileanddockerfile");
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
Assert.Equal(actionId, (steps[0].Data as ContainerSetupInfo).StepIds[0]);
|
||||
Assert.Equal(actionDir, (steps[0].Data as ContainerSetupInfo).Container.WorkingDirectory);
|
||||
@@ -610,7 +610,7 @@ runs:
|
||||
};
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
//Assert
|
||||
Assert.Equal(actionId1, (steps[0].Data as ContainerSetupInfo).StepIds[0]);
|
||||
@@ -671,7 +671,7 @@ runs:
|
||||
};
|
||||
|
||||
//Act
|
||||
var steps = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
var steps = (await _actionManager.PrepareActionsAsync(_ec.Object, actions)).ContainerSetupSteps;
|
||||
|
||||
// node.js based action doesn't need any extra steps to build/pull containers.
|
||||
Assert.True(steps.Count == 0);
|
||||
@@ -682,6 +682,104 @@ runs:
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public async void PrepareActions_RepositoryActionWithInvalidWrapperActionfile_Node()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Arrange
|
||||
Setup();
|
||||
var actionId = Guid.NewGuid();
|
||||
var actions = new List<Pipelines.ActionStep>
|
||||
{
|
||||
new Pipelines.ActionStep()
|
||||
{
|
||||
Name = "action",
|
||||
Id = actionId,
|
||||
Reference = new Pipelines.RepositoryPathReference()
|
||||
{
|
||||
Name = "TingluoHuang/runner_L0",
|
||||
Ref = "RepositoryActionWithInvalidWrapperActionfile_Node",
|
||||
RepositoryType = "GitHub"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Act
|
||||
try
|
||||
{
|
||||
await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
var traceFile = Path.GetTempFileName();
|
||||
File.Copy(_hc.TraceFileName, traceFile, true);
|
||||
Assert.Contains("Entry javascript file is not provided.", File.ReadAllText(traceFile));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public async void PrepareActions_RepositoryActionWithWrapperActionfile_PreSteps()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Arrange
|
||||
Setup();
|
||||
|
||||
_hc.EnqueueInstance<IActionRunner>(new Mock<IActionRunner>().Object);
|
||||
_hc.EnqueueInstance<IActionRunner>(new Mock<IActionRunner>().Object);
|
||||
|
||||
var actionId1 = Guid.NewGuid();
|
||||
var actionId2 = Guid.NewGuid();
|
||||
_hc.GetTrace().Info(actionId1);
|
||||
_hc.GetTrace().Info(actionId2);
|
||||
var actions = new List<Pipelines.ActionStep>
|
||||
{
|
||||
new Pipelines.ActionStep()
|
||||
{
|
||||
Name = "action1",
|
||||
Id = actionId1,
|
||||
Reference = new Pipelines.RepositoryPathReference()
|
||||
{
|
||||
Name = "TingluoHuang/runner_L0",
|
||||
Ref = "RepositoryActionWithWrapperActionfile_Node",
|
||||
RepositoryType = "GitHub"
|
||||
}
|
||||
},
|
||||
new Pipelines.ActionStep()
|
||||
{
|
||||
Name = "action2",
|
||||
Id = actionId2,
|
||||
Reference = new Pipelines.RepositoryPathReference()
|
||||
{
|
||||
Name = "TingluoHuang/runner_L0",
|
||||
Ref = "RepositoryActionWithWrapperActionfile_Docker",
|
||||
RepositoryType = "GitHub"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Act
|
||||
var preResult = await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||
Assert.Equal(2, preResult.PreStepTracker.Count);
|
||||
Assert.NotNull(preResult.PreStepTracker[actionId1]);
|
||||
Assert.NotNull(preResult.PreStepTracker[actionId2]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
@@ -1426,7 +1524,7 @@ runs:
|
||||
|
||||
Assert.NotNull((definition.Data.Execution as NodeJSActionExecutionData));
|
||||
Assert.Equal("task.js", (definition.Data.Execution as NodeJSActionExecutionData).Script);
|
||||
Assert.Equal("cleanup.js", (definition.Data.Execution as NodeJSActionExecutionData).Cleanup);
|
||||
Assert.Equal("cleanup.js", (definition.Data.Execution as NodeJSActionExecutionData).Post);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -1506,7 +1604,7 @@ runs:
|
||||
Assert.NotNull((definition.Data.Execution as ContainerActionExecutionData)); // execution.Node
|
||||
Assert.Equal("image:1234", (definition.Data.Execution as ContainerActionExecutionData).Image);
|
||||
Assert.Equal("main.sh", (definition.Data.Execution as ContainerActionExecutionData).EntryPoint);
|
||||
Assert.Equal("cleanup.sh", (definition.Data.Execution as ContainerActionExecutionData).Cleanup);
|
||||
Assert.Equal("cleanup.sh", (definition.Data.Execution as ContainerActionExecutionData).Post);
|
||||
|
||||
foreach (var arg in (definition.Data.Execution as ContainerActionExecutionData).Arguments)
|
||||
{
|
||||
@@ -1595,7 +1693,7 @@ runs:
|
||||
|
||||
Assert.NotNull((definition.Data.Execution as PluginActionExecutionData));
|
||||
Assert.Equal("plugin.class, plugin", (definition.Data.Execution as PluginActionExecutionData).Plugin);
|
||||
Assert.Equal("plugin.cleanup, plugin", (definition.Data.Execution as PluginActionExecutionData).Cleanup);
|
||||
Assert.Equal("plugin.cleanup, plugin", (definition.Data.Execution as PluginActionExecutionData).Post);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -65,6 +65,52 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public void Load_ContainerAction_Dockerfile_Pre()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Arrange
|
||||
Setup();
|
||||
|
||||
var actionManifest = new ActionManifestManager();
|
||||
actionManifest.Initialize(_hc);
|
||||
|
||||
//Act
|
||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerfileaction_init.yml"));
|
||||
|
||||
//Assert
|
||||
|
||||
Assert.Equal("Hello World", result.Name);
|
||||
Assert.Equal("Greet the world and record the time", result.Description);
|
||||
Assert.Equal(2, result.Inputs.Count);
|
||||
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||
|
||||
Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
|
||||
|
||||
var containerAction = result.Execution as ContainerActionExecutionData;
|
||||
|
||||
Assert.Equal("Dockerfile", containerAction.Image);
|
||||
Assert.Equal("main.sh", containerAction.EntryPoint);
|
||||
Assert.Equal("init.sh", containerAction.Pre);
|
||||
Assert.Equal("success()", containerAction.InitCondition);
|
||||
Assert.Equal("bzz", containerAction.Arguments[0].ToString());
|
||||
Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
|
||||
Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
|
||||
Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
|
||||
Assert.Equal("bar", containerAction.Environment[1].Value.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
@@ -97,7 +143,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
|
||||
Assert.Equal("Dockerfile", containerAction.Image);
|
||||
Assert.Equal("main.sh", containerAction.EntryPoint);
|
||||
Assert.Equal("cleanup.sh", containerAction.Cleanup);
|
||||
Assert.Equal("cleanup.sh", containerAction.Post);
|
||||
Assert.Equal("failure()", containerAction.CleanupCondition);
|
||||
Assert.Equal("bzz", containerAction.Arguments[0].ToString());
|
||||
Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
|
||||
@@ -111,6 +157,52 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public void Load_ContainerAction_Dockerfile_Pre_DefaultCondition()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Arrange
|
||||
Setup();
|
||||
|
||||
var actionManifest = new ActionManifestManager();
|
||||
actionManifest.Initialize(_hc);
|
||||
|
||||
//Act
|
||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerfileaction_init_default.yml"));
|
||||
|
||||
//Assert
|
||||
|
||||
Assert.Equal("Hello World", result.Name);
|
||||
Assert.Equal("Greet the world and record the time", result.Description);
|
||||
Assert.Equal(2, result.Inputs.Count);
|
||||
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||
|
||||
Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
|
||||
|
||||
var containerAction = result.Execution as ContainerActionExecutionData;
|
||||
|
||||
Assert.Equal("Dockerfile", containerAction.Image);
|
||||
Assert.Equal("main.sh", containerAction.EntryPoint);
|
||||
Assert.Equal("init.sh", containerAction.Pre);
|
||||
Assert.Equal("always()", containerAction.InitCondition);
|
||||
Assert.Equal("bzz", containerAction.Arguments[0].ToString());
|
||||
Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
|
||||
Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
|
||||
Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
|
||||
Assert.Equal("bar", containerAction.Environment[1].Value.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
@@ -143,7 +235,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
|
||||
Assert.Equal("Dockerfile", containerAction.Image);
|
||||
Assert.Equal("main.sh", containerAction.EntryPoint);
|
||||
Assert.Equal("cleanup.sh", containerAction.Cleanup);
|
||||
Assert.Equal("cleanup.sh", containerAction.Post);
|
||||
Assert.Equal("always()", containerAction.CleanupCondition);
|
||||
Assert.Equal("bzz", containerAction.Arguments[0].ToString());
|
||||
Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
|
||||
@@ -323,6 +415,94 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public void Load_NodeAction_Pre()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Arrange
|
||||
Setup();
|
||||
|
||||
var actionManifest = new ActionManifestManager();
|
||||
actionManifest.Initialize(_hc);
|
||||
|
||||
//Act
|
||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction_init.yml"));
|
||||
|
||||
//Assert
|
||||
Assert.Equal("Hello World", result.Name);
|
||||
Assert.Equal("Greet the world and record the time", result.Description);
|
||||
Assert.Equal(2, result.Inputs.Count);
|
||||
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||
Assert.Equal(1, result.Deprecated.Count);
|
||||
|
||||
Assert.True(result.Deprecated.ContainsKey("greeting"));
|
||||
result.Deprecated.TryGetValue("greeting", out string value);
|
||||
Assert.Equal("This property has been deprecated", value);
|
||||
|
||||
Assert.Equal(ActionExecutionType.NodeJS, result.Execution.ExecutionType);
|
||||
|
||||
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
||||
|
||||
Assert.Equal("main.js", nodeAction.Script);
|
||||
Assert.Equal("init.js", nodeAction.Pre);
|
||||
Assert.Equal("cancelled()", nodeAction.InitCondition);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public void Load_NodeAction_Init_DefaultCondition()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Arrange
|
||||
Setup();
|
||||
|
||||
var actionManifest = new ActionManifestManager();
|
||||
actionManifest.Initialize(_hc);
|
||||
|
||||
//Act
|
||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction_init_default.yml"));
|
||||
|
||||
//Assert
|
||||
Assert.Equal("Hello World", result.Name);
|
||||
Assert.Equal("Greet the world and record the time", result.Description);
|
||||
Assert.Equal(2, result.Inputs.Count);
|
||||
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||
Assert.Equal(1, result.Deprecated.Count);
|
||||
|
||||
Assert.True(result.Deprecated.ContainsKey("greeting"));
|
||||
result.Deprecated.TryGetValue("greeting", out string value);
|
||||
Assert.Equal("This property has been deprecated", value);
|
||||
|
||||
Assert.Equal(ActionExecutionType.NodeJS, result.Execution.ExecutionType);
|
||||
|
||||
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
||||
|
||||
Assert.Equal("main.js", nodeAction.Script);
|
||||
Assert.Equal("init.js", nodeAction.Pre);
|
||||
Assert.Equal("always()", nodeAction.InitCondition);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
@@ -358,7 +538,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
||||
|
||||
Assert.Equal("main.js", nodeAction.Script);
|
||||
Assert.Equal("cleanup.js", nodeAction.Cleanup);
|
||||
Assert.Equal("cleanup.js", nodeAction.Post);
|
||||
Assert.Equal("cancelled()", nodeAction.CleanupCondition);
|
||||
}
|
||||
finally
|
||||
@@ -402,7 +582,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
||||
|
||||
Assert.Equal("main.js", nodeAction.Script);
|
||||
Assert.Equal("cleanup.js", nodeAction.Cleanup);
|
||||
Assert.Equal("cleanup.js", nodeAction.Post);
|
||||
Assert.Equal("always()", nodeAction.CleanupCondition);
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -199,20 +199,20 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
|
||||
|
||||
var postRunner1 = hc.CreateService<IActionRunner>();
|
||||
postRunner1.Action = new Pipelines.ActionStep() { Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
|
||||
postRunner1.Action = new Pipelines.ActionStep() { Id = Guid.NewGuid(), Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
|
||||
postRunner1.Stage = ActionRunStage.Post;
|
||||
postRunner1.Condition = "always()";
|
||||
postRunner1.DisplayName = "post1";
|
||||
|
||||
|
||||
var postRunner2 = hc.CreateService<IActionRunner>();
|
||||
postRunner2.Action = new Pipelines.ActionStep() { Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
|
||||
postRunner2.Action = new Pipelines.ActionStep() { Id = Guid.NewGuid(), Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
|
||||
postRunner2.Stage = ActionRunStage.Post;
|
||||
postRunner2.Condition = "always()";
|
||||
postRunner2.DisplayName = "post2";
|
||||
|
||||
action1.RegisterPostJobStep("post1", postRunner1);
|
||||
action2.RegisterPostJobStep("post2", postRunner2);
|
||||
action1.RegisterPostJobStep(postRunner1);
|
||||
action2.RegisterPostJobStep(postRunner2);
|
||||
|
||||
Assert.NotNull(jobContext.JobSteps);
|
||||
Assert.NotNull(jobContext.PostJobSteps);
|
||||
@@ -238,6 +238,91 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public void RegisterPostJobAction_NotRegisterPostTwice()
|
||||
{
|
||||
using (TestHostContext hc = CreateTestContext())
|
||||
{
|
||||
// Arrange: Create a job request message.
|
||||
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
||||
TimelineReference timeline = new TimelineReference();
|
||||
Guid jobId = Guid.NewGuid();
|
||||
string jobName = "some job name";
|
||||
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null, null);
|
||||
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
||||
{
|
||||
Alias = Pipelines.PipelineConstants.SelfAlias,
|
||||
Id = "github",
|
||||
Version = "sha1"
|
||||
});
|
||||
jobRequest.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();
|
||||
jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true";
|
||||
|
||||
// Arrange: Setup the paging logger.
|
||||
var pagingLogger1 = new Mock<IPagingLogger>();
|
||||
var pagingLogger2 = new Mock<IPagingLogger>();
|
||||
var pagingLogger3 = new Mock<IPagingLogger>();
|
||||
var pagingLogger4 = new Mock<IPagingLogger>();
|
||||
var pagingLogger5 = new Mock<IPagingLogger>();
|
||||
var jobServerQueue = new Mock<IJobServerQueue>();
|
||||
jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny<Guid>(), It.IsAny<TimelineRecord>()));
|
||||
jobServerQueue.Setup(x => x.QueueWebConsoleLine(It.IsAny<Guid>(), It.IsAny<string>())).Callback((Guid id, string msg) => { hc.GetTrace().Info(msg); });
|
||||
|
||||
var actionRunner1 = new ActionRunner();
|
||||
actionRunner1.Initialize(hc);
|
||||
var actionRunner2 = new ActionRunner();
|
||||
actionRunner2.Initialize(hc);
|
||||
|
||||
hc.EnqueueInstance(pagingLogger1.Object);
|
||||
hc.EnqueueInstance(pagingLogger2.Object);
|
||||
hc.EnqueueInstance(pagingLogger3.Object);
|
||||
hc.EnqueueInstance(pagingLogger4.Object);
|
||||
hc.EnqueueInstance(pagingLogger5.Object);
|
||||
hc.EnqueueInstance(actionRunner1 as IActionRunner);
|
||||
hc.EnqueueInstance(actionRunner2 as IActionRunner);
|
||||
hc.SetSingleton(jobServerQueue.Object);
|
||||
|
||||
var jobContext = new Runner.Worker.ExecutionContext();
|
||||
jobContext.Initialize(hc);
|
||||
|
||||
// Act.
|
||||
jobContext.InitializeJob(jobRequest, CancellationToken.None);
|
||||
|
||||
var action1 = jobContext.CreateChild(Guid.NewGuid(), "action_1_pre", "action_1_pre", null, null);
|
||||
var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_1_main", "action_1_main", null, null);
|
||||
|
||||
var actionId = Guid.NewGuid();
|
||||
var postRunner1 = hc.CreateService<IActionRunner>();
|
||||
postRunner1.Action = new Pipelines.ActionStep() { Id = actionId, Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
|
||||
postRunner1.Stage = ActionRunStage.Post;
|
||||
postRunner1.Condition = "always()";
|
||||
postRunner1.DisplayName = "post1";
|
||||
|
||||
|
||||
var postRunner2 = hc.CreateService<IActionRunner>();
|
||||
postRunner2.Action = new Pipelines.ActionStep() { Id = actionId, Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
|
||||
postRunner2.Stage = ActionRunStage.Post;
|
||||
postRunner2.Condition = "always()";
|
||||
postRunner2.DisplayName = "post2";
|
||||
|
||||
action1.RegisterPostJobStep(postRunner1);
|
||||
action2.RegisterPostJobStep(postRunner2);
|
||||
|
||||
Assert.NotNull(jobContext.JobSteps);
|
||||
Assert.NotNull(jobContext.PostJobSteps);
|
||||
Assert.Equal(1, jobContext.PostJobSteps.Count);
|
||||
var post1 = jobContext.PostJobSteps.Pop();
|
||||
|
||||
Assert.Equal("post1", (post1 as IActionRunner).Action.Name);
|
||||
|
||||
Assert.Equal(ActionRunStage.Post, (post1 as IActionRunner).Stage);
|
||||
|
||||
Assert.Equal("always()", (post1 as IActionRunner).Condition);
|
||||
}
|
||||
}
|
||||
|
||||
private TestHostContext CreateTestContext([CallerMemberName] String testName = "")
|
||||
{
|
||||
var hc = new TestHostContext(this, testName);
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
jobExtension.Initialize(hc);
|
||||
|
||||
_actionManager.Setup(x => x.PrepareActionsAsync(It.IsAny<IExecutionContext>(), It.IsAny<IEnumerable<Pipelines.JobStep>>()))
|
||||
.Returns(Task.FromResult(new List<JobExtensionRunner>()));
|
||||
.Returns(Task.FromResult(new PrepareResult(new List<JobExtensionRunner>(), new Dictionary<Guid, IActionRunner>())));
|
||||
|
||||
List<IStep> result = await jobExtension.InitializeJob(_jobEc, _message);
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
jobExtension.Initialize(hc);
|
||||
|
||||
_actionManager.Setup(x => x.PrepareActionsAsync(It.IsAny<IExecutionContext>(), It.IsAny<IEnumerable<Pipelines.JobStep>>()))
|
||||
.Returns(Task.FromResult(new List<JobExtensionRunner>() { new JobExtensionRunner(null, "", "prepare1", null), new JobExtensionRunner(null, "", "prepare2", null) }));
|
||||
.Returns(Task.FromResult(new PrepareResult(new List<JobExtensionRunner>() { new JobExtensionRunner(null, "", "prepare1", null), new JobExtensionRunner(null, "", "prepare2", null) }, new Dictionary<Guid, IActionRunner>())));
|
||||
|
||||
List<IStep> result = await jobExtension.InitializeJob(_jobEc, _message);
|
||||
|
||||
|
||||
27
src/Test/TestData/dockerfileaction_init.yml
Normal file
27
src/Test/TestData/dockerfileaction_init.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
name: 'Hello World'
|
||||
description: 'Greet the world and record the time'
|
||||
author: 'Test Corporation'
|
||||
inputs:
|
||||
greeting: # id of input
|
||||
description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout'
|
||||
required: true
|
||||
default: 'Hello'
|
||||
entryPoint: # id of input
|
||||
description: 'optional docker entrypoint overwrite.'
|
||||
required: false
|
||||
outputs:
|
||||
time: # id of output
|
||||
description: 'The time we did the greeting'
|
||||
icon: 'hello.svg' # vector art to display in the GitHub Marketplace
|
||||
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
args:
|
||||
- 'bzz'
|
||||
entrypoint: 'main.sh'
|
||||
env:
|
||||
Token: foo
|
||||
Url: bar
|
||||
pre-entrypoint: 'init.sh'
|
||||
pre-if: 'success()'
|
||||
26
src/Test/TestData/dockerfileaction_init_default.yml
Normal file
26
src/Test/TestData/dockerfileaction_init_default.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
name: 'Hello World'
|
||||
description: 'Greet the world and record the time'
|
||||
author: 'Test Corporation'
|
||||
inputs:
|
||||
greeting: # id of input
|
||||
description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout'
|
||||
required: true
|
||||
default: 'Hello'
|
||||
entryPoint: # id of input
|
||||
description: 'optional docker entrypoint overwrite.'
|
||||
required: false
|
||||
outputs:
|
||||
time: # id of output
|
||||
description: 'The time we did the greeting'
|
||||
icon: 'hello.svg' # vector art to display in the GitHub Marketplace
|
||||
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
args:
|
||||
- 'bzz'
|
||||
entrypoint: 'main.sh'
|
||||
env:
|
||||
Token: foo
|
||||
Url: bar
|
||||
pre-entrypoint: 'init.sh'
|
||||
22
src/Test/TestData/nodeaction_init.yml
Normal file
22
src/Test/TestData/nodeaction_init.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
name: 'Hello World'
|
||||
description: 'Greet the world and record the time'
|
||||
author: 'Test Corporation'
|
||||
inputs:
|
||||
greeting: # id of input
|
||||
description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout'
|
||||
required: true
|
||||
default: 'Hello'
|
||||
deprecationMessage: 'This property has been deprecated'
|
||||
entryPoint: # id of input
|
||||
description: 'optional docker entrypoint overwrite.'
|
||||
required: false
|
||||
outputs:
|
||||
time: # id of output
|
||||
description: 'The time we did the greeting'
|
||||
icon: 'hello.svg' # vector art to display in the GitHub Marketplace
|
||||
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'main.js'
|
||||
pre: 'init.js'
|
||||
pre-if: 'cancelled()'
|
||||
21
src/Test/TestData/nodeaction_init_default.yml
Normal file
21
src/Test/TestData/nodeaction_init_default.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
name: 'Hello World'
|
||||
description: 'Greet the world and record the time'
|
||||
author: 'Test Corporation'
|
||||
inputs:
|
||||
greeting: # id of input
|
||||
description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout'
|
||||
required: true
|
||||
default: 'Hello'
|
||||
deprecationMessage: 'This property has been deprecated'
|
||||
entryPoint: # id of input
|
||||
description: 'optional docker entrypoint overwrite.'
|
||||
required: false
|
||||
outputs:
|
||||
time: # id of output
|
||||
description: 'The time we did the greeting'
|
||||
icon: 'hello.svg' # vector art to display in the GitHub Marketplace
|
||||
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'main.js'
|
||||
pre: 'init.js'
|
||||
@@ -1 +1 @@
|
||||
2.169.0
|
||||
2.169.1
|
||||
|
||||
Reference in New Issue
Block a user