Swift Packages and GitHub Actions
Recently I was working on a matching library. Once I wrote the library, I wanted to have a CI that would verify the code on every push and pull request. There are services like Bitrise that can do this, but as I host the sources on GitHub, I decided to try built-in GitHub Actions.
To be honest, at first, I was skeptical. But to my surprise, GitHub Actions are great for Swift Packages. They are powerful, fast, and free for public repositories.
Let's see how to use them.
Adding GitHub Action to the project
Adding action to the project is very simple. On the main page of your repository:
1. Click on the Actions tab,
2. Click on the set up a workflow yourself,
3. In the editor, set the name of your action, and remember to add the .yml
extension,
4. Write your action or copy & paste one of the actions below.
You can also use action suggested by GitHub. For Swift Packages, such action will build the package and run the tests.
Defining secret configuration values
Some actions might require configuration values. Some of those values might be secret, and we don't want to expose them in the action code. Fortunately, GitHub allows to easily define such secrets:
- Open repository settings,
- Select Secrets,
- Click on the New repository secret button,
- Provide the name and value.
That's it. Now, we can access the secret using the following syntax:
${{ secrets.SECRET_NAME }}
GitHub Actions helpful during Swift Packages development
Build package
This action builds a Swift Package:
name: Build Package
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: macos-11
steps:
- uses: actions/checkout@v2
- name: Build
run: swift build -v
Test package
This action builds a Swift Package and runs tests:
name: Test Package
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: macos-11
steps:
- uses: actions/checkout@v2
- name: Build Package
run: swift build -v
- name: Run tests
run: swift test -v
Test package, gather code coverage & upload report to codecov.io
This action builds a Swift Package and runs tests with code coverage enabled. Once tests are finished, the code coverage report is uploaded to codecov.io.
Token used by Codecov is defined as CODECOV_TOKEN
in the repository secrets.
Replace the {YOUR_PACKAGE_NAME}
with the name of your package. For example, if the name of the package is gacalc
, then replace the fragment {YOUR_PACKAGE_NAME}PackageTests
with GacalcPackageTests
.
Although the name of the package is all lowercased, the replaced name starts with uppercased first letter!
You can double check the name locally. Run theswift build
command in the Terminal. Then open the.build
folder:open .build
. Inside the.build/debug
folder you will find either{YOUR_PACKAGE_NAME}PackageTests.product
or{YOUR_PACKAGE_NAME}PackageTests.xctest
file.
name: Test Package
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: macos-11
steps:
- name: Get Sources
uses: actions/checkout@v2
- name: Build Package
run: swift build -v
- name: Run tests
run: swift test --enable-code-coverage -v
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1.4.0
with:
xcode-version: "13.1"
- name: Gather code coverage
run: xcrun llvm-cov export -format="lcov" .build/debug/{YOUR_PACKAGE_NAME}PackageTests.xctest/Contents/MacOS/{YOUR_PACKAGE_NAME}PackageTests -instr-profile .build/debug/codecov/default.profdata > coverage_report.lcov
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: fail
files: ./coverage_report.lcov
verbose: true
When this action is executed for a pull request, the Codecov bot will add a comment with a new code coverage statistics:
Test package, gather code coverage & upload report to Code Climate
This action builds a Swift Package and runs tests with code coverage enabled. Once tests are finished, the code coverage report is uploaded to Code Climate.
Token used by Code Climate is defined as CODE_CLIMATE_TOKEN
in the repository secrets.
name: Test Package
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: macos-11
steps:
- name: Get Sources
uses: actions/checkout@v2
- name: Build Package
run: swift build -v
- name: Test & publish code coverage to Code Climate
uses: paambaati/codeclimate-action@v3.0.0
env:
CC_TEST_REPORTER_ID: ${{ secrets.CODE_CLIMATE_TOKEN }}
with:
coverageCommand: swift test --enable-code-coverage
debug: true
coverageLocations: |
${{github.workspace}}/.build/debug/codecov/*.json:lcov-json
Lint code using SwiftLint
This action lints the code using SwiftLint. Code linting for Swift Package can be done on macOS or Ubuntu environments.
Lint code using macOS
as host machine:
name: Lint code
on:
pull_request:
paths:
- '.github/workflows/codelint.yml'
- '.swiftlint.yml'
- '**/*.swift'
jobs:
SwiftLint:
runs-on: macos-11
steps:
- uses: actions/checkout@v1
- name: Lint code using SwiftLint
run: swiftlint lint --reporter github-actions-logging
Lint code using ubuntu
as host machine:
name: Lint code
on:
pull_request:
paths:
- '.github/workflows/codelint.yml'
- '.swiftlint.yml'
- '**/*.swift'
jobs:
SwiftLint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Lint code using SwiftLint
uses: norio-nomura/action-swiftlint@3.2.1
If there are any warnings or errors they will be added, as comments, to the PR's code:
That's it. As you can see, using GitHub Actions as CI for Swift Packages is very easy. I hope those that provided code snippets will help you configure your own Continues Integration process. If you want to see them in action, check out this sample repository: