Fix malformed version: crash for gh --repo in DIFC proxy steps#35293
Conversation
…Vars()
The DIFC proxy was injecting GH_HOST=localhost:18443 as step-level env on
custom steps. The gh CLI treats any non-github.com/non-*.ghe.com host as
GHES and performs a /meta version check before --repo calls. The proxy
forwards the check to github.com, which omits installed_version, causing
gh to fail with "malformed version: ".
Fix: use ${{ env.GH_HOST || 'github.com' }} instead of localhost:18443.
This picks up the identity host set by configure_gh_for_ghe.sh:
- github.com/GHEC: gh skips the GHES version check entirely
- GHES: gh does the version check via GITHUB_API_URL (proxy -> real GHES)
All API traffic continues to flow through the proxy via GITHUB_API_URL.
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
malformed version: crash for gh --repo in DIFC proxy steps
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed for PR #35293: PR does not have the 'implementation' label and has only 54 new lines (≤100 threshold) in business logic directories. |
|
🧪 Test Quality Sentinel completed test quality analysis. |
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
|
✅ PR Code Quality Reviewer completed the code quality review. |
|
🚀 Smoke Pi MISSION COMPLETE! Pi delivered. 🥧 |
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 |
|
🚀 Smoke Antigravity MISSION COMPLETE! Antigravity has spoken. ✨ |
|
🚀 Smoke Gemini MISSION COMPLETE! Gemini has spoken. ✨ Testing safeoutputs CLI |
|
💫 TO BE CONTINUED... Smoke Claude failed! Our hero faces unexpected challenges... |
There was a problem hiding this comment.
Pull request overview
Fixes a malformed version: crash in gh --repo calls within DIFC proxy-protected custom steps by switching the injected GH_HOST from the proxy address (localhost:18443) to the identity host expression ${{ env.GH_HOST || 'github.com' }}, which is supplied by the preceding configure_gh_for_ghe.sh step.
Changes:
- Replace hardcoded
GH_HOST: localhost:18443inproxyEnvVars()with${{ env.GH_HOST || 'github.com' }}soghdoesn't misclassify the proxy as GHES. - Expand function-level and call-site comments documenting the rationale across github.com / GHEC / GHES deployments.
- Update tests and the changeset to reflect the new value and root-cause analysis.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/compiler_difc_proxy.go | Change injected GH_HOST value and document deployment-type rationale. |
| pkg/workflow/compiler_difc_proxy_test.go | Update assertions for new GH_HOST expression. |
| .changeset/patch-fix-difc-proxy-gh-host-mismatch.md | Rewrite changeset to describe the actual fix and root cause. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 0
Agent Container Tool Check
Result: 12/12 tools available ✅ Overall Status: PASS
|
|
Smoke test results: GitHub-MCP:✅, Web-Fetch:✅, File-Write:✅, Bash:✅, Build:❌. Overall: FAIL Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "localhost"See Network Configuration for more information.
|
There was a problem hiding this comment.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 1.2M
|
|
||
| require.NotEmpty(t, vars, "proxyEnvVars should return a non-empty map") | ||
| assert.Equal(t, "localhost:18443", vars["GH_HOST"], "GH_HOST should be the proxy address") | ||
| // GH_HOST should use the identity host expression, not the proxy address. |
There was a problem hiding this comment.
[/tdd] The unit test for proxyEnvVars verifies the expression string is correct, but there's no test case explicitly covering the GHES deployment path (where env.GH_HOST holds a real enterprise hostname like ghes.example.com). Since the expression is evaluated at GitHub Actions runtime rather than compile time, a companion test with a table-driven case or a descriptive comment would make the intent of each deployment scenario explicit as a living spec.
💡 Example: add a table-driven scenario to TestInjectProxyEnvIntoCustomSteps
// Add to TestInjectProxyEnvIntoCustomSteps test table to document the GHES scenario
{
name: "GHES: expression selects real GHES hostname at runtime",
customSteps: "steps:\n- name: gh call\n run: gh issue list --repo owner/repo\n",
expectedContains: []string{
// The injected expression picks up the hostname set by configure_gh_for_ghe.sh;
// on GHES this resolves to the real GHES host, not the proxy address.
"GH_HOST: ${{ env.GH_HOST || 'github.com' }}",
"GITHUB_API_URL: (localhost/redacted),
},
desc: "GHES path: identity host expression injected; API traffic still routes via proxy",
},The test already exists as a string assertion, so this is low-effort to add and documents intent clearly.
There was a problem hiding this comment.
Smoke test reply: noted, and the existing assertion line is a good anchor for the GH_HOST identity-host behavior.
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · gpt55 3.3M
🧪 Test Quality Sentinel Report✅ Test Quality Score: 97/100 — Excellent
📊 Metrics & Test Classification (3 tests analyzed)
Test Classification Details
Language SupportTests analyzed:
Verdict
📖 Understanding Test ClassificationsDesign Tests (High Value) verify what the system does:
Implementation Tests (Low Value) verify how the system does it:
Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.
|
There was a problem hiding this comment.
LGTM — focused, correct fix
The GH_HOST=localhost:18443 root cause is clearly understood and well-documented. The expression ${{ env.GH_HOST || 'github.com' }} correctly resolves to the right identity host for all three deployment types (github.com, GHEC, GHES) without breaking proxy routing through GITHUB_API_URL.
Analysis details
What I checked:
-
Self-referential env — step-level
env:expressions are evaluated before the step executes, soenv.GH_HOSTreads the job-level value (written byconfigure_gh_for_ghe.shviaGITHUB_ENV) without any circular reference. -
YAML single-quote serialization — the value contains single quotes. Regardless of whether the YAML serializer emits them as a plain scalar or single-quoted scalar (doubling the internal quotes), the post-YAML-parse value is identical and GitHub Actions evaluates the expression correctly.
-
Ordering dependency — the fix implicitly requires
configure_gh_for_ghe.shto have run before any custom step receives the injected env. Based on the compiler flow described in the file header (proxy starts after "Configure gh CLI"), this ordering is architecturally guaranteed — not a new risk introduced by this PR. -
GHES proxy forwarding — the claim that the proxy forwards
/api/v3/metato the real GHES upstream (returninginstalled_version) is an assumption about proxy behavior not verifiable from this diff, but it is the same assumption the existing GHES proxy support relies on and is clearly documented. -
Test coverage — tests verify the correct expression string is emitted in compiled output. Runtime expression resolution is GitHub Actions behavior and not testable at the Go unit test level. Coverage is appropriate.
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
proxy.golang.org
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "proxy.golang.org"See Network Configuration for more information.
🔎 Code quality review by PR Code Quality Reviewer · sonnet46 2M
|
Smoke test run Merged PRs: #35275 "Widen review_path_unresolved_422 safe-output fallback to match 'Path could not be resolved'"; #35274 "refactor(cli): consolidate local tokenClassWeights into types.TokenClassWeights" Result: FAIL
Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
Comment MemoryNote This comment is managed by comment memory.It stores persistent context for this thread in the code block at the top of this comment. Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
|
PRs: Refactor docs landing-page guardrails section into visual security overview; Add cost management guidance to the docs home page; Fix Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
Smoke review complete: checked the DIFC proxy GH_HOST changes and regression assertions.
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · gpt55 3.3M
| "GH_HOST": "localhost:18443", | ||
| // Identity host from configure_gh_for_ghe.sh, not the proxy address. | ||
| // See function-level comment for full rationale. | ||
| "GH_HOST": "${{ env.GH_HOST || 'github.com' }}", |
There was a problem hiding this comment.
Smoke review: this is the core behavior change, keeping GH_HOST as the identity host while proxying API URLs.
| require.NotEmpty(t, vars, "proxyEnvVars should return a non-empty map") | ||
| assert.Equal(t, "localhost:18443", vars["GH_HOST"], "GH_HOST should be the proxy address") | ||
| // GH_HOST should use the identity host expression, not the proxy address. | ||
| assert.Equal(t, "${{ env.GH_HOST || 'github.com' }}", vars["GH_HOST"], "GH_HOST should use the identity host from configure_gh_for_ghe.sh, not the proxy address") |
There was a problem hiding this comment.
Smoke review: this assertion directly captures the regression guard for the gh --repo crash scenario.
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
|
@copilot investigate why the playwright cli skills is failing to install https://github.com/github/gh-aw/actions/runs/26537099387/job/78168949897 |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
When the DIFC proxy is active, every custom step received
GH_HOST=localhost:18443as step-level env. TheghCLI treats any non-github.com/non-*.ghe.comhost as GHES and performs a/api/v3/metaversion check before--repocalls. The proxy forwards this to github.com, which omitsinstalled_version, soghaborts withmalformed version:.Changes
proxyEnvVars()— changeGH_HOSTfromlocalhost:18443to${{ env.GH_HOST || 'github.com' }}, picking up the identity host written by the precedingconfigure_gh_for_ghe.shstep:*.ghe.com): resolves togithub.comortenant.ghe.com→ghskips the GHES version check; API traffic still routes through the proxy viaGITHUB_API_URLghperforms the version check viaGITHUB_API_URL(proxy → real GHES/meta) which returnsinstalled_versionand passesComments —
proxyEnvVars()andinjectProxyEnvIntoCustomSteps()now document why GH_HOST must differ between GHES and non-GHES environmentsTests — updated to assert the new expression; changeset updated to accurately describe the fix