Skip to content

Add infrastructure for background step support: thread safety, SDK models, and results plumbing#4416

Open
lokesh755 wants to merge 4 commits into
actions:mainfrom
lokesh755:lokesh755-background-steps
Open

Add infrastructure for background step support: thread safety, SDK models, and results plumbing#4416
lokesh755 wants to merge 4 commits into
actions:mainfrom
lokesh755:lokesh755-background-steps

Conversation

@lokesh755
Copy link
Copy Markdown
Contributor

@lokesh755 lokesh755 commented May 12, 2026

Summary

Add infrastructure for background step support

This PR lays the groundwork for background steps by adding the necessary infrastructure without changing step execution behavior.

Thread safety

Adds CollectionLock to GlobalContext and wraps all concurrent access to shared collections (JobTelemetry, DeprecatedNode20Actions, etc.) with locks, preparing for multiple steps executing simultaneously.

SDK step models

Introduces WaitStep, WaitAllStep, and CancelStep pipeline types alongside StepType enum extensions and StepConverter deserialization support.

Timeline & results plumbing

Extends TimelineRecord with IsBackground, StepType, WaitStepIds, CancelStepId, and ParallelGroupId fields. Wires them through ResultsHttpClient and JobServerQueue merge logic.

StepsContext

Refactors locking to use CollectionLock for thread-safe outcome/conclusion/output writes from concurrent background steps.

Related to

https://github.com/github/actions-runtime/issues/5420
https://github.com/github/actions-runtime/issues/5421

Copilot AI review requested due to automatic review settings May 12, 2026 14:25
@lokesh755 lokesh755 requested a review from a team as a code owner May 12, 2026 14:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class “background step” support to the runner by allowing action steps to run concurrently, introducing control steps (wait / wait-all / cancel), and surfacing related metadata to the Results service contracts.

Changes:

  • Introduces new pipeline step types (Wait, WaitAll, Cancel) and runner step implementations to coordinate background execution.
  • Extends StepsRunner to start background actions concurrently, provide wait/cancel semantics, and attempt to isolate per-step GitHub context.
  • Adds Results/RunService contract fields and L0 tests to validate concurrency and metadata propagation.
Show a summary per file
File Description
src/Test/L0/Worker/BackgroundStepsL0.cs Adds L0 coverage for concurrent background steps, waits, cancels, and steps-context thread-safety.
src/Sdk/WebApi/WebApi/ResultsHttpClient.cs Adds mapping of timeline record variables into workflow step payloads (but also includes debug file logging).
src/Sdk/WebApi/WebApi/Contracts.cs Extends Results service Step contract with background/control-step metadata DTOs.
src/Sdk/RSWebApi/Contracts/StepResult.cs Extends RunService step result contract with background/control-step metadata fields.
src/Sdk/DTPipelines/Pipelines/WaitStep.cs Adds pipeline model for a “wait” step.
src/Sdk/DTPipelines/Pipelines/WaitAllStep.cs Adds pipeline model for a “wait-all” step.
src/Sdk/DTPipelines/Pipelines/CancelStep.cs Adds pipeline model for a “cancel” step.
src/Sdk/DTPipelines/Pipelines/StepConverter.cs Enables JSON deserialization for new step types.
src/Sdk/DTPipelines/Pipelines/Step.cs Registers new known step types and extends the StepType enum.
src/Sdk/DTPipelines/Pipelines/ActionStep.cs Adds Background flag and ensures it’s cloned.
src/Runner.Worker/WaitStepRunner.cs Adds runner step type for “wait” control step.
src/Runner.Worker/WaitAllStepRunner.cs Adds runner step type for “wait-all” control step.
src/Runner.Worker/CancelStepRunner.cs Adds runner step type for “cancel” control step.
src/Runner.Worker/StepsRunner.cs Implements background execution, wait/wait-all/cancel handling, slot limiting, and GitHubContext isolation.
src/Runner.Worker/StepsContext.cs Adds locking around step output/outcome/conclusion mutations.
src/Runner.Worker/JobExtension.cs Wires new pipeline step types into job initialization and sets timeline variables for results metadata.
src/Runner.Worker/ExecutionContext.cs Adds timeline-record variable setter and maps those variables into StepResult; adjusts template evaluator feature gating.
src/Runner.Worker/BackgroundStepContext.cs Adds per-background-step tracking (task, CTS, result, external id).

