KMMBridgegithubPublish SPM to Another GitHub Repo

Publish SPM to Another GitHub Repo

You may want to publish your SPM builds to a separate repo. The two common use-cases for this are:

  • Your KMP code lives in a module inside the Android repo, and your Android repo uses git tags and releases for other reasons.
  • You want to publish an iOS Framework but keep your source code private.

SPM uses git repos as the basic unit of a dependency, and it uses git tags for versions. To publish to an external repo, we’ll need to push the generated Package.swift file to the external repo, push the XCFramework binary to a GitHub release, and apply the version tag to the repo.

We’ll modify the Quick Start guide template to demonstrate the changes necessary.

Prepare Your Repos

Create a repo for your KMP code using the Quick Start template. In our example we’ll call it owner/kmprepo. Clone it locally and open the project in your favorite IDE.

Create a new repo where you’ll publish your releases to. In our example we’ll call it owner/publishrepo.

Make sure you push at least one commit to this repo. If you’re creating it with GitHub’s web interface, you can click the option to add a README, which will create a single commit for you.

Configure GitHub Deploy Keys

You’ll need to give your KMP repo write access to your publishing repo. To do that, you’ll need to set up deploy keys.

Automatic Deploy Key Configuration

In order grant CI access to your repos you’ll need to add deploy keys. This can be done manually via the command line and GitHub, however for convenience we’ve added a gradle task called setupDeployKeys to help automate the process.

To use this gradle task you’ll have to install GitHub CLI and make sure you are authenticated with GitHub.

./gradlew setupDeployKeys --no-configuration-cache \
  -PgithubDeploySourceRepo=YOUR_ORG/YOUR_KMP_REPO \
  -PgithubDeployTargetRepo=YOUR_ORG/YOUR_PODSPEC_REPO

The task setupDeployKeys creates an ssh public/private key pair on your local machine. Then it adds the public key to your target repo’s deploy keys, and the private key to the source repos action secrets (named KMMBRIDGE_SSH_KEY). It takes in two parameters: githubDeploySourceRepo and githubDeployTargetRepo. These parameters point to your KMP source repo and your Podspec deployment repos, respectively.

If you want you can double-check that this task succeeded by checking your two repos:

  • In your KMP repo click on the “Settings” tab, then go to “Secrets and Variables” -> “Actions”. You should see KMMBRIDGE_SSH_KEY.
  • In your podspec repo click on the “Settings” tab, then go to “Deploy Keys”. You should see KMMBridge Key.

Manual Setup

See Deploy Key Manual Setup.

GitHub Actions Workflow Changes

Add ssh config

Open .github/workflows/KMMBridge-iOS-publish.yml.

Above the Build Main action, add the ssh-agent action.

      - name: Apply SSH Key
        uses: webfactory/ssh-agent@v0.5.4
        with:
          ssh-private-key: ${{ secrets.KMMBRIDGE_SSH_KEY }}

If you used a different name for your SSH key secret, replace KMMBRIDGE_SSH_KEY with whatever name you chose.

The Build Main action needs to be pointed at the publish repo. Change -PGITHUB_REPO=${{ github.repository }} to point to the publish repo -PGITHUB_REPO=owner/kmppublish.

      - name: Build Main
        run: ./gradlew kmmBridgePublish -PENABLE_PUBLISHING=true -PGITHUB_PUBLISH_TOKEN=${{ secrets.GITHUB_TOKEN }} -PGITHUB_REPO=owner/publishrepo --no-daemon --info --stacktrace
        env:
          GRADLE_OPTS: -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx3g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:MaxMetaspaceSize=512m"

Finally, replace the update-release-tag action with the following:

      - uses: touchlab/ga-push-remote-swift-package@v1
        id: push-remote-swift-package
        with:
          commitMessage: "KMP SPM package release for ${{ steps.versionPropertyValue.outputs.propVal }}"
          tagMessage: "KMP release version ${{ steps.versionPropertyValue.outputs.propVal }}"
          tagVersion: ${{ steps.versionPropertyValue.outputs.propVal }}
          remoteRepo: owner/publishrepo
          remoteBranch: main