Context
Reported in #27670. When jobs.pre_activation.pre-steps or jobs.activation.pre-steps are set, injected pre-steps get spliced inside the auto-generated Setup Scripts step instead of after it, producing invalid YAML with duplicate uses:/with: keys that fails actionlint and GitHub Actions at runtime.
Root Cause
In pkg/workflow/compiler_jobs.go, insertPreStepsAfterSetupBeforeCheckout uses the regex (?m)^\s*id:\s*setup\s*$ to find the splice point, then sets insertIdx = lastSetupIdx + 1.
However, generateSetupStep in pkg/workflow/compiler_yaml_step_generation.go emits the Setup Scripts step as multiple separate []string entries (one per YAML line):
- index N:
- name: Setup Scripts\n
- index N+1:
id: setup\n ← regex matches here
- index N+2:
uses: ...\n ← splice happens here, mid-step
This splits the step's YAML block in half.
Objective
Fix the splice-point logic so pre-steps are inserted after the complete Setup Scripts step.
Approach
Choose Option A (preferred) from the issue:
- Detect the end of the
Setup Scripts step by finding the next entry that starts a new step (begins with - at the same indentation level), and use that index as the splice point — rather than lastSetupIdx + 1.
Alternatively:
- Emit the
Setup Scripts step as a single []string entry containing the full multi-line YAML block.
Files to Modify
pkg/workflow/compiler_jobs.go — fix insertPreStepsAfterSetupBeforeCheckout splice logic
pkg/workflow/compiler_yaml_step_generation.go — (if taking single-entry approach) adjust generateSetupStep
pkg/workflow/compiler_jobs_test.go — add regression tests
Acceptance Criteria
Generated by Plan Command for issue #27670 · ● 242.8K · ◷
Context
Reported in #27670. When
jobs.pre_activation.pre-stepsorjobs.activation.pre-stepsare set, injected pre-steps get spliced inside the auto-generatedSetup Scriptsstep instead of after it, producing invalid YAML with duplicateuses:/with:keys that failsactionlintand GitHub Actions at runtime.Root Cause
In
pkg/workflow/compiler_jobs.go,insertPreStepsAfterSetupBeforeCheckoutuses the regex(?m)^\s*id:\s*setup\s*$to find the splice point, then setsinsertIdx = lastSetupIdx + 1.However,
generateSetupStepinpkg/workflow/compiler_yaml_step_generation.goemits theSetup Scriptsstep as multiple separate[]stringentries (one per YAML line):- name: Setup Scripts\nid: setup\n← regex matches hereuses: ...\n← splice happens here, mid-stepThis splits the step's YAML block in half.
Objective
Fix the splice-point logic so pre-steps are inserted after the complete
Setup Scriptsstep.Approach
Choose Option A (preferred) from the issue:
Setup Scriptsstep by finding the next entry that starts a new step (begins with-at the same indentation level), and use that index as the splice point — rather thanlastSetupIdx + 1.Alternatively:
Setup Scriptsstep as a single[]stringentry containing the full multi-line YAML block.Files to Modify
pkg/workflow/compiler_jobs.go— fixinsertPreStepsAfterSetupBeforeCheckoutsplice logicpkg/workflow/compiler_yaml_step_generation.go— (if taking single-entry approach) adjustgenerateSetupSteppkg/workflow/compiler_jobs_test.go— add regression testsAcceptance Criteria
jobs.pre_activation.pre-stepscontaining auses:-style step compiles to valid YAMLjobs.activation.pre-stepscontaining arun:-style step compiles to valid YAML.lock.ymlpassesactionlintSetup Scriptsstep and before the firstactions/checkout@*steppre_activationandactivationwithuses:andrun:pre-stepsmake agent-finishpassesRelated to on.github-app credentials cannot be sourced from a custom job's outputs (jobs.{pre_activation,activation}.pre-steps splicing/needs bugs + missing on.needs API) #27670