So the background is this: I have an Xcode project that depends on a swift package that's in a private repository on github. Of course, this requires a key to access. So far, I've managed to configure CI such that I can ssh into the instance and git clone
the required repository for the swift package. Unfortunately when running it with xcbuild
as CI does, it doesn't work and I get this message:
static:ios distiller$ xcodebuild -showBuildSettings -workspace ./Project.xcworkspace \
-scheme App\ Prod
Resolve Package Graph
Fetching [email protected]:company-uk/ProjectDependency.git
xcodebuild: error: Could not resolve package dependencies:
Authentication failed because the credentials were rejected
In contrast, git clone
will happily fetch this repo as seen here:
static:ios distiller$ git clone [email protected]:company-uk/ProjectDependency.git
Cloning into 'ProjectDependency'...
Warning: Permanently added the RSA host key for IP address '11.22.33.44' to the list of known hosts.
remote: Enumerating objects: 263, done.
remote: Counting objects: 100% (263/263), done.
remote: Compressing objects: 100% (171/171), done.
remote: Total 1335 (delta 165), reused 174 (delta 86), pack-reused 1072
Receiving objects: 100% (1335/1335), 1.11 MiB | 5.67 MiB/s, done.
Resolving deltas: 100% (681/681), done.
For a bit more context, this is running on CircleCI, set up with a Deploy key on GitHub, which has been added to the Job on CI.
Any suggestions about what might be different between the way Xcode tries to fetch dependencies and the way vanilla git does it would be great. Thanks.
Xcode will create your new project along with a new Git repository. All source control systems, including Git, store their data into a repository so that they can manage your project versions and keep track of changes throughout the development cycle.
When you add a package dependency to a project, Xcode creates the Package. resolved file. It lists the specific Git commits to which each package dependency resolves and the checksum of each binary dependency. Commit this file in Git to ensure that everyone is using the same version of a package dependency.
Go to Source Control in Xcode and select Projectname -- master, then Configure... In the Address field, paste the Git clone URL for your repo copied in the previous step. Select Add Remote, then select Done to finish creating the origin remote for your local Git repo.
For CI pipelines where you cannot sign into GitHub or other repository hosts this is the solution I found that bypasses the restrictions/bugs of Xcode around private Swift packages.
Use https urls for the private dependencies because the ssh config is currently ignored by xcodebuild even though the documentation says otherwise.
Once you can build locally with https go to your repository host and create a personal access token (PAT). For GitHub instructions are found here.
With your CI system add this PAT as a secret environment variable. In the script below it is referred to as GITHUB_PAT
.
Then in your CI pipeline before you run xcodebuild
make sure you run an appropriately modified version of this bash script:
for FILE in $(grep -Ril "https://github.com/[org_name]" .); do
sed -i '' "s/https:\/\/github.com\/[org_name]/https:\/\/${GITHUB_PAT}@github.com\/[org_name]/g" ${FILE}
done
This script will find all https references and inject the PAT into it so it can be used without a password.
Don't forget:
[org_name]
with your organization name.${GITHUB_PAT}
with the name of your CI Secret if you named it differently. grep
command to ignore any paths you don't want modified by the script.This seems to be a bug in Xcode 11 with SSH. Switching to HTTPS for resolving Swift Packages fixes the issue:
So from this:
E29801192303068A00018344 /* XCRemoteSwiftPackageReference "ProjectDependency" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "[email protected]:company-uk/ProjectDependency.git";
requirement = {
branch = "debug";
kind = branch;
};
};
to:
E29801192303068A00018344 /* XCRemoteSwiftPackageReference "ProjectDependency" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/company-uk/ProjectDependency.git";
requirement = {
branch = "debug";
kind = branch;
};
};
Also, now that Xcode 12 is out, you can use that, where it's fixed.
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