Multi-platform Swift Package releases with GitHub Actions

RevenueCat logo
Relax, you can roll back your mobile release

No one is immune from shipping critical bugs to production, but Runway helps you limit the amount of havoc that can cause.

I have recently been working on a new Swift Package library that supports iOS, macOS and Linux. As I wanted the development lifecycle to be fast and iterative, I decided to make the library’s release process as automated and as error-proof as possible.

I came up with a GitHub Actions workflow that runs every time a new tag is pushed to the repository and performs the following steps:

  • Build the library and run the test suite for all supported platforms.
  • Check all source files to prevent non-inclusive language from making it to the release cut.
  • If the two previous checks were successful, create a new GitHub release with auto-generated release notes.

The release workflow

The workflow I ended up with extends and modifies the CI workflow from Matt Massicotte’s Swift Package template repository, which I always use when starting a new project.

The template already has two steps to build and test the library on Apple platforms (iOS and macOS) and Linux.

I changed the on trigger to only be executed when a new tag matching the ‘..*’ pattern is pushed and then added a new job that checks for inclusive language using the woke GitHub action in the source files and creates a new GitHub release with auto-generated release notes if the two previous checks pass:

name: Release

      - "*.*.*"

  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
  cancel-in-progress: true

  DEVELOPER_DIR: /Applications/

    name: Test on iOS and macOS
    runs-on: macOS-13
          - "platform=macOS"
          - "platform=iOS Simulator,name=iPhone 12"

      - uses: actions/checkout@v4
      - name: Test platform ${{ matrix.destination }}
        run: set -o pipefail && xcodebuild -scheme XcodeCloudKit -destination "${{ matrix.destination }}" test | xcbeautify

    name: Test Linux
    runs-on: ubuntu-latest
      - name: Checkout
        uses: actions/checkout@v4
      - name: Install swiftly
        run: curl -L | bash -s -- -y
      - name: Install the latest Swift toolchain
        run: swiftly install latest
      - name: Test
        run: swift test

    needs: [test_apple_platforms, test_linux]
    name: Create a new GitHub release
    runs-on: ubuntu-latest
      - name: Checkout
        uses: actions/checkout@v4
      - name: woke
        uses: get-woke/woke-action@v0
          fail-on-error: true
      - name: Release
        uses: softprops/action-gh-release@v2
          generate_release_notes: true
          token: ${{ secrets.GITHUB_TOKEN }}

After pushing a new tag to the repository, the workflow runs all jobs and creates a new GitHub release: