Warn for soon to be deprecated OS versions (#3413)

This commit is contained in:
eric sciple
2024-08-02 14:37:46 -05:00
committed by GitHub
parent 12506842c0
commit ae04147f96
13 changed files with 457 additions and 22 deletions

View File

@@ -127,6 +127,10 @@ namespace GitHub.Runner.Worker
}
}
// Check OS warning
var osWarningChecker = HostContext.GetService<IOSWarningChecker>();
await osWarningChecker.CheckOSAsync(context, message.OSWarnings);
try
{
var tokenPermissions = jobContext.Global.Variables.Get("system.github.token.permissions") ?? "";

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using GitHub.DistributedTask.WebApi;
using GitHub.DistributedTask.Pipelines;
using GitHub.Runner.Common;
using GitHub.Runner.Sdk;
namespace GitHub.Runner.Worker
{
[ServiceLocator(Default = typeof(OSWarningChecker))]
public interface IOSWarningChecker : IRunnerService
{
Task CheckOSAsync(IExecutionContext context, IList<OSWarning> osWarnings);
}
#if OS_WINDOWS || OS_OSX
public sealed class OSWarningChecker : RunnerService, IOSWarningChecker
{
public Task CheckOSAsync(IExecutionContext context, IList<OSWarning> osWarnings)
{
ArgUtil.NotNull(context, nameof(context));
ArgUtil.NotNull(osWarnings, nameof(osWarnings));
return Task.CompletedTask;
}
}
#else
public sealed class OSWarningChecker : RunnerService, IOSWarningChecker
{
private static readonly TimeSpan s_matchTimeout = TimeSpan.FromMilliseconds(100);
private static readonly RegexOptions s_regexOptions = RegexOptions.CultureInvariant | RegexOptions.IgnoreCase;
public async Task CheckOSAsync(IExecutionContext context, IList<OSWarning> osWarnings)
{
ArgUtil.NotNull(context, nameof(context));
ArgUtil.NotNull(osWarnings, nameof(osWarnings));
foreach (var osWarning in osWarnings)
{
if (string.IsNullOrEmpty(osWarning.FilePath))
{
Trace.Error("The file path is not specified in the OS warning check.");
continue;
}
if (string.IsNullOrEmpty(osWarning.RegularExpression))
{
Trace.Error("The regular expression is not specified in the OS warning check.");
continue;
}
if (string.IsNullOrEmpty(osWarning.Warning))
{
Trace.Error("The warning message is not specified in the OS warning check.");
continue;
}
try
{
if (File.Exists(osWarning.FilePath))
{
var lines = await File.ReadAllLinesAsync(osWarning.FilePath, context.CancellationToken);
var regex = new Regex(osWarning.RegularExpression, s_regexOptions, s_matchTimeout);
foreach (var line in lines)
{
if (regex.IsMatch(line))
{
context.Warning(osWarning.Warning);
context.Global.JobTelemetry.Add(new JobTelemetry() { Type = JobTelemetryType.General, Message = $"OS warning: {osWarning.Warning}" });
return;
}
}
}
}
catch (Exception ex)
{
Trace.Error("An error occurred while checking OS warnings for file '{0}' and regex '{1}'.", osWarning.FilePath, osWarning.RegularExpression);
Trace.Error(ex);
context.Global.JobTelemetry.Add(new JobTelemetry() { Type = JobTelemetryType.General, Message = $"An error occurred while checking OS warnings for file '{osWarning.FilePath}' and regex '{osWarning.RegularExpression}': {ex.Message}" });
}
}
}
}
#endif
}

View File

@@ -44,6 +44,7 @@ namespace GitHub.DistributedTask.Pipelines
IList<TemplateToken> defaults,
ActionsEnvironmentReference actionsEnvironment,
TemplateToken snapshot,
IList<OSWarning> osWarnings,
String messageType = JobRequestMessageTypes.PipelineAgentJobRequest)
{
this.MessageType = messageType;
@@ -73,6 +74,11 @@ namespace GitHub.DistributedTask.Pipelines
m_defaults = new List<TemplateToken>(defaults);
}
if (osWarnings?.Count > 0)
{
m_osWarnings = new List<OSWarning>(osWarnings);
}
this.ContextData = new Dictionary<String, PipelineContextData>(StringComparer.OrdinalIgnoreCase);
if (contextData?.Count > 0)
{
@@ -288,6 +294,18 @@ namespace GitHub.DistributedTask.Pipelines
}
}
public IList<OSWarning> OSWarnings
{
get
{
if (m_osWarnings == null)
{
m_osWarnings = new List<OSWarning>();
}
return m_osWarnings;
}
}
// todo: remove after feature-flag DistributedTask.EvaluateContainerOnRunner is enabled everywhere
public void SetJobSidecarContainers(IDictionary<String, String> value)
{
@@ -425,6 +443,11 @@ namespace GitHub.DistributedTask.Pipelines
{
JobContainer = new StringToken(null, null, null, m_jobContainerResourceAlias);
}
if (m_osWarnings?.Count == 0)
{
m_osWarnings = null;
}
}
[DataMember(Name = "EnvironmentVariables", EmitDefaultValue = false)]
@@ -449,6 +472,9 @@ namespace GitHub.DistributedTask.Pipelines
[DataMember(Name = "JobSidecarContainers", EmitDefaultValue = false)]
private IDictionary<String, String> m_jobSidecarContainers;
[DataMember(Name = "OSWarnings", EmitDefaultValue = false)]
private List<OSWarning> m_osWarnings;
// todo: remove after feature-flag DistributedTask.EvaluateContainerOnRunner is enabled everywhere
[IgnoreDataMember]
private string m_jobContainerResourceAlias;

