KINTO Tech Blog
KMP

Credential Setup for Private Repositories in SwiftPM

Cover Image for Credential Setup for Private Repositories in SwiftPM

この記事は KINTOテクノロジーズアドベントカレンダー2024 の10日目の記事です🎅🎄


Background

When developing the KINTO かんたん申し込みアプリ App, we implemented some shared code using KMP (Kotlin Multiplatform) and published it as a Swift Package. This approach allowed us to efficiently share code across platforms and simplify the development process by avoiding code duplication.

Our iOS Team currently uses XcodeGen to manage dependencies, and importing KMP code can be as simple as making a 4-line modification to the project.yml file. Here is an example of such a modification:

packages:
+  Shared:
+    url: https://github.com/[your organization]/private-android-repository
+    minorVersion: 1.0.0
targets:
  App:
    dependencies:
+     - package: Shared
      - package: ...

However, since our code resides in private repositories, some additional setup is required. This blog will outline those steps and explain how we streamlined the process.

About Package.swift

Here’s a brief explanation of how we publish KMP code as a Swift Package:

  1. Compile the KMP code into an .xcframework.
  2. Package the .xcframework into a zip file and calculate its checksum.
  3. Create a new release page on GitHub and upload the zip file as part of the release assets.
  4. Obtain the zip file’s URL from the release page.
  5. Generate the Package.swift file based on the URL and checksum.
  6. Commit the Package.swift file and add a git tag to mark the release.
  7. Associate the git tag with the release page and officially publish the GitHub release.

The resulting Package.swift file will look something like this:

// swift-tools-version: 5.10

import PackageDescription

let packageName = "Shared"

let package = Package(
    name: packageName,
    ...
    targets: [
        .binaryTarget(
            name: packageName,
            url: "https://api.github.com/repos/[your organization]/private-android-repository/releases/assets/<asset_id>.zip",
            checksum: "<checksum>"
        )
    ]
)

Permission Setup for Development Environment

Since the URL resides in a private repository, you will encounter the following error if no permission configuration is done:

badResponseStatusCode_404

To resolve this, we explore two options: .netrc files and Keychain.

Option 1: Using a .netrc File

You can store your GitHub credentials in a .netrc file, which is a simple way to authenticate API requests:

#Example: echo "machine api.github.com login username password ghp_AbCdEf1234567890" >> ~/.netrc 
echo "machine api.github.com login <Your Github Username> password <Your Personal Access Token>" >> ~/.netrc

This method is quick and effective but may pose security risks since the token is stored in plaintext.

Option 2: Using Keychain

If you prefer not to store the token in plaintext, you can use Keychain to securely store your credentials:

keychain new item

  1. Open Keychain Access.app.
  2. Select ①, the login keychain.
  3. Select ②, to create a new Password Item.

In the dialog box, enter the following information:

  • Keychain Item Name: https://api.github.com
  • Account Name: Your GitHub username
  • Password: Your Personal Access Token

This approach is more secure and integrates seamlessly with macOS authentication mechanisms.

For SSH Users

The above instructions assume you cloned the iOS repository using the https protocol. If you did, you already have the necessary permissions for github.com configured.

However, if you cloned the repository using the ssh protocol, you might lack permissions for github.com, leading to permission-related errors during the resolveDependencies phase.

To fix this, you can add an entry for the domain github.com in the .netrc file:

#Example: echo "machine github.com login username password ghp_AbCdEf1234567890" >> ~/.netrc 
echo "machine github.com login <Your Github Username> password <Your Personal Access Token>" >> ~/.netrc

Alternatively, use Keychain Access to add an item with the name https://github.com. Either method ensures your system has the required permissions.

GitHub Actions

After resolving the local development environment issues, you also need to address permission issues in the CI environment to ensure smooth automation during builds.

Retrieving Tokens in GitHub Actions

Using a Personal Token

One straightforward approach is to create a Personal Access Token (PAT) with access to private repositories and pass it to the CI environment via Actions secrets. While effective, this method has several drawbacks:

  • Token Expiration
    • Tokens with an expiration date require periodic updates, and forgetting to update them may cause CI failures.
    • Tokens without an expiration date pose long-term security risks.
  • Broad Permissions
    • A personal account usually has access to multiple private repositories, making it difficult to restrict PAT permissions to a single repository.
  • Personal Dependency
    • If the account owner loses access to private repositories due to role changes, CI workflows will fail.

Using a GitHub App

Using a GitHub App is a more robust solution, offering several advantages:

  • Fine-grained permissions for repositories
  • No dependency on individual accounts
  • Temporary tokens that enhance security

Setting Up a GitHub App

We ultimately used a GitHub App to configure access permissions. Here is the process:

  1. Create a GitHub App in your organization.
  2. Install the App in both iOS and Android projects to manage repository access.
  3. Configure the App’s AppID and Private Key in the iOS project’s Actions secrets.
  4. Add code in the workflows to retrieve a temporary Access Token. Here’s an example:
steps:
    - name: create app token
      uses: actions/create-github-app-token@v1
      id: app-token
      with:
        app-id: ${{ secrets.APP_ID }}
        private-key: ${{ secrets.APP_PRIVATE_KEY }}
        owner: "YourOrgName"

    - name: set access token for private repository
      shell: bash
      env:
        ACCESS_TOKEN: ${{ steps.app-token.outputs.token }}
      run: |
        git config --global url."https://x-access-token:$ACCESS_TOKEN@github.com/".insteadOf "https://github.com/"
        touch ~/.netrc
        echo "machine github.com login x-access-token password $ACCESS_TOKEN" >> ~/.netrc
        echo "machine api.github.com login x-access-token password $ACCESS_TOKEN" >> ~/.netrc

By using a GitHub App, we ensure our CI workflows are secure, efficient, and free from dependency on individual user accounts. This approach minimizes risk and streamlines development across teams.

Facebook

関連記事 | Related Posts

We are hiring!

【iOSエンジニア】モバイルアプリ開発G/東京

モバイルアプリ開発GについてKINTOテクノロジーズにおける、モバイルアプリ開発のスペシャリストが集まっているグループです。KINTOやmy routeなどのサービスを開発・運用しているグループと協調しながら品質の高いモバイルアプリを開発し、サービスの発展に貢献する事を目標としています。

【iOSエンジニア】モバイルアプリ開発G/大阪

モバイルアプリ開発GについてKINTOテクノロジーズにおける、モバイルアプリ開発のスペシャリストが集まっているグループです。KINTOやmy routeなどのサービスを開発・運用しているグループと協調しながら品質の高いモバイルアプリを開発し、サービスの発展に貢献する事を目標としています。