Swift Package Registry
Avrea runs a Swift package registry
that caches public and eligible organization-private Swift packages hosted on
GitHub. SwiftPM can resolve semantic-version dependencies as checksummed source
archives served from colocated storage instead of running a full git clone
for each dependency.
Public package source is shared across Avrea customers. Private package source and metadata remain isolated to the organization that is authorized to access the corresponding GitHub repository.
The registry caches package source, not compiled output. Xcode Compilation Cache reuses compiler results, while Tuist Module Cache substitutes complete prebuilt targets.
Enable the registry
Section titled “Enable the registry”Public registry configuration is on by default. SwiftPM and Tuist commands opt into replacing Git dependencies as described below. Private package resolution also requires an explicit opt-in. Both require the Package Manager Cache and Swift Package Registry settings to remain enabled.
Enable private packages for an organization or repository in the console, or via the CLI:
avr settings set cache.swift-private-registry.enabled trueThe setting applies to new jobs. A repository-level override takes precedence over the organization setting.
Xcode projects
Section titled “Xcode projects”On macOS runners with Xcode 26 or later, Avrea configures the package registry before workflow steps run. When Avrea creates the native registry configuration, it also enables Xcode's source-control-to-registry transformation. Eligible version-based Git dependencies then resolve through the registry. Branch and revision dependencies continue to download through Git.
Xcode Compilation Cache separately reuses compiler output without requiring registry transformation.
Local packages and registry compatibility
Section titled “Local packages and registry compatibility”If resolution fails with invalid package type registry <identity>, check the
swift-tools-version declaration in every local root package loaded by the
Xcode workspace. SwiftPM selects the lockfile format using the lowest root
tools version. Versions below 5.6 select the legacy format, which cannot store
registry dependencies. Update those local manifests to at least 5.6:
// swift-tools-version:5.6If a branch or revision dependency then reports a missing product, give its
dependency declaration an explicit name matching the product's package
reference. Registry transformation changes the dependency identity while
retaining Git fetching; the explicit name preserves product lookup:
.package( name: "MetaTextKit", url: "https://github.com/mastodon/MetaTextKit.git", branch: "2.2.5-xcode16")// The target's product reference stays unchanged:.product(name: "MetaTextKit", package: "MetaTextKit")The same applies to dependencies declared with revision:.
Tuist and SwiftPM CLI
Section titled “Tuist and SwiftPM CLI”The SwiftPM CLI does not use Xcode's transformation preference. Commands such
as tuist install, swift package resolve, and swift build need the
--replace-scm-with-registry option to replace eligible GitHub URL
dependencies with registry downloads.
Avrea configures its registry as the default before workflow steps run. The
same managed configuration is available to native SwiftPM and embedded
SwiftPM clients such as Tuist. Normal workflows do not need to run
swift package-registry set or associate individual public scopes.
Resolve Tuist dependencies
Section titled “Resolve Tuist dependencies”Commit Tuist/Package.resolved and run:
tuist install \ --replace-scm-with-registry \ --force-resolved-versions--replace-scm-with-registry asks SwiftPM to replace eligible source-control
dependencies. --force-resolved-versions uses the committed versions and fails
if the manifest and lockfile disagree.
To make replacement part of the Tuist project configuration, pass the SwiftPM
option through installOptions:
import ProjectDescription
let tuist = Tuist( fullHandle: "my-organization/my-project", project: .tuist( installOptions: .options( passthroughSwiftPackageManagerArguments: [ "--replace-scm-with-registry" ] ) ))Alternatively, declare a package by registry identity when it must always use the registry:
dependencies: [ .package(id: "apple.swift-log", exact: "1.6.4")]Direct identities do not fall back to Git. Avrea's managed default resolves eligible public identities. Resolution fails if customer-managed configuration does not provide a registry for the identity.
Dependency behavior
Section titled “Dependency behavior”The following combinations were validated with tuist install on Avrea macOS
runners:
| Package declaration | Additional configuration | Result |
|---|---|---|
Public identity such as apple.swift-log with an exact version | None | Avrea public registry |
| Public GitHub URL with an exact semantic version | Pass --replace-scm-with-registry | Avrea public registry |
| Public GitHub URL with an exact semantic version, without the replacement option | None | Git |
GitHub URL with branch: "main" | None | Git |
GitHub URL with a commit hash in revision | None | Git |
GitHub URL with revision: "1.6.4" | None | Git tag or ref, not a registry version |
| Eligible private GitHub URL with an exact semantic version | Enable Private Swift Packages and pass --replace-scm-with-registry | Organization-isolated private registry |
A dependency graph can mix registry and Git dependencies. Only eligible semantic-version packages move to the registry.
Tuist's installed dependency state
Section titled “Tuist's installed dependency state”tuist install stores dependency checkouts, registry downloads, extracted
source, binary artifacts, plugins, macros, and SwiftPM workspace state under
Tuist/.build. It can contain complete private dependency source. The Tuist
Module Cache guide
shows how to store this state in the repository-scoped GitHub Actions cache and
use it in main-branch warming and pull-request jobs.
How registry resolution works
Section titled “How registry resolution works”Package identities map to GitHub repositories. The package at
github.com/apple/swift-numerics has the public registry identity
apple.swift-numerics. The first time a version is requested, Avrea fetches
the tagged source from GitHub, creates a stable source archive, and caches it.
Later requests for that version receive the same archive and checksum from
colocated storage.
When Private Swift Packages is enabled, eligible private packages can keep
their existing https://github.com/{owner}/{repository} declaration. Avrea
selects the organization's private mirror behind the scenes. No GitHub or
Avrea service credential is added to the runner VM.
Branch and commit requirements, private repositories outside the organization's GitHub App installation, unsupported origins, and packages that cannot be represented by a registry identity continue to use Git.
Package.resolved
Section titled “Package.resolved”When a dependency resolves through the registry, Package.resolved records a
registry identity and archive checksum instead of a Git URL and commit. If the
checked-out lockfile contains eligible Git-form pins, CI may rewrite them in
the runner's ephemeral working tree while preserving the selected versions.
The committed file is unaffected unless the workflow explicitly persists it.
If workflows diff or hash-key Package.resolved, keep the registry behavior
consistent across the repository so pins do not alternate between Git and
registry forms. On a developer machine, local SwiftPM can continue resolving
the original GitHub URL with the developer's own credentials.
If tooling requires Package.resolved to remain byte-for-byte unchanged
during CI, disable registry resolution:
avr settings set cache.swift-registry.enabled falseFaster resolution in CI
Section titled “Faster resolution in CI”For a regular Swift package, commit Package.resolved and resolve with:
swift package resolve \ --replace-scm-with-registry \ --force-resolved-versionsFor Xcode projects, the strict resolved-version equivalent is
xcodebuild -disableAutomaticPackageResolution.
The effect is largest on a fresh runner. Resolving Vapor's 28-package dependency graph produced:
| Setup | Resolve time |
|---|---|
| Git, no lockfile | 23s |
| Registry, no lockfile | 11s |
Git, committed lockfile and --force-resolved-versions | 12s |
Registry, committed lockfile and --force-resolved-versions | 4s |
Requirements
Section titled “Requirements”- macOS runner with Xcode 26 or later: registry resolution relies on current SwiftPM and Xcode support. Older Xcode versions continue to use Git.
- GitHub-hosted dependencies: public repositories are eligible. Private packages additionally require Private Swift Packages, an Avrea GitHub App installation that covers the organization, and an available private mirror.
- Semantic-version requirements: branch and revision dependencies continue to use Git and the workflow's existing credentials.
Custom registry configuration
Section titled “Custom registry configuration”Avrea preserves a registries.json supplied by the workflow or runner image.
This customer-owned file takes precedence over Avrea's managed configuration
for the SwiftPM client that reads it. Normal workflows should remove the
custom file and use the managed configuration.
If the custom configuration is intentional, associate its default registry and the reserved private scope with Avrea:
swift package-registry set --global \ https://cache.avrea.com:8443/swift
swift package-registry set --global \ --scope avrea-com \ https://cache.avrea.com:8443/swiftThe avrea-com association selects Avrea's private package namespace; it does
not grant access. Private requests remain subject to the organization setting,
GitHub App installation, package mirror, and authorization checks.
Tuist and other embedded SwiftPM clients can read
~/.swiftpm/configuration/registries.json instead of native SwiftPM's
~/Library/org.swift.swiftpm/configuration/registries.json. Keep both files
aligned when managing them explicitly.
Troubleshooting
Section titled “Troubleshooting”No registry is configured for a public scope
Section titled “No registry is configured for a public scope”Avrea's managed default registry handles public scopes without workflow
configuration. Check whether the workflow or runner image creates a custom
registries.json. Remove that custom configuration, or associate its default
registry with Avrea as described in Custom registry
configuration.
A GitHub URL still uses Git
Section titled “A GitHub URL still uses Git”Confirm that the dependency uses a semantic-version requirement and the
SwiftPM or Tuist command includes --replace-scm-with-registry.
Branches, commit hashes, and values passed via revision intentionally remain
Git dependencies.
SwiftPM warns that the source archive is not signed
Section titled “SwiftPM warns that the source archive is not signed”Avrea registry archives currently use a stable checksum but are not signed. The runner config treats this as a warning so installation continues. A checksum mismatch remains an error.