Artifacts
Artifacts allow you to collect and preserve build outputs like .ipa, .app, and other build products. RunnerHub automatically uploads artifacts at the end of every job, regardless of whether the job succeeded or failed.
Basic Configuration
Section titled “Basic Configuration”Define artifacts using glob patterns in the artifacts field:
artifacts: - build/**/*.ipa - build/**/*.dSYMArtifacts are collected after all pipeline steps complete — whether the job status is SUCCESS, FAILED, or TIMEOUT. This means test reports, crash logs, and partial build outputs are preserved even when a build fails. Artifacts are not uploaded only when a job is cancelled.
Upload Limits
Section titled “Upload Limits”Artifact uploads have the following limits:
- Per-file limit: 2 GB per artifact file
- Per-job limit: 5 GB total per job
- File count limit: 20 files per job
Uploads exceeding these limits are rejected by the agent.
Glob Pattern Syntax
Section titled “Glob Pattern Syntax”Artifact patterns use standard glob syntax:
| Pattern | Matches |
|---------|---------|
| build/**/*.ipa | All .ipa files in build directory and subdirectories |
| build/*.app | All .app files directly in build directory |
| **/*.dSYM | All .dSYM files anywhere in the repository |
| build/output/* | All files directly in build/output |
| dist/app.{ipa,app} | app.ipa or app.app in the dist directory |
Multiple Artifact Patterns
Section titled “Multiple Artifact Patterns”Define multiple patterns to collect different types of artifacts:
name: iOS Buildplatform: ios
environment: xcode: "16.4"
triggers: - push
steps: - name: Build run: fastlane build
artifacts: - build/**/*.ipa # Release builds - build/**/*.app # Debug builds - build/**/*.dSYM # Debug symbols - fastlane/report.html # Build reportAll matching files are collected and uploaded.
Common Artifact Patterns
Section titled “Common Artifact Patterns”iOS Projects
Section titled “iOS Projects”artifacts: - build/**/*.ipa # App archive - build/**/*.app # Unpackaged app - build/**/*.dSYM # Debug symbols - build/**/*.xcarchive # Xcode archivemacOS Projects
Section titled “macOS Projects”artifacts: - build/**/*.app # App bundle - build/**/*.dmg # Disk image - build/**/*.dSYM # Debug symbolsReact Native / Flutter
Section titled “React Native / Flutter”artifacts: - ios/build/**/*.app # iOS app (debug) - ios/build/**/*.ipa # iOS release build - ios/build/**/*.dSYM # iOS debug symbols - android/app/build/outputs/**/*.apk # Android release APK - android/app/build/outputs/bundle/**/*.aab # Android App BundleBuild Reports
Section titled “Build Reports”artifacts: - fastlane/report.html # Fastlane build report - build/reports/**/*.xml # Test reports - coverage/report.html # Coverage reportsUsing RUNNERHUB_ARTIFACTS_DIR
Section titled “Using RUNNERHUB_ARTIFACTS_DIR”The system variable RUNNERHUB_ARTIFACTS_DIR points to a directory where you can explicitly place artifacts:
name: Buildplatform: ios
environment: xcode: "16.4"
steps: - name: Build run: | fastlane build # Optionally copy artifacts to the artifacts directory cp build/app.ipa $RUNNERHUB_ARTIFACTS_DIR/ cp build/app.dSYM $RUNNERHUB_ARTIFACTS_DIR/Artifacts in this directory are automatically collected, or you can use glob patterns to collect them from elsewhere in your build.
Artifact Retention by Plan
Section titled “Artifact Retention by Plan”How long artifacts are stored depends on your RunnerHub plan:
| Plan | Retention | Download | Storage |
|------|-----------|----------|---------|
| Free | Not available | — | Artifact upload is skipped on the Free plan; no artifacts are stored. Listing artifacts: in YAML on Free has no effect. |
| Pay-as-you-go (PAYG) | 7 days | Dashboard | Stored in RunnerHub |
| Pro | 30 days | Dashboard | Stored in RunnerHub |
| Business | 90 days | Dashboard | Stored in RunnerHub |
Free plan: Artifact upload is skipped entirely on the Free plan — no files are stored and no error is returned. The artifacts: field is silently ignored. To collect build outputs, upgrade your plan or configure your own upload in the pipeline (S3, Firebase App Distribution, TestFlight, etc.).
PAYG and above: Artifacts are stored and downloadable from the RunnerHub dashboard for the specified retention period.
Downloading Artifacts
Section titled “Downloading Artifacts”From the Dashboard
Section titled “From the Dashboard”- Open a completed job in your app
- Navigate to the Artifacts tab
- Click the download icon next to each artifact
- Artifacts are available for the retention period of your plan
Using RUNNERHUB_ARTIFACTS_DIR
Section titled “Using RUNNERHUB_ARTIFACTS_DIR”Access artifacts programmatically in your pipeline:
name: Uploadplatform: ios
environment: xcode: "16.4"
steps: - name: Upload to Google Cloud Storage run: | gsutil -m cp -r $RUNNERHUB_ARTIFACTS_DIR gs://my-bucket/builds/Complete Pipeline Example
Section titled “Complete Pipeline Example”Here's a full iOS pipeline that builds and collects artifacts:
name: iOS Release Buildplatform: ios
environment: xcode: "16.4" variables: LC_ALL: en_US.UTF-8
triggers: - push - pull_request
steps: - name: Install dependencies run: bundle install
- name: Install pods run: pod install
- name: Run tests run: fastlane test
- name: Build Release run: fastlane build
- name: Copy artifacts run: | cp -r build/Release-iphoneos/*.ipa $RUNNERHUB_ARTIFACTS_DIR/ cp -r build/Release-iphoneos/*.dSYM $RUNNERHUB_ARTIFACTS_DIR/
artifacts: - build/**/*.ipa - build/**/*.dSYM
timeout: 45Managing Artifact Size
Section titled “Managing Artifact Size”Considerations:
- Artifacts are stored on RunnerHub servers (PAYG+)
- Large artifacts may take longer to upload
- Free plan artifacts are cleaned up, so size is less critical
- Consider storage limits for your plan
Optimization Tips:
# Good: Only essential artifactsartifacts: - build/**/*.ipa # Final release build - build/**/*.dSYM # Debug symbols
# Avoid: Unnecessary intermediate filesartifacts: - build/**/* # Everything (too broad) - build/DerivedData/** # Redundant (already cached) - build/**/*.o # Object files (not needed)Zero Artifacts (No Collection)
Section titled “Zero Artifacts (No Collection)”To skip artifact collection, omit the artifacts field:
name: Tests Onlyplatform: ios
environment: xcode: "16.4"
triggers: - pull_request
steps: - name: Run tests run: fastlane test
# No artifacts field → no collectionConditional Artifact Upload
Section titled “Conditional Artifact Upload”Use your build system's built-in features to conditionally upload artifacts:
name: Conditional Buildplatform: ios
environment: xcode: "16.4"
steps: - name: Build and Upload run: | fastlane build
if [ "$RUNNERHUB_TRIGGER" = "push" ] && [ "$RUNNERHUB_BRANCH" = "main" ]; then echo "Uploading to TestFlight..." fastlane upload else echo "Debug build, artifacts only for internal review" fi
artifacts: - build/**/*.ipa - build/**/*.dSYMFree Plan Artifact Strategy
Section titled “Free Plan Artifact Strategy”On the Free plan, artifacts are not retained in RunnerHub. Use this strategy:
name: iOS Buildplatform: ios
environment: xcode: "16.4" variables: AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
triggers: - push
steps: - name: Build run: fastlane build
- name: Upload to Google Cloud Storage run: | gsutil -m cp -r build/app.ipa gs://my-build-artifacts/$RUNNERHUB_BRANCH/ gsutil -m cp -r build/app.dSYM gs://my-build-artifacts/$RUNNERHUB_BRANCH/
artifacts: - build/**/*.ipa - build/**/*.dSYMArtifacts are still collected (visible in dashboard logs), but for long-term storage, use S3, Firebase, or another service.
Passing Artifacts Between Jobs
Section titled “Passing Artifacts Between Jobs”In a multi-job pipeline, each job runs in its own fresh VM with a fresh repository clone. Files written by one job are not automatically visible to another — with one exception: the needs-based artifact restore.
How it works
Section titled “How it works”- Producer job — declare
artifacts:with glob patterns as normal. The agent uploads matching files when the job finishes. - Consumer job — declare
needs: [producerJobKey]. Before the consumer's first step runs, RunnerHub automatically downloads all artifacts from every job listed inneeds:and restores them into the consumer's workspace.
Restored artifacts are placed under the directory pointed to by the RUNNERHUB_NEEDS_DIR environment variable, namespaced by producer job key:
$RUNNERHUB_NEEDS_DIR/<producer-job-key>/<relative-path-of-artifact>For example, if the producer job key is build and it uploaded build/MyApp.ipa, the consumer can read it at:
$RUNNERHUB_NEEDS_DIR/build/build/MyApp.ipaMatrix producers
Section titled “Matrix producers”If the producer job was matrix-expanded (e.g., build × 2 variants), all variants' artifacts are restored, each under its own expanded job key:
$RUNNERHUB_NEEDS_DIR/build-Release/build/MyApp-Release.ipa$RUNNERHUB_NEEDS_DIR/build-Debug/build/MyApp-Debug.ipaExample: build → deploy
Section titled “Example: build → deploy”name: Build and Deployplatform: ios
environment: xcode: "16.4"
triggers: - push
jobs: build: name: Build App steps: - name: Install dependencies run: bundle install && pod install
- name: Archive run: | xcodebuild archive \ -scheme MyApp \ -archivePath build/MyApp.xcarchive
- name: Export IPA run: | xcodebuild -exportArchive \ -archivePath build/MyApp.xcarchive \ -exportPath build/ \ -exportOptionsPlist ExportOptions.plist
artifacts: - build/**/*.ipa - build/**/*.dSYM
deploy: name: Deploy to TestFlight needs: [build] # Waits for build; restores its artifacts steps: - name: Upload to TestFlight run: | IPA="$RUNNERHUB_NEEDS_DIR/build/build/MyApp.ipa" echo "Uploading $IPA" xcrun altool --upload-app -f "$IPA" \ -u "$APPLE_ID" -p "$APP_SPECIFIC_PASSWORD"Troubleshooting Artifacts
Section titled “Troubleshooting Artifacts”Artifacts Not Uploading
Section titled “Artifacts Not Uploading”Check these issues:
- Job was cancelled — Artifacts are skipped when a job is cancelled; they upload on SUCCESS, FAILED, and TIMEOUT outcomes
- Pattern mismatch — Verify glob pattern matches the actual file path
- File doesn't exist — Verify the build actually creates the expected files
- Permission denied — Ensure files are readable by the RunnerHub process
- Free plan — Artifact upload is skipped on the Free plan; no artifacts are stored (see Artifact Retention by Plan)
Verify Artifact Path
Section titled “Verify Artifact Path”Use a step to verify the path:
name: Verifyplatform: ios
environment: xcode: "16.4"
steps: - name: Build run: fastlane build
- name: Verify Artifacts run: | echo "Checking for artifacts..." find . -name "*.ipa" -o -name "*.dSYM" ls -la build/
artifacts: - build/**/*.ipa - build/**/*.dSYMLarge Artifact Upload Times
Section titled “Large Artifact Upload Times”If uploads are slow:
- Check network conditions
- Consider compressing artifacts before uploading
- Upload to your own storage (S3, Firebase) in parallel
name: Compress and Uploadplatform: ios
environment: xcode: "16.4"
steps: - name: Compress and Upload run: | tar -czf app.tar.gz build/app.ipa curl -X POST -T app.tar.gz https://webhook.example.com/uploadBest Practices
Section titled “Best Practices”Keep Artifacts Minimal Only collect essential build outputs:
artifacts: - build/**/*.ipa # ✓ Essential - build/**/*.dSYM # ✓ Essential # build/**/*.o # ✗ Not needed # build/DerivedData/** # ✗ Already cachedUse Descriptive Paths Organize artifacts in the build directory with clear names:
name: Buildplatform: ios
environment: xcode: "16.4"
steps: - name: Build run: | fastlane build # Rename for clarity cp build/Release-iphoneos/app.ipa build/MyApp-release.ipa cp -r build/Release-iphoneos/app.dSYM build/MyApp-release.dSYMUpgrade Plan for Long-Term Storage If you need artifact retention:
- Free → PAYG/Pro: Get 7-30 day retention
- Use cloud storage (S3, Firebase) for permanent archival
Use Dashboard Triggers for Important Builds
To preserve artifacts, use manual triggers from the dashboard for important builds. Your triggers: field can focus on webhook-driven runs:
triggers: - push - pull_requestClick Trigger Build in the dashboard for builds you want to preserve with artifact retention.
Next Steps
Section titled “Next Steps”- Configure Triggers to control when your pipeline runs
- Set up Caching to speed up builds
- Define Environment Variables for your build
- Learn about Timeout & Limits
- Review the YAML Reference