diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index 46f516999..449b43537 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -48,6 +48,7 @@ namespace GitHub.Runner.Worker Dictionary IntraActionState { get; } Dictionary JobOutputs { get; } + ActionsEnvironmentReference ActionsEnvironment { get; } DictionaryContextData ExpressionValues { get; } IList ExpressionFunctions { get; } JobContext JobContext { get; } @@ -137,6 +138,8 @@ namespace GitHub.Runner.Worker public CancellationToken CancellationToken => _cancellationTokenSource.Token; public Dictionary IntraActionState { get; private set; } public Dictionary JobOutputs { get; private set; } + + public ActionsEnvironmentReference ActionsEnvironment { get; private set; } public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData(); public IList ExpressionFunctions { get; } = new List(); @@ -252,7 +255,7 @@ namespace GitHub.Runner.Worker /// /// Helper function used in CompositeActionHandler::RunAsync to - /// add a child node, aka a step, to the current job to the Root.JobSteps based on the location. + /// add a child node, aka a step, to the current job to the Root.JobSteps based on the location. /// public IStep CreateCompositeStep( string scopeName, @@ -378,7 +381,7 @@ namespace GitHub.Runner.Worker if (Root != this) { - // only dispose TokenSource for step level ExecutionContext + // only dispose TokenSource for step level ExecutionContext _cancellationTokenSource?.Dispose(); } @@ -611,6 +614,9 @@ namespace GitHub.Runner.Worker // Job Outputs JobOutputs = new Dictionary(StringComparer.OrdinalIgnoreCase); + // Actions environment + ActionsEnvironment = message.ActionsEnvironment; + // Service container info Global.ServiceContainers = new List(); @@ -718,7 +724,6 @@ namespace GitHub.Runner.Worker } _jobServerQueue.QueueWebConsoleLine(_record.Id, msg, totalLines); - return totalLines; } diff --git a/src/Runner.Worker/JobExtension.cs b/src/Runner.Worker/JobExtension.cs index e68f5cd4c..ce19c4678 100644 --- a/src/Runner.Worker/JobExtension.cs +++ b/src/Runner.Worker/JobExtension.cs @@ -365,6 +365,24 @@ namespace GitHub.Runner.Worker context.Start(); context.Debug("Starting: Complete job"); + Trace.Info("Initialize Env context"); + +#if OS_WINDOWS + var envContext = new DictionaryContextData(); +#else + var envContext = new CaseSensitiveDictionaryContextData(); +#endif + context.ExpressionValues["env"] = envContext; + foreach (var pair in context.Global.EnvironmentVariables) + { + envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty); + } + + // Populate env context for each step + Trace.Info("Initialize steps context"); + context.ExpressionValues["steps"] = context.Global.StepsContext.GetScope(context.ScopeName); + + var templateEvaluator = context.ToPipelineTemplateEvaluator(); // Evaluate job outputs if (message.JobOutputs != null && message.JobOutputs.Type != TokenType.Null) { @@ -374,21 +392,7 @@ namespace GitHub.Runner.Worker // Populate env context for each step Trace.Info("Initialize Env context for evaluating job outputs"); -#if OS_WINDOWS - var envContext = new DictionaryContextData(); -#else - var envContext = new CaseSensitiveDictionaryContextData(); -#endif - context.ExpressionValues["env"] = envContext; - foreach (var pair in context.Global.EnvironmentVariables) - { - envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty); - } - Trace.Info("Initialize steps context for evaluating job outputs"); - context.ExpressionValues["steps"] = context.Global.StepsContext.GetScope(context.ScopeName); - - var templateEvaluator = context.ToPipelineTemplateEvaluator(); var outputs = templateEvaluator.EvaluateJobOutput(message.JobOutputs, context.ExpressionValues, context.ExpressionFunctions); foreach (var output in outputs) { @@ -417,6 +421,34 @@ namespace GitHub.Runner.Worker } } + // Evaluate environment data + if (jobContext.ActionsEnvironment?.Url != null && jobContext.ActionsEnvironment?.Url.Type != TokenType.Null) + { + try + { + context.Output($"Evaluate and set environment url"); + + var environmentUrlToken = templateEvaluator.EvaluateEnvironmentUrl(jobContext.ActionsEnvironment.Url, context.ExpressionValues, context.ExpressionFunctions); + var environmentUrl = environmentUrlToken.AssertString("environment.url"); + if (string.Equals(environmentUrl.Value, HostContext.SecretMasker.MaskSecrets(environmentUrl.Value))) + { + context.Warning($"Skip setting environment url as environment '{jobContext.ActionsEnvironment.Name}' may contain secret."); + } + else + { + context.Output($"Evaluated environment url: {environmentUrl}"); + jobContext.ActionsEnvironment.Url = environmentUrlToken; + } + } + catch (Exception ex) + { + context.Result = TaskResult.Failed; + context.Error($"Failed to evaluate environment url"); + context.Error(ex); + jobContext.Result = TaskResultUtil.MergeTaskResults(jobContext.Result, TaskResult.Failed); + } + } + if (context.Global.Variables.GetBoolean(Constants.Variables.Actions.RunnerDebug) ?? false) { Trace.Info("Support log upload starting."); diff --git a/src/Runner.Worker/JobRunner.cs b/src/Runner.Worker/JobRunner.cs index 4fb6662eb..ca81e51b5 100644 --- a/src/Runner.Worker/JobRunner.cs +++ b/src/Runner.Worker/JobRunner.cs @@ -216,7 +216,7 @@ namespace GitHub.Runner.Worker } Trace.Info("Raising job completed event."); - var jobCompletedEvent = new JobCompletedEvent(message.RequestId, message.JobId, result, jobContext.JobOutputs); + var jobCompletedEvent = new JobCompletedEvent(message.RequestId, message.JobId, result, jobContext.JobOutputs, jobContext.ActionsEnvironment); var completeJobRetryLimit = 5; var exceptions = new List(); diff --git a/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateConstants.cs b/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateConstants.cs index 21e70e4b9..d7378a872 100644 --- a/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateConstants.cs +++ b/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateConstants.cs @@ -52,6 +52,7 @@ namespace GitHub.DistributedTask.ObjectTemplating internal const String String = "string"; internal const String StringDefinition = "string-definition"; internal const String StringDefinitionProperties = "string-definition-properties"; + internal const String StringRunnerContextNoSecrets = "string-runner-context-no-secrets"; internal const String Structure = "structure"; internal const String TemplateSchema = "template-schema"; internal const String True = "true"; diff --git a/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs b/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs index 7aa21e7ff..74650a12e 100644 --- a/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs +++ b/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs @@ -41,7 +41,8 @@ namespace GitHub.DistributedTask.Pipelines IEnumerable steps, IList fileTable, TemplateToken jobOutputs, - IList defaults) + IList defaults, + ActionsEnvironmentReference actionsEnvironment) { this.MessageType = JobRequestMessageTypes.PipelineAgentJobRequest; this.Plan = plan; @@ -54,7 +55,7 @@ namespace GitHub.DistributedTask.Pipelines this.Resources = jobResources; this.Workspace = workspaceOptions; this.JobOutputs = jobOutputs; - + this.ActionsEnvironment = actionsEnvironment; m_variables = new Dictionary(variables, StringComparer.OrdinalIgnoreCase); m_maskHints = new List(maskHints); m_steps = new List(steps); @@ -228,6 +229,13 @@ namespace GitHub.DistributedTask.Pipelines } } + [DataMember(EmitDefaultValue = false)] + public ActionsEnvironmentReference ActionsEnvironment + { + get; + set; + } + /// /// Gets the collection of variables associated with the current context. /// diff --git a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs index f769b1719..7d7bf14e7 100644 --- a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs +++ b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs @@ -17,6 +17,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating public const String Credentials = "credentials"; public const String Defaults = "defaults"; public const String Env = "env"; + public const String Environment = "environment"; public const String Event = "event"; public const String EventPattern = "github.event"; public const String Exclude = "exclude"; diff --git a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs index a0041fbc5..f0cabf4e2 100644 --- a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs +++ b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs @@ -279,6 +279,33 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating return result; } + public TemplateToken EvaluateEnvironmentUrl( + TemplateToken token, + DictionaryContextData contextData, + IList expressionFunctions) + { + var result = default(TemplateToken); + if (token != null && token.Type != TokenType.Null) + { + var context = CreateContext(contextData, expressionFunctions); + try + { + token = TemplateEvaluator.Evaluate(context, TemplateConstants.StringRunnerContextNoSecrets, token, 0, null, omitHeader: true); + context.Errors.Check(); + result = token.AssertString("environment.url"); + } + catch (Exception ex) when (!(ex is TemplateValidationException)) + { + context.Errors.Add(ex); + } + + context.Errors.Check(); + } + + return result; + } + + public Dictionary EvaluateJobDefaultsRun( TemplateToken token, DictionaryContextData contextData, diff --git a/src/Sdk/DTPipelines/workflow-v1.0.json b/src/Sdk/DTPipelines/workflow-v1.0.json index 9902a36dc..1ebc81065 100644 --- a/src/Sdk/DTPipelines/workflow-v1.0.json +++ b/src/Sdk/DTPipelines/workflow-v1.0.json @@ -515,6 +515,20 @@ "string": {} }, + "string-runner-context-no-secrets": { + "context": [ + "github", + "needs", + "strategy", + "matrix", + "steps", + "job", + "runner", + "env" + ], + "string": {} + }, + "string-steps-context": { "context": [ "github", @@ -531,4 +545,4 @@ "string": {} } } -} \ No newline at end of file +} diff --git a/src/Sdk/DTWebApi/WebApi/ActionsEnvironmentReference.cs b/src/Sdk/DTWebApi/WebApi/ActionsEnvironmentReference.cs new file mode 100644 index 000000000..a37dcb68e --- /dev/null +++ b/src/Sdk/DTWebApi/WebApi/ActionsEnvironmentReference.cs @@ -0,0 +1,23 @@ +using System.Runtime.Serialization; +using GitHub.DistributedTask.ObjectTemplating.Tokens; + +namespace GitHub.DistributedTask.WebApi +{ + /// + /// Information about an environment parsed from YML with evaluated name, URL will be evaluated on runner + /// + [DataContract] + public class ActionsEnvironmentReference + { + public ActionsEnvironmentReference(string name) + { + Name = name; + } + + [DataMember(EmitDefaultValue = false)] + public string Name { get; set; } + + [DataMember(EmitDefaultValue = false)] + public TemplateToken Url { get; set; } + } +} diff --git a/src/Sdk/DTWebApi/WebApi/JobEvent.cs b/src/Sdk/DTWebApi/WebApi/JobEvent.cs index 7566cde94..6cf56898b 100644 --- a/src/Sdk/DTWebApi/WebApi/JobEvent.cs +++ b/src/Sdk/DTWebApi/WebApi/JobEvent.cs @@ -131,6 +131,17 @@ namespace GitHub.DistributedTask.WebApi this.Outputs = outputs; } + public JobCompletedEvent( + Int64 requestId, + Guid jobId, + TaskResult result, + Dictionary outputs, + ActionsEnvironmentReference actionsEnvironment) + : this(requestId, jobId, result, outputs) + { + this.ActionsEnvironment = actionsEnvironment; + } + [DataMember(EmitDefaultValue = false)] public Int64 RequestId { @@ -151,6 +162,13 @@ namespace GitHub.DistributedTask.WebApi get; set; } + + [DataMember(EmitDefaultValue = false)] + public ActionsEnvironmentReference ActionsEnvironment + { + get; + set; + } } [DataContract] diff --git a/src/Test/L0/Listener/JobDispatcherL0.cs b/src/Test/L0/Listener/JobDispatcherL0.cs index 9408da922..a8062b206 100644 --- a/src/Test/L0/Listener/JobDispatcherL0.cs +++ b/src/Test/L0/Listener/JobDispatcherL0.cs @@ -33,7 +33,7 @@ namespace GitHub.Runner.Common.Tests.Listener TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = null; Guid jobId = Guid.NewGuid(); - var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); result.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData(); return result; } diff --git a/src/Test/L0/Listener/RunnerL0.cs b/src/Test/L0/Listener/RunnerL0.cs index 5d8bc3e0f..32a21521b 100644 --- a/src/Test/L0/Listener/RunnerL0.cs +++ b/src/Test/L0/Listener/RunnerL0.cs @@ -43,7 +43,7 @@ namespace GitHub.Runner.Common.Tests.Listener TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = null; Guid jobId = Guid.NewGuid(); - return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); } private JobCancelMessage CreateJobCancelMessage() diff --git a/src/Test/L0/Worker/ActionCommandManagerL0.cs b/src/Test/L0/Worker/ActionCommandManagerL0.cs index 3cc1c5ceb..3bea6eeb1 100644 --- a/src/Test/L0/Worker/ActionCommandManagerL0.cs +++ b/src/Test/L0/Worker/ActionCommandManagerL0.cs @@ -148,7 +148,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(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, diff --git a/src/Test/L0/Worker/ExecutionContextL0.cs b/src/Test/L0/Worker/ExecutionContextL0.cs index 39dbb2dda..4c20244a2 100644 --- a/src/Test/L0/Worker/ExecutionContextL0.cs +++ b/src/Test/L0/Worker/ExecutionContextL0.cs @@ -26,7 +26,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(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, @@ -102,7 +102,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(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, @@ -153,7 +153,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(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, @@ -251,7 +251,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(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, @@ -335,7 +335,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(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, diff --git a/src/Test/L0/Worker/JobExtensionL0.cs b/src/Test/L0/Worker/JobExtensionL0.cs index 4ce643d4e..ba7c95c04 100644 --- a/src/Test/L0/Worker/JobExtensionL0.cs +++ b/src/Test/L0/Worker/JobExtensionL0.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using Xunit; using System.Threading; +using GitHub.DistributedTask.ObjectTemplating.Tokens; using Pipelines = GitHub.DistributedTask.Pipelines; namespace GitHub.Runner.Common.Tests.Worker @@ -98,7 +99,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(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null, null, null); + _message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null, null, null, null); GitHubContext github = new GitHubContext(); github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner"); _message.ContextData.Add("github", github); @@ -281,5 +282,70 @@ namespace GitHub.Runner.Common.Tests.Worker Times.Never); } } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void EnsureFinalizeJobRunsIfMessageHasNoEnvironmentUrl() + { + using (TestHostContext hc = CreateTestContext()) + { + var jobExtension = new JobExtension(); + jobExtension.Initialize(hc); + + _message.ActionsEnvironment = new ActionsEnvironmentReference("production"); + + _jobEc = new Runner.Worker.ExecutionContext {Result = TaskResult.Succeeded}; + _jobEc.Initialize(hc); + _jobEc.InitializeJob(_message, _tokenSource.Token); + + jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow); + + Assert.Equal(TaskResult.Succeeded, _jobEc.Result); + } + } + + [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] + public void EnsureFinalizeJobHandlesNullEnvironmentUrl() + { + using (TestHostContext hc = CreateTestContext()) + { + var jobExtension = new JobExtension(); + jobExtension.Initialize(hc); + + _message.ActionsEnvironment = new ActionsEnvironmentReference("production") + { + Url = null + }; + + _jobEc = new Runner.Worker.ExecutionContext {Result = TaskResult.Succeeded}; + _jobEc.Initialize(hc); + _jobEc.InitializeJob(_message, _tokenSource.Token); + + jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow); + + Assert.Equal(TaskResult.Succeeded, _jobEc.Result); + } + } + + [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] + public void EnsureFinalizeJobHandlesNullEnvironment() + { + using (TestHostContext hc = CreateTestContext()) + { + var jobExtension = new JobExtension(); + jobExtension.Initialize(hc); + + _message.ActionsEnvironment = null; + + _jobEc = new Runner.Worker.ExecutionContext {Result = TaskResult.Succeeded}; + _jobEc.Initialize(hc); + _jobEc.InitializeJob(_message, _tokenSource.Token); + + jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow); + + Assert.Equal(TaskResult.Succeeded, _jobEc.Result); + } + } } } diff --git a/src/Test/L0/Worker/JobRunnerL0.cs b/src/Test/L0/Worker/JobRunnerL0.cs index 61f418b12..198d378b9 100644 --- a/src/Test/L0/Worker/JobRunnerL0.cs +++ b/src/Test/L0/Worker/JobRunnerL0.cs @@ -60,7 +60,7 @@ namespace GitHub.Runner.Common.Tests.Worker TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new Timeline(Guid.NewGuid()); Guid jobId = Guid.NewGuid(); - _message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, testName, testName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); + _message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, testName, testName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); _message.Variables[Constants.Variables.System.Culture] = "en-US"; _message.Resources.Endpoints.Add(new ServiceEndpoint() { diff --git a/src/Test/L0/Worker/WorkerL0.cs b/src/Test/L0/Worker/WorkerL0.cs index ed930f184..80e5eaa0a 100644 --- a/src/Test/L0/Worker/WorkerL0.cs +++ b/src/Test/L0/Worker/WorkerL0.cs @@ -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(), resources, context, null, actions, null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, new StringToken(null, null, null, "ubuntu"), sidecarContainers, null, variables, new List(), resources, context, null, actions, null, null, null, null); return jobRequest; }