feat(artifact): unblock v4+ on self-hosted GHES when ACTIONS_RESULTS_URL is set#2438
feat(artifact): unblock v4+ on self-hosted GHES when ACTIONS_RESULTS_URL is set#2438camjay wants to merge 1 commit into
Conversation
…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.
|
Hey @actions/artifacts-actions, @danwkennedy, @jasongin: bumping this on the back of the artifact README's own note that v4 is "not currently supported on GHES yet." GHES 3.13+ ships the v2 artifact backend; on those releases the runner already exports Related: #2439 (issue) and the older #2123 (different approach to the same problem, open since early 2026). Happy to adjust scope/tests/style. Just looking for a triage decision so we know whether to keep iterating here or pursue an ADR per CONTRIBUTING.md. |
|
@camjay Thanks for the PR! The v2 (Results) backend that
This isn't the case, it's still unsupported on GHES (the README calls this out too). GHES runners also don't set Let me know if I'm misunderstanding something! 😄 |
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()inpackages/artifact/src/internal/shared/config.tscurrently throwsGHESNotSupportedErroron 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_URLis the runtime signal for v2 availability; the same package'sgetResultsServiceUrl()already requires it. This change makesisGhes()returnfalsewhen the hostname looks like GHES andACTIONS_RESULTS_URLis set.Behaviour matrix:
github.com,*.ghe.com,*.localhost: hostname check still returnsfalse. No change.ACTIONS_RESULTS_URLunset):isGhes()returnstrue, throws as before. No change.ACTIONS_RESULTS_URLset):isGhes()returnsfalse, upload/download/list proceed.Tests in
packages/artifact/__tests__/config.test.tscover both new branches. Also added abeforeEachcleanup ofGITHUB_SERVER_URLandACTIONS_RESULTS_URLinside theisGhesdescribe block; the previous setup relied onjest.resetModules()alone and could leakACTIONS_RESULTS_URLfrom sibling tests. The previously-misleadingly-titled "should return false ... is specific to an enterprise" test (which expectedtrue) 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_VENDORenv 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.