View File

@@ -0,0 +1,44 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.Pipelines
{
/// <summary>
/// Information to check whether the OS is going to be deprecated soon
/// </summary>
[DataContract]
[EditorBrowsable(EditorBrowsableState.Never)]
public sealed class OSWarning
{
/// <summary>
/// Gets or sets the file to check
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String FilePath
{
get;
set;
}
/// <summary>
/// Gets or sets the regular expression to match
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String RegularExpression
{
get;
set;
}
/// <summary>
/// Gets or sets the warning annotation message, if the regular expression matches the content of the file
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Warning
{
get;
set;
}
}
}

View File

@@ -41,7 +41,7 @@ namespace GitHub.Runner.Common.Tests.Listener
TaskOrchestrationPlanReference plan = new();
TimelineReference timeline = null;
Guid jobId = Guid.NewGuid();
var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", 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, null);
var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", 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, null, null);
result.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();
return result;
}
@@ -810,6 +810,7 @@ namespace GitHub.Runner.Common.Tests.Listener
null,
new List<TemplateToken>(),
new ActionsEnvironmentReference("env"),
null,
null
);
return message;

View File

@@ -44,7 +44,7 @@ namespace GitHub.Runner.Common.Tests.Listener
TaskOrchestrationPlanReference plan = new();
TimelineReference timeline = null;
Guid jobId = Guid.NewGuid();
return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", 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, null);
return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", 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, null, null);
}
private JobCancelMessage CreateJobCancelMessage()

View File

@@ -232,7 +232,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,

View File

@@ -193,7 +193,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
Guid jobId = Guid.NewGuid();
string jobName = "Summary Job";
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,

View File

@@ -29,7 +29,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -106,7 +106,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -162,7 +162,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -216,7 +216,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -271,7 +271,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -322,7 +322,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -373,7 +373,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -471,7 +471,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -555,7 +555,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -610,7 +610,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -653,7 +653,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -717,7 +717,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -781,7 +781,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -969,7 +969,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new();
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -1014,7 +1014,7 @@ namespace GitHub.Runner.Common.Tests.Worker
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -1057,7 +1057,7 @@ namespace GitHub.Runner.Common.Tests.Worker
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, null);
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, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{
Alias = Pipelines.PipelineConstants.SelfAlias,

View File

@@ -114,7 +114,7 @@ namespace GitHub.Runner.Common.Tests.Worker
};
Guid jobId = Guid.NewGuid();
_message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null, null, null, null, null);
_message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null, null, null, null, null, null);
GitHubContext github = new();
github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner");
github["secret_source"] = new Pipelines.ContextData.StringContextData("Actions");
@@ -140,6 +140,7 @@ namespace GitHub.Runner.Common.Tests.Worker
hc.SetSingleton(_diagnosticLogManager.Object);
hc.SetSingleton(_jobHookProvider.Object);
hc.SetSingleton(_snapshotOperationProvider.Object);
hc.SetSingleton(new Mock<IOSWarningChecker>().Object);
hc.EnqueueInstance<IPagingLogger>(_logger.Object); // JobExecutionContext
hc.EnqueueInstance<IPagingLogger>(_logger.Object); // job start hook
hc.EnqueueInstance<IPagingLogger>(_logger.Object); // Initial Job

