Skip to content

fix: propagate environment: frontmatter field to all safe-output jobs#20384

Merged
pelikhan merged 3 commits intomainfrom
copilot/fix-safe-outputs-environment-field
Mar 10, 2026
Merged

fix: propagate environment: frontmatter field to all safe-output jobs#20384
pelikhan merged 3 commits intomainfrom
copilot/fix-safe-outputs-environment-field

Conversation

Copy link
Contributor

Copilot AI commented Mar 10, 2026

The environment: frontmatter field was only applied to the agent job. All other compiler-generated jobs ran without any environment context, making environment-scoped secrets (e.g., GitHub App credentials for token minting) silently inaccessible.

Changes

  • SafeOutputsConfig: Added Environment field to support an explicit per-job environment override (safe-outputs.environment:)
  • safe_outputs_config.go: Parses environment from the safe-outputs map (string or name/url object, consistent with top-level field)
  • compiler_safe_outputs_job.go: Added resolveSafeOutputsEnvironment() helper that uses safe-outputs.environment if set, otherwise falls back to the top-level environment: value. Applies to the safe_outputs job.
  • notify_comment.go: Applies resolved environment to the conclusion job
  • safe_outputs_jobs.go: Applies resolved environment to jobs built via buildSafeOutputJob (e.g. upload_assets)
  • safe_jobs.go: Applies resolved environment to custom safe-jobs (safe-outputs.jobs)
  • compiler_pre_activation_job.go: Applies resolved environment to the pre_activation job
  • main_workflow_schema.json: Adds environment as an allowed property under safe-outputs

Behavior

# Top-level environment is now automatically propagated to all safe-output jobs:
environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
safe-outputs:
  github-app:
    app-id: ${{ secrets.WORKFLOW_APP_ID }}          # now accessible in all jobs
    private-key: ${{ secrets.WORKFLOW_APP_PRIVATE_KEY }}

# Or override explicitly for safe-output jobs only:
safe-outputs:
  environment: dev   # overrides top-level environment for all safe-output jobs

All compiler-generated safe-output jobs (safe_outputs, conclusion, pre_activation, custom safe-jobs, upload_assets) will now include the environment field:

safe_outputs:
  environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
conclusion:
  environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
pre_activation:
  environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}

🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

…ts-environment-field)

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix environment frontmatter propagation to safe_outputs job fix: propagate environment: frontmatter field to safe_outputs job Mar 10, 2026
@pelikhan
Copy link
Contributor

@copilot apply to pr jobs too

… pre_activation, safe-jobs, upload_assets)

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 10, 2026

@copilot apply to pr jobs too

