Skip to content

feat(github-enterprise): support GitHub Enterprise Cloud (GHE.com) webhooks and API#113966

Merged
tnt-sentry merged 4 commits intomasterfrom
tnt-sentry/ghe-cloud-support
Apr 27, 2026
Merged

feat(github-enterprise): support GitHub Enterprise Cloud (GHE.com) webhooks and API#113966
tnt-sentry merged 4 commits intomasterfrom
tnt-sentry/ghe-cloud-support

Conversation

@tnt-sentry
Copy link
Copy Markdown
Contributor

@tnt-sentry tnt-sentry commented Apr 24, 2026

GitHub Enterprise Cloud with data residency (GHE.com, e.g. `acme-corp.ghe.com`) uses a different webhook header and API URL pattern than GitHub Enterprise Server (GHES). This PR adds support for it within the existing `github_enterprise` integration.

The two differences:

  1. Webhook host identification: GHES sends `X-GitHub-Enterprise-Host: hostname`. GHE.com sends `X-Github-Tenant: {slug}` (no host header). `get_host()` now falls back to `X-Github-Tenant` and synthesises `{tenant}.ghe.com` as the host identifier.

  2. API base URL: GHES exposes its API at `https://{host}/api/v3/`. GHE.com exposes it at `https://api.{tenant}.ghe.com/\` (no `/api/v3` path prefix, API subdomain instead). The `.ghe.com` suffix is used as the discriminator everywhere:

    • `client.py`: `base_url` and `build_url()` skip the `/api/v3` rewrite for GHE.com
    • `integration.py`: new `_api_base_url()` helper used in `get_user_info` and `_get_ghe_installation_info`

Existing GHES behaviour is unchanged. The `X-GitHub-Enterprise-Host` header takes precedence if both headers are somehow present.

The webhook routing through hybrid cloud already works without changes — `get_host()` returns a host, `external_id` is stored as `{host}:{installation_id}` during `build_integration`, and `urlparse(installation["account"]["html_url"]).netloc` naturally extracts `{tenant}.ghe.com` from GHE.com payload URLs.

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Apr 24, 2026
@tnt-sentry tnt-sentry force-pushed the tnt-sentry/ghe-cloud-support branch from 0b2132d to 5b09d7d Compare April 24, 2026 18:06
@tnt-sentry tnt-sentry marked this pull request as ready for review April 24, 2026 18:32
@tnt-sentry tnt-sentry requested review from a team as code owners April 24, 2026 18:32
@tnt-sentry tnt-sentry merged commit ea62783 into master Apr 27, 2026
57 checks passed
@tnt-sentry tnt-sentry deleted the tnt-sentry/ghe-cloud-support branch April 27, 2026 12:51
cleptric pushed a commit that referenced this pull request May 5, 2026
…bhooks and API (#113966)

GitHub Enterprise Cloud with data residency (GHE.com, e.g.
\`acme-corp.ghe.com\`) uses a different webhook header and API URL
pattern than GitHub Enterprise Server (GHES). This PR adds support for
it within the existing \`github_enterprise\` integration.

**The two differences:**

1. **Webhook host identification**: GHES sends
\`X-GitHub-Enterprise-Host: hostname\`. GHE.com sends \`X-Github-Tenant:
{slug}\` (no host header). \`get_host()\` now falls back to
\`X-Github-Tenant\` and synthesises \`{tenant}.ghe.com\` as the host
identifier.

2. **API base URL**: GHES exposes its API at \`https://{host}/api/v3/\`.
GHE.com exposes it at \`https://api.{tenant}.ghe.com/\` (no \`/api/v3\`
path prefix, API subdomain instead). The \`.ghe.com\` suffix is used as
the discriminator everywhere:
- \`client.py\`: \`base_url\` and \`build_url()\` skip the \`/api/v3\`
rewrite for GHE.com
- \`integration.py\`: new \`_api_base_url()\` helper used in
\`get_user_info\` and \`_get_ghe_installation_info\`

Existing GHES behaviour is unchanged. The \`X-GitHub-Enterprise-Host\`
header takes precedence if both headers are somehow present.

The webhook routing through hybrid cloud already works without changes —
\`get_host()\` returns a host, \`external_id\` is stored as
\`{host}:{installation_id}\` during \`build_integration\`, and
\`urlparse(installation["account"]["html_url"]).netloc\` naturally
extracts \`{tenant}.ghe.com\` from GHE.com payload URLs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants