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.target
platform
: Name of the platform to use inbriefcase
commands; if blank, thentarget
is used insteadoutput-format
: Name of the platform output format forbriefcase
commandsruns-on
: A valid GitHub runner image name forjobs.<job id>.runs-on
pre-command
: Arbitrary Bash commands to run before the Briefcase commandsbriefcase-args
: Briefcase arguments to use with allbriefcase
commandsbriefcase-build-prefix
: Bash commands to prefix to thebriefcase build
commandbriefcase-build-args
: Briefcase arguments to use with thebriefcase build
commandbriefcase-run-prefix
: Bash commands to prefix to thebriefcase run
commandbriefcase-run-args
: Briefcase arguments to use with thebriefcase run
commandbriefcase-package-prefix
: Bash commands to prefix to thebriefcase package
commandbriefcase-package-args
: Briefcase arguments to use with thebriefcase package
command
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/*