You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
the value never reaches the safe-outputs MCP server, so create_pull_request fails with:
ERR_SYSTEM: No remote refs available for merge-base calculation
and no pull request is created.
The compiler stores the value in config.json as the placeholder"base_branch":"${GH_AW_INPUT_BASE_BRANCH}" and relies on the MCP server resolving it at read-time from process.env.GH_AW_INPUT_BASE_BRANCH. Since the safe-outputs MCP server was moved into a container (#39100), GH_AW_INPUT_* is not in the container's -e env allowlist, so the placeholder is never substituted. The MCP then tries to compute a merge-base against a branch literally named ${GH_AW_INPUT_BASE_BRANCH} and throws.
This is a regression: it worked on v0.79.8 (MCP ran as an HTTP sidecar that inherited the full step env) and broke in v0.80.0 (MCP containerized with a filtered env allowlist).
Impact
create_pull_request is broken for any workflow using a dynamic base-branch: ${{ inputs.* }} — no PR is produced, only a report_incomplete/noop.
The same read-time-substitution path is used for other input-derived safe-outputs config values (e.g. allowed_base_branches, target-repo inputs), so those are affected too.
Compilation succeeds; the failure only surfaces at runtime inside the MCP container, making it hard to diagnose.
A staticbase-branch: develop works (it compiles to a literal, needing no substitution), which can mask the bug.
Environment
Reproduced on v0.82.14; re-verified byte-identical on v0.83.1 (latest stable) and v0.83.2 (pre-release).
Regression bisected to v0.80.0 (worked on v0.79.8).
Engine: copilot. Observed with runner.topology: arc-dind, but the cause (container env allowlist) is topology-independent.
Minimal reproduction
.github/workflows/repro.md:
---on:
workflow_dispatch:
inputs:
base_branch:
required: falsedefault: developtype: stringruns-on: ubuntu-latestpermissions:
contents: readengine:
id: copilotsafe-outputs:
create-pull-request:
base-branch: ${{ inputs.base_branch }}---# Repro
Make a trivial change and open a PR.
Then gh aw compile repro and inspect repro.lock.yml:
The step env sets GH_AW_INPUT_BASE_BRANCH: ${{ inputs.base_branch }} (correct).
But the safe-outputs MCP docker run command's -e allowlist contains no GH_AW_INPUT_* entry — so the container process never sees GH_AW_INPUT_BASE_BRANCH.
At runtime the MCP logs (with DEBUG) show the literal placeholder:
[generate_git_patch] Strategy 1 (full): Computing merge-base with ${GH_AW_INPUT_BASE_BRANCH} ...
git show-ref --verify --quiet refs/remotes/origin/${GH_AW_INPUT_BASE_BRANCH} (fails)
Strategy 1 (full): No remote refs available ... ERR_SYSTEM: No remote refs available for merge-base calculation
Root cause
Permalinks pinned to 6e6860cce13c4eff003828de391f7db980e60920 (main; identical behavior on v0.82.14/v0.83.1/v0.83.2):
By design — inputs are extracted to a GH_AW_INPUT_* step env and written into config.json as a shell-style placeholder:
pkg/workflow/secret_extraction.go maps ${{ inputs['base-branch'] }} → env GH_AW_INPUT_BASE_BRANCH + placeholder ${GH_AW_INPUT_BASE_BRANCH} (see the doc comment around L305–L346).
pkg/workflow/mcp_setup_generator.go#L283 writes config.json via a single-quoted heredoc (no shell expansion — intended; resolution is deferred to the reader).
actions/setup/js/safe_outputs_config.cjs#L20 resolves placeholders at read-time:
Note the ?? match: if the env var is absent, the literal placeholder is kept.
The regression — the safe-outputs MCP server was moved into a container in Run safe-outputs MCP in the gh-aw node container #39100 (ce429bfcc3, v0.80.0). The container is launched with an explicit -e VAR allowlist built by pkg/workflow/mcp_setup_generator.go#L783 (appendMCPGatewayBaseEnvFlags) — it passes GITHUB_*, DEFAULT_BRANCH, RUNNER_TEMP, GH_AW_SAFE_OUTPUTS*, etc., but no GH_AW_INPUT_*. So inside the container process.env.GH_AW_INPUT_BASE_BRANCH is undefined, safe_outputs_config.cjs#L20 keeps the literal, and actions/setup/js/generate_git_bundle.cjs#L212 throws No remote refs available for merge-base calculation.
Before #39100 the MCP ran as an HTTP sidecar that inherited the whole step environment (including GH_AW_INPUT_BASE_BRANCH), so the substitution resolved and PRs were created — which is why v0.79.8 works and v0.80.0+ does not.
v0.80.0 (ce429bfcc3 / Run safe-outputs MCP in the gh-aw node container #39100 "Run safe-outputs MCP in the gh-aw node container"): MCP containerized with filtered -e allowlist omitting GH_AW_INPUT_* → placeholder unresolved → merge-base throw. ❌
Still reproduces on v0.83.1 and v0.83.2 (GH_AW_INPUT_* still absent from the -e list).
Implementation plan
Pass GH_AW_INPUT_* into the MCP container — pkg/workflow/mcp_setup_generator.go, appendMCPGatewayBaseEnvFlags (~L783): add the input-derived env vars the safe-outputs config depends on to the -e allowlist. Prefer forwarding all GH_AW_INPUT_* that were emitted for this workflow (they're already computed by secret_extraction.go) rather than hard-coding GH_AW_INPUT_BASE_BRANCH, so allowed_base_branches / target-repo inputs are covered too.
Test — extend the safe-outputs compile tests (e.g. pkg/workflow/safe_outputs_dynamic_allowed_repos_test.go, which already checks GH_AW_INPUT_BASE_BRANCH in the step env and the ${GH_AW_INPUT_BASE_BRANCH} config placeholder): add an assertion that the generated MCP container docker run command includes -e GH_AW_INPUT_BASE_BRANCH (and generally the GH_AW_INPUT_* the config references).
Optional hardening — in safe_outputs_config.cjs, when a ${GH_AW_INPUT_*} placeholder cannot be resolved, emit a clear error (or core.warning) instead of silently passing the literal through to generate_git_bundle.cjs, so the failure mode is diagnosable rather than surfacing later as No remote refs available for merge-base calculation.
Docs/guidelines — follow the console/error-message style guide; run make agent-finish before completing.
Notes
Diagnosed with the agentic-workflows dispatcher + source bisection on the local github/gh-aw clone.
Workaround for consumers meanwhile: hardcode a literal create-pull-request.base-branch: <branch> (compiles to a literal, needs no substitution).
Summary
For
safe-outputs.create-pull-requestwith a dynamicbase-branchthat references a workflow input:the value never reaches the safe-outputs MCP server, so
create_pull_requestfails with:and no pull request is created.
The compiler stores the value in
config.jsonas the placeholder"base_branch":"${GH_AW_INPUT_BASE_BRANCH}"and relies on the MCP server resolving it at read-time fromprocess.env.GH_AW_INPUT_BASE_BRANCH. Since the safe-outputs MCP server was moved into a container (#39100),GH_AW_INPUT_*is not in the container's-eenv allowlist, so the placeholder is never substituted. The MCP then tries to compute a merge-base against a branch literally named${GH_AW_INPUT_BASE_BRANCH}and throws.This is a regression: it worked on v0.79.8 (MCP ran as an HTTP sidecar that inherited the full step env) and broke in v0.80.0 (MCP containerized with a filtered env allowlist).
Impact
create_pull_requestis broken for any workflow using a dynamicbase-branch: ${{ inputs.* }}— no PR is produced, only areport_incomplete/noop.allowed_base_branches, target-repo inputs), so those are affected too.base-branch: developworks (it compiles to a literal, needing no substitution), which can mask the bug.Environment
copilot. Observed withrunner.topology: arc-dind, but the cause (container env allowlist) is topology-independent.Minimal reproduction
.github/workflows/repro.md:Then
gh aw compile reproand inspectrepro.lock.yml:GH_AW_INPUT_BASE_BRANCH: ${{ inputs.base_branch }}(correct).docker runcommand's-eallowlist contains noGH_AW_INPUT_*entry — so the container process never seesGH_AW_INPUT_BASE_BRANCH.At runtime the MCP logs (with
DEBUG) show the literal placeholder:Root cause
Permalinks pinned to
6e6860cce13c4eff003828de391f7db980e60920(main; identical behavior on v0.82.14/v0.83.1/v0.83.2):By design — inputs are extracted to a
GH_AW_INPUT_*step env and written intoconfig.jsonas a shell-style placeholder:pkg/workflow/secret_extraction.gomaps${{ inputs['base-branch'] }}→ envGH_AW_INPUT_BASE_BRANCH+ placeholder${GH_AW_INPUT_BASE_BRANCH}(see the doc comment around L305–L346).pkg/workflow/mcp_setup_generator.go#L283writesconfig.jsonvia a single-quoted heredoc (no shell expansion — intended; resolution is deferred to the reader).actions/setup/js/safe_outputs_config.cjs#L20resolves placeholders at read-time:?? match: if the env var is absent, the literal placeholder is kept.The regression — the safe-outputs MCP server was moved into a container in Run safe-outputs MCP in the gh-aw node container #39100 (
ce429bfcc3, v0.80.0). The container is launched with an explicit-e VARallowlist built bypkg/workflow/mcp_setup_generator.go#L783(appendMCPGatewayBaseEnvFlags) — it passesGITHUB_*,DEFAULT_BRANCH,RUNNER_TEMP,GH_AW_SAFE_OUTPUTS*, etc., but noGH_AW_INPUT_*. So inside the containerprocess.env.GH_AW_INPUT_BASE_BRANCHisundefined,safe_outputs_config.cjs#L20keeps the literal, andactions/setup/js/generate_git_bundle.cjs#L212throwsNo remote refs available for merge-base calculation.Before #39100 the MCP ran as an HTTP sidecar that inherited the whole step environment (including
GH_AW_INPUT_BASE_BRANCH), so the substitution resolved and PRs were created — which is why v0.79.8 works and v0.80.0+ does not.Regression bisection
${GH_AW_INPUT_BASE_BRANCH}resolves → PR created. ✅ce429bfcc3/ Run safe-outputs MCP in the gh-aw node container #39100 "Run safe-outputs MCP in the gh-aw node container"): MCP containerized with filtered-eallowlist omittingGH_AW_INPUT_*→ placeholder unresolved → merge-base throw. ❌GH_AW_INPUT_*still absent from the-elist).Implementation plan
GH_AW_INPUT_*into the MCP container —pkg/workflow/mcp_setup_generator.go,appendMCPGatewayBaseEnvFlags(~L783): add the input-derived env vars the safe-outputs config depends on to the-eallowlist. Prefer forwarding allGH_AW_INPUT_*that were emitted for this workflow (they're already computed bysecret_extraction.go) rather than hard-codingGH_AW_INPUT_BASE_BRANCH, soallowed_base_branches/ target-repo inputs are covered too.pkg/workflow/safe_outputs_dynamic_allowed_repos_test.go, which already checksGH_AW_INPUT_BASE_BRANCHin the step env and the${GH_AW_INPUT_BASE_BRANCH}config placeholder): add an assertion that the generated MCP containerdocker runcommand includes-e GH_AW_INPUT_BASE_BRANCH(and generally theGH_AW_INPUT_*the config references).safe_outputs_config.cjs, when a${GH_AW_INPUT_*}placeholder cannot be resolved, emit a clear error (orcore.warning) instead of silently passing the literal through togenerate_git_bundle.cjs, so the failure mode is diagnosable rather than surfacing later asNo remote refs available for merge-base calculation.make agent-finishbefore completing.Notes
agentic-workflowsdispatcher + source bisection on the localgithub/gh-awclone.create-pull-request.base-branch: <branch>(compiles to a literal, needs no substitution).