Copilot's findings

Comments suppressed due to low confidence (4)

src/Sdk/WebApi/WebApi/ResultsHttpClient.cs:568

  • File.AppendAllText("/tmp/bg-steps-debug.log", ...) is executed without a try/catch here. If the path is unavailable (e.g., Windows runner, locked filesystem, permissions), it will throw and can break step updates. Remove this statement or guard it behind safe, platform-appropriate diagnostics.

            System.IO.File.AppendAllText("/tmp/bg-steps-debug.log", $"[BG-DEBUG]   Result: name={step.Name}, isBackground={step.IsBackground}, stepType={step.StepType}\n");
            return step;

src/Sdk/WebApi/WebApi/ResultsHttpClient.cs:644

  • Serializing and logging full StepsUpdateRequest JSON payloads to /tmp can expose tokens/PII (steps metadata can contain user-controlled values) and adds unbounded I/O in a hot path. Please remove this debug logging or route it through existing trace logging with appropriate redaction and opt-in controls.
                // DEBUG: Serialize and log the JSON payload
                try
                {
                    var json = Newtonsoft.Json.JsonConvert.SerializeObject(request, Newtonsoft.Json.Formatting.None);
                    System.IO.File.AppendAllText("/tmp/bg-steps-debug.log", $"[BG-DEBUG] JSON payload: {json}\n");
                }
                catch (Exception ex)
                {
                    System.IO.File.AppendAllText("/tmp/bg-steps-debug.log", $"[BG-DEBUG] Serialize error: {ex.Message}\n");
                }

