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:
- Compile the KMP code into an
.xcframework
. - Package the
.xcframework
into a zip file and calculate its checksum. - Create a new release page on GitHub and upload the zip file as part of the release assets.
- Obtain the zip file’s URL from the release page.
- Generate the
Package.swift
file based on the URL and checksum. - Commit the
Package.swift
file and add a git tag to mark the release. - 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:
To resolve this, we explore two options: .netrc
files and Keychain.
.netrc
File
Option 1: Using a 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:
- Open
Keychain Access.app
. - Select ①, the
login
keychain. - 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:
- Create a GitHub App in your organization.
- Install the App in both iOS and Android projects to manage repository access.
- Configure the App’s
AppID
andPrivate Key
in the iOS project’s Actions secrets. - 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.
関連記事 | Related Posts
Applying KMP to an Existing App: Our Team’s Experience and Achievements
SwiftUIをCompose Multiplatformで使用する
Bitriseを活用したiOSアプリ開発の効率化
【iOSDC Japan 2024】KINTOテクノロジーズ的振り返り
Flutter開発効率化:GitHub ActionsとFirebase Hostingを用いたWebプレビュー自動化の方法をstep-by-stepでご紹介
Kotlin Multiplatform Mobile(KMM)およびCompose Multiplatformを使用したモバイルアプリケーションの開発
We are hiring!
【iOSエンジニア】モバイルアプリ開発G/東京
モバイルアプリ開発GについてKINTOテクノロジーズにおける、モバイルアプリ開発のスペシャリストが集まっているグループです。KINTOやmy routeなどのサービスを開発・運用しているグループと協調しながら品質の高いモバイルアプリを開発し、サービスの発展に貢献する事を目標としています。
【iOSエンジニア】モバイルアプリ開発G/大阪
モバイルアプリ開発GについてKINTOテクノロジーズにおける、モバイルアプリ開発のスペシャリストが集まっているグループです。KINTOやmy routeなどのサービスを開発・運用しているグループと協調しながら品質の高いモバイルアプリを開発し、サービスの発展に貢献する事を目標としています。