Skip to content

feat(artifact): unblock v4+ on self-hosted GHES when ACTIONS_RESULTS_URL is set#2438

Open
camjay wants to merge 1 commit into
actions:mainfrom
camjay:feat/artifact-unblock-ghes-with-results-url
Open

feat(artifact): unblock v4+ on self-hosted GHES when ACTIONS_RESULTS_URL is set#2438
camjay wants to merge 1 commit into
actions:mainfrom
camjay:feat/artifact-unblock-ghes-with-results-url

Conversation

@camjay

@camjay camjay commented Jun 19, 2026

Copy link
Copy Markdown

Closes #2439
Related to #2123 (more general vendor-aware approach for non-GitHub servers; this PR addresses the narrower GHES-3.13+ case via existing runtime signals)

isGhes() in packages/artifact/src/internal/shared/config.ts currently throws GHESNotSupportedError on any GHES, regardless of release. GHES 3.13 added the artifact-storage-v2 backend that v4+ requires, but the gate is hostname-only and ignores the release. ACTIONS_RESULTS_URL is the runtime signal for v2 availability; the same package's getResultsServiceUrl() already requires it. This change makes isGhes() return false when the hostname looks like GHES and ACTIONS_RESULTS_URL is set.

Behaviour matrix:

  • github.com, *.ghe.com, *.localhost: hostname check still returns false. No change.
  • GHES <3.13 (no v2 backend, ACTIONS_RESULTS_URL unset): isGhes() returns true, throws as before. No change.
  • GHES 3.13+ (v2 backend present, ACTIONS_RESULTS_URL set): isGhes() returns false, upload/download/list proceed.

Tests in packages/artifact/__tests__/config.test.ts cover both new branches. Also added a beforeEach cleanup of GITHUB_SERVER_URL and ACTIONS_RESULTS_URL inside the isGhes describe block; the previous setup relied on jest.resetModules() alone and could leak ACTIONS_RESULTS_URL from sibling tests. The previously-misleadingly-titled "should return false ... is specific to an enterprise" test (which expected true) is renamed to match its actual assertion.

Verified on a GHES 3.19.5 instance where the v2 backend is operational but v4+ artifact actions were blocked solely by the hostname gate.

Relationship to #2123: that PR takes a more general approach with an ACTIONS_VENDOR env var as an explicit opt-in, supporting non-GitHub vendor servers (Gitea, Forgejo, etc.) in addition to GHES. This PR is narrower: it consults an existing runtime signal (ACTIONS_RESULTS_URL) that GHES 3.13+ runners already emit, so no operator action is required and no new env-var contract is introduced. The two approaches are complementary; if both land, the check here would short-circuit before vendor detection on v2-supporting GHES.

…URL is set

The current isGhes() check returns true for any GitHub Server URL that
isn't github.com, *.ghe.com, or *.localhost. When isGhes() returns true,
client.ts throws GHESNotSupportedError on every upload, download, and
list call - so the artifact-v4+ family is completely blocked on
self-hosted GHES instances.

This made sense at v4 launch when the artifact-storage-v2 backend was
github.com-only. GHES 3.13 added the v2 backend, and 3.16+ has full
production support, but the hostname-based gate doesn't reflect that:
it continues to throw on any GHES regardless of release.

The runtime already exposes a clean signal for whether v2 is reachable:
the runner sets ACTIONS_RESULTS_URL exactly when the storage backend is
available. The artifact client's own getResultsServiceUrl() in the same
package throws if ACTIONS_RESULTS_URL is unset, so it's already a
precondition for the upload/download/list paths to succeed. Treating
that env var as the authority on "is the v2 backend reachable here?"
unblocks GHES 3.13+ without changing behaviour anywhere else.

Compatibility:

  - github.com / *.ghe.com / *.localhost: hostname check returns
    isGhes()=false. No change.
  - GHES <3.13 (no v2 backend, ACTIONS_RESULTS_URL unset): hostname is
    GHES-shaped, env var is missing -> isGhes()=true -> existing
    GHESNotSupportedError. No change.
  - GHES 3.13+ (v2 backend present, ACTIONS_RESULTS_URL set): hostname
    is GHES-shaped, env var IS set -> isGhes()=false -> upload /
    download / list proceed normally. This is the unblock.

Tests added in packages/artifact/__tests__/config.test.ts cover both
new branches; the existing 'enterprise hostname' test is kept and now
explicitly verifies the unset-env-var case.
@camjay camjay requested a review from a team as a code owner June 19, 2026 19:20
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.

artifact: v4+ blocked on self-hosted GHES even on releases that ship the v2 backend (3.13+)

1 participant