Skip to content

Commit

Permalink
Warn for soon to be deprecated OS versions (actions#3413)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsciple authored Aug 2, 2024
1 parent 1250684 commit ae04147
Show file tree
Hide file tree
Showing 13 changed files with 457 additions and 22 deletions.
4 changes: 4 additions & 0 deletions src/Runner.Worker/JobExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ public async Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipel
}
}

// 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") ?? "";
Expand Down
87 changes: 87 additions & 0 deletions src/Runner.Worker/OSWarningChecker.cs
Original file line number Diff line number Diff line change
@@ -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
}

26 changes: 26 additions & 0 deletions src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public AgentJobRequestMessage(
IList<TemplateToken> defaults,
ActionsEnvironmentReference actionsEnvironment,
TemplateToken snapshot,
IList<OSWarning> osWarnings,
String messageType = JobRequestMessageTypes.PipelineAgentJobRequest)
{
this.MessageType = messageType;
Expand Down Expand Up @@ -73,6 +74,11 @@ public AgentJobRequestMessage(
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)
{
Expand Down Expand Up @@ -288,6 +294,18 @@ public IList<String> FileTable
}
}

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)
{
Expand Down Expand Up @@ -425,6 +443,11 @@ private void OnSerializing(StreamingContext context)
{
JobContainer = new StringToken(null, null, null, m_jobContainerResourceAlias);
}

if (m_osWarnings?.Count == 0)
{
m_osWarnings = null;
}
}

[DataMember(Name = "EnvironmentVariables", EmitDefaultValue = false)]
Expand All @@ -449,6 +472,9 @@ private void OnSerializing(StreamingContext context)
[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;
Expand Down
44 changes: 44 additions & 0 deletions src/Sdk/DTPipelines/Pipelines/OSWarning.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
3 changes: 2 additions & 1 deletion src/Test/L0/Listener/JobDispatcherL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private Pipelines.AgentJobRequestMessage CreateJobRequestMessage()
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;
}
Expand Down Expand Up @@ -810,6 +810,7 @@ private static AgentJobRequestMessage GetAgentJobRequestMessage()
null,
new List<TemplateToken>(),
new ActionsEnvironmentReference("env"),
null,
null
);
return message;
Expand Down
2 changes: 1 addition & 1 deletion src/Test/L0/Listener/RunnerL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private Pipelines.AgentJobRequestMessage CreateJobRequestMessage(string jobName)
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()
Expand Down
2 changes: 1 addition & 1 deletion src/Test/L0/Worker/ActionCommandManagerL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public void EchoProcessCommandDebugOn()
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,
Expand Down
2 changes: 1 addition & 1 deletion src/Test/L0/Worker/CreateStepSummaryCommandL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ private TestHostContext Setup([CallerMemberName] string name = "")
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,
Expand Down
Loading

0 comments on commit ae04147

Please sign in to comment.