Tips on Use Swift Package Manager (SPM) with Continuous Integration / Delivery (CI/CD)
Continuous integration (CI) is the process of automating and streamlining the building, analyzing, testing, archiving, and publishing of your apps to ensure that they’re always in a releasable state.
Resolve Package Dependencies
xcodebuild options related resolve package dependencies:
xcodebuild -resolvePackageDependencies [-project <projectname>|-workspace <workspacename>] -clonedSourcePackagesDirPath <path> -runFirstLaunch install packages and agree to the license -clonedSourcePackagesDirPath PATH specifies the directory to which remote source packages are fetch or expected to be found -resolvePackageDependencies resolves any Swift package dependencies referenced by the project or workspace -disableAutomaticPackageResolution prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file -onlyUsePackageVersionsFromResolvedFile prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file -skipPackageUpdates Skip updating package dependencies from their remote -disablePackageRepositoryCache disable use of a local cache of remote package repositories -skipPackagePluginValidation Skip validation of package plugins (this can be a security risk if they are not from trusted sources) -packageCachePath path of caches used for package support
The easiest way to resolve package dependencies is to simply run
There are two directories for the SPM cache.
~/Library/Caches/org.swift.swiftpm/repositories/ includes git clone for remote package repo.
Sometimes we may need to clear these caches before the build to make sure the build is clean.
Two lanes you for resolving dependencies and clear SPM cache.
You may also need
clear_derived_data before your build to make sure the build is clean.
lane :resolve_package_dependencies do Dir.chdir("..") do sh("xcodebuild -resolvePackageDependencies -onlyUsePackageVersionsFromResolvedFile") end end lane :clear_spm_cache do sh("rm -rf ~/Library/org.swift.swiftpm") sh("rm -rf ~/Library/Caches/org.swift.swiftpm") end
Sample code in
Fastfile to an ipa:
lane :build do clear_derived_data clear_spm_cache resolve_package_dependencies gym(...) end
Private SPM dependencies
If your Xcode project have depends on private git repo. To resolve package dependencies that require authentication, or private packages, you need to provide credentials to your CI setup. In CI environment, Xcode can reuse git credential which used from clone code. The token may store in keychain, so make sure your keychain is accessible by CI scripts.
If you’re using the xcodebuild command directly, use SSH–based Git URLs for your packages and configure your SSH credentials. Set up your known_hosts file in the ~/.ssh directory of the macOS user that runs your CI tasks. xcodebuild honors your SSH configuration — there’s no additional setup required.
Package.resolved file to your Git repository
Commit your project’s Package.resolved file to your Git repository. This ensures a reliable CI workflow that always uses the expected version of a package dependency.
Use the expected version of a package dependency
To ensure the CI workflow’s reliability, make sure it uses the appropriate version of package dependencies. Xcode stores the exact version of each package dependency in a file called Package.resolved. The file automatically updates when package requirements in your Xcode project or in the Package.swift manifest file change. Commit this file to your Git repository to ensure it’s always up-to-date on the CI environment to prevent the CI from building your project with unexpected versions of package dependencies.
You can find the
Package.resolved file inside your
.xcodeproj directory at
In CI/CD, We want to prevent packages from automatically being resolved to versions other than those recorded in the
Package.resolved file. This can be done with
xcodebuild -resolvePackageDependencies -onlyUsePackageVersionsFromResolvedFile
IDEPackageOnlyUseVersionsFromResolvedFile = YES.
$ xcodebuild -resolvePackageDependencies -onlyUsePackageVersionsFromResolvedFile Command line invocation: /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -resolvePackageDependencies -onlyUsePackageVersionsFromResolvedFile User defaults from command line: IDEPackageOnlyUseVersionsFromResolvedFile = YES IDEPackageSupportUseBuiltinSCM = YES Resolve Package Graph ... ... resolved source packages: ...
Here is another option
-disableAutomaticPackageResolution. You might be wondering: What’s the difference?
The answser is they are they same. From
xcodebuild -help shows the same description.
-disableAutomaticPackageResolution prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file -onlyUsePackageVersionsFromResolvedFile prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file
I also tried to play with
-disableAutomaticPackageResolution and it have the same output with
You can compare this output with above output with
-onlyUsePackageVersionsFromResolvedFile, both set
IDEPackageOnlyUseVersionsFromResolvedFile = YES:
$ xcodebuild -resolvePackageDependencies -disableAutomaticPackageResolution Command line invocation: /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -resolvePackageDependencies -disableAutomaticPackageResolution User defaults from command line: IDEPackageOnlyUseVersionsFromResolvedFile = YES IDEPackageSupportUseBuiltinSCM = YES Resolve Package Graph ...
Could not resolve package dependencies due to could not read Username for git server
xcodebuild: error: Could not resolve package dependencies: Couldn’t fetch updates from remote repositories: fatal: could not read Username for 'https://some-git-server.com': terminal prompts disabled
Root Cause Analyze:
This is indicate there is no git credentienal, incorrect or token expired (if use token like bitbucket SCM token.)
To verify the issue, run
git pull should get password promot:
$ git pull Password for 'https://some-git-server':
Keychain UI may also popup in this scenario.
git ssh based authentication to avoid authentication issue. e.g. change from
- Building Swift packages or apps that use them in continuous integration workflows
- Swift Package Manager build times in a continuous integration platform
A1 - Block / Hide iOS Apps
Hide Apps from Home Screen, App Library and Lock Apps to protect your privacy even further (requires iOS 16).
DNS Firewall for iOS and Mac OS
Encrypted your DNS to protect your privacy and firewall to block phishing, malicious domains, block ads in all browsers and apps