mirror of
https://github.com/actions/runner.git
synced 2025-12-12 05:37:01 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1413297394 | ||
|
|
6a063ae7be | ||
|
|
76bb4961fb | ||
|
|
bf3d32e631 | ||
|
|
11aa006d30 | ||
|
|
586c8a7fa5 |
@@ -1,12 +1,12 @@
|
|||||||
## Features
|
## Features
|
||||||
- Set Default shell to powershell for windows runners (#135)
|
- N/A
|
||||||
- Use Powershell as fallback if Powershell Core is not available for default shell on windows (#142)
|
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- Removed unintended additional fields on error and warning commands (#137)
|
- Reverted removal of additional fields error and warning fields (#147)
|
||||||
|
- Actions cache would incorrectly cache the action if the tag was updated (#148)
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
- N/A
|
- Updated to .NET Core 3.0 (#127)
|
||||||
|
|
||||||
## Agent Downloads
|
## Agent Downloads
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ namespace GitHub.Runner.Common
|
|||||||
Add<T>(extensions, "GitHub.Runner.Worker.DebugCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.DebugCommandExtension, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.GroupCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.GroupCommandExtension, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.EndGroupCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.EndGroupCommandExtension, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.EchoCommandExtension, Runner.Worker");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
|
|||||||
@@ -236,15 +236,15 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
// try upload all files for the first time.
|
// try upload all files for the first time.
|
||||||
UploadResult uploadResult = await ParallelUploadAsync(context, files, maxConcurrentUploads, _uploadCancellationTokenSource.Token);
|
UploadResult uploadResult = await ParallelUploadAsync(context, files, maxConcurrentUploads, _uploadCancellationTokenSource.Token);
|
||||||
|
|
||||||
if (uploadResult.RetryFiles.Count == 0)
|
if (uploadResult.FailedFiles.Count == 0)
|
||||||
{
|
{
|
||||||
// all files have been upload succeed.
|
// all files have been upload succeed.
|
||||||
context.Output("File upload complete.");
|
context.Output("File upload succeed.");
|
||||||
return uploadResult.TotalFileSizeUploaded;
|
return uploadResult.TotalFileSizeUploaded;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Output($"{uploadResult.RetryFiles.Count} files failed to upload, retry these files after a minute.");
|
context.Output($"{uploadResult.FailedFiles.Count} files failed to upload, retry these files after a minute.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay 1 min then retry failed files.
|
// Delay 1 min then retry failed files.
|
||||||
@@ -255,13 +255,13 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retry upload all failed files.
|
// Retry upload all failed files.
|
||||||
context.Output($"Start retry {uploadResult.RetryFiles.Count} failed files upload.");
|
context.Output($"Start retry {uploadResult.FailedFiles.Count} failed files upload.");
|
||||||
UploadResult retryUploadResult = await ParallelUploadAsync(context, uploadResult.RetryFiles, maxConcurrentUploads, _uploadCancellationTokenSource.Token);
|
UploadResult retryUploadResult = await ParallelUploadAsync(context, uploadResult.FailedFiles, maxConcurrentUploads, _uploadCancellationTokenSource.Token);
|
||||||
|
|
||||||
if (retryUploadResult.RetryFiles.Count == 0)
|
if (retryUploadResult.FailedFiles.Count == 0)
|
||||||
{
|
{
|
||||||
// all files have been upload succeed after retry.
|
// all files have been upload succeed after retry.
|
||||||
context.Output("File upload complete after retry.");
|
context.Output("File upload succeed after retry.");
|
||||||
return uploadResult.TotalFileSizeUploaded + retryUploadResult.TotalFileSizeUploaded;
|
return uploadResult.TotalFileSizeUploaded + retryUploadResult.TotalFileSizeUploaded;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -465,61 +465,75 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
using (FileStream fs = File.Open(fileToUpload, FileMode.Open, FileAccess.Read, FileShare.Read))
|
using (FileStream fs = File.Open(fileToUpload, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||||
{
|
{
|
||||||
string itemPath = (_containerPath.TrimEnd('/') + "/" + fileToUpload.Remove(0, _sourceParentDirectory.Length + 1)).Replace('\\', '/');
|
string itemPath = (_containerPath.TrimEnd('/') + "/" + fileToUpload.Remove(0, _sourceParentDirectory.Length + 1)).Replace('\\', '/');
|
||||||
bool failAndExit = false;
|
uploadTimer.Restart();
|
||||||
|
bool catchExceptionDuringUpload = false;
|
||||||
|
HttpResponseMessage response = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uploadTimer.Restart();
|
response = await _fileContainerHttpClient.UploadFileAsync(_containerId, itemPath, fs, _projectId, cancellationToken: token, chunkSize: 4 * 1024 * 1024);
|
||||||
using (HttpResponseMessage response = await _fileContainerHttpClient.UploadFileAsync(_containerId, itemPath, fs, _projectId, cancellationToken: token, chunkSize: 4 * 1024 * 1024))
|
|
||||||
{
|
|
||||||
if (response == null || response.StatusCode != HttpStatusCode.Created)
|
|
||||||
{
|
|
||||||
context.Output($"Unable to copy file to server StatusCode={response?.StatusCode}: {response?.ReasonPhrase}. Source file path: {fileToUpload}. Target server path: {itemPath}");
|
|
||||||
|
|
||||||
if (response?.StatusCode == HttpStatusCode.Conflict)
|
|
||||||
{
|
|
||||||
// fail upload task but continue with any other files
|
|
||||||
context.Error($"Error '{fileToUpload}' has already been uploaded.");
|
|
||||||
}
|
|
||||||
else if (_fileContainerHttpClient.IsFastFailResponse(response))
|
|
||||||
{
|
|
||||||
// Fast fail: we received an http status code where we should abandon our efforts
|
|
||||||
context.Output($"Cannot continue uploading files, so draining upload queue of {_fileUploadQueue.Count} items.");
|
|
||||||
DrainUploadQueue(context);
|
|
||||||
failedFiles.Clear();
|
|
||||||
failAndExit = true;
|
|
||||||
throw new UploadFailedException($"Critical failure uploading '{fileToUpload}'");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.Debug($"Adding '{fileToUpload}' to retry list.");
|
|
||||||
failedFiles.Add(fileToUpload);
|
|
||||||
}
|
|
||||||
throw new UploadFailedException($"Http failure response '{response?.StatusCode}': '{response?.ReasonPhrase}' while uploading '{fileToUpload}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadTimer.Stop();
|
|
||||||
context.Debug($"File: '{fileToUpload}' took {uploadTimer.ElapsedMilliseconds} milliseconds to finish upload");
|
|
||||||
uploadedSize += fs.Length;
|
|
||||||
OutputLogForFile(context, fileToUpload, $"Detail upload trace for file: {itemPath}", context.Debug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
context.Output($"File upload has been cancelled during upload file: '{fileToUpload}'.");
|
context.Output($"File upload has been cancelled during upload file: '{fileToUpload}'.");
|
||||||
|
if (response != null)
|
||||||
|
{
|
||||||
|
response.Dispose();
|
||||||
|
response = null;
|
||||||
|
}
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
catchExceptionDuringUpload = true;
|
||||||
context.Output($"Fail to upload '{fileToUpload}' due to '{ex.Message}'.");
|
context.Output($"Fail to upload '{fileToUpload}' due to '{ex.Message}'.");
|
||||||
context.Output(ex.ToString());
|
context.Output(ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
OutputLogForFile(context, fileToUpload, $"Detail upload trace for file that fail to upload: {itemPath}", context.Output);
|
uploadTimer.Stop();
|
||||||
|
if (catchExceptionDuringUpload || (response != null && response.StatusCode != HttpStatusCode.Created))
|
||||||
if (failAndExit)
|
{
|
||||||
|
if (response != null)
|
||||||
{
|
{
|
||||||
context.Debug("Exiting upload.");
|
context.Output($"Unable to copy file to server StatusCode={response.StatusCode}: {response.ReasonPhrase}. Source file path: {fileToUpload}. Target server path: {itemPath}");
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// output detail upload trace for the file.
|
||||||
|
ConcurrentQueue<string> logQueue;
|
||||||
|
if (_fileUploadTraceLog.TryGetValue(itemPath, out logQueue))
|
||||||
|
{
|
||||||
|
context.Output($"Detail upload trace for file that fail to upload: {itemPath}");
|
||||||
|
string message;
|
||||||
|
while (logQueue.TryDequeue(out message))
|
||||||
|
{
|
||||||
|
context.Output(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tracking file that failed to upload.
|
||||||
|
failedFiles.Add(fileToUpload);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Debug($"File: '{fileToUpload}' took {uploadTimer.ElapsedMilliseconds} milliseconds to finish upload");
|
||||||
|
uploadedSize += fs.Length;
|
||||||
|
// debug detail upload trace for the file.
|
||||||
|
ConcurrentQueue<string> logQueue;
|
||||||
|
if (_fileUploadTraceLog.TryGetValue(itemPath, out logQueue))
|
||||||
|
{
|
||||||
|
context.Debug($"Detail upload trace for file: {itemPath}");
|
||||||
|
string message;
|
||||||
|
while (logQueue.TryDequeue(out message))
|
||||||
|
{
|
||||||
|
context.Debug(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response != null)
|
||||||
|
{
|
||||||
|
response.Dispose();
|
||||||
|
response = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,30 +590,6 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrainUploadQueue(RunnerActionPluginExecutionContext context)
|
|
||||||
{
|
|
||||||
while (_fileUploadQueue.TryDequeue(out string fileToUpload))
|
|
||||||
{
|
|
||||||
context.Debug($"Clearing upload queue: '{fileToUpload}'");
|
|
||||||
Interlocked.Increment(ref _uploadFilesProcessed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OutputLogForFile(RunnerActionPluginExecutionContext context, string itemPath, string logDescription, Action<string> log)
|
|
||||||
{
|
|
||||||
// output detail upload trace for the file.
|
|
||||||
ConcurrentQueue<string> logQueue;
|
|
||||||
if (_fileUploadTraceLog.TryGetValue(itemPath, out logQueue))
|
|
||||||
{
|
|
||||||
log(logDescription);
|
|
||||||
string message;
|
|
||||||
while (logQueue.TryDequeue(out message))
|
|
||||||
{
|
|
||||||
log(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UploadFileTraceReportReceived(object sender, ReportTraceEventArgs e)
|
private void UploadFileTraceReportReceived(object sender, ReportTraceEventArgs e)
|
||||||
{
|
{
|
||||||
ConcurrentQueue<string> logQueue = _fileUploadTraceLog.GetOrAdd(e.File, new ConcurrentQueue<string>());
|
ConcurrentQueue<string> logQueue = _fileUploadTraceLog.GetOrAdd(e.File, new ConcurrentQueue<string>());
|
||||||
@@ -617,22 +607,22 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
{
|
{
|
||||||
public UploadResult()
|
public UploadResult()
|
||||||
{
|
{
|
||||||
RetryFiles = new List<string>();
|
FailedFiles = new List<string>();
|
||||||
TotalFileSizeUploaded = 0;
|
TotalFileSizeUploaded = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UploadResult(List<string> retryFiles, long totalFileSizeUploaded)
|
public UploadResult(List<string> failedFiles, long totalFileSizeUploaded)
|
||||||
{
|
{
|
||||||
RetryFiles = retryFiles ?? new List<string>();
|
FailedFiles = failedFiles;
|
||||||
TotalFileSizeUploaded = totalFileSizeUploaded;
|
TotalFileSizeUploaded = totalFileSizeUploaded;
|
||||||
}
|
}
|
||||||
public List<string> RetryFiles { get; set; }
|
public List<string> FailedFiles { get; set; }
|
||||||
|
|
||||||
public long TotalFileSizeUploaded { get; set; }
|
public long TotalFileSizeUploaded { get; set; }
|
||||||
|
|
||||||
public void AddUploadResult(UploadResult resultToAdd)
|
public void AddUploadResult(UploadResult resultToAdd)
|
||||||
{
|
{
|
||||||
this.RetryFiles.AddRange(resultToAdd.RetryFiles);
|
this.FailedFiles.AddRange(resultToAdd.FailedFiles);
|
||||||
this.TotalFileSizeUploaded += resultToAdd.TotalFileSizeUploaded;
|
this.TotalFileSizeUploaded += resultToAdd.TotalFileSizeUploaded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -667,19 +657,4 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
this.FailedFiles.AddRange(resultToAdd.FailedFiles);
|
this.FailedFiles.AddRange(resultToAdd.FailedFiles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UploadFailedException : Exception
|
|
||||||
{
|
|
||||||
public UploadFailedException()
|
|
||||||
: base()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public UploadFailedException(string message)
|
|
||||||
: base(message)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public UploadFailedException(string message, Exception inner)
|
|
||||||
: base(message, inner)
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -74,22 +74,17 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
context.Output($"Uploading artifact '{artifactName}' from '{fullPath}' for run #{buildId}");
|
context.Output($"Uploading artifact '{artifactName}' from '{fullPath}' for run #{buildId}");
|
||||||
|
|
||||||
FileContainerServer fileContainerHelper = new FileContainerServer(context.VssConnection, projectId, containerId, artifactName);
|
FileContainerServer fileContainerHelper = new FileContainerServer(context.VssConnection, projectId, containerId, artifactName);
|
||||||
|
long size = await fileContainerHelper.CopyToContainerAsync(context, fullPath, token);
|
||||||
var propertiesDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
var propertiesDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
try
|
propertiesDictionary.Add("artifactsize", size.ToString());
|
||||||
{
|
|
||||||
long size = await fileContainerHelper.CopyToContainerAsync(context, fullPath, token);
|
string fileContainerFullPath = StringUtil.Format($"#/{containerId}/{artifactName}");
|
||||||
propertiesDictionary.Add("artifactsize", size.ToString());
|
context.Output($"Uploaded '{fullPath}' to server");
|
||||||
context.Output($"Uploaded '{size}' bytes from '{fullPath}' to server");
|
|
||||||
}
|
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
||||||
// if any of the results were successful, make sure to attach them to the build
|
string jobId = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobId).Value ?? string.Empty;
|
||||||
finally
|
var artifact = await buildHelper.AssociateArtifact(projectId, buildId, jobId, artifactName, ArtifactResourceTypes.Container, fileContainerFullPath, propertiesDictionary, token);
|
||||||
{
|
context.Output($"Associated artifact {artifactName} ({artifact.Id}) with run #{buildId}");
|
||||||
string fileContainerFullPath = StringUtil.Format($"#/{containerId}/{artifactName}");
|
|
||||||
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
|
||||||
string jobId = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobId).Value ?? string.Empty;
|
|
||||||
var artifact = await buildHelper.AssociateArtifact(projectId, buildId, jobId, artifactName, ArtifactResourceTypes.Container, fileContainerFullPath, propertiesDictionary, token);
|
|
||||||
context.Output($"Associated artifact {artifactName} ({artifact.Id}) with run #{buildId}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,35 +107,26 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else if (_commandExtensions.TryGetValue(actionCommand.Command, out IActionCommandExtension extension))
|
else if (_commandExtensions.TryGetValue(actionCommand.Command, out IActionCommandExtension extension))
|
||||||
{
|
{
|
||||||
bool commandHasBeenOutput = false;
|
bool omitEcho;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (context.EchoOnActionCommand)
|
extension.ProcessCommand(context, input, actionCommand, out omitEcho);
|
||||||
{
|
|
||||||
context.Output(input);
|
|
||||||
context.Debug($"Processing command '{actionCommand.Command}'");
|
|
||||||
commandHasBeenOutput = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
extension.ProcessCommand(context, input, actionCommand);
|
|
||||||
|
|
||||||
if (context.EchoOnActionCommand)
|
|
||||||
{
|
|
||||||
context.Debug($"Processed command '{actionCommand.Command}' successfully");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (!commandHasBeenOutput)
|
omitEcho = true;
|
||||||
{
|
context.Output(input);
|
||||||
context.Output(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Error($"Unable to process command '{input}' successfully.");
|
context.Error($"Unable to process command '{input}' successfully.");
|
||||||
context.Error(ex);
|
context.Error(ex);
|
||||||
context.CommandResult = TaskResult.Failed;
|
context.CommandResult = TaskResult.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!omitEcho)
|
||||||
|
{
|
||||||
|
context.Output(input);
|
||||||
|
context.Debug($"Processed command");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -152,7 +143,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
string Command { get; }
|
string Command { get; }
|
||||||
|
|
||||||
void ProcessCommand(IExecutionContext context, string line, ActionCommand command);
|
void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension
|
||||||
@@ -161,7 +152,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
if (!command.Properties.TryGetValue(SetRepoPathCommandProperties.repoFullName, out string repoFullName) || string.IsNullOrEmpty(repoFullName))
|
if (!command.Properties.TryGetValue(SetRepoPathCommandProperties.repoFullName, out string repoFullName) || string.IsNullOrEmpty(repoFullName))
|
||||||
{
|
{
|
||||||
@@ -175,6 +166,8 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
var directoryManager = HostContext.GetService<IPipelineDirectoryManager>();
|
var directoryManager = HostContext.GetService<IPipelineDirectoryManager>();
|
||||||
var trackingConfig = directoryManager.UpdateRepositoryDirectory(context, repoFullName, command.Data, StringUtil.ConvertToBoolean(workspaceRepo));
|
var trackingConfig = directoryManager.UpdateRepositoryDirectory(context, repoFullName, command.Data, StringUtil.ConvertToBoolean(workspaceRepo));
|
||||||
|
|
||||||
|
omitEcho = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SetRepoPathCommandProperties
|
private static class SetRepoPathCommandProperties
|
||||||
@@ -190,7 +183,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
if (!command.Properties.TryGetValue(SetEnvCommandProperties.Name, out string envName) || string.IsNullOrEmpty(envName))
|
if (!command.Properties.TryGetValue(SetEnvCommandProperties.Name, out string envName) || string.IsNullOrEmpty(envName))
|
||||||
{
|
{
|
||||||
@@ -199,7 +192,9 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
context.EnvironmentVariables[envName] = command.Data;
|
context.EnvironmentVariables[envName] = command.Data;
|
||||||
context.SetEnvContext(envName, command.Data);
|
context.SetEnvContext(envName, command.Data);
|
||||||
|
context.Output(line);
|
||||||
context.Debug($"{envName}='{command.Data}'");
|
context.Debug($"{envName}='{command.Data}'");
|
||||||
|
omitEcho = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SetEnvCommandProperties
|
private static class SetEnvCommandProperties
|
||||||
@@ -214,7 +209,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName))
|
if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName))
|
||||||
{
|
{
|
||||||
@@ -222,7 +217,9 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.SetOutput(outputName, command.Data, out var reference);
|
context.SetOutput(outputName, command.Data, out var reference);
|
||||||
|
context.Output(line);
|
||||||
context.Debug($"{reference}='{command.Data}'");
|
context.Debug($"{reference}='{command.Data}'");
|
||||||
|
omitEcho = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SetOutputCommandProperties
|
private static class SetOutputCommandProperties
|
||||||
@@ -237,7 +234,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName))
|
if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName))
|
||||||
{
|
{
|
||||||
@@ -246,6 +243,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
context.IntraActionState[stateName] = command.Data;
|
context.IntraActionState[stateName] = command.Data;
|
||||||
context.Debug($"Save intra-action state {stateName} = {command.Data}");
|
context.Debug($"Save intra-action state {stateName} = {command.Data}");
|
||||||
|
omitEcho = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SaveStateCommandProperties
|
private static class SaveStateCommandProperties
|
||||||
@@ -260,17 +258,19 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(command.Data))
|
if (string.IsNullOrWhiteSpace(command.Data))
|
||||||
{
|
{
|
||||||
context.Warning("Can't add secret mask for empty string in ##[add-mask] command.");
|
context.Warning("Can't add secret mask for empty string.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HostContext.SecretMasker.AddValue(command.Data);
|
HostContext.SecretMasker.AddValue(command.Data);
|
||||||
Trace.Info($"Add new secret mask with length of {command.Data.Length}");
|
Trace.Info($"Add new secret mask with length of {command.Data.Length}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
omitEcho = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,11 +280,12 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
ArgUtil.NotNullOrEmpty(command.Data, "path");
|
ArgUtil.NotNullOrEmpty(command.Data, "path");
|
||||||
context.PrependPath.RemoveAll(x => string.Equals(x, command.Data, StringComparison.CurrentCulture));
|
context.PrependPath.RemoveAll(x => string.Equals(x, command.Data, StringComparison.CurrentCulture));
|
||||||
context.PrependPath.Add(command.Data);
|
context.PrependPath.Add(command.Data);
|
||||||
|
omitEcho = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,8 +295,9 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
|
omitEcho = false;
|
||||||
var file = command.Data;
|
var file = command.Data;
|
||||||
|
|
||||||
// File is required
|
// File is required
|
||||||
@@ -340,22 +342,23 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
|
omitEcho = false;
|
||||||
command.Properties.TryGetValue(RemoveMatcherCommandProperties.Owner, out string owner);
|
command.Properties.TryGetValue(RemoveMatcherCommandProperties.Owner, out string owner);
|
||||||
var file = command.Data;
|
var file = command.Data;
|
||||||
|
|
||||||
// Owner and file are mutually exclusive
|
// Owner and file are mutually exclusive
|
||||||
if (!string.IsNullOrEmpty(owner) && !string.IsNullOrEmpty(file))
|
if (!string.IsNullOrEmpty(owner) && !string.IsNullOrEmpty(file))
|
||||||
{
|
{
|
||||||
context.Warning("Either specify an owner name or a file path in ##[remove-matcher] command. Both values cannot be set.");
|
context.Warning("Either specify a matcher owner name or a file path. Both values cannot be set.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Owner or file is required
|
// Owner or file is required
|
||||||
if (string.IsNullOrEmpty(owner) && string.IsNullOrEmpty(file))
|
if (string.IsNullOrEmpty(owner) && string.IsNullOrEmpty(file))
|
||||||
{
|
{
|
||||||
context.Warning("Either an owner name or a file path must be specified in ##[remove-matcher] command.");
|
context.Warning("Either a matcher owner name or a file path must be specified.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,8 +410,9 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
|
omitEcho = true;
|
||||||
context.Debug(command.Data);
|
context.Debug(command.Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,8 +438,13 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
|
omitEcho = true;
|
||||||
|
command.Properties.TryGetValue(IssueCommandProperties.File, out string file);
|
||||||
|
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
||||||
|
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
||||||
|
|
||||||
Issue issue = new Issue()
|
Issue issue = new Issue()
|
||||||
{
|
{
|
||||||
Category = "General",
|
Category = "General",
|
||||||
@@ -443,8 +452,54 @@ namespace GitHub.Runner.Worker
|
|||||||
Message = command.Data
|
Message = command.Data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(file))
|
||||||
|
{
|
||||||
|
issue.Category = "Code";
|
||||||
|
|
||||||
|
if (context.Container != null)
|
||||||
|
{
|
||||||
|
// Translate file path back from container path
|
||||||
|
file = context.Container.TranslateToHostPath(file);
|
||||||
|
command.Properties[IssueCommandProperties.File] = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the values that represent the server path given a local path
|
||||||
|
string repoName = context.GetGitHubContext("repository");
|
||||||
|
var repoPath = context.GetGitHubContext("workspace");
|
||||||
|
|
||||||
|
string relativeSourcePath = IOUtil.MakeRelative(file, repoPath);
|
||||||
|
if (!string.Equals(relativeSourcePath, file, IOUtil.FilePathStringComparison))
|
||||||
|
{
|
||||||
|
// add repo info
|
||||||
|
if (!string.IsNullOrEmpty(repoName))
|
||||||
|
{
|
||||||
|
command.Properties["repo"] = repoName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(relativeSourcePath))
|
||||||
|
{
|
||||||
|
// replace sourcePath with the new relative path
|
||||||
|
// prefer `/` on all platforms
|
||||||
|
command.Properties[IssueCommandProperties.File] = relativeSourcePath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var property in command.Properties)
|
||||||
|
{
|
||||||
|
issue.Data[property.Key] = property.Value;
|
||||||
|
}
|
||||||
|
|
||||||
context.AddIssue(issue);
|
context.AddIssue(issue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class IssueCommandProperties
|
||||||
|
{
|
||||||
|
public const String File = "file";
|
||||||
|
public const String Line = "line";
|
||||||
|
public const String Column = "col";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class GroupCommandExtension : GroupingCommandExtension
|
public sealed class GroupCommandExtension : GroupingCommandExtension
|
||||||
@@ -462,37 +517,11 @@ namespace GitHub.Runner.Worker
|
|||||||
public abstract string Command { get; }
|
public abstract string Command { get; }
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
||||||
{
|
{
|
||||||
var data = this is GroupCommandExtension ? command.Data : string.Empty;
|
var data = this is GroupCommandExtension ? command.Data : string.Empty;
|
||||||
context.Output($"##[{Command}]{data}");
|
context.Output($"##[{Command}]{data}");
|
||||||
}
|
omitEcho = true;
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class EchoCommandExtension : RunnerService, IActionCommandExtension
|
|
||||||
{
|
|
||||||
public string Command => "echo";
|
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
|
||||||
{
|
|
||||||
ArgUtil.NotNullOrEmpty(command.Data, "value");
|
|
||||||
|
|
||||||
switch (command.Data.Trim().ToUpperInvariant())
|
|
||||||
{
|
|
||||||
case "ON":
|
|
||||||
context.EchoOnActionCommand = true;
|
|
||||||
context.Debug("Setting echo command value to 'on'");
|
|
||||||
break;
|
|
||||||
case "OFF":
|
|
||||||
context.EchoOnActionCommand = false;
|
|
||||||
context.Debug("Setting echo command value to 'off'");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Exception($"Invalid echo command value. Possible values can be: 'on', 'off'. Current value is: '{command.Data}'.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ namespace GitHub.Runner.Worker
|
|||||||
executionContext.Warning("The 'PREVIEW_ACTION_TOKEN' secret is depreciated. Please remove it from the repository's secrets");
|
executionContext.Warning("The 'PREVIEW_ACTION_TOKEN' secret is depreciated. Please remove it from the repository's secrets");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the cache (local runner)
|
||||||
|
IOUtil.DeleteDirectory(HostContext.GetDirectory(WellKnownDirectory.Actions), executionContext.CancellationToken);
|
||||||
|
|
||||||
foreach (var action in actions)
|
foreach (var action in actions)
|
||||||
{
|
{
|
||||||
if (action.Reference.Type == Pipelines.ActionSourceType.ContainerRegistry)
|
if (action.Reference.Type == Pipelines.ActionSourceType.ContainerRegistry)
|
||||||
@@ -445,7 +448,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// make sure we get an clean folder ready to use.
|
// make sure we get a clean folder ready to use.
|
||||||
IOUtil.DeleteDirectory(destDirectory, executionContext.CancellationToken);
|
IOUtil.DeleteDirectory(destDirectory, executionContext.CancellationToken);
|
||||||
Directory.CreateDirectory(destDirectory);
|
Directory.CreateDirectory(destDirectory);
|
||||||
executionContext.Output($"Download action repository '{repositoryReference.Name}@{repositoryReference.Ref}'");
|
executionContext.Output($"Download action repository '{repositoryReference.Name}@{repositoryReference.Ref}'");
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ using GitHub.Services.WebApi;
|
|||||||
using GitHub.DistributedTask.Pipelines;
|
using GitHub.DistributedTask.Pipelines;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating;
|
||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating;
|
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
{
|
{
|
||||||
@@ -62,8 +62,6 @@ namespace GitHub.Runner.Worker
|
|||||||
// Only job level ExecutionContext has PostJobSteps
|
// Only job level ExecutionContext has PostJobSteps
|
||||||
Stack<IStep> PostJobSteps { get; }
|
Stack<IStep> PostJobSteps { get; }
|
||||||
|
|
||||||
bool EchoOnActionCommand { get; set; }
|
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
||||||
void CancelToken();
|
void CancelToken();
|
||||||
@@ -155,8 +153,6 @@ namespace GitHub.Runner.Worker
|
|||||||
// Only job level ExecutionContext has PostJobSteps
|
// Only job level ExecutionContext has PostJobSteps
|
||||||
public Stack<IStep> PostJobSteps { get; private set; }
|
public Stack<IStep> PostJobSteps { get; private set; }
|
||||||
|
|
||||||
public bool EchoOnActionCommand { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public TaskResult? Result
|
public TaskResult? Result
|
||||||
{
|
{
|
||||||
@@ -296,7 +292,6 @@ namespace GitHub.Runner.Worker
|
|||||||
child.PrependPath = PrependPath;
|
child.PrependPath = PrependPath;
|
||||||
child.Container = Container;
|
child.Container = Container;
|
||||||
child.ServiceContainers = ServiceContainers;
|
child.ServiceContainers = ServiceContainers;
|
||||||
child.EchoOnActionCommand = EchoOnActionCommand;
|
|
||||||
|
|
||||||
if (recordOrder != null)
|
if (recordOrder != null)
|
||||||
{
|
{
|
||||||
@@ -709,9 +704,6 @@ namespace GitHub.Runner.Worker
|
|||||||
_logger = HostContext.CreateService<IPagingLogger>();
|
_logger = HostContext.CreateService<IPagingLogger>();
|
||||||
_logger.Setup(_mainTimelineId, _record.Id);
|
_logger.Setup(_mainTimelineId, _record.Id);
|
||||||
|
|
||||||
// Initialize 'echo on action command success' property, default to false, unless Step_Debug is set
|
|
||||||
EchoOnActionCommand = Variables.Step_Debug ?? false;
|
|
||||||
|
|
||||||
// Verbosity (from GitHub.Step_Debug).
|
// Verbosity (from GitHub.Step_Debug).
|
||||||
WriteDebug = Variables.Step_Debug ?? false;
|
WriteDebug = Variables.Step_Debug ?? false;
|
||||||
|
|
||||||
|
|||||||
@@ -397,11 +397,6 @@ namespace GitHub.Services.FileContainer.Client
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (IsFastFailResponse(response))
|
|
||||||
{
|
|
||||||
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request and cannot continue.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request.");
|
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request.");
|
||||||
@@ -543,17 +538,6 @@ namespace GitHub.Services.FileContainer.Client
|
|||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsFastFailResponse(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
int statusCode = (int)response?.StatusCode;
|
|
||||||
return statusCode >= 400 && statusCode <= 499;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool ShouldThrowError(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
return !response.IsSuccessStatusCode && !IsFastFailResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> ContainerGetRequestAsync(
|
private async Task<HttpResponseMessage> ContainerGetRequestAsync(
|
||||||
Int64 containerId,
|
Int64 containerId,
|
||||||
String itemPath,
|
String itemPath,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using GitHub.DistributedTask.WebApi;
|
|||||||
using GitHub.Runner.Worker;
|
using GitHub.Runner.Worker;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common.Tests.Worker
|
namespace GitHub.Runner.Common.Tests.Worker
|
||||||
{
|
{
|
||||||
@@ -147,159 +146,5 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar"));
|
Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void EchoProcessCommand()
|
|
||||||
{
|
|
||||||
using (TestHostContext _hc = new TestHostContext(this))
|
|
||||||
{
|
|
||||||
var extensionManager = new Mock<IExtensionManager>();
|
|
||||||
var echoCommand = new EchoCommandExtension();
|
|
||||||
echoCommand.Initialize(_hc);
|
|
||||||
|
|
||||||
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
|
|
||||||
.Returns(new List<IActionCommandExtension>() { echoCommand });
|
|
||||||
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
|
|
||||||
|
|
||||||
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
|
|
||||||
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
|
|
||||||
.Returns((string tag, string line) =>
|
|
||||||
{
|
|
||||||
_hc.GetTrace().Info($"{tag} {line}");
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
_ec.SetupAllProperties();
|
|
||||||
|
|
||||||
ActionCommandManager commandManager = new ActionCommandManager();
|
|
||||||
commandManager.Initialize(_hc);
|
|
||||||
|
|
||||||
Assert.False(_ec.Object.EchoOnActionCommand);
|
|
||||||
|
|
||||||
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::on"));
|
|
||||||
Assert.True(_ec.Object.EchoOnActionCommand);
|
|
||||||
|
|
||||||
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::off"));
|
|
||||||
Assert.False(_ec.Object.EchoOnActionCommand);
|
|
||||||
|
|
||||||
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::ON"));
|
|
||||||
Assert.True(_ec.Object.EchoOnActionCommand);
|
|
||||||
|
|
||||||
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::Off "));
|
|
||||||
Assert.False(_ec.Object.EchoOnActionCommand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void EchoProcessCommandDebugOn()
|
|
||||||
{
|
|
||||||
using (TestHostContext _hc = new TestHostContext(this))
|
|
||||||
{
|
|
||||||
// Set up a few things
|
|
||||||
// 1. Job request message (with ACTIONS_STEP_DEBUG = true)
|
|
||||||
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
|
||||||
TimelineReference timeline = new TimelineReference();
|
|
||||||
JobEnvironment environment = new JobEnvironment();
|
|
||||||
environment.SystemConnection = new ServiceEndpoint();
|
|
||||||
List<TaskInstance> tasks = new List<TaskInstance>();
|
|
||||||
Guid JobId = Guid.NewGuid();
|
|
||||||
string jobName = "some job name";
|
|
||||||
var jobRequest = Pipelines.AgentJobRequestMessageUtil.Convert(new AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, environment, tasks));
|
|
||||||
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";
|
|
||||||
|
|
||||||
// Some service dependencies
|
|
||||||
var jobServerQueue = new Mock<IJobServerQueue>();
|
|
||||||
jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny<Guid>(), It.IsAny<TimelineRecord>()));
|
|
||||||
|
|
||||||
_hc.SetSingleton(jobServerQueue.Object);
|
|
||||||
|
|
||||||
var extensionManager = new Mock<IExtensionManager>();
|
|
||||||
var echoCommand = new EchoCommandExtension();
|
|
||||||
echoCommand.Initialize(_hc);
|
|
||||||
|
|
||||||
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
|
|
||||||
.Returns(new List<IActionCommandExtension>() { echoCommand });
|
|
||||||
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
|
|
||||||
|
|
||||||
var configurationStore = new Mock<IConfigurationStore>();
|
|
||||||
configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings());
|
|
||||||
_hc.SetSingleton(configurationStore.Object);
|
|
||||||
|
|
||||||
var pagingLogger = new Mock<IPagingLogger>();
|
|
||||||
_hc.EnqueueInstance(pagingLogger.Object);
|
|
||||||
|
|
||||||
ActionCommandManager commandManager = new ActionCommandManager();
|
|
||||||
commandManager.Initialize(_hc);
|
|
||||||
|
|
||||||
var _ec = new Runner.Worker.ExecutionContext();
|
|
||||||
_ec.Initialize(_hc);
|
|
||||||
|
|
||||||
// Initialize the job (to exercise logic that sets EchoOnActionCommand)
|
|
||||||
_ec.InitializeJob(jobRequest, System.Threading.CancellationToken.None);
|
|
||||||
|
|
||||||
_ec.Complete();
|
|
||||||
|
|
||||||
Assert.True(_ec.EchoOnActionCommand);
|
|
||||||
|
|
||||||
Assert.True(commandManager.TryProcessCommand(_ec, "::echo::off"));
|
|
||||||
Assert.False(_ec.EchoOnActionCommand);
|
|
||||||
|
|
||||||
Assert.True(commandManager.TryProcessCommand(_ec, "::echo::on"));
|
|
||||||
Assert.True(_ec.EchoOnActionCommand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void EchoProcessCommandInvalid()
|
|
||||||
{
|
|
||||||
using (TestHostContext _hc = new TestHostContext(this))
|
|
||||||
{
|
|
||||||
var extensionManager = new Mock<IExtensionManager>();
|
|
||||||
var echoCommand = new EchoCommandExtension();
|
|
||||||
echoCommand.Initialize(_hc);
|
|
||||||
|
|
||||||
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
|
|
||||||
.Returns(new List<IActionCommandExtension>() { echoCommand });
|
|
||||||
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
|
|
||||||
|
|
||||||
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
|
|
||||||
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
|
|
||||||
.Returns((string tag, string line) =>
|
|
||||||
{
|
|
||||||
_hc.GetTrace().Info($"{tag} {line}");
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
_ec.SetupAllProperties();
|
|
||||||
|
|
||||||
ActionCommandManager commandManager = new ActionCommandManager();
|
|
||||||
commandManager.Initialize(_hc);
|
|
||||||
|
|
||||||
// Echo commands below are considered "processed", but are invalid
|
|
||||||
// 1. Invalid echo value
|
|
||||||
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::invalid"));
|
|
||||||
Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult);
|
|
||||||
Assert.False(_ec.Object.EchoOnActionCommand);
|
|
||||||
|
|
||||||
// 2. No value
|
|
||||||
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::"));
|
|
||||||
Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult);
|
|
||||||
Assert.False(_ec.Object.EchoOnActionCommand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,6 +233,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -272,6 +273,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Teardown();
|
Teardown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
@@ -306,6 +308,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#if OS_LINUX
|
#if OS_LINUX
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
@@ -772,6 +775,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Teardown();
|
Teardown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.159.2
|
2.160.0
|
||||||
Reference in New Issue
Block a user