Skip to content

fix(internal): vendor-aware GHES detection in isGhes() to support non-GitHub servers - #2123

Open
MahdiBaghbani wants to merge 1 commit into
actions:mainfrom
MahdiBaghbani:fix-isGhes-compatibility
Open

fix(internal): vendor-aware GHES detection in isGhes() to support non-GitHub servers#2123
MahdiBaghbani wants to merge 1 commit into
actions:mainfrom
MahdiBaghbani:fix-isGhes-compatibility

Conversation

@MahdiBaghbani

@MahdiBaghbani MahdiBaghbani commented Aug 30, 2025

Copy link
Copy Markdown

Introduce a minimal, explicit vendor switch to prevent isGhes() from misclassifying non GitHub platforms (e.g., Forgejo/Gitea) as GHES, This PR adds a positive allowlist for GHES aliases and preserves current behavior for github.

On self-hosted non-GitHub servers, the current heuristic (GITHUB_SERVER_URL hostname) often evaluates to enterprise sending actions down GHES specific code paths and causing failures.
A tiny, explicit environment switch avoids this without changing default behavior on GitHub

for reference when this breaks other platforms please see:
actions/upload-artifact#676
https://code.forgejo.org/actions/upload-artifact
https://code.forgejo.org/forgejo/runner/src/branch/main/RELEASE-NOTES.md#3-4-0

Although this version is able to run actions/upload-artifact@v4 and actions/download-artifact@v4, these actions will fail because it does not run against GitHub.com. A fork of those two actions with this check disabled is made available at:
https://code.forgejo.org/forgejo/upload-artifact/src/tag/v4
https://code.forgejo.org/forgejo/download-artifact/src/tag/v4

go-gitea/gitea#31256

The workaround right now is:
https://gitea.com/actions/gitea-upload-artifact/commit/81f940d004763f986ba3582c007fd842dd5cb0d7
https://code.forgejo.org/forgejo/upload-artifact/commit/16871d9e8cfcf27ff31822cac382bbb5450f1e1e


Update (2026-07-31): reworked the approach. The current commit makes isGhes() forge-aware directly instead of relying on an ACTIONS_VENDOR allowlist.

  1. If the runner sets FORGEJO_ACTIONS or GITEA_ACTIONS, isGhes() returns false. This is the forge-provided signal and fixes Forgejo and Gitea automatically.
  2. ACTIONS_VENDOR is kept only as an optional, corrected escape hatch: github forces false, ghes forces true, unknown values fall through to the hostname heuristic (a typo or spoofed value cannot silently disable the GHES block). The buggy ghe / github-enterprise aliases are gone (they collided with *.ghe.com, which is GitHub Enterprise Cloud, not GHES).
  3. The hostname heuristic (github.com, *.ghe.com, *.localhost) is unchanged, so real GHES with no forge flags still returns true and artifact v4 stays blocked there as before. isGhes() does not consult ACTIONS_RESULTS_URL.