View File

@@ -102,6 +102,7 @@ namespace GitHub.Runner.Common.Tests.Worker
testName, 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,
new ActionsEnvironmentReference("staging"),
null,
null,
messageType: messageType);
message.Variables[Constants.Variables.System.Culture] = "en-US";
message.Resources.Endpoints.Add(new ServiceEndpoint()

View File

@@ -0,0 +1,271 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Worker;
using Moq;
using Xunit;
namespace GitHub.Runner.Common.Tests.Worker
{
public sealed class OSWarningCheckerL0
{
private CancellationTokenSource _ecTokenSource;
private Mock<IExecutionContext> _ec;
private TestHostContext _hc;
private OSWarningChecker _osWarningChecker;
private List<Issue> _issues;
private string _workFolder;
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public async void CheckOS_FileNotExists()
{
try
{
// Arrange
Setup();
var osWarnings = new List<OSWarning>
{
new OSWarning
{
FilePath = Path.Combine(_workFolder, "os-release"),
RegularExpression = "some OS version",
Warning = "Some OS version will be deprecated soon"
},
};
// Act
await _osWarningChecker.CheckOSAsync(_ec.Object, osWarnings);
// Assert
Assert.Equal(0, _issues.Count);
Assert.Equal(0, _ec.Object.Global.JobTelemetry.Count);
}
finally
{
Teardown();
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public async void CheckOS_CaseInsensitive()
{
try
{
// Arrange
Setup();
var osWarnings = new List<OSWarning>
{
new OSWarning
{
FilePath = Path.Combine(_workFolder, "os-release"),
RegularExpression = "some OS verSION",
Warning = "Some OS version will be deprecated soon"
},
};
File.WriteAllText(Path.Combine(_workFolder, "os-release"), "some OS version\n");
// Act
await _osWarningChecker.CheckOSAsync(_ec.Object, osWarnings);
#if OS_WINDOWS || OS_OSX
// Assert
Assert.Equal(0, _issues.Count);
Assert.Equal(0, _ec.Object.Global.JobTelemetry.Count);
#else
// Assert
Assert.Equal(1, _issues.Count);
Assert.Equal(IssueType.Warning, _issues[0].Type);
Assert.Equal("Some OS version will be deprecated soon", _issues[0].Message);
Assert.Equal(1, _ec.Object.Global.JobTelemetry.Count);
Assert.Equal(JobTelemetryType.General, _ec.Object.Global.JobTelemetry[0].Type);
Assert.Equal("OS warning: Some OS version will be deprecated soon", _ec.Object.Global.JobTelemetry[0].Message);
#endif
}
finally
{
Teardown();
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public async void CheckOS_MatchesOnceWithinAFile()
{
try
{
// Arrange
Setup();
var osWarnings = new List<OSWarning>
{
new OSWarning
{
FilePath = Path.Combine(_workFolder, "os-release"),
RegularExpression = "some OS version",
Warning = "Some OS version will be deprecated soon"
},
};
File.WriteAllText(Path.Combine(_workFolder, "os-release"), "some OS version\nsome OS version\n");
// Act
await _osWarningChecker.CheckOSAsync(_ec.Object, osWarnings);
#if OS_WINDOWS || OS_OSX
// Assert
Assert.Equal(0, _issues.Count);
Assert.Equal(0, _ec.Object.Global.JobTelemetry.Count);
#else
// Assert
Assert.Equal(1, _issues.Count);
Assert.Equal(IssueType.Warning, _issues[0].Type);
Assert.Equal("Some OS version will be deprecated soon", _issues[0].Message);
Assert.Equal(1, _ec.Object.Global.JobTelemetry.Count);
Assert.Equal(JobTelemetryType.General, _ec.Object.Global.JobTelemetry[0].Type);
Assert.Equal("OS warning: Some OS version will be deprecated soon", _ec.Object.Global.JobTelemetry[0].Message);
#endif
}
finally
{
Teardown();
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public async void CheckOS_MatchesOnceAcrossFiles()
{
try
{
// Arrange
Setup();
var osWarnings = new List<OSWarning>
{
new OSWarning
{
FilePath = Path.Combine(_workFolder, "os-release"),
RegularExpression = "some OS version",
Warning = "Some OS version will be deprecated soon"
},
new OSWarning
{
FilePath = Path.Combine(_workFolder, "os-release-2"),
RegularExpression = "some OS version",
Warning = "Some OS version will be deprecated soon"
},
};
File.WriteAllText(Path.Combine(_workFolder, "os-release"), "some OS version\n");
File.WriteAllText(Path.Combine(_workFolder, "os-release-2"), "some OS version\n");
// Act
await _osWarningChecker.CheckOSAsync(_ec.Object, osWarnings);
#if OS_WINDOWS || OS_OSX
// Assert
Assert.Equal(0, _issues.Count);
Assert.Equal(0, _ec.Object.Global.JobTelemetry.Count);
#else
// Assert
Assert.Equal(1, _issues.Count);
Assert.Equal(IssueType.Warning, _issues[0].Type);
Assert.Equal("Some OS version will be deprecated soon", _issues[0].Message);
Assert.Equal(1, _ec.Object.Global.JobTelemetry.Count);
Assert.Equal(JobTelemetryType.General, _ec.Object.Global.JobTelemetry[0].Type);
Assert.Equal("OS warning: Some OS version will be deprecated soon", _ec.Object.Global.JobTelemetry[0].Message);
#endif
}
finally
{
Teardown();
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public async void CheckOS_LogsTelemetryUponException()
{
try
{
// Arrange
Setup();
var osWarnings = new List<OSWarning>
{
new OSWarning
{
FilePath = Path.Combine(_workFolder, "os-release"),
RegularExpression = "abc[", // Invalid pattern
Warning = "Some OS version will be deprecated soon"
},
};
File.WriteAllText(Path.Combine(_workFolder, "os-release"), "some OS version\n");
// Act
await _osWarningChecker.CheckOSAsync(_ec.Object, osWarnings);
#if OS_WINDOWS || OS_OSX
// Assert
Assert.Equal(0, _issues.Count);
Assert.Equal(0, _ec.Object.Global.JobTelemetry.Count);
#else
// Assert
Assert.Equal(0, _issues.Count);
Assert.Equal(1, _ec.Object.Global.JobTelemetry.Count);
Assert.Equal(JobTelemetryType.General, _ec.Object.Global.JobTelemetry[0].Type);
Assert.Equal(
$"An error occurred while checking OS warnings for file '{osWarnings[0].FilePath}' and regex '{osWarnings[0].RegularExpression}': Invalid pattern 'abc[' at offset 4. Unterminated [] set.",
_ec.Object.Global.JobTelemetry[0].Message);
#endif
}
finally
{
Teardown();
}
}
private void Setup([CallerMemberName] string name = "")
{
_issues = new List<Issue>();
// Test host context
_hc = new TestHostContext(this, name);
// Random work folder
_workFolder = _hc.GetDirectory(WellKnownDirectory.Work);
Directory.CreateDirectory(_workFolder);
// Execution context token source
_ecTokenSource?.Dispose();
_ecTokenSource = new CancellationTokenSource();
// Execution context
_ec = new Mock<IExecutionContext>();
_ec.Setup(x => x.Global).Returns(new GlobalContext());
_ec.Setup(x => x.CancellationToken).Returns(_ecTokenSource.Token);
_ec.Object.Global.JobTelemetry = new List<JobTelemetry>();
_ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<ExecutionContextLogOptions>())).Callback((Issue issue, ExecutionContextLogOptions logOptions) => { _issues.Add(issue); });
// OS warning checker
_osWarningChecker = new OSWarningChecker();
_osWarningChecker.Initialize(_hc);
}
private void Teardown()
{
_hc?.Dispose();
if (!string.IsNullOrEmpty(_workFolder) && Directory.Exists(_workFolder))
{
Directory.Delete(_workFolder, recursive: true);
}
}
}
}

View File

@@ -67,7 +67,7 @@ namespace GitHub.Runner.Common.Tests.Worker
new Pipelines.ContextData.DictionaryContextData()
},
};
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, new StringToken(null, null, null, "ubuntu"), sidecarContainers, null, variables, new List<MaskHint>(), resources, context, null, actions, null, null, null, null, null);
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, new StringToken(null, null, null, "ubuntu"), sidecarContainers, null, variables, new List<MaskHint>(), resources, context, null, actions, null, null, null, null, null, null);
return jobRequest;
}