From 41a5001db2ecec29a41d5178931393d22e5d2333 Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Fri, 30 Aug 2024 14:33:20 -0400 Subject: [PATCH 1/3] Add a basic how-to for building apps in GitHub CI --- changes/xxx.doc.rst | 1 + docs/how-to/ci.rst | 160 ++++++++++++++++++++++++++++++++++++++++++ docs/how-to/index.rst | 5 +- 3 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 changes/xxx.doc.rst create mode 100644 docs/how-to/ci.rst diff --git a/changes/xxx.doc.rst b/changes/xxx.doc.rst new file mode 100644 index 000000000..4102ef55a --- /dev/null +++ b/changes/xxx.doc.rst @@ -0,0 +1 @@ +A how-to guide for building apps in GitHub Actions CI was added. diff --git a/docs/how-to/ci.rst b/docs/how-to/ci.rst new file mode 100644 index 000000000..047df49c5 --- /dev/null +++ b/docs/how-to/ci.rst @@ -0,0 +1,160 @@ +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. + +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. + +The 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 it is the code in your default branch + +* Install Python 3.12 +* Install the latest version of Briefcase +* Build the test version of the app +* Run the test suite +* Package the release version of the app for the platform +* Upload the distributable artifact created for the platform +* If an error occurs, the Briefcase log file is uploaded + +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. + +.. code-block:: YAML + + 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" + briefcase-run-prefix: "sudo apt -y install socat && xvfb-run" + briefcase-args: "--target ubuntu:24.04" + + - target: "Fedora-40" + platform: "Linux" + output-format: "system" + runs-on: "ubuntu-latest" + briefcase-run-prefix: "sudo apt -y install socat && 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" + # Enable KVM permissions for the emulator and use GitHub's preinstalled JDK + briefcase-run-prefix: >- + 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 + && JAVA_HOME="${JAVA_HOME_17_X64}" + briefcase-run-args: >- + --device '{"avd":"beePhone"}' + --Xemulator=-no-window + --Xemulator=-no-snapshot + --Xemulator=-no-audio + --Xemulator=-no-boot-anim + --shutdown-on-exit + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + + - name: Install Briefcase + run: | + python -m pip install -U pip setuptools wheel + python -m pip install briefcase + + - name: Build App + run: | + briefcase build \ + ${{ matrix.platform || matrix.target }} \ + ${{ matrix.output-format }} \ + --test --no-input \ + ${{ matrix.briefcase-args }} + + - name: Test App + run: | + ${{ matrix.briefcase-run-prefix }} \ + briefcase run \ + ${{ matrix.platform || matrix.target }} \ + ${{ matrix.output-format }} \ + --test --no-input \ + ${{ matrix.briefcase-run-args }} \ + ${{ matrix.briefcase-args }} + + - name: Package App + run: | + briefcase package \ + ${{ matrix.platform || matrix.target }} \ + ${{ matrix.output-format }} \ + --update --adhoc-sign --no-input \ + ${{ matrix.briefcase-args }} + + - name: Upload App + 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-${{ matrix.target }} + path: logs/* diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst index a59af3298..fcd703754 100644 --- a/docs/how-to/index.rst +++ b/docs/how-to/index.rst @@ -14,9 +14,10 @@ stand alone. :glob: code-signing/index - upgrade-from-v0.2 access-packaging-metadata + ci + publishing/index + upgrade-from-v0.2 contribute-code contribute-docs internal/index - publishing/index From f974bfb60b4a1d8480744e3280aeb5c49d6a9e43 Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Fri, 30 Aug 2024 21:51:43 -0400 Subject: [PATCH 2/3] Bolster guide for running Briefcase in CI --- changes/{xxx.doc.rst => 400.doc.rst} | 0 docs/how-to/ci.rst | 132 ++++++++++++++++++++++----- 2 files changed, 110 insertions(+), 22 deletions(-) rename changes/{xxx.doc.rst => 400.doc.rst} (100%) diff --git a/changes/xxx.doc.rst b/changes/400.doc.rst similarity index 100% rename from changes/xxx.doc.rst rename to changes/400.doc.rst diff --git a/docs/how-to/ci.rst b/docs/how-to/ci.rst index 047df49c5..571629ca0 100644 --- a/docs/how-to/ci.rst +++ b/docs/how-to/ci.rst @@ -5,30 +5,105 @@ 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. -The workflow steps: +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: + +.. code-block:: YAML + + 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 from ``strategy.matrix.target`` +* ``platform``: Name of the platform to use in ``briefcase`` commands; if + blank, then ``target`` is used instead +* ``output-format``: Name of the platform output format for ``briefcase`` + commands +* ``runs-on``: A valid GitHub runner image name for ``jobs..runs-on`` +* ``pre-command``: Arbitrary Bash commands to run before the Briefcase commands +* ``briefcase-args``: Briefcase arguments to use with all ``briefcase`` commands +* ``briefcase-build-prefix``: Bash commands to prefix to the ``briefcase build`` + command +* ``briefcase-build-args``: Briefcase arguments to use with the ``briefcase + build`` command +* ``briefcase-run-prefix``: Bash commands to prefix to the ``briefcase run`` + command +* ``briefcase-run-args``: Briefcase arguments to use with the ``briefcase + run`` command +* ``briefcase-package-prefix``: Bash commands to prefix to the ``briefcase + package`` command +* ``briefcase-package-args``: Briefcase arguments to use with the ``briefcase + 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 it is the code in your default branch + * 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 test suite +* Run the app's test suite * Package the release version of the app for the platform -* Upload the distributable artifact created 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 -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. +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 <../how-to/code-signing/>`_. + +Workflow File Contents +---------------------- .. code-block:: YAML @@ -72,14 +147,16 @@ will be triggered in the Actions tab. platform: "Linux" output-format: "system" runs-on: "ubuntu-latest" - briefcase-run-prefix: "sudo apt -y install socat && xvfb-run" + 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" - briefcase-run-prefix: "sudo apt -y install socat && xvfb-run" + pre-command: "sudo apt -y install socat" + briefcase-run-prefix: "xvfb-run" briefcase-args: "--target fedora:40" - target: "iOS" @@ -91,40 +168,47 @@ will be triggered in the Actions tab. output-format: "Gradle" runs-on: "ubuntu-latest" # Enable KVM permissions for the emulator and use GitHub's preinstalled JDK - briefcase-run-prefix: >- - 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 - && JAVA_HOME="${JAVA_HOME_17_X64}" + pre-command: | + 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-prefix: "JAVA_HOME=${JAVA_HOME_17_X64}" briefcase-run-args: >- --device '{"avd":"beePhone"}' + --shutdown-on-exit --Xemulator=-no-window --Xemulator=-no-snapshot --Xemulator=-no-audio --Xemulator=-no-boot-anim - --shutdown-on-exit steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up Python + - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.12" + 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 + if: matrix.pre-command + run: ${{ matrix.pre-command }} + - name: Build App run: | + ${{ matrix.briefcase-build-prefix }} \ briefcase build \ ${{ matrix.platform || matrix.target }} \ ${{ matrix.output-format }} \ --test --no-input \ - ${{ matrix.briefcase-args }} + ${{ matrix.briefcase-args }} \ + ${{ matrix.briefcase-build-args }} - name: Test App run: | @@ -133,18 +217,22 @@ will be triggered in the Actions tab. ${{ matrix.platform || matrix.target }} \ ${{ matrix.output-format }} \ --test --no-input \ - ${{ matrix.briefcase-run-args }} \ - ${{ matrix.briefcase-args }} + ${{ 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 \ - ${{ matrix.briefcase-args }} + ${{ 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: @@ -156,5 +244,5 @@ will be triggered in the Actions tab. if: failure() uses: actions/upload-artifact@v4 with: - name: log-${{ matrix.target }} + name: Log-Failure-${{ matrix.target }} path: logs/* From 463743a5059101db862829e7a06e5d648b22e630 Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Sat, 31 Aug 2024 16:41:10 -0400 Subject: [PATCH 3/3] Sample CI always uses GH's JDK 17 and creates log files --- docs/how-to/ci.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/how-to/ci.rst b/docs/how-to/ci.rst index 571629ca0..51feeee78 100644 --- a/docs/how-to/ci.rst +++ b/docs/how-to/ci.rst @@ -167,13 +167,12 @@ Workflow File Contents - target: "Android" output-format: "Gradle" runs-on: "ubuntu-latest" - # Enable KVM permissions for the emulator and use GitHub's preinstalled JDK 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-prefix: "JAVA_HOME=${JAVA_HOME_17_X64}" briefcase-run-args: >- --device '{"avd":"beePhone"}' --shutdown-on-exit @@ -197,8 +196,10 @@ Workflow File Contents python -m pip install briefcase - name: Setup Environment - if: matrix.pre-command - run: ${{ matrix.pre-command }} + 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: | @@ -206,7 +207,7 @@ Workflow File Contents briefcase build \ ${{ matrix.platform || matrix.target }} \ ${{ matrix.output-format }} \ - --test --no-input \ + --test --no-input --log \ ${{ matrix.briefcase-args }} \ ${{ matrix.briefcase-build-args }} @@ -216,7 +217,7 @@ Workflow File Contents briefcase run \ ${{ matrix.platform || matrix.target }} \ ${{ matrix.output-format }} \ - --test --no-input \ + --test --no-input --log \ ${{ matrix.briefcase-args }} \ ${{ matrix.briefcase-run-args }} @@ -226,7 +227,7 @@ Workflow File Contents briefcase package \ ${{ matrix.platform || matrix.target }} \ ${{ matrix.output-format }} \ - --update --adhoc-sign --no-input \ + --update --adhoc-sign --no-input --log \ ${{ matrix.briefcase-args }} \ ${{ matrix.briefcase-package-args }}