Done in 597a0c9. The environment is now propagated to all compiler-generated safe-output jobs: conclusion, pre_activation, custom safe-jobs (safe-outputs.jobs), and upload_assets. Added a resolveSafeOutputsEnvironment() helper to centralize the override-or-fallback logic.

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:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD GOMODCACHE git rev-�� --show-toplevel GOPROXY /usr/bin/git GOSUMDB GOWORK 64/bin/go git (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha -json GO111MODULE ache/go/1.25.0/x64/bin/bash GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha g/mathutil/mathuGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD ode-gyp-bin/node-json ache/go/1.25.0/xGO111MODULE env 3889154/b369/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE b/gh-aw/tmp GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -json GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel ache/go/1.25.0/xGO111MODULE /usr/bin/git 3889154/b357/_pkgit GO111MODULE 64/bin/go git rev-�� --show-toplevel go /usr/bin/git dE7X/UmkCwvEwafxgit GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel ortcfg /usr/bin/git g/timeutil/formagit g/timeutil/formarev-parse 64/bin/go git rev-�� --show-toplevel ache/go/1.25.0/xGO111MODULE /usr/bin/git 3889154/b415/_pkgit GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go git rev-�� lcache -maxdepth 4 -type d -name bin 2&gt;/dev/null | tr &#39;\n&#39; &#39;:&#39;)$PATH&#34;; [ -n &#34;$GOROOT&#34; ] &amp;&amp; exporgit ache/go/1.25.0/xGO111MODULE /usr/bin/git 3889154/b419/_pkgit GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE ortcfg env bf0813d7488cf446GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE ache/go/1.25.0/xGO111MODULE (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE ortcfg env 80bf13b2620176ebGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE ache/go/1.25.0/xGO111MODULE (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title fix: propagate environment: frontmatter field to safe_outputs job fix: propagate environment: frontmatter field to all safe-output jobs Mar 10, 2026
@pelikhan pelikhan marked this pull request as ready for review March 10, 2026 18:09
Copilot AI review requested due to automatic review settings March 10, 2026 18:09
@pelikhan pelikhan merged commit 5cc49e8 into main Mar 10, 2026
80 checks passed
@pelikhan pelikhan deleted the copilot/fix-safe-outputs-environment-field branch March 10, 2026 18:09
Copy link
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

This PR ensures the workflow-level environment: context is propagated to all compiler-generated safe-output jobs so environment-scoped secrets are available outside the agent job, with support for an explicit safe-outputs.environment override.

Changes:

  • Add SafeOutputsConfig.Environment and parse safe-outputs.environment from frontmatter.
  • Introduce resolveSafeOutputsEnvironment() and apply the resolved environment to all safe-output job builders (safe_outputs, conclusion, pre_activation, custom safe-jobs, and jobs created via buildSafeOutputJob).
  • Extend schema to allow safe-outputs.environment and add an integration test covering propagation to safe_outputs.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/workflow/safe_outputs_jobs.go Applies resolved environment to jobs built via buildSafeOutputJob.
pkg/workflow/safe_outputs_config.go Extracts/parses safe-outputs.environment from frontmatter into config.
pkg/workflow/safe_jobs.go Applies resolved environment to custom safe-jobs (safe-outputs.jobs).
pkg/workflow/notify_comment.go Applies resolved environment to the conclusion job.
pkg/workflow/environment_test.go Adds an integration test asserting env propagation to safe_outputs.
pkg/workflow/compiler_types.go Adds Environment field to SafeOutputsConfig.
pkg/workflow/compiler_safe_outputs_job.go Adds resolveSafeOutputsEnvironment() and applies env to safe_outputs.
pkg/workflow/compiler_pre_activation_job.go Applies resolved environment to pre_activation job.
pkg/parser/schemas/main_workflow_schema.json Allows environment under safe-outputs in schema.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

"examples": ["my-workflow-safe-outputs", "safe-outputs-${{ github.repository }}"]
},
"environment": {
"description": "Override the GitHub deployment environment for the safe-outputs job. When set, this environment is used instead of the top-level environment: field. When not set, the top-level environment: field is propagated automatically so that environment-scoped secrets are accessible in the safe-outputs job.",
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The schema description says the safe-outputs.environment override (and top-level propagation) applies to the “safe-outputs job”, but the implementation applies it to all safe-output jobs (including conclusion, pre_activation, upload_assets, and custom safe-jobs). Please update the description to match the implemented behavior so users aren’t surprised by environment protections/secret scoping across those jobs.

Suggested change
"description": "Override the GitHub deployment environment for the safe-outputs job. When set, this environment is used instead of the top-level environment: field. When not set, the top-level environment: field is propagated automatically so that environment-scoped secrets are accessible in the safe-outputs job.",
"description": "Override the GitHub deployment environment for all safe-output jobs (including the main safe-outputs job, conclusion, pre_activation, upload_assets, and any custom safe-output jobs). When set, this environment is used instead of the top-level environment: field. When not set, the top-level environment: field is propagated automatically so that environment-scoped secrets are accessible across all safe-output jobs.",

Copilot uses AI. Check for mistakes.
Comment on lines +227 to +233
// TestSafeOutputsEnvironmentPropagation verifies that the top-level environment: field is
// propagated to the safe_outputs job so that environment-scoped secrets are accessible.
func TestSafeOutputsEnvironmentPropagation(t *testing.T) {
tests := []struct {
name string
frontmatter string
expectEnvInSafe bool
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

This test only asserts environment propagation for the safe_outputs job, but the PR also adds environment propagation to other generated safe-output jobs (e.g., conclusion, pre_activation, upload_assets, and custom safe-jobs). Please extend test coverage to assert at least one additional job (conclusion or pre_activation) receives the resolved environment, so future changes don’t regress propagation on those jobs silently.

Copilot uses AI. Check for mistakes.
Steps []any `yaml:"steps,omitempty"` // User-provided steps injected after setup/checkout and before safe-output code
IDToken *string `yaml:"id-token,omitempty"` // Override id-token permission: "write" to force-add, "none" to disable auto-detection
ConcurrencyGroup string `yaml:"concurrency-group,omitempty"` // Concurrency group for the safe-outputs job (cancel-in-progress is always false)
Environment string `yaml:"environment,omitempty"` // Override the GitHub deployment environment for the safe-outputs job (defaults to the top-level environment: field)
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The new SafeOutputsConfig.Environment field/comment says it overrides the environment for the “safe-outputs job”, but this PR applies the resolved environment to multiple safe-output jobs (safe_outputs, conclusion, pre_activation, buildSafeOutputJob jobs, and custom safe-jobs). Please update the field comment to reflect that it overrides the deployment environment for all safe-output jobs (or adjust behavior to match the comment).

Suggested change
Environment string `yaml:"environment,omitempty"` // Override the GitHub deployment environment for the safe-outputs job (defaults to the top-level environment: field)
Environment string `yaml:"environment,omitempty"` // Override the GitHub deployment environment for all safe-output jobs (defaults to the top-level environment: field)

Copilot uses AI. Check for mistakes.
Comment on lines +509 to +512
// Handle environment configuration (override for safe-outputs job; falls back to top-level environment)
config.Environment = c.extractTopLevelYAMLSection(outputMap, "environment")
if config.Environment != "" {
safeOutputsConfigLog.Printf("Configured environment override for safe-outputs job: %s", config.Environment)
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

This log message and nearby comment refer to an environment override “for safe-outputs job”, but the resolved environment is used for all safe-output jobs in this PR. Please adjust wording to avoid misleading operators when reading logs/debugging.

Suggested change
// Handle environment configuration (override for safe-outputs job; falls back to top-level environment)
config.Environment = c.extractTopLevelYAMLSection(outputMap, "environment")
if config.Environment != "" {
safeOutputsConfigLog.Printf("Configured environment override for safe-outputs job: %s", config.Environment)
// Handle environment configuration (override for all safe-outputs jobs; falls back to top-level environment)
config.Environment = c.extractTopLevelYAMLSection(outputMap, "environment")
if config.Environment != "" {
safeOutputsConfigLog.Printf("Configured environment override for all safe-outputs jobs: %s", config.Environment)

Copilot uses AI. Check for mistakes.
github-actions bot added a commit that referenced this pull request Mar 11, 2026
Add reference section for the `safe-outputs.environment:` frontmatter
field, which allows specifying a deployment environment for all
compiler-generated safe-output jobs. The top-level `environment:` field
is now automatically propagated to safe-output jobs; this new field
allows overriding it independently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

environment: frontmatter field not propagated to safe_outputs job — breaks environment-level secrets

3 participants