Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Xcode and git for resolving swift packages

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.

like image 586
ratbum Avatar asked Nov 25 '19 15:11

ratbum


People also ask

Does Xcode use Git?

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.

What is Package resolved Xcode?

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.

How do I use Git repository in Xcode?

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.


2 Answers

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:

  • Replace [org_name] with your organization name.
  • Replace ${GITHUB_PAT} with the name of your CI Secret if you named it differently.
  • Configure the grep command to ignore any paths you don't want modified by the script.
like image 113
bscothern Avatar answered Nov 09 '22 23:11

bscothern


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.

like image 29
ratbum Avatar answered Nov 10 '22 00:11

ratbum