How to use the Swift Package Manager with dependencies stored in private repositories?
Adding a username
and password
can functionally work:
let package = Package(
name: "MyPackage",
dependencies: [
.package(url: "https://username:[email protected]/me/MyPackage.git", .branch("develop"))
]
)
However, the username:password
approach has issues including (but not limited to) making the Package.swift
username specified, and putting plain text credentials in the repository.
Ideally, a solution would:
One solution, that I eventually found for "unix" type systems, is to use SSH git
URLs and add Host
configurations to ~/.ssh/config
. This approach works for both macOS/Linux command line and Xcode.
Use a ssh form for the dependency url in Package.swift
.
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "Example",
dependencies: [
.package(url: "[email protected]:abc/private-repo.git", .branch("develop") ),
],
)
In the above example, gitlab.com.myteam
corresponds to a Host
in ~/.ssh/config
### GITLAB WorkTeamOne
Host gitlab.com.workteam
HostName gitlab.com
User git
IdentityFile ~/.ssh/my_work_key_rsa
UseKeychain yes # for macOS keychain
AddKeysToAgent yes # for macOS keychain
PreferredAuthentications publickey
### GITLAB Hobby
Host gitlab.com.hobby
HostName gitlab.com
User git
IdentityFile ~/.ssh/my_hobby_key_rsa
UseKeychain yes # for macOS keychain
AddKeysToAgent yes # for macOS keychain
PreferredAuthentications publickey
SSH key pairs can be generated as needed for accounts and applied to an individual's online git service.
ssh-keygen \
-b 4096 \
-t rsa \
-C "[email protected]" \
-f ~/.ssh/my_work_key_rsa
Each team member could setup an individual, corresponding Host
ssh configuration. The Host
would be the same, however, the actual public/private key pairs (a) are specific to the user, (b) can be managed separately from any of the code development and (c) can be used automatically after the setup.
When using spm with private repos that are
vpn
or proxies
,ssh
Note that Xcode keeps its own folder of .ssh
and known_hosts
.
You can see it in
~/Library/Preferences/com.apple.dt.Xcode.plist
It will look like this
In a ci environment, this is not pleasant and you might get the following errors:
xcodebuild: error: Could not resolve package dependencies: The server SSH fingerprint failed to verify.
xcodebuild: error: Could not resolve package dependencies: Authentication failed because the credentials were rejected
An unknown error occurred. failed to connect to localhost: Connection refused (-1)
You can actually tell Xcode to use standard location of ssh keys and known hosts ~/.ssh
via one of the following:
a. This works on container based ci like circle ci
sudo defaults write com.apple.dt.Xcode IDEPackageSupportUseBuiltinSCM YES
b. This works on bare metal
/usr/libexec/Plistbuddy -c "Add :IDEPackageSupportUseBuiltinSCM bool 1" ~/Library/Preferences/com.apple.dt.Xcode.plist
c. If the above didn't work for you try adding -scmProvider system
on your xcodebuild command
gym(
...
use_system_scm: true
)
scan(
...
use_system_scm: true
)
fastlane run spm --use_system_scm true
xcodebuild -scmProvider system
Make sure your private repo host is added to ~/.ssh/known_hosts
a. for bitbucket
for ip in $(dig @8.8.8.8 bitbucket.org +short); do ssh-keyscan bitbucket.org,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts || true
b. for github
for ip in $(dig @8.8.8.8 github.com +short); do ssh-keyscan github.com,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts || true
c. others
ssh-keyscan your-host.com >> ~/.ssh/known_hosts
I've made it without SSH for my iOS project in Xcode. My private repo with package hosted on GitLab, but can be hosted on GitHub, Bitbucket, self-hosted Gitlab.
The process is straight: create a private repo with SPM package on one of the hostings above. Then add it as a dependency in your Xcode project as a usual package. Since the repo is private, Xcode will ask for credentials (in case of Gitlab it's an access token which you can generate in your Gitlab account). Xcode will remember it and will authorize you next time automatically. Thus you (and your colleagues) have to enter credentials only one time at setup. And both of your 1 and 2 conditions are satisfied.
You can manage Source Control Accounts in Xcode -> Preference -> Accounts (press + for add one).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With