fix(ci): artifacts move to stock upload-artifact@v7 / download-artifact@v8
test-go / test (push) Successful in 1m4s
test-go / integration (push) Successful in 3m54s
android / Build + lint + test (push) Successful in 4m58s
release / Build signed APK (releases and dev) (push) Successful in 5m11s
release / Build + push container image (push) Successful in 1m52s
release / Verify release artifacts (tag releases only) (push) Skipped
test-go / test (push) Successful in 1m4s
test-go / integration (push) Successful in 3m54s
android / Build + lint + test (push) Successful in 4m58s
release / Build signed APK (releases and dev) (push) Successful in 5m11s
release / Build + push container image (push) Successful in 1m52s
release / Verify release artifacts (tag releases only) (push) Skipped
android.yml's debug upload and release.yml's minstrel-apk pair went through the bvandeusen fork mirrors, with comments saying stock actions refuse this hostname, that the pair had to be matched on the bundled @actions/artifact major, and that download v7 was off-limits for node24. None of that holds on gitea/runner 3.x: the runner edits the GHES refusal out of the action bundles, every download major v4-v8 reads every upload major v4-v7 (Scribe spike #3843, CI-runner run 6312), and every CI image carries Node 24. The mirror pair itself was last verified at tag run 6286. Same artifact names, paths and if-no-files-found. ci-requirements.md drops the pairing table and keeps what is still true: @v3 is invisible. Scribe snippet #2271, milestone 395. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DwoKYuw3qJmUUYsJeNherB
This commit is contained in:
@@ -80,15 +80,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload debug APK
|
- name: Upload debug APK
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
# Mirrored action, never actions/upload-artifact. @v4+ throws
|
# Stock action: it works on this forge since the runner moved to
|
||||||
# GHESNotSupportedError client-side on the hostname (no server setting
|
# gitea/runner 3.x, which edits upload-artifact's client-side GHES refusal
|
||||||
# reaches that check), and @v3 is worse — it reports success while Gitea
|
# out of the action bundle (Scribe snippet #2271). Never @v3 — it reports
|
||||||
# serves artifacts back only through the v4 API, so the upload is stored
|
# success while Gitea serves artifacts back only through the v4 API, and
|
||||||
# and invisible to every retrieval path. @v3 is what left 72 unreachable
|
# it is what left 72 unreachable artifacts on this repo (Scribe 2270).
|
||||||
# artifacts on this repo. Pinned by SHA because the mirror auto-syncs;
|
uses: actions/upload-artifact@v7
|
||||||
# full URL because DEFAULT_ACTIONS_URL sends bare owner/repo to github.com.
|
|
||||||
# See Scribe issues 2255 / 2270.
|
|
||||||
uses: https://git.fabledsword.com/bvandeusen/upload-artifact@cb8afe72b42edc798abfb8fcb556cf660d894245
|
|
||||||
with:
|
with:
|
||||||
name: minstrel-android-debug-${{ github.sha }}
|
name: minstrel-android-debug-${{ github.sha }}
|
||||||
path: android/app/build/outputs/apk/debug/app-debug.apk
|
path: android/app/build/outputs/apk/debug/app-debug.apk
|
||||||
|
|||||||
@@ -232,13 +232,12 @@ jobs:
|
|||||||
-PMINSTREL_VERSION_CODE=${{ steps.ver.outputs.code }}
|
-PMINSTREL_VERSION_CODE=${{ steps.ver.outputs.code }}
|
||||||
|
|
||||||
- name: Upload APK as workflow artifact
|
- name: Upload APK as workflow artifact
|
||||||
# Mirrored action, never actions/upload-artifact — @v4+ refuses on the
|
# Stock action (snippet #2271) — never @v3, which uploads something Gitea
|
||||||
# hostname, @v3 uploads something Gitea will never serve back. This is
|
# will never serve back. This is the producing half of a pair:
|
||||||
# the producing half of a pair: image-release downloads `minstrel-apk`
|
# image-release downloads `minstrel-apk` below. Any upload v4+ pairs with
|
||||||
# below with the matching download-artifact mirror. Both must stay on
|
# any download v4+ on this forge (every combination tested 2026-09-10,
|
||||||
# the v4 protocol — mixing a v3 upload with a v4 download (or the
|
# Scribe spike #3843), so the two pins need not move together.
|
||||||
# reverse) yields an empty listing, not an error. See Scribe 2255 / 2270.
|
uses: actions/upload-artifact@v7
|
||||||
uses: https://git.fabledsword.com/bvandeusen/upload-artifact@cb8afe72b42edc798abfb8fcb556cf660d894245
|
|
||||||
with:
|
with:
|
||||||
name: minstrel-apk
|
name: minstrel-apk
|
||||||
path: android/app/build/outputs/apk/release/app-release.apk
|
path: android/app/build/outputs/apk/release/app-release.apk
|
||||||
@@ -435,20 +434,11 @@ jobs:
|
|||||||
if: >-
|
if: >-
|
||||||
steps.guard.outputs.ready == 'true' &&
|
steps.guard.outputs.ready == 'true' &&
|
||||||
(startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/dev')
|
(startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/dev')
|
||||||
# Consuming half of the pair — never actions/download-artifact. Same fork,
|
# Consuming half of the pair: stock download-artifact, which works here for
|
||||||
# same reason: upstream's client-side GHES check rejects this hostname
|
# the same reason as the upload (gitea/runner 3.x edits the GHES refusal
|
||||||
# before it connects. bvandeusen/download-artifact mirrors
|
# out of the bundle; snippet #2271). v8 runs on node24, which every
|
||||||
# code.forgejo.org/forgejo/download-artifact.
|
# CI-runner image carries — the runner uses the image's own node.
|
||||||
#
|
uses: actions/download-artifact@v8
|
||||||
# SHA below is that fork's `v6` tag. Match on @actions/artifact, NOT on
|
|
||||||
# the action's own version number — the two actions release on unrelated
|
|
||||||
# cadences, and download v5 would pair a ^2.3.2 client with this file's
|
|
||||||
# ^4.0.0 uploader. v6 is the tag whose bundled library major (^4.0.0) is
|
|
||||||
# the same one proven against this instance by the upload side.
|
|
||||||
# Deliberately NOT v7: it moves to node24 and upstream requires runner
|
|
||||||
# >= 2.327.1 for it, which act_runner does not claim to satisfy.
|
|
||||||
# Pinned, not tagged — the mirror auto-syncs every 8h.
|
|
||||||
uses: https://git.fabledsword.com/bvandeusen/download-artifact@8d4e9521a5f7e5f8b6351f341f719f9f45a92a3a
|
|
||||||
with:
|
with:
|
||||||
name: minstrel-apk
|
name: minstrel-apk
|
||||||
path: client/
|
path: client/
|
||||||
|
|||||||
+20
-47
@@ -62,57 +62,30 @@ None.
|
|||||||
- **Go toolchain pin.** `go.mod` is on `go 1.25.0` because `golang.org/x/crypto v0.51.0` declares 1.25 as its minimum. `ci-go:1.26` satisfies this with headroom. Future `x/crypto` bumps that move the Go floor should be paired with an image-tag bump in this file + the workflows.
|
- **Go toolchain pin.** `go.mod` is on `go 1.25.0` because `golang.org/x/crypto v0.51.0` declares 1.25 as its minimum. `ci-go:1.26` satisfies this with headroom. Future `x/crypto` bumps that move the Go floor should be paired with an image-tag bump in this file + the workflows.
|
||||||
- **In-app update channel — `needs:`, not polling.** `release.yml`'s `image-release` job declares `needs: [android-release]`, so on tag pushes the signed APK is guaranteed present before the image build starts — no polling window, no race. (The old cross-workflow polling against `flutter.yml` is gone with that workflow.) On non-tag `main` pushes `android-release` is skipped and `image-release` instead pulls the most recent release's APK and reconstructs its exact `versionName`, so `:latest` never ships without an update channel. It degrades to an empty `client/` — never a wrong version — if no release, asset, or tag commit-count can be resolved.
|
- **In-app update channel — `needs:`, not polling.** `release.yml`'s `image-release` job declares `needs: [android-release]`, so on tag pushes the signed APK is guaranteed present before the image build starts — no polling window, no race. (The old cross-workflow polling against `flutter.yml` is gone with that workflow.) On non-tag `main` pushes `android-release` is skipped and `image-release` instead pulls the most recent release's APK and reconstructs its exact `versionName`, so `:latest` never ships without an update channel. It degrades to an empty `client/` — never a wrong version — if no release, asset, or tag commit-count can be resolved.
|
||||||
- **Cache server reachability.** `test-web.yml` does NOT use `cache: 'npm'` on `actions/setup-node` — the Gitea Actions cache server isn't reachable from this runner's container network and `setup-node` was burning ~4m41s on ETIMEDOUT before failing open. With the migration to `ci-go:1.26`, `setup-node` is removed entirely (Node is in the image). The cache concern reappears if a future change re-introduces a network-dependent action.
|
- **Cache server reachability.** `test-web.yml` does NOT use `cache: 'npm'` on `actions/setup-node` — the Gitea Actions cache server isn't reachable from this runner's container network and `setup-node` was burning ~4m41s on ETIMEDOUT before failing open. With the migration to `ci-go:1.26`, `setup-node` is removed entirely (Node is in the image). The cache concern reappears if a future change re-introduces a network-dependent action.
|
||||||
- **Artifacts — use the mirrored actions, never `actions/{upload,download}-artifact`.**
|
- **Artifacts — stock `actions/upload-artifact@v7` and `actions/download-artifact@v8`; never `@v3`.**
|
||||||
```yaml
|
```yaml
|
||||||
uses: https://git.fabledsword.com/bvandeusen/upload-artifact@cb8afe72b42edc798abfb8fcb556cf660d894245
|
uses: actions/upload-artifact@v7
|
||||||
uses: https://git.fabledsword.com/bvandeusen/download-artifact@8d4e9521a5f7e5f8b6351f341f719f9f45a92a3a
|
uses: actions/download-artifact@v8
|
||||||
```
|
```
|
||||||
Upstream's `@v4+` cannot work against this instance and no server-side change
|
Stock works on this forge since the runner moved to gitea/runner 3.x, which
|
||||||
will help: `isGhes()` rejects any hostname that isn't `github.com` /
|
edits the actions' client-side `isGhes()` refusal out of their bundles. Proven
|
||||||
`*.ghe.com` / `*.localhost` and throws before it opens a connection, so the
|
on 2026-09-10 for upload v4–v7 and download v4–v8 (Scribe spike #3843). Until
|
||||||
server is never asked what it supports. `@v3` is worse — it reports success,
|
then this repo pinned SHA mirrors of the Forgejo project's forks, because
|
||||||
and Gitea then serves artifacts back only through the v4 API
|
upstream threw on the hostname before it opened a connection (Scribe 2255).
|
||||||
(`content_encoding = application/zip`), so a v3 upload is stored but invisible
|
|
||||||
to every retrieval path. A green job producing nothing retrievable; that is how
|
|
||||||
72 unreachable artifacts accumulated on this repo. Scribe issues 2255 / 2270.
|
|
||||||
|
|
||||||
Both are pull mirrors of the Forgejo project's forks
|
`@v3` is still broken: it reports success, and Gitea serves artifacts back only
|
||||||
(`code.forgejo.org/forgejo/{upload,download}-artifact`, one commit on upstream
|
through the v4 API (`content_encoding = application/zip`), so a v3 upload is
|
||||||
disabling that check), mirrored so CI depends on commits we hold and pinned by
|
stored but invisible to every retrieval path. That is how 72 unreachable
|
||||||
SHA because the mirrors auto-sync every 8h — a moved upstream tag would
|
artifacts accumulated on this repo (Scribe 2270).
|
||||||
otherwise silently change what runs.
|
|
||||||
|
|
||||||
**Match the pins on `@actions/artifact`, not on the actions' own version
|
**Pairing no longer needs managing.** This entry used to pin upload v5 against
|
||||||
numbers.** The two actions release on unrelated cadences, so equal version
|
download v6 so both bundled `@actions/artifact` ^4.0.0, warning that a mismatch
|
||||||
numbers do NOT mean a compatible pair — upload `v5` bundles `@actions/artifact`
|
across `release.yml`'s producer/consumer pair would list empty. Tested, and not
|
||||||
^4.0.0 while download `v5` bundles ^2.3.2. The pins above are upload **v5** and
|
true on this instance: every download major v4–v8 read the artifacts of every
|
||||||
download **v6**, which is the pairing that puts ^4.0.0 on both sides. This
|
upload major v4–v7, by name and by pattern (CI-runner run 6312). The only real
|
||||||
matters because `release.yml` is a producer/consumer pair — `android-release`
|
protocol break is v3 → v4. node24 is no longer a concern either — every
|
||||||
uploads `minstrel-apk`, `image-release` downloads it — and a protocol mismatch
|
CI-runner image carries Node 24 and the runner runs actions with the image's
|
||||||
across it yields an empty listing rather than an error, exactly the silent
|
`node`.
|
||||||
failure this entry exists to prevent.
|
|
||||||
|
|
||||||
| tag | `@actions/artifact` | runtime |
|
|
||||||
|---|---|---|
|
|
||||||
| upload v4 | ^2.1.1 | node20 |
|
|
||||||
| **upload v5** ← pinned | **^4.0.0** | node20 |
|
|
||||||
| download v4 | ^2.1.1 | node20 |
|
|
||||||
| download v5 | ^2.3.2 | node20 |
|
|
||||||
| **download v6** ← pinned | **^4.0.0** | node20 |
|
|
||||||
| download v7 | ^5.0.0 | **node24** |
|
|
||||||
|
|
||||||
The only true protocol break in this history was **v3 → v4** (upstream:
|
|
||||||
"Downloading artifacts that were created from `actions/upload-artifact@v3` and
|
|
||||||
below are not supported"); v4-and-up are one family. Later majors are mostly
|
|
||||||
ergonomics and runtime — upload v4 forbids re-uploading a name and caps a job
|
|
||||||
at 500 artifacts; download v5 made by-ID extraction match by-name.
|
|
||||||
|
|
||||||
**Do not jump the download pin to v7.** That major is a runner requirement, not
|
|
||||||
a feature change: it moves to `runs.using: node24` and upstream states it
|
|
||||||
"requires a minimum Actions Runner version of 2.327.1 … if you are using
|
|
||||||
self-hosted runners, ensure they are updated before upgrading." act_runner is
|
|
||||||
not GitHub's runner and makes no such version claim, so node24 is unverified
|
|
||||||
here. Everything currently pinned is node20.
|
|
||||||
|
|
||||||
Upload steps set `if-no-files-found: error` rather than the default `warn`, so
|
Upload steps set `if-no-files-found: error` rather than the default `warn`, so
|
||||||
an upload that matches nothing fails its own job instead of failing the
|
an upload that matches nothing fails its own job instead of failing the
|
||||||
|
|||||||
Reference in New Issue
Block a user