fix: stop artifact uploads depending on the cache server reaching Gitea (#1216)

Cache v2 makes the cache server the `ACTIONS_RESULTS_URL` origin, so artifact calls arrived there and were proxied on to Gitea, failing whenever it could not reach the instance.

- Artifact calls are answered with a redirect, so the cache server opens no connection to Gitea. A scheme change or an untrusted instance is still proxied, but there the cache server is the runner itself, which already reaches Gitea.
- Failures answer in twirp, not an empty `502` that clients report as `Unexpected end of JSON input`.
- `cache.v2: false` really points artifacts at Gitea now.
- Cache reservations are bound to the job that made them, so two jobs saving one key cannot commit against each other's upload, and a retry after a lost answer no longer fails a saved entry.
- The toolkit patch, which edits the GitHub-host check out of an action's bundle, was left in the shared checkout where a job running with `runner.patch_actions: false` could inherit it. It is put back after the job's copy.
- `exec` names an origin for the cache v2 it advertises, and masks its runtime token.

Behaviour changes: `no_proxy` no longer exempts `cache.external_server`, and `cache.enabled: false` also stops external registration.

Fixes https://gitea.com/gitea/runner/issues/1208
Fixes https://gitea.com/gitea/runner/issues/1211

Assisted by Claude (Opus 5).

Reviewed-on: https://gitea.com/gitea/runner/pulls/1216
Reviewed-by: bircni <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
silverwind
2026-09-08 18:45:10 +00:00
committed by bircni
parent ff9965e940
commit 2ed8cdb76e
22 changed files with 533 additions and 82 deletions
+9 -6
View File
@@ -176,16 +176,16 @@ func TestPatchedBundleSurvivesInsideAStringLiteral(t *testing.T) {
func TestPatchBundleIsIdempotent(t *testing.T) {
script := bundleFile(t, gateTSC)
done, err := patchBundle(script)
original, err := patchBundle(script)
require.NoError(t, err)
require.True(t, done)
require.NotNil(t, original)
patched, err := os.ReadFile(script)
require.NoError(t, err)
require.True(t, gateOpened(string(patched)))
done, err = patchBundle(script)
original, err = patchBundle(script)
require.NoError(t, err)
assert.False(t, done, "a patched bundle is not patched again")
assert.Nil(t, original, "a patched bundle is not patched again")
again, err := os.ReadFile(script)
require.NoError(t, err)
assert.Equal(t, string(patched), string(again))
@@ -194,9 +194,9 @@ func TestPatchBundleIsIdempotent(t *testing.T) {
func TestPatchBundleLeavesOtherActionsAlone(t *testing.T) {
script := bundleFile(t, `console.log("checkout")`)
done, err := patchBundle(script)
original, err := patchBundle(script)
require.NoError(t, err)
assert.False(t, done)
assert.Nil(t, original)
body, err := os.ReadFile(script)
require.NoError(t, err)
assert.Equal(t, `console.log("checkout")`, string(body))
@@ -251,6 +251,9 @@ func TestPatchActionsAtTheContainerCopy(t *testing.T) {
return nil
})
require.NoError(t, maybeCopyToActionDir(t.Context(), sar, sar.actionDir(), "sub", "/var/run/act/actions/repo/sub"))
source, err := os.ReadFile(script)
require.NoError(t, err)
assert.Equal(t, gateTSC, string(source), "the shared copy is left as it was found")
return copied
}