Builds / Remote builds
Caching
Speed up remote builds with compilation and configured path caches
Every remote build runs in a clean, single-use VM. Revyl uses two kinds of caching to make repeat builds faster:
| Cache | Default | Best for |
|---|---|---|
| Compilation cache | On | Xcode, Gradle, and native C/C++ compilation |
| Configured path cache | Opt-in | Dependencies, generated files, and other project state |
Automatic compilation caching
Revyl enables the right compilation caches for each platform without changing your build commands:
| Platform | Caches |
|---|---|
| iOS | Xcode compilation cache |
| Android | Gradle build cache and ccache for native C/C++ |
The first compatible build warms the cache. Later builds on the same toolchain can reuse its compiler outputs across apps and branches in your organization.
The snippets below focus on cache fields. Keep the selected recipe's runnable
app_id, build_commands, and output_path from your build configuration.
You can turn each cache off independently:
build:
framework: react_native
profiles:
development:
ios:
build_commands: ["./scripts/build-ios"]
env:
REVYL_XCODE_COMPILATION_CACHE_ENABLED: "0"
android:
build_commands: ["./scripts/build-android"]
env:
REVYL_GRADLE_BUILD_CACHE_ENABLED: "0"
REVYL_CCACHE_ENABLED: "0"Each setting accepts "0" (off) or "1" (on) and defaults to "1".
Compilation caching is an optimization, not a build dependency. If it is unavailable, the build continues normally. It is also skipped when the build timeout is longer than 60 minutes.
Configured path caches
Declare defaults under build.caches and recipe-specific additions under
build.profiles.<name>.<platform>.caches. Each cache has a key and a list of
paths stored under it:
build:
framework: react_native
caches:
- key: javascript-dependencies
paths:
- node_modules
profiles:
development:
ios:
build_commands: ["./scripts/build-ios"]
caches:
- key: ios-dependencies
paths:
- ios/Pods
android:
build_commands: ["./scripts/build-android"]
caches:
- key: android-dependencies
paths:
- .gradle-homePaths can be project-relative or start with ~/ to cache files in the build
user's home directory. Absolute paths and paths that escape either root are
rejected.
How configured caches work
Build-level and recipe caches merge by key. For a matching key, build-level paths come first and recipe paths are appended with duplicates removed. Each effective key maps to one compressed archive that Revyl stores between builds:
- After checkout, Revyl restores the latest archive to its declared project or home locations. A new key starts empty.
- Your commands read and write the configured paths normally, such as
node_modules,Pods, or DerivedData. - If the build succeeds, Revyl archives those exact paths and saves them for the next build. Failed builds don't update caches, so a broken run can't poison them.
Compressed archives larger than 4 GiB are not saved. The build still succeeds, and the previous saved archive remains available for later builds.
Cache keys are scoped to your organization and platform. Builds using the same key share that archive across apps and branches. Concurrent builds work in private VMs; the last successful upload becomes the next saved state.
What to cache
| Work | Recommended cache |
|---|---|
| Xcode or Gradle compilation | Automatic compilation cache |
| Android native compilation | Automatic ccache |
| JavaScript dependencies | Configured path cache |
| CocoaPods | Configured path cache |
| Gradle dependency downloads | Configured path cache |
| DerivedData or generated files | Optional path cache; measure first |
For example:
build:
framework: android
profiles:
release:
android:
build_commands:
- ./gradlew assembleRelease
caches:
- key: android-dependencies
paths:
- ~/.gradle/caches/modules-*/files-*
- ~/.gradle/caches/modules-*/metadata-*
- ~/.gradle/wrapperIf you cache a build-output directory, keep output_path specific enough that
it cannot select a stale artifact.
Cold builds and clearing caches
# Bypass every cache for one build without deleting anything
revyl build --profile development --platform ios --remote --no-cache
# Inspect and delete configured caches
revyl cache list
revyl cache delete ios-dependenciesrevyl cache list and delete manage configured caches only. Compilation
caches are managed automatically and can be bypassed with --no-cache or the
individual environment settings above.
Troubleshooting
- The second build is still slow: make sure the first build completed successfully and compare builds using the same toolchain.
- Dependency installation is still slow: add its download or install directory to a configured cache.
- A configured cache looks stale: try
--no-cache, then delete the cache if the cold build fixes the problem. - Compilation caching is missing: check the build logs for
compilation-cachemessages and confirm the timeout is 60 minutes or less.
Related
- Fingerprinting: skip unnecessary native rebuilds for Expo and React Native apps
- Configuration: the full
build:reference - Toolchain Images: what's already installed