src/Runner.Worker/StepsRunner.cs:605

  • In HandleWaitAsync, the local completed is assigned but never used. With TreatWarningsAsErrors enabled in this repo, this will fail the build. Remove the unused assignment (or use it if intended).
                Trace.Info($"Waiting for {tasks.Count} background step(s)...");
                var cancelTask = Task.Delay(Timeout.Infinite, cancellationToken);
                var completed = await Task.WhenAny(Task.WhenAll(tasks), cancelTask);
                if (cancellationToken.IsCancellationRequested)
                {

src/Runner.Worker/JobExtension.cs:494

  • This sets cancel_step_id on the cancel step timeline record to the logical step id, but later logic expects to publish the background step's external/timeline id. If StepsRunner can't resolve the id, this logical value will be reported upstream. Consider deferring this variable until you can resolve the external id (or always overwrite/clear it during execution).
                            cancelRunner.ExecutionContext.SetTimelineRecordVariable("step_type", "cancel");
                            if (!string.IsNullOrEmpty(cancelRunner.CancelStepId))
                            {
                                cancelRunner.ExecutionContext.SetTimelineRecordVariable("cancel_step_id", cancelRunner.CancelStepId);
                            }
  • Files reviewed: 18/18 changed files
  • Comments generated: 14

Comment thread src/Sdk/WebApi/WebApi/ResultsHttpClient.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Sdk/DTPipelines/Pipelines/WaitAllStep.cs Outdated
Comment thread src/Sdk/DTPipelines/Pipelines/CancelStep.cs Outdated
Comment thread src/Runner.Worker/BackgroundStepContext.cs Outdated
Comment thread src/Test/L0/Worker/BackgroundStepsL0.cs Outdated
Comment thread src/Runner.Worker/ExecutionContext.cs
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/JobExtension.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/BackgroundStepContext.cs Outdated
Comment thread src/Runner.Worker/JobExtension.cs Outdated
Comment thread src/Runner.Worker/StepsContext.cs
Comment thread src/Sdk/WebApi/WebApi/ResultsHttpClient.cs Outdated
Comment thread src/Sdk/WebApi/WebApi/ResultsHttpClient.cs Outdated
Comment thread src/Sdk/WebApi/WebApi/ResultsHttpClient.cs Outdated
Comment thread src/Sdk/WebApi/WebApi/Contracts.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsContext.cs
Comment thread src/Sdk/WebApi/WebApi/Contracts.cs Outdated
Comment thread src/Sdk/WebApi/WebApi/ResultsHttpClient.cs Outdated
Comment thread src/Sdk/WebApi/WebApi/ResultsHttpClient.cs Outdated
Comment thread src/Runner.Worker/GlobalContext.cs
Comment thread src/Runner.Worker/StepsContext.cs
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/ExecutionContext.cs Outdated
Comment thread src/Runner.Worker/ExecutionContext.cs
Comment thread src/Runner.Worker/ExecutionContext.cs Outdated
Comment thread src/Runner.Worker/CancelStepRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/JobExtension.cs Outdated
Comment thread src/Runner.Worker/JobExtension.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Runner.Worker/StepsRunner.cs Outdated
Comment thread src/Sdk/WebApi/WebApi/Contracts.cs Outdated
Comment thread src/Sdk/RSWebApi/Contracts/StepResult.cs Outdated
Comment thread src/Runner.Worker/WaitAllStepRunner.cs Outdated
@lokesh755 lokesh755 force-pushed the lokesh755-background-steps branch from a3ba289 to affa859 Compare June 3, 2026 15:51
@lokesh755 lokesh755 changed the title support background steps Add infrastructure for background step support: thread safety, SDK models, and results plumbing Jun 3, 2026
@lokesh755 lokesh755 force-pushed the lokesh755-background-steps branch from affa859 to 3825592 Compare June 3, 2026 15:56
Comment thread src/Sdk/DTWebApi/WebApi/TimelineRecord.cs Outdated
Comment thread src/Sdk/DTWebApi/WebApi/TimelineRecord.cs
Comment thread src/Sdk/WebApi/WebApi/Contracts.cs Outdated
Comment thread src/Sdk/DTPipelines/Pipelines/Step.cs Outdated
Comment thread src/Sdk/DTWebApi/WebApi/TimelineRecord.cs Outdated
Comment thread src/Sdk/RSWebApi/Contracts/StepResult.cs Outdated
Comment thread src/Sdk/WebApi/WebApi/Contracts.cs Outdated
@lokesh755 lokesh755 force-pushed the lokesh755-background-steps branch from 3825592 to 09598e3 Compare June 3, 2026 20:06
Thread safety:
- Add CollectionLock to GlobalContext, wrap shared collections
  (JobTelemetry, DeprecatedNode20Actions, etc.) with locks

SDK step models:
- Add unified BackgroundStepControl pipeline type with StepType enum
  and StepConverter deserialization support

Timeline & results plumbing:
- Extend TimelineRecord with IsBackground, BackgroundControlType,
  BackgroundControlStepIds, and ParallelGroupId
- Wire through ResultsHttpClient and JobServerQueue merge logic

StepsContext:
- Refactor to use CollectionLock for thread-safe outcome/conclusion/
  output writes from concurrent background steps
@lokesh755 lokesh755 force-pushed the lokesh755-background-steps branch from 09598e3 to bc2513d Compare June 3, 2026 20:26
[DataMember(EmitDefaultValue = false)]
public bool IsBackground;
[DataMember(EmitDefaultValue = false)]
[JsonProperty("backgroundControlType")]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to provide [JsonProperty("backgroundControlType")]?

public string[] StepIds => Data?.StepIds;

[JsonIgnore]
public string ParallelGroupId => Data?.ParallelGroupId;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we move it to JobStep?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants