From 1e51143a8535be94f5725ee32649ff17b8dee0f1 Mon Sep 17 00:00:00 2001 From: Jon Jensen Date: Mon, 22 Sep 2025 13:46:43 -0600 Subject: [PATCH] Add JOB_ env vars Add env vars for top-level primitives in job context job.check_run_id => JOB_CHECK_RUN_ID job.status => JOB_STATUS job.workflow_ref => JOB_WORKFLOW_REF job.workflow_sha => JOB_WORKFLOW_SHA job.workflow_repository => JOB_WORKFLOW_REPOSITORY job.workflow_file_path => JOB_WORKFLOW_FILE_PATH --- src/Runner.Worker/JobContext.cs | 34 ++++++++++++++++++++++++++++-- src/Test/L0/Worker/JobContextL0.cs | 27 +++++++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/Runner.Worker/JobContext.cs b/src/Runner.Worker/JobContext.cs index 7150f2e8bc1..e19ec07bd2f 100644 --- a/src/Runner.Worker/JobContext.cs +++ b/src/Runner.Worker/JobContext.cs @@ -1,10 +1,12 @@ -using GitHub.DistributedTask.Pipelines.ContextData; +using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.Runner.Common.Util; using GitHub.Runner.Common; +using System; +using System.Collections.Generic; namespace GitHub.Runner.Worker { - public sealed class JobContext : DictionaryContextData + public sealed class JobContext : DictionaryContextData, IEnvironmentContextData { public ActionResult? Status { @@ -146,5 +148,33 @@ public string WorkflowFilePath this["workflow_file_path"] = value != null ? new StringContextData(value) : null; } } + + private readonly HashSet _contextEnvAllowlist = new(StringComparer.OrdinalIgnoreCase) + { + "check_run_id", + "status", + "workflow_ref", + "workflow_sha", + "workflow_repository", + "workflow_file_path", + }; + + public IEnumerable> GetRuntimeEnvironmentVariables() + { + foreach (var data in this) + { + if (_contextEnvAllowlist.Contains(data.Key)) + { + if (data.Value is StringContextData value) + { + yield return new KeyValuePair($"JOB_{data.Key.ToUpperInvariant()}", value.ToString()); + } + else if (data.Value is NumberContextData numberValue) + { + yield return new KeyValuePair($"JOB_{data.Key.ToUpperInvariant()}", numberValue.ToString()); + } + } + } + } } } diff --git a/src/Test/L0/Worker/JobContextL0.cs b/src/Test/L0/Worker/JobContextL0.cs index a99d841a626..4ab376e4b8c 100644 --- a/src/Test/L0/Worker/JobContextL0.cs +++ b/src/Test/L0/Worker/JobContextL0.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.Collections.Generic; using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.Runner.Worker; using Xunit; @@ -138,5 +139,29 @@ public void WorkflowFilePath_SetNull_ClearsValue() ctx.WorkflowFilePath = null; Assert.Null(ctx.WorkflowFilePath); } + + [Fact] + public void GetRuntimeEnvironmentVariables_ReturnsCorrectVariables() + { + var ctx = new JobContext(); + ctx.CheckRunId = 12345; + ctx.Status = ActionResult.Success; + ctx.WorkflowRef = "owner/repo/.github/workflows/ci.yml@refs/heads/main"; + ctx.WorkflowSha = "abc123def456"; + ctx.WorkflowRepository = "owner/repo"; + ctx.WorkflowFilePath = ".github/workflows/ci.yml"; + + var dict = new Dictionary(ctx.GetRuntimeEnvironmentVariables()); + Assert.Equal("12345", dict["JOB_CHECK_RUN_ID"]); + Assert.Equal("success", dict["JOB_STATUS"]); + Assert.Equal("owner/repo/.github/workflows/ci.yml@refs/heads/main", dict["JOB_WORKFLOW_REF"]); + Assert.Equal("abc123def456", dict["JOB_WORKFLOW_SHA"]); + Assert.Equal("owner/repo", dict["JOB_WORKFLOW_REPOSITORY"]); + Assert.Equal(".github/workflows/ci.yml", dict["JOB_WORKFLOW_FILE_PATH"]); + + ctx = new JobContext(); + dict = new Dictionary(ctx.GetRuntimeEnvironmentVariables()); + Assert.Empty(dict); + } } }