From ac874bf7469c4cbba8b290c54a0fe866b789fffd Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Wed, 1 Jul 2026 09:32:16 +0200 Subject: [PATCH] ci(mutation): make Stryker report upload best-effort (refs #62) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Gitea artifact backend returns 500 to actions/upload-artifact@v3 (server-side, distinct from the @v4 GHES guard). With if: always() that 500 failed the whole mutation job even though the ratchet passed — red on main and on every PR. Mark the three report uploads continue-on-error: true so the mutation *gate* stays the Stryker ratchet (make mutation's exit code), not the report upload. Documented in gitea-actions-gotchas.md §4. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/ci.yaml | 13 +++++++++---- docs/runbooks/gitea-actions-gotchas.md | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 16901c6..f857747 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -51,25 +51,30 @@ jobs: with: dotnet-version: '10.0.x' - run: make mutation - # Publish the Stryker HTML report. `if: always()` uploads it even when the + # Publish the Stryker HTML reports. `if: always()` uploads them even when the # ratchet fails — that is exactly when you want to inspect the survivors. - # Glob handles Stryker's non-deterministic StrykerOutput// dir. - # Pinned to @v3 deliberately: @v4 refuses to run on Gitea (GHES guard) — - # see docs/runbooks/gitea-actions-gotchas.md §4. + # `continue-on-error` keeps the upload best-effort: the mutation *gate* is the + # ratchet (make mutation's exit code), not the report, so a Gitea artifact-backend + # 500 must not fail the job (gitea-actions-gotchas.md §4). Glob handles Stryker's + # non-deterministic StrykerOutput// dir. Pinned @v3: @v4's bundled + # @actions/artifact hard-aborts on non-github.com (GHES guard) — see the runbook. - uses: https://github.com/actions/upload-artifact@v3 if: always() + continue-on-error: true with: name: acl-mutation-report path: services/acl/StrykerOutput/**/reports/mutation-report.html if-no-files-found: warn - uses: https://github.com/actions/upload-artifact@v3 if: always() + continue-on-error: true with: name: event-subscriber-mutation-report path: services/event-subscriber/StrykerOutput/**/reports/mutation-report.html if-no-files-found: warn - uses: https://github.com/actions/upload-artifact@v3 if: always() + continue-on-error: true with: name: domain-mutation-report path: services/domain/StrykerOutput/**/reports/mutation-report.html diff --git a/docs/runbooks/gitea-actions-gotchas.md b/docs/runbooks/gitea-actions-gotchas.md index 1632671..29f97d2 100644 --- a/docs/runbooks/gitea-actions-gotchas.md +++ b/docs/runbooks/gitea-actions-gotchas.md @@ -14,6 +14,7 @@ those containers share a filesystem — or a `localhost` — breaks. | `docker compose up --wait` is unsupported / flaky | poll health with `docker inspect` | `infra/wait-healthy.sh` | | `pg_isready` passes before PostGIS is ready | add a `PostGIS_Version()` probe | the db healthchecks | | `upload-artifact@v4` fails ("not supported on GHES") | pin `@v3` | `.gitea/workflows/ci.yaml` (`mutation` job) | +| `upload-artifact@v3` fails with "Artifact service responded with 500" | mark the upload `continue-on-error: true` (server-side; issue #62) | `.gitea/workflows/ci.yaml` (`mutation` job) | --- @@ -125,6 +126,22 @@ guard. Inputs are the same (`name`, `path`, `if-no-files-found`), so it is a dro swap. Do **not** bump to `@v4` until act_runner advertises github.com-compatible artifact support. +**Second failure mode — the server's artifact backend returns 500.** Even on the +correctly-pinned `@v3`, uploads can fail with: + +``` +Create Artifact Container - Attempt 5 of 5 failed with error: Artifact service responded with 500 +::error::Create Artifact Container failed: Artifact service responded with 500 +``` + +This is the **Gitea server's** artifact storage failing (not the action's GHES guard), +so it is outside the repo's control. Because the `mutation` job's upload steps run with +`if: always()`, that 500 would fail the job even though the ratchet passed. **Fix:** mark +the uploads `continue-on-error: true` (issue #62). The mutation *gate* is the Stryker +ratchet — `make mutation`'s exit code fails the job on a real regression — so the report +upload is best-effort: when the server's artifact storage is restored, reports publish +again with no workflow change. + --- ## 5. A runner process can't reach a service container's published port