Accepted tradeoffs, documented in packages/cache/src/internal/config.ts: on forges the cache client now honors ACTIONS_CACHE_SERVICE_V2 (which can 404 until forges implement the v2 CacheService, see go-gitea/gitea#33393), and the client-side 10GB cache cap becomes active on forges.

@MahdiBaghbani
MahdiBaghbani requested review from a team as code owners August 30, 2025 08:02
@DaanSelen

DaanSelen commented Jan 13, 2026

Copy link
Copy Markdown

Could this be inplemented?

I believe that customizing the isGhes function no longer works?

@silverwind

silverwind commented Jul 30, 2026

Copy link
Copy Markdown

The isGhes() existance forces very ugly workarounds on non-github runners to enable cache v2. Feature flags like ACTIONS_CACHE_SERVICE_V2 should be authorative source whether to enable a feature or not.

export function getCacheServiceVersion(): string {
// Cache service v2 is not supported on GHES. We will default to
// cache service v1 even if the feature flag was enabled by user.
if (isGhes()) return 'v1'
return process.env['ACTIONS_CACHE_SERVICE_V2'] ? 'v2' : 'v1'
}

Signed-off-by: Mahdi Baghbani <mahdi-baghbani@azadehafzar.io>
@MahdiBaghbani
MahdiBaghbani force-pushed the fix-isGhes-compatibility branch from 6e3a7ad to 87cd75c Compare July 31, 2026 13:00
@MahdiBaghbani

MahdiBaghbani commented Jul 31, 2026

Copy link
Copy Markdown
Author

@DaanSelen yes, this is still worth doing, and I just force-pushed a reworked commit that changes the approach.

To your point about customizing isGhes: the problem is that isGhes() classifies anything whose GITHUB_SERVER_URL is not github.com, *.ghe.com, or *.localhost as GitHub Enterprise Server. A Forgejo or Gitea host falls into that bucket, so the artifact client throws GHESNotSupportedError and artifact v4 is blocked, and the cache client is forced onto v1. There was no supported way to override that from a workflow.

The new commit fixes it at the source: isGhes() now returns false when the runner sets FORGEJO_ACTIONS or GITEA_ACTIONS, which is how forge runners self-identify. No hostname allowlist to maintain, and real GHES is unaffected because GHES runners do not set those flags. If you are on a recent Forgejo or Gitea act_runner this should just work without any custom patching. Let me know if you can test it against your setup.

@MahdiBaghbani

MahdiBaghbani commented Jul 31, 2026

Copy link
Copy Markdown
Author

@silverwind agreed that ACTIONS_CACHE_SERVICE_V2 should be authoritative, and the new commit moves in that direction. Before this change isGhes() returned true on any non-github host, so getCacheServiceVersion() hard-forced v1 and ignored the flag on forges. That is the "ugly workaround" you are describing.

With the new commit, isGhes() returns false on forge runners (FORGEJO_ACTIONS or GITEA_ACTIONS set), so getCacheServiceVersion() now honors ACTIONS_CACHE_SERVICE_V2 just like it does on github.com. The flag becomes authoritative on forges.

I want to be honest about the tradeoff, because it is not free. Gitea act_runner sets ACTIONS_CACHE_SERVICE_V2=true by default, but the forge cache backends do not yet implement the v2 CacheService Twirp API (tracked in go-gitea/gitea#33393). So on those runners, honoring the flag currently means the cache client asks for v2 and gets a 404 until the forge ships the v2 service or stops defaulting the flag on. The old behavior masked this by pretending the forge was GHES and quietly falling back to v1.

I think honoring the flag is still the correct behavior: the toolkit should not be second-guessing a runner-provided signal, and the remaining gap is a forge-side implementation detail rather than a misclassification in this library. I documented this tradeoff in a comment at the top of the cache config so it is not a surprise. If you would prefer the toolkit keep a safety net for forges that advertise v2 without a backend, that is a separate design decision and I am happy to discuss it.

@MahdiBaghbani

MahdiBaghbani commented Jul 31, 2026

Copy link
Copy Markdown
Author

@camjay @philip-gai following the discussion on #2438, a quick note on how this PR relates.

#2438 unblocks the v2 artifact backend on GHES 3.13+ by consulting ACTIONS_RESULTS_URL, which was rejected because GHES runners do not set that variable and it can mask a clear GHESNotSupportedError. This PR is deliberately scoped to forge runners (Forgejo/Gitea) and keys off FORGEJO_ACTIONS / GITEA_ACTIONS instead. isGhes() does not read ACTIONS_RESULTS_URL, and GHES behavior is unchanged, so it does not reintroduce the failure mode raised on #2438 and does not conflict with #2438 / #2439; the two could land independently.

Happy to adjust if you see any overlap or risk I missed.

@silverwind

silverwind commented Jul 31, 2026

Copy link
Copy Markdown

the forge cache backends do not yet implement the v2 CacheService Twirp API (tracked in go-gitea/gitea#33393)

We implement v2 CacheService now with https://gitea.com/gitea/runner/pulls/1110 which includes a runtime patch that disables actions/toolkit's isGhes check.

I don't think the maintainers here will accept a check targeting non-github runners and therefor I still ask to remove isGhes altogether and make features gated only by feature flags.

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.

3 participants