Skip to content

Compiler does not inject GH_HOST or telemetry domain for GHE Cloud data residency (*.ghe.com) #21407

Description

@lpcox

Summary

The gh aw compile command does not inject GH_HOST into workflow steps that use the gh CLI on GHE Cloud with data residency instances (*.ghe.com). This causes all gh CLI commands (like gh issue list, gh pr list) to fail with:

none of the git remotes configured for this repository point to a known GitHub host.
To tell gh about a new GitHub host, please use `gh auth login`

Additionally, the compiler does not add copilot-telemetry-service.<slug>.ghe.com to the firewall allowed domains list.

Environment

  • gh-aw: v0.60.0
  • Platform: GHE Cloud with data residency (EU)
  • Domain: contoso-aw.ghe.com
  • Workflow: repo-assist (from githubnext/agentics)

Reproduction

  1. Create a workflow on a GHE Cloud data residency instance with api-target: "copilot-api.<slug>.ghe.com" in frontmatter
  2. Run gh aw compile <workflow>
  3. Dispatch the compiled lock file
  4. The first step that uses gh CLI fails (e.g., "Fetch repo data for task weighting")

Evidence: Run 22287496 on contoso-aw.ghe.com/platform/aw-test — freshly compiled lock file, no manual edits. Fails at the very first gh CLI step.

Gap 1: GH_HOST not injected (BREAKING)

The compiled lock file does not set GH_HOST for steps that invoke the gh CLI. On *.ghe.com instances, the gh CLI requires GH_HOST to know which GitHub host to target.

Steps that need GH_HOST: <slug>.ghe.com:

  • "Fetch repo data for task weighting" (uses gh issue list, gh pr list)
  • "Clone repo-memory branch" (uses gh for git operations)
  • "Execute GitHub Copilot CLI" (Copilot CLI needs GH_HOST for auth)
  • Any other step that calls gh commands

The compiler already sets GH_HOST: github.com in one place (line 441 in the compiled output). For *.ghe.com instances, it should derive the correct value from GITHUB_SERVER_URL or the api-target frontmatter field.

Workaround: Manually add GH_HOST: <slug>.ghe.com to the env block of every gh-using step in the lock file. This gets wiped on every recompile.

Gap 2: copilot-telemetry-service domain missing (NON-BREAKING but suboptimal)

The compiler auto-adds copilot-api.<slug>.ghe.com to --allow-domains (fixed in gh-aw-firewall#1331), but does NOT add copilot-telemetry-service.<slug>.ghe.com.

HTTP traffic capture (run 22235251) showed the Copilot CLI contacts 4 hosts on data residency:

Host In compiled allow-list?
api.<slug>.ghe.com ✅ Yes
copilot-api.<slug>.ghe.com ✅ Yes
copilot-telemetry-service.<slug>.ghe.com ❌ No
api.githubcopilot.com ✅ Yes

The telemetry domain is likely non-fatal (the CLI works without it), but telemetry requests will be blocked by the firewall, which may cause delays or warnings.

Note: gh-aw-firewall#1331 added telemetry domain auto-injection in extractGhecDomainsFromServerUrl(), but the gh-aw compiler may not be calling that function or may have its own domain list.

Comparison Methodology

Created a copy of the working (manually fixed) repo-assist.md, compiled it fresh with gh aw compile, then diffed the two lock files:

Manual lock file:  2141 lines (working — run 22240726 succeeded)
Compiled lock file: 1529 lines (failing — run 22287496 failed)

Key differences (excluding diagnostic steps we'd added):

  • GH_HOST: contoso-aw.ghe.com present in 4 places in manual, 0 in compiled
  • copilot-telemetry-service.contoso-aw.ghe.com in manual allow-list, absent in compiled
  • copilot-api-target correctly set in both (compiler gets this right ✅)
  • copilot-api.contoso-aw.ghe.com in allow-list in both (compiler gets this right ✅)

Suggested Fix

In the compiler, when GITHUB_SERVER_URL is a *.ghe.com domain:

  1. Inject GH_HOST: <hostname> into the env: block of every step that uses gh CLI commands or the Copilot CLI
  2. Add copilot-telemetry-service.<slug>.ghe.com to the --allow-domains and GH_AW_ALLOWED_DOMAINS lists

The hostname can be derived from GITHUB_SERVER_URL (available as ${{ github.server_url }} in Actions) or from the api-target frontmatter field.

Activity

  1. lpcox commented on Mar 17, 2026

    @lpcox
    CollaboratorAuthor

    Additional Analysis: Where GH_HOST Is Needed and Suggested Fix

    After deeper analysis of the compiled lock file, the fix is more nuanced than "inject GH_HOST wherever GH_TOKEN is used." There are three distinct categories of steps that need GH_HOST:

    1. User-authored steps (from .md frontmatter steps:)

    The compiler copies these verbatim. For example, repo-assist.md defines:

    steps:
      - name: Fetch repo data for task weighting
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          gh issue list --state open --limit 500 ...
          gh pr list --state open --limit 200 ...

    The compiler passes through GH_TOKEN but does not inject GH_HOST. On *.ghe.com, gh issue list fails immediately.

    2. Compiler-generated steps

    The compiler already emits GH_HOST for the "Install GitHub Copilot CLI" step — but hardcodes it to github.com:

    - name: Install GitHub Copilot CLI
      run: /opt/gh-aw/actions/install_copilot_cli.sh latest
      env:
        GH_HOST: github.com   # ← wrong for *.ghe.com

    For data residency instances, this should be the actual host (e.g., contoso-aw.ghe.com).

    3. The Execute step

    The Copilot CLI Execute step needs GH_HOST for its auth flow (GET /copilot_internal/user), even though it may not have GH_TOKEN in its env explicitly.

    Suggested Fix: Job-level GH_HOST

    Rather than injecting GH_HOST into individual steps, the cleanest fix is to set GH_HOST at the job-level env: block for the agent job. The compiler already manages this block:

    agent:
      env:
        DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
        GH_AW_ASSETS_ALLOWED_EXTS: ""
        # ... other GH_AW_* vars ...

    Adding one line here covers all three categories at once:

    agent:
      env:
        GH_HOST: contoso-aw.ghe.com   # ← derived from github.server_url
        DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
        # ...

    The value can be derived from ${{ github.server_url }} (strip https://). For github.com this is a no-op; for *.ghe.com it fixes every gh CLI and Copilot CLI call in the job.

    The one exception is the "Install GitHub Copilot CLI" step (line 442 in our lock file), which currently hardcodes GH_HOST: github.com. If that step specifically needs github.com (e.g., to download the CLI binary from github.com regardless of where the repo lives), it could keep its step-level override. Otherwise, it should also use the derived value.

    Evidence

    • Run 22287496 (freshly compiled, no manual edits): Failed at "Fetch repo data for task weighting" with none of the git remotes configured for this repository point to a known GitHub host
    • Run 22240726 (manual GH_HOST added to 4 steps): All jobs passed ✅
  2. added a commit that references this issue on Mar 18, 2026
    04558a6
  3. added a commit that references this issue on Mar 18, 2026
    ef76aff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions