Skip to content

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 successful builds.

Define artifacts using glob patterns in the artifacts field:

artifacts:
- build/**/*.ipa
- build/**/*.dSYM

Artifacts are collected after all pipeline steps complete successfully. If a step fails, artifacts are not uploaded.

Artifact patterns use standard glob syntax:

PatternMatches
build/**/*.ipaAll .ipa files in build directory and subdirectories
build/*.appAll .app files directly in build directory
**/*.dSYMAll .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

Define multiple patterns to collect different types of artifacts:

name: iOS Build
platform: 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 report

All matching files are collected and uploaded.

artifacts:
- build/**/*.ipa # App archive
- build/**/*.app # Unpackaged app
- build/**/*.dSYM # Debug symbols
- build/**/*.xcarchive # Xcode archive
artifacts:
- build/**/*.app # App bundle
- build/**/*.dmg # Disk image
- build/**/*.dSYM # Debug symbols
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 Bundle
artifacts:
- fastlane/report.html # Fastlane build report
- build/reports/**/*.xml # Test reports
- coverage/report.html # Coverage reports

The system variable RUNNERHUB_ARTIFACTS_DIR points to a directory where you can explicitly place artifacts:

name: Build
platform: 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.

How long artifacts are stored depends on your RunnerHub plan:

PlanRetentionDownloadStorage
FreeNoneDashboard (during job)Not persisted — available during the job
Pay-as-you-go (PAYG)7 daysDashboardStored in RunnerHub
Pro30 daysDashboardStored in RunnerHub
Business90 daysDashboardStored in RunnerHub

Free plan: Artifacts are not persisted — they are available via the dashboard during the job but deleted at job completion. To preserve artifacts, 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.

  1. Open a completed job in your app
  2. Navigate to the Artifacts tab
  3. Click the download icon next to each artifact
  4. Artifacts are available for the retention period of your plan

Access artifacts programmatically in your pipeline:

name: Upload
platform: ios
environment:
xcode: "16.4"
steps:
- name: Upload to Google Cloud Storage
run: |
gsutil -m cp -r $RUNNERHUB_ARTIFACTS_DIR gs://my-bucket/builds/

Here’s a full iOS pipeline that builds and collects artifacts:

name: iOS Release Build
platform: 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: 45

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 artifacts
artifacts:
- build/**/*.ipa # Final release build
- build/**/*.dSYM # Debug symbols
# Avoid: Unnecessary intermediate files
artifacts:
- build/**/* # Everything (too broad)
- build/DerivedData/** # Redundant (already cached)
- build/**/*.o # Object files (not needed)

To skip artifact collection, omit the artifacts field:

name: Tests Only
platform: ios
environment:
xcode: "16.4"
triggers:
- pull_request
steps:
- name: Run tests
run: fastlane test
# No artifacts field → no collection

Use your build system’s built-in features to conditionally upload artifacts:

name: Conditional Build
platform: 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/**/*.dSYM

On the Free plan, artifacts are not retained in RunnerHub. Use this strategy:

name: iOS Build
platform: 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/**/*.dSYM

Artifacts are still collected (visible in dashboard logs), but for long-term storage, use S3, Firebase, or another service.

Check these issues:

  1. Build failed — Artifacts only upload on successful builds
  2. Pattern mismatch — Verify glob pattern matches the actual file path
  3. File doesn’t exist — Verify the build actually creates the expected files
  4. Permission denied — Ensure files are readable by the RunnerHub process

Use a step to verify the path:

name: Verify
platform: 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/**/*.dSYM

If uploads are slow:

  1. Check network conditions
  2. Consider compressing artifacts before uploading
  3. Upload to your own storage (S3, Firebase) in parallel
name: Compress and Upload
platform: 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/upload

Keep Artifacts Minimal Only collect essential build outputs:

artifacts:
- build/**/*.ipa # ✓ Essential
- build/**/*.dSYM # ✓ Essential
# build/**/*.o # ✗ Not needed
# build/DerivedData/** # ✗ Already cached

Use Descriptive Paths Organize artifacts in the build directory with clear names:

name: Build
platform: 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.dSYM

Upgrade 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_request

Click Trigger Build in the dashboard for builds you want to preserve with artifact retention.