Artifact Storage Management
Added: 2026-01-24 Status: Active in production PR: #477
Overview
GitHub Actions artifact storage has quota limits that can cause CI failures. This system proactively manages storage to prevent quota exhaustion.
Key Components:
- Scheduled cleanup workflow - Deletes old artifacts weekly
- Non-blocking uploads - CI continues even if upload fails
- Self-hosted runner migration - Reduces quota pressure
The Problem
GitHub artifact storage has several constraints:
| Tier | Storage Quota | Retention |
|---|---|---|
| Free | 500 MB | 90 days |
| Pro | 2 GB | 90 days |
Critical Issue: After deleting artifacts, quota recalculation is delayed 6-12 hours. During this window, CI can still fail with quota exhaustion errors even though artifacts were deleted.
Symptoms of quota exhaustion:
Error: Not enough artifact storage quota available
Solution 1: Artifact Cleanup Workflow
File: .github/workflows/artifact-cleanup.yml
Scheduled Execution
Runs automatically every Sunday at 3 AM UTC to delete artifacts older than 3 days.
on:
schedule:
- cron: '0 3 * * 0' # Every Sunday at 3 AM UTCManual Trigger
Can be triggered manually with configurable options:
- max_age_days: Delete artifacts older than N days (default: 3)
- dry_run: Preview what would be deleted without actually deleting
To run manually:
- Go to Actions tab
- Select “Artifact Cleanup” workflow
- Click “Run workflow”
- Set options and run
How It Works
// Lists all artifacts and deletes those older than cutoff
const cutoffDate = new Date(Date.now() - maxAgeDays * 24 * 60 * 60 * 1000);
for (const artifact of artifacts) {
if (createdAt < cutoffDate) {
await github.rest.actions.deleteArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id
});
}
}Required Permissions
The workflow requires actions: write permission to delete artifacts:
permissions:
actions: write # Required to delete artifactsSolution 2: Non-Blocking Artifact Uploads
All artifact upload steps now include continue-on-error: true to prevent CI failures when quota is exhausted.
Before (Blocking)
- name: Upload test reports
uses: actions/upload-artifact@v4
with:
name: test-reports
path: build/reports/CI fails if upload fails.
After (Non-Blocking)
- name: Upload test reports
uses: actions/upload-artifact@v4
continue-on-error: true # Don't fail CI if upload fails
with:
name: test-reports
path: build/reports/CI continues even if upload fails. The upload failure is logged but doesn’t block the workflow.
Affected Workflows
| Workflow | Artifacts Made Non-Blocking |
|---|---|
android-ci.yml | Lint reports, JaCoCo coverage, test reports, OWASP reports |
ios-ci.yml | Unit test results, UI test results |
android-integration-tests.yml | Integration test results, UI test results |
Solution 3: Self-Hosted Runner Migration
PR #477 also migrated android-integration-tests.yml to use self-hosted runners by default. This reduces GitHub-hosted runner quota consumption.
Key Changes
- Added
decide_runnerjob - Platform-conditional runner selection - Made KVM setup Linux-only - Software rendering on Windows/macOS
- Added
[github]escape hatch - Force GitHub-hosted if needed
Runner Selection Logic
decide_runner:
runs-on: self-hosted # Decision runs on self-hosted (no quota)
outputs:
runner_label: ${{ steps.decide.outputs.runner_label }}Jobs queue when self-hosted runners are offline instead of auto-fallback.
Monitoring
Check Current Storage Usage
- Go to Repository Settings > Actions > General
- Look for “Artifact and log storage used”
Check Cleanup Results
After cleanup runs, check the workflow summary for:
- Number of artifacts deleted
- Total storage freed (in MB)
Emergency Cleanup
If CI is failing due to quota:
-
Manually trigger cleanup:
- Go to Actions > Artifact Cleanup
- Run with
max_age_days: 1for aggressive cleanup
-
Wait 6-12 hours for quota to recalculate
-
Use
[self-hosted]flag in commit messages to bypass GitHub-hosted runners temporarily
Best Practices
Do’s
- Keep retention low (3 days is usually sufficient)
- Schedule cleanup during low-activity hours (weekends)
- Use dry-run before aggressive cleanup
- Monitor quota weekly (see Maintenance Tasks)
Don’ts
- Don’t rely on immediate quota recalculation
- Don’t upload large binary artifacts (APKs, IPAs)
- Don’t keep artifacts for weeks/months
- Don’t skip
continue-on-erroron artifact uploads
Related Documentation
- CD Maintenance Tasks - Weekly quota review procedures
- Hybrid Runner System - Self-hosted runner setup
- CD Operations Index - Operations overview
Tags: ci-cd github-actions artifacts quota-management Status: Active in production