Conversation
Pre-steps allow users to mint short-lived tokens or perform other setup
that must run in the same job as checkout. This avoids the GitHub Actions
runner masked-value bug (v2.308+) where tokens minted in a separate job
are silently dropped when passed via job outputs.
Users can now reference pre-step outputs in checkout.token:
pre-steps:
- name: Mint token
id: mint
uses: some-org/token-action@v1
checkout:
- repository: target-org/target-repo
token: ${{ steps.mint.outputs.token }}
Changes:
- JSON schema: add pre-steps property
- FrontmatterConfig: add PreSteps field
- WorkflowData: add PreSteps field
- compiler_orchestrator_workflow: add processAndMergePreSteps
- compiler_yaml: add generatePreSteps function
- compiler_yaml_main_job: emit pre-steps before checkout/app-token steps
- strict_mode_steps_validation: include pre-steps in secret validation
- compiler_presteps_test: add tests for pre-steps functionality
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/86c17acc-cd92-4ba9-9c18-c2f101070c71
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
pre-steps to agent job for same-job token minting
There was a problem hiding this comment.
Pull request overview
Adds support for a new pre-steps frontmatter section so workflows can run user-defined steps at the start of the agent job (before checkout and other built-in steps), enabling same-job token minting that avoids masked job-output drops in newer GitHub Actions runners.
Changes:
- Extend schema and Go frontmatter/compiler types to support
pre-steps. - Parse/merge
pre-stepsin the orchestrator (including action pinning) and emit them early in the agent job YAML. - Update strict-mode secrets validation and add compilation tests covering pre-steps ordering and checkout-token usage.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/strict_mode_steps_validation.go | Includes pre-steps in secrets-expression validation. |
| pkg/workflow/frontmatter_types.go | Adds typed PreSteps to frontmatter config + map conversion. |
| pkg/workflow/compiler_yaml.go | Implements generatePreSteps YAML emission helper. |
| pkg/workflow/compiler_yaml_main_job.go | Emits pre-steps early in agent job step sequence. |
| pkg/workflow/compiler_types.go | Adds PreSteps field to WorkflowData. |
| pkg/workflow/compiler_presteps_test.go | Adds tests validating pre-steps ordering and checkout token reference. |
| pkg/workflow/compiler_orchestrator_workflow.go | Extracts and action-pins pre-steps from frontmatter. |
| pkg/parser/schemas/main_workflow_schema.json | Adds pre-steps to workflow frontmatter schema. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 8/8 changed files
- Comments generated: 2
| // Add pre-steps before checkout and any other built-in steps. | ||
| // This allows users to mint short-lived tokens (via custom actions) in the same | ||
| // job as checkout, so the tokens are never dropped by the GitHub Actions runner's | ||
| // add-mask behaviour that silently suppresses masked values across job boundaries. | ||
| // Step outputs are available as ${{ steps.<id>.outputs.<name> }} and can be | ||
| // referenced directly in checkout.token. |
There was a problem hiding this comment.
The comment says pre-steps run "before checkout and any other built-in steps", but in this function OTLP header masking is emitted before pre-steps, and the overall agent job can also prepend setup steps earlier (see buildMainJob in pkg/workflow/compiler_main_job.go). Suggest rewording to clarify that pre-steps run before checkout and the subsequent built-in steps in the agent job (but not necessarily before every earlier compiler-injected setup step).
| // Add pre-steps before checkout and any other built-in steps. | |
| // This allows users to mint short-lived tokens (via custom actions) in the same | |
| // job as checkout, so the tokens are never dropped by the GitHub Actions runner's | |
| // add-mask behaviour that silently suppresses masked values across job boundaries. | |
| // Step outputs are available as ${{ steps.<id>.outputs.<name> }} and can be | |
| // referenced directly in checkout.token. | |
| // Add pre-steps before checkout and the subsequent built-in steps in this agent job. | |
| // This allows users to mint short-lived tokens (via custom actions) in the same | |
| // job as checkout, so the tokens are never dropped by the GitHub Actions runner's | |
| // add-mask behaviour that silently suppresses masked values across job boundaries. | |
| // Step outputs are available as ${{ steps.<id>.outputs.<name> }} and can be | |
| // referenced directly in checkout.token. Some compiler-injected setup steps may | |
| // still be emitted earlier than these pre-steps. |
| pre-steps: | ||
| - name: Mint short-lived token | ||
| id: mint | ||
| uses: some-org/token-minting-action@v1 | ||
| with: | ||
| scope: target-org/target-repo | ||
| steps: | ||
| - name: Custom Setup Step | ||
| run: echo "Custom setup" |
There was a problem hiding this comment.
The test YAML uses unpinned action tags (e.g. some-org/token-minting-action@v1 / some-org/token-action@v1). Because action pinning attempts dynamic resolution via gh api on cache misses (see pkg/workflow/action_pins.go:GetActionPinWithData), this makes the unit test non-hermetic and can trigger network calls / firewall failures. Consider switching these examples to pinned SHAs (like other tests do) or seeding the ActionCache / disabling the ActionResolver for this test so it stays offline/deterministic.
|
@copilot review comments, make it work for imported agentic workflows |
…comments - Add preStepsBuilder to importAccumulator in import_field_extractor.go and extract pre-steps from imported workflow files - Add MergedPreSteps field to ImportsResult in import_processor.go - Update processAndMergePreSteps to accept importsResult and merge imported pre-steps before the main workflow's pre-steps - Update processAndMergePostSteps to accept importsResult and merge imported post-steps after the main workflow's post-steps (fixing a pre-existing gap where MergedPostSteps was built but never consumed) - Fix comment wording in compiler_yaml_main_job.go per reviewer suggestion - Use pinned SHAs (40-char) in test fixtures to avoid network calls - Add unit tests for processAndMergePreSteps and imported post-steps Agent-Logs-Url: https://github.com/github/gh-aw/sessions/088642a3-c500-49a7-a249-a7db5353583e Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…rror in tests Agent-Logs-Url: https://github.com/github/gh-aw/sessions/088642a3-c500-49a7-a249-a7db5353583e Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in commit Pre-steps now work for imported agentic workflows:
Also addressed the reviewer comments:
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
pre-steps to agent job for same-job token mintingpre-steps to agent job for same-job token minting (with import support)
Token-minting actions (e.g. octo-sts,
actions/create-github-app-token) call::add-mask::on their output. GitHub Actions runner v2.308+ silently drops masked values crossing job boundaries, socheckout.token: ${{ needs.auth.outputs.token }}arrives empty at runtime even though compilation succeeds.Solution
New
pre-stepsfrontmatter field: steps that run at the very start of the agent job, before checkout and the subsequent built-in steps. Tokens minted here stay within the same job and are referenceable via${{ steps.<id>.outputs.token }}without hitting the masked-value drop. Pre-steps defined in imported agentic workflows are also merged in (imported steps run first, then the main workflow's pre-steps).Changes
main_workflow_schema.json): addpre-stepspropertyfrontmatter_types.go,compiler_types.go):PreStepsfields onFrontmatterConfigandWorkflowDatacompiler_orchestrator_workflow.go):processAndMergePreStepswith action pinning and import merging, called alongsideprocessAndMergeSteps/processAndMergePostSteps;processAndMergePostStepsupdated to also consumeMergedPostStepsfrom imports (pre-existing gap)compiler_yaml.go,compiler_yaml_main_job.go):generatePreStepsemitted after OTLP masking, before checkout app-token minting and checkout stepsstrict_mode_steps_validation.go):pre-stepsincluded in secrets strict/non-strict check alongsidestepsandpost-stepsimport_field_extractor.go,import_processor.go):pre-stepsextracted from imported workflow files and surfaced asImportsResult.MergedPreStepsfor merging