SwiftPM's default way of fetching a dependency is a full git clone of its
repository, history and all, repeated on every fresh CI runner. Avrea's macOS
runners now resolve public Swift packages through a hosted
package registry
instead, enabled by default with Xcode 26 and newer: each version is
served as a small checksummed archive from storage sitting next to your
runners.
- Faster resolution. A dependency downloads as one archive instead of a
full repository clone, and repeat builds hit the cache.
- Less exposure to GitHub. Once a version is cached, resolving it no
longer touches GitHub at all.
- Nothing else changes. Private packages and branch- or commit-pinned
dependencies keep resolving via git exactly as before, in the same build.
Resolving through the registry changes how Package.resolved records its
pins (registry identities and checksums instead of git URLs and commits), so
the first resolve rewrites them. Repositories that need to keep git-form pins
can opt out with the Swift Package Registry setting, per organization or
repository.
While benchmarking the rollout we measured what the classic lockfile advice
is worth here. Resolving vapor's 28-package graph on a fresh runner:
| Setup |
Resolve time |
| git, no lockfile |
23s |
| Registry, no lockfile |
11s |
Registry, committed lockfile + --force-resolved-versions |
4s |
So: commit Package.resolved, and resolve in CI with
swift package resolve --force-resolved-versions (for Xcode projects,
xcodebuild -disableAutomaticPackageResolution). Like npm ci, it uses
exactly the committed pins and fails loudly on drift instead of silently
re-resolving, and it skips the version exploration that dominates cold
resolution.
See the Swift registry docs →