Building your App in CI with GitHub Actions¶
This GitHub Actions workflow provides the basic framework necessary to test, build, and package a Briefcase project in CI for Windows, Linux, macOS, iOS, and Android.
Target Platforms¶
The same set of steps are used for each platform via a matrix strategy. This will create a separate job for each target platform with specific configuration.
These platforms should be updated to match your targets. To remove a platform, delete the entry from strategy.matrix.target as well as the corresponding block of configuration under strategy.matrix.include.
To add a new targeted platform, add the name of the target to strategy.matrix.target. For instance, to target Linux Flatpak, add an entry to strategy.matrix.target named Flatpak and a configuration to build a Flatpak under strategy.matrix.include, for example:
strategy:
matrix:
target: [ "Windows", "macOS", "iOS", "Android", "Flatpak" ]
include:
- target: "Flatpak"
platform: "Linux"
output-format: "Flatpak"
runs-on: "ubuntu-latest"
pre-command: "sudo apt update && sudo apt -y install flatpak flatpak-builder"
briefcase-run-prefix: "xvfb-run"
Target Platform Configuration¶
These configuration properties can be used to alter behavior of the run for each targeted platform configured in the matrix.
target: Name of the target fromstrategy.matrix.targetplatform: Name of the platform to use inbriefcasecommands; if blank, thentargetis used insteadoutput-format: Name of the platform output format forbriefcasecommandsruns-on: A valid GitHub runner image name forjobs.<job id>.runs-onpre-command: Arbitrary Bash commands to run before the Briefcase commandsbriefcase-args: Briefcase arguments to use with allbriefcasecommandsbriefcase-build-prefix: Bash commands to prefix to thebriefcase buildcommandbriefcase-build-args: Briefcase arguments to use with thebriefcase buildcommandbriefcase-run-prefix: Bash commands to prefix to thebriefcase runcommandbriefcase-run-args: Briefcase arguments to use with thebriefcase runcommandbriefcase-package-prefix: Bash commands to prefix to thebriefcase packagecommandbriefcase-package-args: Briefcase arguments to use with thebriefcase packagecommand
Workflow File Location¶
This workflow should be saved in to a file at .github/workflows/ci.yml in your GitHub repository. Once it exists on your default branch on GitHub, a run will be triggered in the Actions tab.
Workflow Steps¶
- Check out the current GitHub repository
- This will be the version of your repository that triggered the CI run
- So, for a pull request (PR), this is the code being submitted in the PR
- After the PR is merged, this is the code in your default branch
- Install Python 3.12
- This version of Python should be updated to match the version of Python your app is targeting
- Install the latest version of Briefcase
- Build the test version of the app
- Run the app's test suite
- Package the release version of the app for the platform
- Upload the distributable artefact created for the platform
- See limitations below for these artefacts
- If an error occurs, the Briefcase log file is uploaded
Limitations of Uploaded Artefacts¶
The artefacts produced and uploaded by this workflow will not be signed; therefore, when the app is executed locally, some platforms may show a disconcerting warning about the security of the app or prevent the app from running altogether. See more information about code signing in the identity guides.
Workflow File Contents¶
name: CI
on:
pull_request:
push:
branches:
- main # update to match the default branch for your repo
# Cancel active CI runs for a PR before starting another run
concurrency:
group: ${{ github.workflow}}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
FORCE_COLOR: "1"
defaults:
run:
shell: bash
jobs:
ci:
name: Test and Package
runs-on: ${{ matrix.runs-on }}
strategy:
fail-fast: false
matrix:
target: [ "Windows", "macOS", "Ubuntu-24.04", "Fedora-40", "iOS", "Android"]
include:
- target: "Windows"
output-format: "app"
runs-on: "windows-latest"
- target: "macOS"
output-format: "app"
runs-on: "macos-latest"
- target: "Ubuntu-24.04"
platform: "Linux"
output-format: "system"
runs-on: "ubuntu-latest"
pre-command: "sudo apt -y install socat"
briefcase-run-prefix: "xvfb-run"
briefcase-args: "--target ubuntu:24.04"
- target: "Fedora-40"
platform: "Linux"
output-format: "system"
runs-on: "ubuntu-latest"
pre-command: "sudo apt -y install socat"
briefcase-run-prefix: "xvfb-run"
briefcase-args: "--target fedora:40"
- target: "iOS"
output-format: "Xcode"
runs-on: "macos-latest"
briefcase-run-args: "--device 'iPhone SE (3rd generation)'"
- target: "Android"
output-format: "Gradle"
runs-on: "ubuntu-latest"
pre-command: |
# Enable KVM permissions for the emulator
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
briefcase-run-args: >-
--device '{"avd":"beePhone"}'
--shutdown-on-exit
--Xemulator=-no-window
--Xemulator=-no-snapshot
--Xemulator=-no-audio
--Xemulator=-no-boot-anim
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.12" # update with your targeted Python version
- name: Install Briefcase
run: |
python -m pip install -U pip setuptools wheel
python -m pip install briefcase
- name: Setup Environment
run: |
# Use GitHub's preinstalled JDK 17 for Android builds
echo JAVA_HOME="${JAVA_HOME_17_X64:-$JAVA_HOME_17_arm64}" | tee -a ${GITHUB_ENV}
${{ matrix.pre-command }}
- name: Build App
run: |
${{ matrix.briefcase-build-prefix }} \
briefcase build \
${{ matrix.platform || matrix.target }} \
${{ matrix.output-format }} \
--test --no-input --log \
${{ matrix.briefcase-args }} \
${{ matrix.briefcase-build-args }}
- name: Test App
run: |
${{ matrix.briefcase-run-prefix }} \
briefcase run \
${{ matrix.platform || matrix.target }} \
${{ matrix.output-format }} \
--test --no-input --log \
${{ matrix.briefcase-args }} \
${{ matrix.briefcase-run-args }}
- name: Package App
run: |
${{ matrix.briefcase-package-prefix }} \
briefcase package \
${{ matrix.platform || matrix.target }} \
${{ matrix.output-format }} \
--update --adhoc-sign --no-input --log \
${{ matrix.briefcase-args }} \
${{ matrix.briefcase-package-args }}
- name: Upload App
# Briefcase cannot create iOS artefacts; instead, apps
# must be packaged and published for iOS through Xcode.
if: matrix.target != 'iOS'
uses: actions/upload-artifact@v4
with:
name: App-${{ matrix.target }}
path: dist
if-no-files-found: error
- name: Upload Log
if: failure()
uses: actions/upload-artifact@v4
with:
name: Log-Failure-${{ matrix.target }}
path: logs/*