Welcome to the Jose Madrid Salsa developer docs — explore features, APIs, and deployment guides.
Jose Madrid SalsaJMS Docs

CI Artifact Storage

Retention windows for GitHub Actions artifacts, and how to run the Artifact Cleanup workflow when the storage quota fills

CI Artifact Storage

GitHub Actions artifacts count against the account's storage quota. When that quota fills, every upload fails — which surfaces as a red CI run whose tests all passed:

Failed to CreateArtifact: Artifact storage quota has been hit

That failure is about storage, not about the code. This page covers the retention windows that keep the store from filling, and the workflow that empties it when it already has.

Retention windows

ArtifactWorkflowRetentionWhy
coverage-reportsci.yml7 daysReporting only; read within days of a run
playwright-reportci.yml7 daysSame, and by far the largest recurring consumer
build-artifactsci.yml7 daysReporting only
windows-installerdesktop-release.yml3 daysHanded to publish in the same run
macos-appdesktop-release.yml3 daysHanded to publish in the same run

Two things are worth knowing before changing any of these numbers.

Volume dominates size. The store fills from many small artifacts held a long time, not from a few large ones. A measurement of 553 unexpired artifacts totalling 4.06 GB found Playwright reports were 3.05 GB of it — 265 reports at roughly 12 MB each, all created within one month. Shortening a widely-produced artifact's window saves far more than deleting a single large one.

The desktop artifacts cannot go to one day. The publish job declares needs: [windows, macos], but each artifact's retention clock starts when its own upload finishes. If one runner completes while the other is still queued, a one-day window can expire the first artifact before publish downloads it, failing an otherwise good release. Three days covers worst-case cross-platform queue latency.

The three ci.yml uploads are also marked continue-on-error: true. Reporting artifacts are a convenience for reading a run after the fact, not a result — a full store must never turn a green test suite red.

Reclaiming storage that is already used

Retention only governs what is written from here on. It never reclaims what is already stored, and the Actions UI deletes one artifact at a time, which is unworkable against several hundred. Use the Artifact Cleanup workflow.

Running it

From Actions → Artifact Cleanup → Run workflow:

InputDefaultMeaning
older_than_days7Delete artifacts older than this many days
name_filter(blank)Restrict to one exact artifact name; blank means every name
dry_runcheckedReport what would be deleted without deleting it

It defaults to a dry run, so the first click is always safe: it writes a job summary table of what it would delete and how many MB that would free, and touches nothing. Read that table, then re-run with dry_run unchecked to perform the deletion.

To free the most space with the least risk, start with name_filter: playwright-report — on the measurement above that alone accounted for 75% of the store.

The workflow requests permissions: actions: write. Listing artifacts needs only read access; deleting them is what requires write.

Reading the result

The job summary reports how many artifacts were deleted and how much was freed. Already-expired artifacts are skipped — they occupy no storage, so deleting them would free nothing and only spend API calls.

When it fails

The sweep continues past individual failures rather than abandoning the remaining artifacts, but it does not finish green if deletions were genuinely refused:

  • A 404 is benign. The artifact expired between listing and deletion, which is the outcome that was wanted anyway. These are reported but do not fail the run.
  • Anything else — 403, rate limiting, 5xx — means the storage is still occupied. The run is marked failed, because a green run would otherwise report the quota as cleared while it is still full.

If the run fails with 403s, the token lacks actions: write for the repository. Check that the workflow's permissions block survived any edit, and that the repository's default workflow permissions are not restricted to read-only under Settings → Actions → General → Workflow permissions.

If it fails on rate limiting, re-run it. The sweep is idempotent — artifacts deleted by the previous attempt simply no longer appear in the listing.

Raising the quota

Deleting artifacts and shortening retention address consumption. If the repository legitimately needs more storage than the plan allows, the limit itself is raised in the account's billing settings, not in this repository.

How is this guide?

Edit on GitHub

Last updated on

On this page