Resolving Binary Target Dependencies from Private GitHub Repositories in Swift Package Manager

Article's main picture
  • #Swift

• 4 min read

Introduction

Swift Package Manager (SPM) allows having binary dependencies to speed up the build process by skipping the compilation step and using a binary off-the-shelf.

SPM, when such a dependency is specified, clones the whole repository, performs a checkout on the specified ref (tag/branch), and searches for the binary artifact there.

In most cases, cloning the whole repository is fine, but in the case of relatively big repositories, this approach will lead to prolonged package dependencies resolution. Using binary targets significantly speeds up initial checkout.

Adding a binary target dependency

Here's an example of Package manifest that uses binary target dependency:

let package = Package(
    name: "PackageName",
    ...
    targets: [
        .target(
            name: "PackageName",
            dependencies: ["BinaryTargetDependency"]
        ),
        .binaryTarget(
          name: "BinaryTargetDependency",
          url: "https://github.com/MacPaw/BinaryTargetDependency/archive/refs/tags/0.1.6.zip",
          checksum: "8520dedf4202bf8e92a067ed4b632396ad157d61b39a2327f4c3e7121e76b530"
        )
    ]
)

This approach works fine for public repositories, but what if we want to access private repositories that require authentication?

Accessing private GitHub repositories

Since Xcode 13.3.x, the xcodebuild command and Xcode itself, when facing the GitHub URL of a private repository, will try to authenticate using a GitHub access token stored in the keychain. To use binary frameworks, we need to put a Github access token to the keychain.

First, we need to get one of those tokens.

Generating a GitHub access token

Generating access tokens is a pretty straightforward operation. Just go to your GitHub account, select a few checkmarks, and that's it: Generate Github Access Token.

Important:

  • Ensure that the access token has repo and user access scopes.
  • Also, enable SSO for the token (if your organization requires it).

The next step will be adding the GitHub access token to the keychain. We can do it from the GUI or the Terminal. Depending on your needs, you can select one option or another.

Creating an item in Keychain (manually)

Launch the Keychain Access, and add the new Password Items. Fill item name, account name and password fields.

FieldValue
Item Namehttps://github.com
Account NameYout Github Account name
PasswordGithub Access Token (should look like ghp_XXXXXXXXXXXXXX)

Allowing Xcode to access items in the Keychain

Once you've added the GitHub access token to the keychain, you can resolve package dependencies. If everything was done right in the previous step, Xcode would try to access the item in the keychain, and the System will show an alert that will ask for allowing Xcode to use an item in keychain.

Just put your password in and press "Always Allow." Or, if you want to be in control every time — press "Allow."

Creating items in the keychain (from the command line)

If you're more of a Terminal user, here are the droids lines you're looking for:

echo "Enter Github Account:"
read ACCOUNT_NAME
echo "Enter Github Api Token (should be like ghp_XXXXXXXXXXXXX format):"
read GITHUB_API_TOKEN
security add-internet-password -a "${ACCOUNT_NAME}" -s "github.com" -r htps -w "${GITHUB_API_TOKEN}" -T "$(xcode-select -p)/usr/bin/xcodebuild" -T "/usr/bin/xcodebuild" -U login.keychain
security set-internet-password-partition-list -S apple-tool:,apple: -s "github.com" login.keychain

Just put those lines in the Terminal and follow the instructions. Also, note that adding a token via the Terminal will (should) automatically allow Xcode to access this item. This is very helpful for setting up access on CI.

Success

Resolve Packages in Xcode again. It should work now. That's all. 🎉

Conclusion

Of course, in some rare cases 😆 something can go wrong. Here are some errors that you can experience:

404 Errors

  • Check if the item in the keychain has the correct Name/Account/Password
  • Check if there are multiple items in the keychain
  • Check if you're using Xcode later than 13.1
  • Make sure that you have access to that repository and that the link is valid (try to open the link in the browser)

403 Errors

  • Make sure that token has enough rights
  • Make sure that SSO is enabled ( if your organization is using it)

More From engineering

Subscribe to our newsletter