Repository: AllYarnsAreBeautiful/ayab-desktop
Pull request #782: Remove caching from build
Author: login: jonathanperret
Created: 2025-04-12T21:30:15Z | Merged: 2025-04-13T17:35:02Z

## Problem

Fixes #774 .

## Proposed solution

This PR changes the build workflow to not use any caching. Instead the required file generation is done separately on each platform.

This has the side benefit of simplifying the build workflow. And the duration of the builds without caching is very similar to the current duration, 5-6 minutes.

Additionally, the trigger for running the build workflow was changed so that it runs on all code pushes (local branches and pull requests). This should reduce the need for manually triggering test releases. As an example, this PR itself triggers the build workflow on its branch. Note that signing and notarization are automatically disabled for builds done from PRs.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Automated deployment of documentation now publishes the latest reference guides.
  - Enhanced firmware release detection improves the accuracy and reliability of firmware downloads.
  - New output variables for firmware version and release detection added to the environment setup.

- **Chores**
  - Streamlined build processes for Windows, macOS, and Linux ensure more efficient release generation.
  - Simplified Python setup in testing workflows boosts consistency across releases.
  - New workflow for continuous deployment of documentation to GitHub Pages introduced.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #774: Disable caching in the CI for the release builds
Result from SignPath review, has to be fixed before being able to be accepted as an organization at SignPath:

Disable caching in the CI for the release builds.
It should be implemented as clearly as possible that no caching is happening in case of a release build.

Reason: avoid unreviewed code from other branches potentially polluting the build result.

Diff:
diff --git a/.github/actions/init-environment/action.yml b/.github/actions/init-environment/action.yml
index aa6038d2..45820e89 100644
--- a/.github/actions/init-environment/action.yml
+++ b/.github/actions/init-environment/action.yml
@@ -1,40 +1,66 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
 runs:
   using: "composite"
   steps:
-    - name: Set up Python ${{ matrix.python-version }}
+    - name: Set up Python ${{ env.PYTHON_VERSION }}
       id: py
       uses: actions/setup-python@v5
       with:
-        python-version: ${{ matrix.python-version }}
-        cache: "pip"
+        python-version: ${{ env.PYTHON_VERSION }}
+
     - name: Set variables
       id: vars
       shell: bash
       run: |
+        if [[ "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+-?[-a-zA-Z0-9]*$ ]]; then
+            echo "do-release=true" >> $GITHUB_OUTPUT
+        fi
         echo "sha-short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
         echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
-        echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT
-        echo "manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)" >> $GITHUB_OUTPUT
         echo "python-minor=$(echo '${{steps.py.outputs.python-version}}' | sed -e 's/\.[^.]*$//')" >> $GITHUB_OUTPUT
         echo "python-appimage=python${{steps.py.outputs.python-version}}-cp311-cp311-manylinux_2_28_x86_64.AppImage" >> $GITHUB_OUTPUT
+
+    - name: Get firmware version matching manifest
+      id: firmware
+      shell: bash
+      run: |
+        manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)
+        echo "manifest=$manifest"
+        available=$(curl -s https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases | grep -oE '/tag/[^\"]+' | sed -E 's/\/tag\///')
+        echo "available=$available"
+        match=$(for x in $available; do echo $x; done | grep "^${manifest}\$" | sort -r | head -1)
+        echo "match=$match"
+        if [[ $match ]]
+        then
+          cd src/main/resources/base/ayab/firmware/
+          url=https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases/download/$match/ayab_monolithic_uno.hex
+          echo "firmware-url=${url}" >> $GITHUB_OUTPUT
+        else
+          echo "Error: could not find firmware release matching manifest"
+          exit 1
+        fi
+
     - name: Set PACKAGE_VERSION
       shell: bash
       run: |
         echo ${{ steps.vars.outputs.tag }} > src/main/resources/base/ayab/package_version
         # remove suffix from semver tag, as fbs does not support them
         version_without_suffix=$(echo ${{ steps.vars.outputs.tag }} | sed -E 's/^v?([0-9]+\.[0-9]+\.[0-9]+).*$/\1/')
-        sed -i -e s/PACKAGE_VERSION/$version_without_suffix/ src/build/settings/base.json
+        sed -i.bak -e "s/PACKAGE_VERSION/$version_without_suffix/" src/build/settings/base.json
diff --git a/.github/workflows/build-multi-os.yml b/.github/workflows/build-multi-os.yml
index 77e7e3ae..9306c20c 100644
--- a/.github/workflows/build-multi-os.yml
+++ b/.github/workflows/build-multi-os.yml
@@ -13,244 +13,49 @@
 # @date   July 2020
 
 name: Build
-on:
-  push:
-    tags:
-      # Not a regex! See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
-      - 'v?[0-9]+.[0-9]+.[0-9]+'
-      - 'v?[0-9]+.[0-9]+.[0-9]+-[a-zA-Z0-9]+'
+on: [push, pull_request]
+
+env:
+  PYTHON_VERSION: 3.11.9
 
 jobs:
-  setup:
-    name: Create cache
-    runs-on: ubuntu-22.04
-    strategy:
-      matrix:
-        python-version: [3.11.9]
+  build-windows:
+    name: Create and upload Windows build
+    runs-on: windows-latest
     steps:
       - name: Checkout code
         uses: actions/checkout@v4
         with:
           submodules: recursive
+          fetch-depth: 0 # necessary for `git describe`
+
       - uses: ./.github/actions/init-environment
         id: vars
+
       - name: Get firmware version matching manifest
+        shell: bash
+        working-directory: src/main/resources/base/ayab/firmware/
         run: |
-          echo ${{ steps.vars.outputs.manifest }}
-          available=$(curl -s https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases | grep -oE '/tag/[^\"]+' | sed -E 's/\/tag\///')
-          echo $available
-          match=$(for x in $available; do echo $x; done | grep ^${{ steps.vars.outputs.manifest }} | sort -r | head -1)
-          echo $match
-          if [[ $match ]]
-          then
-            cd src/main/resources/base/ayab/firmware/
-            wget https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases/download/$match/ayab_monolithic_uno.hex
-          else
-            echo "Error: could not find firmware release matching manifest"
-            exit 1
-          fi
-      - name: Cache firmware
-        uses: actions/cache/save@v4
-        with:
-          path: src/main/resources/base/ayab/firmware/*.hex
-          key: firmware-${{ steps.vars.outputs.manifest }}
+          curl --fail -O '${{ steps.vars.outputs.firmware-url }}'
+
       - name: Install dependencies
+        shell: pwsh
         run: |
-          sudo apt update
-          sudo apt-get install -y avrdude libasound2-dev
-      - name: Install Python modules
-        run: |
+          choco install vcredist2010 # fixes dependency on msvcr100.dll
           python -m pip install --upgrade pip
           python -m pip install -r requirements.build.txt
-      - name: Use cached gui files (1)
-        id: gui1-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/*_gui.py
-          key: gui1-${{ hashFiles('src/main/python/main/ayab/*_gui.ui') }}
-      - name: Use cached gui files (2)
-        id: gui2-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_gui.py
-          key: gui2-${{ hashFiles('src/main/python/main/ayab/engine/*_gui.ui') }}
-      - name: Use cached logo
-        id: logo-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/ayab_logo_rc.py
-          key: logo-${{ hashFiles('src/main/python/main/ayab/ayab_logo_rc.qrc') }}
-      - name: Use cached graphics
-        id: e-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_rc.py
-          key: e-${{ hashFiles('src/main/python/main/ayab/engine/*_rc.qrc') }}
-      - name: Use cached translation files
-        id: qm-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/resources/base/ayab/translations/*.qm
-          key: qm-${{ hashFiles('src/main/resources/base/ayab/translations/ayab-translation-master.tsv') }}
-      - name: Use cached `base.json` file
-        id: base-cache
-        uses: actions/cache@v4
-        with:
-          path: src/build/settings/base.json
-          key: base-${{ steps.vars.outputs.tag }}
+          python -m pip install -r windows-build\windows_build_requirements.txt
+
       - name: Convert UI and translation files
-        if: ${{ (steps.gui1-cache.outputs.cache-hit != 'true') ||
-          (steps.gui2-cache.outputs.cache-hit != 'true') ||
-          (steps.logo-cache.outputs.cache-hit != 'true') ||
-          (steps.e-cache.outputs.cache-hit    != 'true') ||
-          (steps.qm-cache.outputs.cache-hit   != 'true') }}
         run: |
-          # Install qt6 packages to bring in system dependencies only
-          sudo apt install -y qt6-base-dev qt6-tools-dev-tools
           bash setup-environment.ps1
-      - name: Cache gui files (1)
-        if: ${{ (steps.gui1-cache.outputs.cache-hit != 'true') }}
-        uses: actions/cache/save@v4
-        with:
-          path: src/main/python/main/ayab/*_gui.py
-          key: gui1-${{ hashFiles('src/main/python/main/ayab/*_gui.ui') }}
-      - name: Cache gui files (2)
-        if: ${{ (steps.gui2-cache.outputs.cache-hit != 'true') }}
-        uses: actions/cache/save@v4
-        with:
-          path: src/main/python/main/ayab/*_gui.py
-          key: gui2-${{ hashFiles('src/main/python/main/ayab/engine/*_gui.ui') }}
-      - name: Cache logo
-        if: ${{ (steps.logo-cache.outputs.cache-hit != 'true') }}
-        uses: actions/cache/save@v4
-        with:
-          path: src/main/python/main/ayab/ayab_logo_rc.py
-          key: logo-${{ hashFiles('src/main/python/main/ayab/ayab_logo_rc.qrc') }}
-      - name: Cache graphics
-        if: ${{ (steps.e-cache.outputs.cache-hit != 'true') }}
-        uses: actions/cache/save@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_rc.py
-          key: e-${{ hashFiles('src/main/python/main/ayab/engine/*_rc.qrc') }}
-      - name: Cache translation files
-        if: ${{ (steps.qm-cache.outputs.cache-hit != 'true') }}
-        uses: actions/cache/save@v4
-        with:
-          path: src/main/resources/base/ayab/translations/*.qm
-          key: qm-${{ hashFiles('src/main/resources/base/ayab/translations/ayab-translation-master.tsv') }}
-      - name: Cache `base.json` file
-        if: ${{ (steps.base-cache.outputs.cache-hit != 'true') }}
-        uses: actions/cache/save@v4
-        with:
-          path: src/build/settings/base.json
-          key: base-${{ steps.vars.outputs.tag }}
 
-  deploy:
-    name: Create and deploy source code documentation
-    runs-on: ubuntu-22.04
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v4
-        with:
-          submodules: recursive
-      - name: Install dependencies for doxygen
-        run: |
-          sudo apt-get install doxygen graphviz -y
-      - name: Create .nojekyll so that filenames with underscores work on Github Pages
-        run: |
-          mkdir -p docs/html
-          touch docs/html/.nojekyll
-      - name: Deploy to pages
-        uses: DenverCoder1/doxygen-github-pages-action@v1.3.1
-        with:
-          github_token: ${{ secrets.GITHUB_TOKEN }}
-          branch: gh-pages
-          folder: docs/html
-          config_file: Doxyfile
-
-  build-windows:
-    name: Create and upload Windows release
-    needs: setup
-    runs-on: windows-latest
-    strategy:
-      matrix:
-        python-version: [3.11.9]
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v4
-        with:
-          submodules: recursive
-      - uses: ./.github/actions/init-environment
-        id: vars
-      - name: Install dependencies
-        shell: pwsh
-        run: |
-          choco install patch
-          choco install vcredist-all # fixes dependency on msvcr100.dll
-          python -m pip install --upgrade pip
-          python -m pip install -r requirements.build.txt
-          python -m pip install -r windows-build\windows_build_requirements.txt
-      - name: Restore cached firmware
-        id: firmware-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/resources/base/ayab/firmware/*.hex
-          key: firmware-${{ steps.vars.outputs.manifest }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
-      - name: Restore cached gui files (1)
-        id: gui1-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/*_gui.py
-          key: gui1-${{ hashFiles('src/main/python/main/ayab/*_gui.ui') }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
-      - name: Restore cached gui files (2)
-        id: gui2-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_gui.py
-          key: gui2-${{ hashFiles('src/main/python/main/ayab/engine/*_gui.ui') }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
-      - name: Restore cached logo
-        id: logo-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/ayab_logo_rc.py
-          key: logo-${{ hashFiles('src/main/python/main/ayab/ayab_logo_rc.qrc') }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
-      - name: Restore cached graphics
-        id: e-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_rc.py
-          key: e-${{ hashFiles('src/main/python/main/ayab/engine/*_rc.qrc') }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
-      - name: Restore cached translation files
-        id: qm-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/resources/base/ayab/translations/*.qm
-          key: qm-${{ hashFiles('src/main/resources/base/ayab/translations/ayab-translation-master.tsv') }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
-      - name: Restore cached `base.json` file
-        id: base-cache
-        uses: actions/cache@v4
-        with:
-          path: src/build/settings/base.json
-          key: base-${{ steps.vars.outputs.tag }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
       - name: Remove unneeded files
         shell: bash
         run: |
           rm src/main/python/main/ayab/*_gui.ui
           rm src/main/python/main/ayab/ayab_logo_rc.qrc
+
       - name: Change line endings to CRLF
         shell: bash
         run: |
@@ -262,12 +67,6 @@ jobs:
           do
             unix2dos $f
           done
-      - name: Check cached files
-        shell: bash
-        run: |
-          pwd
-          ls -l src/main/python/main/ayab/
-          ls -l src/main/resources/base/ayab/translations/
 
       # The OpenSSL-based backend for QtNetwork requires the OpenSSL dynamic
       # libraries but they are not packaged with Qt or PySide. Pyinstaller
@@ -287,13 +86,16 @@ jobs:
       - name: Build app
         shell: pwsh
         run: python -m fbs freeze
+
       - name: Create installer
         shell: pwsh
         run: |
           python -m fbs installer
           Move-Item -Path target\AYABSetup.exe -Destination target\AYAB-${{ steps.vars.outputs.tag }}.exe
-      - name: Upload asset
+
+      - name: Attach installer to release
         uses: ncipollo/release-action@v1
+        if: steps.vars.outputs.do-release == 'true'
         with:
           token: ${{ secrets.GITHUB_TOKEN }}
           tag: ${{ steps.vars.outputs.tag }}
@@ -310,22 +112,15 @@ jobs:
           omitBodyDuringUpdate: true
           omitDraftDuringUpdate: true
           omitPrereleaseDuringUpdate: true
+
       - uses: actions/upload-artifact@v4
         with:
           name: AYAB-${{ steps.vars.outputs.tag }}.exe
           path: target/AYAB-${{ steps.vars.outputs.tag }}.exe
 
   build-macos:
-    name: Create and upload Mac OSX release
-    needs: setup
+    name: Create and upload Mac OSX build
     runs-on: macos-14
-    outputs:
-      tag: ${{ steps.vars.outputs.tag }}
-      submission_id: ${{ steps.notarize.outputs.submission_id }}
-      image_name: ${{ steps.diskimage.outputs.name }}
-    strategy:
-      matrix:
-        python-version: [3.11.9]
     env:
       APPLE_CERTIFICATE_NAME: ${{ secrets.APPLE_CERTIFICATE_NAME }}
       APPLE_STORE_CONNECT_KEY_ID: ${{ secrets.APPLE_STORE_CONNECT_KEY_ID }}
@@ -334,8 +129,17 @@ jobs:
         uses: actions/checkout@v4
         with:
           submodules: recursive
+          fetch-depth: 0 # necessary for `git describe`
+
       - uses: ./.github/actions/init-environment
         id: vars
+
+      - name: Get firmware version matching manifest
+        shell: bash
+        working-directory: src/main/resources/base/ayab/firmware/
+        run: |
+          curl --fail -O '${{ steps.vars.outputs.firmware-url }}'
+
       - name: Install dependencies
         run: |
           mkdir tmp-wheel/
@@ -360,65 +164,15 @@ jobs:
           python -m pip install tmp-wheel/*.whl bitarray*.whl
 
           python -m pip install --no-binary charset_normalizer -r requirements.build.txt
-      - name: Restore cached firmware
-        id: firmware-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/resources/base/ayab/firmware/*.hex
-          key: firmware-${{ steps.vars.outputs.manifest }}
-          fail-on-cache-miss: true
-      - name: Restore cached gui files (1)
-        id: gui1-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/*_gui.py
-          key: gui1-${{ hashFiles('src/main/python/main/ayab/*_gui.ui') }}
-          fail-on-cache-miss: true
-      - name: Restore cached gui files (2)
-        id: gui2-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_gui.py
-          key: gui2-${{ hashFiles('src/main/python/main/ayab/engine/*_gui.ui') }}
-          fail-on-cache-miss: true
-      - name: Restore cached logo
-        id: logo-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/ayab_logo_rc.py
-          key: logo-${{ hashFiles('src/main/python/main/ayab/ayab_logo_rc.qrc') }}
-          fail-on-cache-miss: true
-      - name: Restore cached graphics
-        id: e-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_rc.py
-          key: e-${{ hashFiles('src/main/python/main/ayab/engine/*_rc.qrc') }}
-          fail-on-cache-miss: true
-      - name: Restore cached translation files
-        id: qm-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/resources/base/ayab/translations/*.qm
-          key: qm-${{ hashFiles('src/main/resources/base/ayab/translations/ayab-translation-master.tsv') }}
-          fail-on-cache-miss: true
-      - name: Restore cached `base.json` file
-        id: base-cache
-        uses: actions/cache@v4
-        with:
-          path: src/build/settings/base.json
-          key: base-${{ steps.vars.outputs.tag }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
+
+      - name: Convert UI and translation files
+        run: |
+          bash setup-environment.ps1
+
       - name: Remove unneeded files
         run: |
           rm src/main/python/main/ayab/*_gui.ui
           rm src/main/python/main/ayab/ayab_logo_rc.qrc
-      - name: Check cached files
-        run: |
-          pwd
-          ls -l src/main/python/main/ayab/
-          ls -l src/main/resources/base/ayab/translations/
 
       - name: Import Apple developer certificate
         if: env.APPLE_CERTIFICATE_NAME
@@ -432,12 +186,18 @@ jobs:
           python -m fbs freeze
 
       - name: Sign app
-        if: env.APPLE_CERTIFICATE_NAME
+        shell: bash
         run: |
-          # Sign the avrdude binary explicitly since `--deep` misses it because it is not
-          # in a directory meant to contain executables.
-          codesign -s "$APPLE_CERTIFICATE_NAME" --force --all-architectures \
-            --timestamp --deep --options=runtime \
+          # - If an actual certificate is not available, we default the identity to "-" to enable
+          #   ad-hoc signing, and disable the hardened runtime.
+          # - We sign the `avrdude_mac` binary explicitly since `--deep` misses it because it
+          #   is not in a directory meant to contain executables.
+          codesign_identity=${APPLE_CERTIFICATE_NAME:-"-"}
+          if [[ -n "$APPLE_CERTIFICATE_NAME" ]]; then
+            codesign_options="--options=runtime"
+          fi
+          codesign -s "$codesign_identity" $codesign_options \
+            --force --all-architectures --timestamp --deep \
             ./target/AYAB-mac.app/Contents/Resources/ayab/firmware/avrdude_mac \
             ./target/AYAB-mac.app
 
@@ -450,102 +210,43 @@ jobs:
           echo 'path=target/AYAB-${{ steps.vars.outputs.tag }}.dmg' >> "$GITHUB_OUTPUT"
 
       - name: Sign disk image
-        if: env.APPLE_CERTIFICATE_NAME
+        if: steps.vars.outputs.do-release == 'true' && env.APPLE_CERTIFICATE_NAME
         run: |
           codesign -s "$APPLE_CERTIFICATE_NAME" --force --all-architectures --timestamp \
             '${{ steps.diskimage.outputs.path }}'
 
-      - name: Upload signed disk image as artifact
-        uses: actions/upload-artifact@v4
-        with:
-          name: AYAB-signed-dmg
-          path: ${{ steps.diskimage.outputs.path }}
-
-      - name: Attach disk image (before notarization) to release
-        uses: ncipollo/release-action@v1
-        with:
-          tag: ${{ steps.vars.outputs.tag }}
-          # Default to draft and prerelease to let a human check the release before it goes live
-          draft: true
-          prerelease: false
-          allowUpdates: true
-          artifacts: ${{ steps.diskimage.outputs.path }}
-          artifactContentType: application/dmg
-          replacesArtifacts: true
-          # Avoid overwriting a release that may have been manually edited
-          omitNameDuringUpdate: true
-          omitBodyDuringUpdate: true
-          omitDraftDuringUpdate: true
-          omitPrereleaseDuringUpdate: true
-
       - name: Submit disk image for notarization
-        if: env.APPLE_STORE_CONNECT_KEY_ID
-        id: notarize
+        if: steps.vars.outputs.do-release == 'true' && env.APPLE_STORE_CONNECT_KEY_ID
         env:
           APPLE_STORE_CONNECT_ISSUER: ${{ secrets.APPLE_STORE_CONNECT_ISSUER }}
           APPLE_STORE_CONNECT_KEY_BASE64: ${{ secrets.APPLE_STORE_CONNECT_KEY_BASE64 }}
         run: |
           printenv APPLE_STORE_CONNECT_KEY_BASE64 | base64 --decode > apple-store-connect.key
 
-          # Submit the disk image for notarization
-          SUBMISSION_ID=$(xcrun notarytool submit '${{ steps.diskimage.outputs.path }}' \
-            -k apple-store-connect.key -d "$APPLE_STORE_CONNECT_KEY_ID" -i "$APPLE_STORE_CONNECT_ISSUER" |
-            tee /dev/stderr |
-            awk '/id:/ {print $2; exit}')
-
-          echo "submission_id=$SUBMISSION_ID" >> "$GITHUB_OUTPUT"
-
-  staple-macos:
-    name: Wait for notarization to complete and staple ticket to disk image
-    needs: build-macos
-    runs-on: macos-14
-    env:
-      APPLE_STORE_CONNECT_KEY_ID: ${{ secrets.APPLE_STORE_CONNECT_KEY_ID }}
-    steps:
-      - name: Download disk image artifact
-        uses: actions/download-artifact@v4
-        if: env.APPLE_STORE_CONNECT_KEY_ID
-        with:
-          # Will download to a file named ${{ needs.build-macos.outputs.image_name }}
-          name: AYAB-signed-dmg
-
-      - name: Wait for notarization and staple ticket to disk image
-        id: staple
-        if: env.APPLE_STORE_CONNECT_KEY_ID
-        env:
-          APPLE_STORE_CONNECT_ISSUER: ${{ secrets.APPLE_STORE_CONNECT_ISSUER }}
-          APPLE_STORE_CONNECT_KEY_BASE64: ${{ secrets.APPLE_STORE_CONNECT_KEY_BASE64 }}
-        run: |
-          printenv APPLE_STORE_CONNECT_KEY_BASE64 | base64 --decode > apple-store-connect.key
-
-          # Wait for the notarization to complete
-          xcrun notarytool wait '${{ needs.build-macos.outputs.submission_id }}' \
-            -k apple-store-connect.key -d "$APPLE_STORE_CONNECT_KEY_ID" -i "$APPLE_STORE_CONNECT_ISSUER"
-
-          # Print the notarization log for debugging purposes
-          xcrun notarytool log '${{ needs.build-macos.outputs.submission_id }}' \
-            -k apple-store-connect.key -d "$APPLE_STORE_CONNECT_KEY_ID" -i "$APPLE_STORE_CONNECT_ISSUER"
+          # Submit the disk image for notarization and wait
+          xcrun notarytool submit '${{ steps.diskimage.outputs.path }}' \
+            -k apple-store-connect.key -d "$APPLE_STORE_CONNECT_KEY_ID" -i "$APPLE_STORE_CONNECT_ISSUER" \
+            --wait
 
           # Staple the notarization ticket to the disk image
-          xcrun stapler staple -v '${{ needs.build-macos.outputs.image_name }}'
+          xcrun stapler staple -v '${{ steps.diskimage.outputs.path }}'
 
-      - name: Upload stapled disk image as artifact
+      - name: Upload disk image as artifact
         uses: actions/upload-artifact@v4
-        if: env.APPLE_STORE_CONNECT_KEY_ID
         with:
-          name: ${{ needs.build-macos.outputs.image_name }}
-          path: ${{ needs.build-macos.outputs.image_name }}
+          name: ${{ steps.diskimage.outputs.name }}
+          path: ${{ steps.diskimage.outputs.path }}
 
-      - name: Attach disk image (after notarization) to release
-        if: env.APPLE_STORE_CONNECT_KEY_ID
+      - name: Attach disk image to release
         uses: ncipollo/release-action@v1
+        if: steps.vars.outputs.do-release == 'true'
         with:
-          tag: ${{ needs.build-macos.outputs.tag }}
+          tag: ${{ steps.vars.outputs.tag }}
           # Default to draft and prerelease to let a human check the release before it goes live
           draft: true
           prerelease: false
           allowUpdates: true
-          artifacts: ${{ needs.build-macos.outputs.image_name }}
+          artifacts: ${{ steps.diskimage.outputs.path }}
           artifactContentType: application/dmg
           replacesArtifacts: true
           # Avoid overwriting a release that may have been manually edited
@@ -554,38 +255,58 @@ jobs:
           omitDraftDuringUpdate: true
           omitPrereleaseDuringUpdate: true
 
-
   # see https://github.com/AppImage/AppImageKit/wiki/Bundling-Python-apps
   build-appimage:
     name: Create and upload Linux AppImage release
-    needs: setup
     runs-on: ubuntu-22.04
-    strategy:
-      matrix:
-        # Using Python 3.11.11 specifically for Linux builds due to python-appimage availability
-        python-version: [3.11.11]
+    env:
+      # Using a specific Python version for Linux builds due to python-appimage availability
+      PYTHON_VERSION: 3.11.12
     steps:
       - name: Checkout repo into AppDir
         uses: actions/checkout@v4
         with:
           submodules: recursive
-          fetch-depth: 0
+          fetch-depth: 0 # necessary for `git describe`
+
       - uses: ./.github/actions/init-environment
         id: vars
+
+      - name: Get firmware version matching manifest
+        shell: bash
+        working-directory: src/main/resources/base/ayab/firmware/
+        run: |
+          curl --fail -O '${{ steps.vars.outputs.firmware-url }}'
+
+      - name: Install Python modules
+        run: |
+          sudo apt-get install -y avrdude libasound2-dev
+          python -m pip install --upgrade pip
+          python -m pip install --upgrade setuptools
+          python -m pip install -r requirements.build.txt
+
+      - name: Convert UI and translation files
+        run: |
+          bash setup-environment.ps1
+
       - name: Relocate
         run: |
           mkdir git
           shopt -s extglob dotglob
           cp -r !(git) git
           shopt -u dotglob
+
       - name: Download AppImage of Python designed for manylinux
         run: wget -c https://github.com/niess/python-appimage/releases/download/python${{steps.vars.outputs.python-minor}}/${{steps.vars.outputs.python-appimage}}
+
       - name: Extract the AppImage
         run: |
           chmod +x ${{steps.vars.outputs.python-appimage}}
           ./${{steps.vars.outputs.python-appimage}} --appimage-extract
+
       - name: Move repo
         run: mv git/* squashfs-root
+
       - name: Install dependencies
         run: |
           cd squashfs-root
@@ -594,86 +315,25 @@ jobs:
           # hack to fix setup.py script with faulty include
           ./AppRun -m pip install --global-option=build_ext --global-option="-I$(pwd)/opt/${{steps.vars.outputs.python-minor}}/include/${{steps.vars.outputs.python-minor}}" simpleaudio
           ./AppRun -m pip install -r requirements.build.txt
+
       - name: Add AppDir subdirectories to PATH
         run: |
           echo "usr/bin" >> $GITHUB_PATH
           echo "opt/${{steps.vars.outputs.python-minor}}/bin" >> $GITHUB_PATH
-      - name: Restore cached firmware
-        id: firmware-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/resources/base/ayab/firmware/*.hex
-          key: firmware-${{ steps.vars.outputs.manifest }}
-          fail-on-cache-miss: true
-      - name: Restore cached gui files (1)
-        id: gui1-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/*_gui.py
-          key: gui1-${{ hashFiles('src/main/python/main/ayab/*_gui.ui') }}
-          fail-on-cache-miss: true
-      - name: Restore cached gui files (2)
-        id: gui2-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_gui.py
-          key: gui2-${{ hashFiles('src/main/python/main/ayab/engine/*_gui.ui') }}
-          fail-on-cache-miss: true
-      - name: Restore cached logo
-        id: logo-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/ayab_logo_rc.py
-          key: logo-${{ hashFiles('src/main/python/main/ayab/ayab_logo_rc.qrc') }}
-          fail-on-cache-miss: true
-      - name: Restore cached graphics
-        id: e-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/python/main/ayab/engine/*_rc.py
-          key: e-${{ hashFiles('src/main/python/main/ayab/engine/*_rc.qrc') }}
-          fail-on-cache-miss: true
-      - name: Restore cached translation files
-        id: qm-cache
-        uses: actions/cache@v4
-        with:
-          path: src/main/resources/base/ayab/translations/*.qm
-          key: qm-${{ hashFiles('src/main/resources/base/ayab/translations/ayab-translation-master.tsv') }}
-          fail-on-cache-miss: true
-      - name: Restore cached `base.json` file
-        id: base-cache
-        uses: actions/cache@v4
-        with:
-          path: src/build/settings/base.json
-          key: base-${{ steps.vars.outputs.tag }}
-          enableCrossOsArchive: true
-          fail-on-cache-miss: true
-      - name: Move cached files
-        run: |
-          mv src/main/resources/base/ayab/firmware/*.hex squashfs-root/src/main/resources/base/ayab/firmware/
-          mv src/main/python/main/ayab/*_gui.py squashfs-root/src/main/python/main/ayab/
-          mv src/main/python/main/ayab/engine/*_gui.py squashfs-root/src/main/python/main/ayab/engine/
-          mv src/main/python/main/ayab/ayab_logo_rc.py squashfs-root/src/main/python/main/ayab/
-          mv src/main/python/main/ayab/engine/lowercase_e_rc.py squashfs-root/src/main/python/main/ayab/engine
-          mv src/main/python/main/ayab/engine/lowercase_e_reversed_rc.py squashfs-root/src/main/python/main/ayab/engine
-          mv src/main/resources/base/ayab/translations/*.qm squashfs-root/src/main/resources/base/ayab/translations/
-          mv src/build/settings/base.json squashfs-root/src/build/settings/base.json
+
       - name: Remove unneeded files
         run: |
           rm squashfs-root/src/main/python/main/ayab/*_gui.ui
           rm squashfs-root/src/main/python/main/ayab/ayab_logo_rc.qrc
           rm squashfs-root/src/main/python/main/ayab/engine/lowercase_e_rc.qrc
           rm squashfs-root/src/main/python/main/ayab/engine/lowercase_e_reversed_rc.qrc
-      - name: Check cached files
-        run: |
-          pwd
-          ls -l squashfs-root/src/main/python/main/ayab/
-          ls -l squashfs-root/src/main/resources/base/ayab/translations/
+
       - name: Replace AppRun
         run: |
           cd squashfs-root
           rm AppRun
           cp linux-build/appimage/AppRun .
+
       - name: Add icon
         run: |
           cd squashfs-root
@@ -682,6 +342,7 @@ jobs:
           cp linux-build/appimage/ayab.png ayab.png
           mkdir -p usr/share/icons/hicolor/128x128/apps/
           cp ayab.png usr/share/icons/hicolor/128x128/apps/
+
       - name: Create desktop file
         run: |
           cd squashfs-root
@@ -690,12 +351,14 @@ jobs:
           rm -f usr/share/applications/*.desktop
           cp linux-build/appimage/com.ayab_knitting.ayab.desktop com.ayab_knitting.ayab.desktop
           cp com.ayab_knitting.ayab.desktop usr/share/applications/com.ayab_knitting.ayab.desktop
+
       - name: Add metadata
         run: |
           cd squashfs-root
           mkdir -p usr/share/metainfo/
           rm -f usr/share/metainfo/*.appdata.xml
           cp linux-build/appimage/ayab.appdata.xml usr/share/metainfo/
+
       - name: Convert to AppImage
         run: |
           wget -c https://github.com/$(wget -q https://github.com/probonopd/go-appimage/releases/expanded_assets/continuous -O - | grep appimagetool-.*-x86_64.AppImage | head -n 1 | cut -d '"' -f 2)
@@ -705,8 +368,10 @@ jobs:
           VERSION=${{steps.vars.outputs.tag}} ./appimagetool-*-x86_64.AppImage squashfs-root/
           sudo apt remove appstream
           mv ayab-${{ steps.vars.outputs.tag }}-x86_64.AppImage AYAB-${{ steps.vars.outputs.tag }}-x86_64.AppImage
-      - name: Upload asset
+
+      - name: Attach AppImage to release
         uses: ncipollo/release-action@v1
+        if: steps.vars.outputs.do-release == 'true'
         with:
           token: ${{ secrets.GITHUB_TOKEN }}
           tag: ${{ steps.vars.outputs.tag }}
@@ -723,6 +388,7 @@ jobs:
           omitBodyDuringUpdate: true
           omitDraftDuringUpdate: true
           omitPrereleaseDuringUpdate: true
+
       - uses: actions/upload-artifact@v4
         with:
           name: AYAB-${{ steps.vars.outputs.tag }}-x86_64.AppImage
diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml
new file mode 100644
index 00000000..fb47d8f6
--- /dev/null
+++ b/.github/workflows/deploy-pages.yml
@@ -0,0 +1,28 @@
+name: Deploy pages
+on:
+  push:
+    branches:
+      - main
+
+jobs:
+  deploy:
+    runs-on: ubuntu-22.04
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v4
+        with:
+          submodules: recursive
+      - name: Install dependencies for doxygen
+        run: |
+          sudo apt-get install doxygen graphviz -y
+      - name: Create .nojekyll so that filenames with underscores work on Github Pages
+        run: |
+          mkdir -p docs/html
+          touch docs/html/.nojekyll
+      - name: Deploy to pages
+        uses: DenverCoder1/doxygen-github-pages-action@v1.3.1
+        with:
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          branch: gh-pages
+          folder: docs/html
+          config_file: Doxyfile
diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml
index 1b24b723..f1f06afd 100644
--- a/.github/workflows/python_tests.yml
+++ b/.github/workflows/python_tests.yml
@@ -5,18 +5,18 @@ name: Python Tests
 
 on: [push, pull_request]
 
+env:
+  PYTHON_VERSION: 3.11.9
+
 jobs:
   run-pytest:
     runs-on: ubuntu-22.04
-    strategy:
-      matrix:
-        python-version: [3.11]
     steps:
       - uses: actions/checkout@v4
-      - name: Set up Python ${{ matrix.python-version }}
+      - name: Set up Python ${{ env.PYTHON_VERSION }}
         uses: actions/setup-python@v5
         with:
-          python-version: ${{ matrix.python-version }}
+          python-version: ${{ env.PYTHON_VERSION }}
           cache: "pip"
       - name: Install dependencies
         run: |


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>.github/workflows/deploy-pages.yml (1)</summary><blockquote>

`1-28`: **New Documentation Deployment Workflow Added**  
This new workflow automates the deployment of documentation to GitHub Pages when pushing to the `main` branch. The steps—from checking out the code (with submodules) to installing doxygen/graphviz, creating a `.nojekyll` file, and deploying using the specified action—are clear and well structured.  


**YAML Format Nudge**  
A newline at the end of the file is missing (line 28). Please add one to satisfy YAML linting requirements.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 28-28: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>.github/actions/init-environment/action.yml (3)</summary><blockquote>

`31-33`: **Improve Regex for Tag Matching**  
The conditional checking for a version tag uses a regex with unescaped dot characters. To strictly match semantic versioning (for example, to match literal dots), consider escaping the dots (e.g., use `\.`).

---

`63-64`: **Robustness in Sed Substitution**  
The `sed` command on line 64 would be more robust if the substitution parameters were quoted. This can help avoid issues with word splitting or unexpected characters in the version string.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 64-64: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

---

`64-64`: **Newline at EOF Needed**  
Static analysis indicates that there is no new line character at the end of the file. Please add a newline to comply with YAML lint requirements.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 64-64: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>.github/workflows/build-multi-os.yml (1)</summary><blockquote>

`64-70`: **Evaluate the 'Check Cached Files' Step**  
Although caching has been removed from the build process per the PR objectives, the 'Check cached files' step remains in the Windows (and similarly in macOS) job. Consider removing or repurposing this step if it’s no longer required.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 628dc3ca33b0b40ff35480dba4959c5021d2e73f and a6715641c06c14676f6f592e7c85d76ab807f582.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `.github/actions/init-environment/action.yml` (2 hunks)
* `.github/workflows/build-multi-os.yml` (7 hunks)
* `.github/workflows/deploy-pages.yml` (1 hunks)
* `.github/workflows/python_tests.yml` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/actions/init-environment/action.yml</summary>

[error] 64-64: no new line character at the end of file

(new-line-at-end-of-file)

</details>
<details>
<summary>.github/workflows/deploy-pages.yml</summary>

[error] 28-28: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>
<details>
<summary>🪛 actionlint (1.7.4)</summary>

<details>
<summary>.github/workflows/build-multi-os.yml</summary>

31-31: description is required in metadata of "Init Environment" action at "/home/jailuser/git/.github/actions/init-environment/action.yml"

(action)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Create and upload Windows release
* GitHub Check: Create and upload Mac OSX release

</details>

<details>
<summary>🔇 Additional comments (10)</summary><blockquote>

<details>
<summary>.github/workflows/python_tests.yml (2)</summary>

`8-10`: **Global Environment Variable Introduced**  
The addition of the `env` block with `PYTHON_VERSION: 3.11.9` replaces the matrix strategy for Python versions. This simplifies the configuration and ensures consistency across workflows.

---

`16-19`: **Consistent Python Setup Update**  
The Python setup step now uses `${{ env.PYTHON_VERSION }}` instead of a matrix variable. This update streamlines the configuration and boosts maintainability.

</details>
<details>
<summary>.github/actions/init-environment/action.yml (2)</summary>

`17-18`: **New 'firmware-url' Output Added**  
A new output variable `firmware-url` has been introduced to capture the firmware download URL from the subsequent matching step. This will help downstream jobs retrieve the correct firmware file.

---

`22-26`: **Python Setup Leverages Global Variable**  
Updating the Python setup to use `${{ env.PYTHON_VERSION }}` keeps this action consistent with the other workflows. This makes version management simpler across jobs.

</details>
<details>
<summary>.github/workflows/build-multi-os.yml (6)</summary>

`16-20`: **Updated Workflow Trigger and Global Python Version**  
Changing the trigger to run on both `push` and `pull_request` events—and setting a global `PYTHON_VERSION: 3.11.9`—simplifies the workflow and ensures consistency with other CI jobs.

---

`28-30`: **Full Git History for Accurate Tag Retrieval**  
Adding `fetch-depth: 0` in the checkout step ensures that `git describe` works correctly by accessing the full commit history. This is essential for generating accurate version tags.

---

`33-37`: **Consistent Firmware Version Fetch**  
The "Get firmware version matching manifest" step now uses `curl -O ${{ steps.vars.outputs.firmware-url }}` to download the firmware. This change aligns with the updates made in the init-environment action.

---

`129-136`: **Streamlined macOS Steps**  
For the macOS job, the addition of `fetch-depth: 0` and the consistent use of the firmware version fetch step reflects the same improvements seen in the Windows job. This consistency is beneficial for cross-platform builds.

---

`250-252`: **Distinct Python Version for AppImage Build**  
The Linux AppImage job sets `PYTHON_VERSION: 3.11.11` (instead of the global 3.11.9) with a clear comment explaining the reason. This divergence is acceptable provided that the specific version is supported for creating the AppImage.

---

`247-370`: **Overall Build Workflow Simplification**  
The removal of caching and setup steps across the build jobs has streamlined the overall CI process, simplifying dependency management and reducing complexity. The adjustments to artifact creation, signing, and release actions remain coherent and well integrated.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

353-353: property "sha" is not defined in object type {do-release: string; draft: string; firmware-url: string; manifest: string; python-appimage: string; python-minor: string; sha-short: string; tag: string}

(expression)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T21:33:18Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (10)</summary><blockquote>

<details>
<summary>.github/workflows/build-multi-os.yml (10)</summary><blockquote>

`33-37`: **Direct Firmware Retrieval**  
The “Get firmware version matching manifest” step now uses a curl command to download the firmware file from the URL provided by the init-environment action. Consider adding error handling (e.g. verifying the file was successfully downloaded) to make the workflow more resilient.

---

`31-32`: **Action Metadata Warning (Init Environment)**  
Static analysis indicates that the metadata for the `init-environment` action (referenced at several points in this workflow) is missing a description. Please update the `.github/actions/init-environment/action.yml` file to include a concise description to satisfy actionlint requirements.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

31-31: description is required in metadata of "Init Environment" action at "/home/jailuser/git/.github/actions/init-environment/action.yml"

(action)

</details>

</details>

---

`45-47`: **Review of UI File Conversion Step**  
The “Convert UI and translation files” step runs `bash setup-environment.ps1`. Although this may be intentional for cross-platform compatibility, it’s unusual to invoke a `.ps1` (PowerShell) script with Bash. Please double-check that this works as expected on the target runners and add documentation or adjust the shell if needed.

---

`126-130`: **Firmware Retrieval on macOS**  
Similar to the Windows job, the macOS “Get firmware version matching manifest” step fetches the firmware with curl. As before, consider incorporating error handling to catch download failures.

---

`151-153`: **UI Conversion on macOS**  
The macOS job also invokes `bash setup-environment.ps1` for converting UI and translation files. Verify that this command runs correctly on macOS and consider clarifying the choice of shell versus file extension if needed.

---

`195-205`: **Streamlined Notarization Process**  
The disk image notarization step efficiently submits the image and waits for the result. Consider adding logging or error checks to handle cases where notarization might fail, to improve debugging in CI.

---

`238-240`: **Linux Build Environment Variable**  
In the build-appimage job, the environment is set to use `PYTHON_VERSION: 3.11.11` specifically for Linux builds. This intentional version difference (from the global 3.11.9) should be documented to avoid confusion.

---

`249-253`: **Firmware Retrieval on Linux**  
The Linux job mirrors the other platforms by using curl to fetch the firmware. As suggested in other jobs, consider robust error handling to catch unsuccessful downloads.

---

`260-262`: **UI Conversion Consistency on Linux**  
Again, the “Convert UI and translation files” step is calling `bash setup-environment.ps1` in the Linux job. Confirm that this approach works in a Linux environment or consider renaming/rewriting the script for clarity.

---

`295-299`: **Removal of Cached Files Check**  
The “Check cached files” step lists contents of certain directories. Since caching was removed as part of this PR, evaluate if this debugging step is still necessary in production. If not, consider removing it to clean up the workflow.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between a6715641c06c14676f6f592e7c85d76ab807f582 and 46bed628eb2bdd82c07204e85f97d0652d679cad.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `.github/actions/init-environment/action.yml` (2 hunks)
* `.github/workflows/build-multi-os.yml` (7 hunks)
* `.github/workflows/deploy-pages.yml` (1 hunks)
* `.github/workflows/python_tests.yml` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary>

* .github/workflows/deploy-pages.yml
* .github/workflows/python_tests.yml
* .github/actions/init-environment/action.yml

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

<details>
<summary>.github/workflows/build-multi-os.yml</summary>

31-31: description is required in metadata of "Init Environment" action at "/home/jailuser/git/.github/actions/init-environment/action.yml"

(action)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (5)</summary>

* GitHub Check: run-pytest
* GitHub Check: Create and upload Linux AppImage release
* GitHub Check: Create and upload Mac OSX release
* GitHub Check: Create and upload Windows release
* GitHub Check: Create and upload Windows release

</details>

<details>
<summary>🔇 Additional comments (11)</summary><blockquote>

<details>
<summary>.github/workflows/build-multi-os.yml (11)</summary>

`16-16`: **Updated Workflow Trigger**  
The trigger has been updated to run on both push and pull_request events. This aligns with the PR objective of automatically running the build on every push, reducing manual triggers.

---

`18-19`: **Global Python Version Defined**  
A global environment variable (`PYTHON_VERSION: 3.11.9`) is now set for the workflow. This simplifies version management across jobs.

---

`30-30`: **Checkout Configuration Review**  
The checkout step now specifies `fetch-depth: 0`, ensuring the complete git history (e.g., for `git describe`) is available. Verify that this depth is acceptable performance-wise for your repository size.

---

`90-90`: **Conditional Asset Upload in Windows Build**  
The release asset upload step is now gated by `if: steps.vars.outputs.do-release == 'true'`. This condition correctly prevents automatic uploads for non-release builds.

---

`123-123`: **Checkout Configuration on macOS**  
The macOS checkout step also uses `fetch-depth: 0`, which is consistent with the Windows job. Ensure that the full history is necessary for your build process on macOS.

---

`189-189`: **Conditional Signing of Disk Image**  
The “Sign disk image” step is correctly conditioned to run only when `do-release` is true and an Apple certificate is provided. This ensures signing occurs only on actual release builds.

---

`211-214`: **Upload Disk Image as Artifact**  
The disk image is uploaded as an artifact using the specified name and path. This step appears straightforward and correctly implemented.

---

`216-222`: **Attach Disk Image to Release**  
The release action that attaches the disk image to the release is conditionally executed on release builds. This is consistent with the intended behavior of disabling automatic signing/notarization on PR builds.

---

`246-246`: **Linux Checkout Fetch Depth**  
The checkout step for the Linux job also uses `fetch-depth: 0` to facilitate version tagging. Confirm that this does not adversely affect build performance on Ubuntu.

---

`254-259`: **Installation of Python Modules (Linux AppImage)**  
The step that installs Python modules and additional packages (like `avrdude` and `libasound2-dev`) appears correct. Ensure that these installations are robust across different Linux runner images.

---

`338-342`: **Conditional AppImage Release Upload**  
In the Linux AppImage job, the release upload step is properly conditioned with `if: steps.vars.outputs.do-release == 'true'`. This maintains consistency across all platforms for conditional artifact publishing.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

342-342: property "sha" is not defined in object type {do-release: string; draft: string; firmware-url: string; manifest: string; python-appimage: string; python-minor: string; sha-short: string; tag: string}

(expression)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T21:48:28Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 46bed628eb2bdd82c07204e85f97d0652d679cad and 02d4bf8b7e3bd8366d16df1cc808c97a09fbc433.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `.github/actions/init-environment/action.yml` (2 hunks)
* `.github/workflows/build-multi-os.yml` (12 hunks)
* `.github/workflows/deploy-pages.yml` (1 hunks)
* `.github/workflows/python_tests.yml` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* .github/workflows/python_tests.yml
* .github/workflows/deploy-pages.yml

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

<details>
<summary>.github/workflows/build-multi-os.yml</summary>

32-32: description is required in metadata of "Init Environment" action at "/home/jailuser/git/.github/actions/init-environment/action.yml"

(action)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (16)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (6)</summary>

`3-4`: **Define new output variable 'do-release'.**

The new output variable `do-release` is correctly set to capture the value from `steps.vars.outputs.do-release`. This output drives conditional logic later in dependent workflows.

---

`17-18`: **Add new output variable 'firmware-url'.**

The addition of the `firmware-url` output, which retrieves its value from `steps.firmware.outputs.firmware-url`, is implemented properly to provide downstream steps with the URL of the firmware release.

---

`22-26`: **Configure Python setup using an environment variable.**

The “Set up Python” step now leverages the `env.PYTHON_VERSION` variable for specifying the Python version. This centralization of the Python version configuration enhances consistency across workflows.

---

`31-33`: **Conditional release flag generation.**

The conditional block checking for a semantic tag in `GITHUB_REF` is a neat solution to set `do-release` accordingly. Ensure that the regular expression accurately reflects your versioning strategy.

---

`40-57`: **Implement firmware version retrieval with error handling.**

The new "Get firmware version matching manifest" step utilizes a curl command and basic bash scripting to derive the appropriate firmware URL. A few suggestions:
- Confirm that changing the working directory (with `cd src/main/resources/base/ayab/firmware/`) is acceptable and won’t affect subsequent steps which might rely on a specific working directory.
- Validate that the grep and sort logic reliably finds the best matching firmware tag.
Overall, the error handling (exiting with an error message if no match is found) is appropriate.

---

`59-65`: **Set PACKAGE_VERSION and update settings file.**

The step to set the package version by removing any semver suffix and updating the `base.json` via sed appears sound.

</details>
<details>
<summary>.github/workflows/build-multi-os.yml (10)</summary>

`15-19`: **Update workflow trigger and global Python version.**

Changing the trigger to run on both push and pull_request events (lines 16–17) and defining a global `PYTHON_VERSION: 3.11.9` (lines 18–19) are aligned with the PR objective of simplifying the build process. This ensures that builds are triggered automatically on code pushes, reducing manual intervention.

---

`27-31`: **Ensure repository history is sufficient for versioning.**

Setting `fetch-depth: 0` (line 31) is necessary for accurate execution of `git describe`. Confirm that this change does not adversely affect overall performance, although it is required to generate correct version information.

---

`35-40`: **Streamline firmware retrieval in build-windows.**

The "Get firmware version matching manifest" step (lines 35–40) in the Windows job correctly downloads the firmware using the URL output from the init-environment action. Verify that the URL is always correctly provided and that wrapping it in single quotes does not prevent proper expansion by the shell (GitHub Actions template interpolation occurs prior to shell execution).

---

`98-110`: **Conditional release artifact attachment.**

The attachment of the installer as a release asset is conditioned on `steps.vars.outputs.do-release == 'true'` (line 98 onward). This logic is appropriate to avoid automatic signing and notarization for pull request builds.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

102-102: property "sha" is not defined in object type {do-release: string; draft: string; firmware-url: string; manifest: string; python-appimage: string; python-minor: string; sha-short: string; tag: string}

(expression)

</details>

</details>

---

`122-132`: **Consistent checkout and versioning for macOS build.**

In the macOS job, using `fetch-depth: 0` (line 132) and the same init-environment action ensures consistency with the Windows job. The removal of caching in these jobs aligns with the PR’s objectives.

---

`203-223`: **Conditional code-signing and notarization for macOS.**

The steps for signing the disk image and submitting it for notarization (lines 203–223) correctly use the `do-release` output and check for relevant environment variables (`APPLE_CERTIFICATE_NAME` and `APPLE_STORE_CONNECT_KEY_ID`). This conditional flow safeguards that notarization only proceeds when appropriate for a release.

---

`252-260`: **Override Python version for Linux AppImage build.**

Although the global Python version is set to 3.11.9 for Windows and macOS, the Linux AppImage build explicitly overrides it to 3.11.11 (lines 252–254). Confirm that this version difference is intentional and documented, as it appears to be due to `python-appimage` availability requirements.

---

`265-270`: **Repeat firmware retrieval for AppImage build.**

The AppImage job includes a similar "Get firmware version matching manifest" step (lines 265–270) as seen in other jobs. Consistency across jobs is beneficial—ensure that any changes in firmware URL retrieval are maintained in all similar steps.

---

`271-277`: **Install dependencies for AppImage in a streamlined fashion.**

The installation of Python modules and additional dependencies (lines 271–277) reflects the removal of caching steps and simplifies the build. Verify that the set of installed packages covers all necessary dependencies for creating accurate and portable AppImages.

---

`310-314`: **Adjust PATH configuration for AppImage build.**

Appending the AppDir subdirectories to the PATH (lines 310–313) is a good practice ensuring that locally installed binaries can be found during runtime.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T22:18:50Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary><blockquote>

`41-59`: **Firmware Version Retrieval – Consider Future-Proofing**  
The step "Get firmware version matching manifest" successfully extracts release tags from the GitHub releases page and determines the correct firmware URL. However, relying on HTML parsing (using `curl` and `grep`) can be brittle if GitHub changes its markup. As an optional improvement, consider using the official GitHub API to fetch release data, which would provide a more robust solution.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 02d4bf8b7e3bd8366d16df1cc808c97a09fbc433 and 35ccfc5b7dd6411e7b2c5691625a07cde43669f8.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (5)</summary>

`1-2`: **Metadata Description Added**  
The addition of the `description` field on line 2 clearly documents the purpose of this action. This meets the metadata requirements and addresses previous review feedback.

---

`3-18`: **Output Variables Are Well-Documented**  
The output variables (`do-release`, `tag`, `python-minor`, `python-appimage`, and `firmware-url`) have clear and concise descriptions. They correctly reference other steps’ outputs, which helps in understanding how each variable is computed.

---

`22-27`: **Python Setup Step is Consistent**  
Using the environment variable `env.PYTHON_VERSION` to configure the Python version via `actions/setup-python@v5` is a good move. It ensures consistency across workflows.

---

`28-40`: **Robust Variable Initialization**  
The "Set variables" step correctly uses a Bash script to set various outputs based on the Git reference and runtime values. The regex for detecting semver tags is appropriately implemented. If desired, consider handling cases where files (e.g., the manifest) might be missing, though that may be managed elsewhere.

---

`60-67`: **Setting PACKAGE_VERSION is Clear and Direct**  
The final step sets the package version by capturing the Git tag and removing any semver suffix. The use of `sed` here is straightforward. Ensure that the target file (`src/build/settings/base.json`) consistently contains the placeholder string (`PACKAGE_VERSION`) so that the substitution works as expected.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T22:24:14Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (2)</summary><blockquote>

`41-61`: **Firmware Version Retrieval with Error Handling**  
The "Get firmware version matching manifest" step effectively retrieves the available firmware releases via the GitHub API, filters them based on the manifest content, and assigns the matching version to the `firmware-url` output. The error handling (exiting with an error message when no match is found) is appropriate.  
For improved readability, consider replacing the loop construction with a simpler pipeline:  

```diff
-        match=$(for x in $available; do echo $x; done | grep ^${{ steps.vars.outputs.manifest }} | sort -r | head -1)
+        match=$(echo "$available" | grep "^${{ steps.vars.outputs.manifest }}" | sort -r | head -1)
```  

This refactor simplifies the command without changing its functionality.

---

`62-68`: **Setting PACKAGE_VERSION Using Sed**  
The step extracts a version without the suffix and updates `src/build/settings/base.json` accordingly.  
**Note:** The `sed -i` command may behave differently on BSD-based systems (e.g., macOS), where it often requires an argument for the backup extension. Consider specifying a backup extension for cross-platform compatibility (e.g., using `sed -i.bak` and then removing the backup file) if these scripts are intended to run in varied environments.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 35ccfc5b7dd6411e7b2c5691625a07cde43669f8 and 649ad835ac3a235fc99717671d88f36fe13ae665.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (8)</summary>

`2-2`: **Metadata Description Added**  
The `description` field is now included immediately after the `name`, clearly explaining the purpose of the action. This addresses the previous metadata warning.

---

`4-6`: **Output Variable "do-release" Configuration**  
The `do-release` output is defined with a descriptive message and proper value assignment using `${{steps.vars.outputs.do-release}}`. This output will be useful for downstream conditionals in your workflows.

---

`8-9`: **Output Variable "tag" Configuration**  
The addition of a clear description for the `tag` output improves clarity regarding its purpose (current Git tag from `git describe`).

---

`10-12`: **Output Variable "python-minor" Definition**  
The description indicating that this output represents the Python version without the patch number (e.g., 3.11) is clear and concise.

---

`13-15`: **Output Variable "python-appimage" Definition**  
Providing a description for the `python-appimage` output ensures that the expected filename format for Linux builds is well documented.

---

`16-18`: **Output Variable "firmware-url" Definition**  
The new `firmware-url` output variable has been added with a concise description and is set to the value provided by the firmware retrieval step. This will help downstream steps access the correct download URL for the firmware hex file.

---

`22-27`: **Consistent Python Setup**  
The Python setup step now correctly uses `${{ env.PYTHON_VERSION }}` in both the step name and within the `with` block. This ensures a unified Python version configuration across workflows.

---

`28-40`: **Enhanced Environment Variable Setup**  
The "Set variables" step efficiently sets multiple outputs (e.g., `do-release`, `sha-short`, `tag`, `manifest`, `python-minor`, and `python-appimage`), which supports downstream workflow logic.  
- The regex condition to check for a semantic version tag is robust for determining release builds.  
- The extraction commands for `python-minor` and construction of the `python-appimage` filename are clear.  
Overall, the implementation meets the requirements for unifying environment management.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T23:32:49Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (2)</summary><blockquote>

`41-61`: **Firmware Version Matching Step**

This step successfully retrieves available firmware releases via a `curl` command and uses `jq` to extract the tag names. It then searches for a matching release based on the manifest value and sets the `firmware-url` output accordingly.  
   
*Suggestions:*  
- Consider adding error handling for the `cd src/main/resources/base/ayab/firmware/` command to ensure that the directory change does not fail silently.  
- Verify that the JSON output from the GitHub API is always valid before piping it to `jq`, which could prevent potential runtime issues.

---

`62-69`: **Setting PACKAGE_VERSION**

The final step correctly writes the current tag to a local file and then uses `sed` to strip any semantic suffixes—ensuring compatibility with downstream tools.  

*Note:* If cross-platform support is necessary (e.g., running on macOS and Linux), verify that the `sed -i` syntax is compatible across environments.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 649ad835ac3a235fc99717671d88f36fe13ae665 and 7a9f77b745dbe8020833c9fcb7c499a43b5de7e3.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (8)</summary>

`1-2`: **Metadata Description Added**

The inclusion of the `description` field on line 2 clearly documents the action’s purpose. This change directly addresses previous warnings about missing metadata and improves the clarity of this GitHub Action.

---

`4-6`: **New Output: do-release**

The addition of the `do-release` output variable—with a clear description that indicates whether the current ref is a valid release tag using semantic versioning—is well implemented.

---

`7-9`: **Updated Output: tag**

The updated description for the `tag` output accurately conveys that it holds the current Git tag from `git describe`. This change enhances clarity for downstream steps that consume this output.

---

`10-12`: **Output: python-minor Clarification**

The `python-minor` output now explicitly states that it represents the Python version without the patch number (e.g., 3.11). This precise description improves maintainability.

---

`13-15`: **Output: python-appimage Clarity**

The `python-appimage` output variable is clearly described, which aids in identifying the correct Python AppImage filename for Linux builds. This level of detail is beneficial.

---

`16-18`: **New Output: firmware-url**

Adding the `firmware-url` output variable with its related download URL for the firmware hex file is a useful enhancement. The description is concise and aligns with the workflow’s intended functionality.

---

`22-27`: **Python Setup Step Updated**

The "Set up Python" step now leverages the `env.PYTHON_VERSION` environment variable, which aligns with the updated strategy across workflows. This ensures consistency and simplifies version management.

---

`28-40`: **Enhanced Variable Setup**

In the "Set variables" step, the conditional check on `$GITHUB_REF` (line 32) properly determines if the current ref represents a release tag by using a semver pattern validation. The outputs for `do-release`, along with additional variables (e.g., `sha-short`, `tag`, `manifest`, `python-minor`, and `python-appimage`), are correctly emitted.  
   
*Recommendation:* Double-check that the regex used covers all desired valid semver cases.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T13:50:17Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (2)</summary><blockquote>

`41-60`: **Firmware Version Matching Step – Consider Literal Matching**  
The "Get firmware version matching manifest" step effectively retrieves available firmware releases and selects a matching version. One suggestion: if the manifest value is meant to be matched exactly (as a literal string), consider using fixed-string options (e.g., `grep -Fx` or `grep -xF`) to avoid unintended matches if the manifest contains regex metacharacters. For example:  

```diff
- match=$(echo "$available" | grep '^${{ steps.vars.outputs.manifest }}$' | sort -r | head -1)
+ match=$(echo "$available" | grep -Fx '${{ steps.vars.outputs.manifest }}' | sort -r | head -1)
```  

This change is optional and should be applied based on whether literal matching is desired.

---

`62-69`: **PACKAGE_VERSION Update – Cross-Platform Consideration**  
The step that updates the PACKAGE_VERSION by using `sed -i` is clear; however, note that the `-i` flag for in-place editing may have different requirements on non-Linux platforms (for example, macOS often requires an argument like `-i ''`). Please verify whether this command behaves as expected in your target environments, or consider using a more portable solution if cross-platform compatibility is required.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7a9f77b745dbe8020833c9fcb7c499a43b5de7e3 and 384837ba4476fea5c103328588c741cd27c78595.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (8)</summary>

`1-2`: **Metadata Description Added**  
The addition of the `description` field immediately after the `name` ensures the action is well documented and satisfies metadata requirements.

---

`4-6`: **Clear Definition of `do-release` Output**  
The `do-release` output is now accompanied by a concise description and correctly assigns its value from the variables step.

---

`7-9`: **Well-Documented `tag` Output**  
The `tag` output now includes a clear description explaining its purpose (retrieving the current Git tag). This improves readability and maintainability.

---

`10-12`: **Descriptive `python-minor` Output**  
The `python-minor` output now clearly states that it represents the Python version without the patch number, which aids in clarity when this output is consumed later in the workflow.

---

`13-15`: **Clear `python-appimage` Output Documentation**  
The output for `python-appimage` includes a suitable description, ensuring that its purpose is well understood by maintainers and downstream processes.

---

`16-18`: **Addition of `firmware-url` Output**  
Introducing the `firmware-url` output with a descriptive message provides clarity on its purpose and integrates well with the downstream steps that require the firmware download URL.

---

`22-27`: **Consistent Python Setup**  
The step setting up Python using `${{ env.PYTHON_VERSION }}` is consistent with other workflow changes. This centralized configuration helps reduce complexity in version management.

---

`28-40`: **Comprehensive Variable Setting**  
In the "Set variables" step, various outputs are correctly established, including a conditional check to set `do-release` based on the Git reference. The regex pattern used appears appropriate for capturing standard semver tags.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T14:02:06Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary><blockquote>

`41-61`: **Firmware Version Retrieval Step.**  
This step fetches available firmware release tags via the GitHub API and compares them against the manifest. The error handling (exiting with an error if no match is found) is appropriate. It is recommended to verify that the grep pattern substitution (especially with the use of single quotes) behaves as intended after GitHub Actions interpolates the expression.

</blockquote></details>
<details>
<summary>.github/workflows/build-multi-os.yml (4)</summary><blockquote>

`48-52`: **Execution of UI Conversion Script.**  
The "Convert UI and translation files" step runs `bash setup-environment.ps1`. Given that a `.ps1` file typically indicates a PowerShell script, please confirm that this script is intended to run under Bash or consider switching to `pwsh` if PowerShell syntax is required.

---

`164-167`: **UI Conversion for macOS.**  
The step to convert UI and translation files reuses the same setup script. As with the Windows job, confirm that the script’s execution in a Bash shell is intentional, given its `.ps1` extension.

---

`278-281`: **UI Conversion in AppImage Build.**  
The UI conversion step calls the same setup script as in other jobs. As previously noted, please ensure the script is compatible with the shell used in this environment.

---

`300-308`: **Installing Dependencies in AppImage Build.**  
The dependency installation within the extracted AppImage (including a workaround for a faulty include in setup.py) is a pragmatic solution. Consider adding more detailed comments if this “hack” may require future adjustments.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 384837ba4476fea5c103328588c741cd27c78595 and 8e521a3866abcf9dbb530abc0222b5e275e52cbc.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)
* `.github/workflows/build-multi-os.yml` (12 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (35)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (5)</summary>

`2-2`: **Metadata Description Added.**  
The addition of the `description` field immediately after the `name` clearly documents the action’s purpose and addresses previous metadata warnings.

---

`4-18`: **Clear Output Variables Definition.**  
The new outputs—especially `do-release` and `firmware-url`—are defined with clear descriptions and an appropriate value source. This improves downstream readability and reliability.

---

`22-27`: **Python Setup Using Environment Variable.**  
The Python setup step now references `${{ env.PYTHON_VERSION }}`, which streamlines configuration across workflows. Ensure that this environment variable is consistently defined in all triggering workflows.

---

`28-40`: **Variable Initialization and Git Tag Handling.**  
The "Set variables" step correctly detects a semver tag and sets the `do-release` flag accordingly, while also capturing key build details. Double-check that the regex correctly covers all intended tag formats.

---

`62-69`: **PACKAGE_VERSION Setting.**  
The extraction of the version from the Git tag and its substitution into the settings file is correctly implemented. Consider verifying that the `sed` command is compatible across different runner environments if portability is a concern.

</details>
<details>
<summary>.github/workflows/build-multi-os.yml (30)</summary>

`16-19`: **Updated Workflow Trigger and Global Python Version.**  
Changing the trigger to `[push, pull_request]` ensures that builds run on every code push, which aligns with the PR’s goal of eliminating caching and simplifying the build process. The global `PYTHON_VERSION: 3.11.9` ensures consistency for Windows and macOS builds.

---

`22-24`: **Build-Windows Job Definition.**  
The Windows build job is clearly defined with `runs-on: windows-latest` and shows no inclusion of caching steps. This change meets the PR objective of streamlining the process.

---

`35-39`: **Firmware Retrieval in Windows Build.**  
Invoking the firmware URL using the output from the `init-environment` action ensures that the latest firmware is fetched during the Windows build. Verify that the URL fetched by `curl` is consistently accessible and that transient network issues are handled appropriately.

---

`59-69`: **Change Line Endings to CRLF.**  
The loop converting line endings using `unix2dos` is implemented correctly. It is worth confirming that the specified file paths (e.g. `/main/python/main/ayab/*_gui.py`) are valid in the Windows context.

---

`90-95`: **Installer Creation Step.**  
The installer is created with `python -m fbs installer` and then renamed to include the Git tag. Ensure that this naming convention aligns with any downstream processes that expect a specific format.

---

`96-115`: **Conditional Release Attachment.**  
Attaching the installer to the release only if `do-release` is true prevents accidental publication from non-release branches. This conditional logic is well implemented.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

102-102: property "sha" is not defined in object type {do-release: string; firmware-url: string; python-appimage: string; python-minor: string; tag: string}

(expression)

</details>

</details>

---

`137-142`: **Firmware Retrieval in macOS Build.**  
The macOS build similarly fetches the firmware using the output from the `init-environment` action, maintaining consistency with the Windows workflow.

---

`143-163`: **Dependency Installation for macOS.**  
The dependency installation steps—including the downloads for numpy, Pillow, and bitarray—are clearly laid out with delocate commands to support multi-architecture builds. Ensure that these commands function reliably on the specified macOS platforms.

---

`194-201`: **Disk Image Creation.**  
The disk image is generated and renamed with the Git tag, and its path is stored in the GITHUB_OUTPUT. This implementation is correct, but it is good practice to verify that the file operations succeed in the macOS environment.

---

`203-207`: **Conditional Disk Image Signing.**  
The disk image signing step is conditionally executed based on the presence of `do-release` and an Apple certificate. Check that the `codesign` parameters meet Apple’s latest signing requirements.

---

`208-223`: **Disk Image Notarization Process.**  
The notarization process—submitting via `xcrun notarytool` and subsequently stapling the ticket—is correctly implemented. Ensure that the Apple Store Connect environment variables are accurate and that the process is robust against transient failures.

---

`224-229`: **Artifact Upload for Disk Image.**  
Uploading the disk image using `actions/upload-artifact@v4` is straightforward and correctly configured.

---

`230-247`: **Disk Image Release Attachment.**  
The disk image is attached to the release conditionally, and all parameters (e.g., draft and prerelease flags) are appropriately set.

---

`249-255`: **Linux AppImage Build Configuration.**  
The AppImage build job specifies a global `PYTHON_VERSION: 3.11.12`, which differs from the 3.11.9 used for Windows and macOS. Please verify that this version difference is intentional (for instance, to support the available Python AppImage) and documented where appropriate.

---

`256-261`: **Checkout for AppImage Build.**  
The checkout step for the AppImage build uses full history (via `fetch-depth: 0`) and includes submodules, which is essential for accurate version retrieval.

---

`265-270`: **Firmware Retrieval in AppImage Build.**  
Fetching the firmware URL in the AppImage job ensures consistency across all build types.

---

`271-277`: **Python Modules Installation for AppImage.**  
The step to install necessary Python modules (along with system packages) on Ubuntu is concise and meets the job’s requirements. Verify that all dependencies are available in the build environment.

---

`282-287`: **Repository Relocation.**  
Relocating the repository contents into a separate `git` directory can streamline the AppImage packaging. Confirm that this relocation does not inadvertently exclude any critical files.

---

`289-291`: **Downloading Python AppImage.**  
The step to download a pre-built Python AppImage based on the `${{steps.vars.outputs.python-minor}}` output is well targeted. Verify that the URL pattern reliably points to the correct asset version.

---

`292-296`: **AppImage Extraction.**  
Extraction of the downloaded AppImage (with the proper settings of execution permissions) appears consistent with common AppImage usage.

---

`297-299`: **Repository Move for AppImage.**  
Moving the repository files into the `squashfs-root` directory is effective for the subsequent packaging steps. Make sure this operation preserves all necessary files.

---

`309-313`: **PATH Adjustment for AppImage Build.**  
Appending the `usr/bin` and Python binary directory to `$GITHUB_PATH` ensures that subsequent commands will find the necessary executables.

---

`314-320`: **Cleanup of Unneeded Files in AppImage.**  
Removing extraneous UI and resource files from the `squashfs-root` directory helps to reduce the final package size. Ensure that none of these removals affect application functionality at runtime.

---

`321-326`: **AppRun Replacement.**  
Replacing the `AppRun` file with the designated version from the build artifacts is handled cleanly. Verify that the source path (`linux-build/appimage/AppRun`) is always available in the repository.

---

`327-335`: **Adding Application Icon.**  
The steps to add and reposition the application icon are clear. Double-check that the icon file `ayab.png` exists at the expected location during the build.

---

`336-344`: **Desktop File Creation.**  
Creating and deploying the desktop file is handled appropriately. Make sure that the generated desktop file complies with standard specifications for compatibility in Linux environments.

---

`345-351`: **Adding Metadata for AppImage.**  
Copying the metadata file into the proper directory supports integration with Linux desktop environments. This step is straightforward and correctly implemented.

---

`352-361`: **AppImage Conversion Process.**  
The use of `appimagetool` to convert the prepared `squashfs-root` into an AppImage, followed by renaming the output, is well executed. Confirm that the dynamic retrieval of the appimagetool URL functions reliably.

---

`362-381`: **Conditional AppImage Release Attachment.**  
Attaching the final AppImage to the release is conditioned on the `do-release` flag, ensuring consistency with other build jobs. All parameters are correctly provided for a seamless release process.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

368-368: property "sha" is not defined in object type {do-release: string; firmware-url: string; python-appimage: string; python-minor: string; tag: string}

(expression)

</details>

</details>

---

`382-386`: **Final Artifact Upload for AppImage.**  
Uploading the AppImage as an artifact using the `actions/upload-artifact` action is configured properly, ensuring the built AppImage is available for later retrieval.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T14:20:28Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (2)</summary><blockquote>

`4-18`: **Enhance Output Variable Documentation**  
The updated outputs now include detailed descriptions for new variables (`do-release`, `firmware-url`) and for updated ones (`tag`, `python-minor`, `python-appimage`). This improves readability and maintainability. One suggestion: please verify that omitting the `manifest` output from the declared outputs (while still echoing it later) is intentional.

---

`41-60`: **Firmware Version Retrieval Step**  
The new “Get firmware version matching manifest” step robustly fetches available firmware releases and picks the matching tag. A minor point to consider: using `cd` to change directories inside a composite action can sometimes lead to unexpected side effects. If possible, using an absolute or parameterized path might make the step more resilient.

</blockquote></details>
<details>
<summary>.github/workflows/build-multi-os.yml (1)</summary><blockquote>

`49-52`: **Attention on UI Conversion Command**  
The “Convert UI and translation files” step (lines 49–52) calls `bash setup-environment.ps1`. Since the `.ps1` extension typically indicates a PowerShell script, please confirm that executing it via Bash is intentional and that the script is compatible with the Bash environment.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8e521a3866abcf9dbb530abc0222b5e275e52cbc and 8abcb1c33bc47d0b6f2f621250dc07c1203329a3.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)
* `.github/workflows/build-multi-os.yml` (12 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (3)</summary>

`1-2`: **Add Metadata Description**  
The new `description` field (line 2) provides clear context on the action’s purpose. This addresses previous feedback and enhances the documentation.

---

`28-37`: **Review “Set Variables” Step**  
The script correctly determines if the Git reference matches a semver pattern and sets several outputs. Although using `echo` to write to `$GITHUB_OUTPUT` is standard, ensure that the echoed values (like `tag` and `sha-short`) meet downstream expectations.

---

`62-69`: **PACKAGE_VERSION Processing**  
The step replacing `PACKAGE_VERSION` in the JSON file using `sed` is a practical solution. Please ensure that the sed command syntax is compatible with the environments where this action will run (e.g., GNU sed vs. BSD sed).

</details>
<details>
<summary>.github/workflows/build-multi-os.yml (5)</summary>

`15-20`: **Updated Workflow Trigger and Global Environment Variable**  
The workflow now triggers on both push and pull_request events (line 16) and defines a global `PYTHON_VERSION` (line 18). These changes align with the PR objectives by automating builds and reducing manual intervention. Note that while the global value is set to 3.11.9, the Linux AppImage job overrides it to 3.11.12—ensure this divergence is intentional for compatibility reasons.

---

`32-40`: **Streamlined Firmware Download in Windows Build**  
The “Get firmware version matching manifest” step (lines 35–40) downloads the firmware file using the URL from the init-environment outputs. This is a clear and direct approach after removing caching. Just verify that the firmware URL output always provides a valid file path.

---

`41-48`: **Simplified Dependency Installation in Windows Build**  
The removal of caching in the dependency installation step (lines 41–48) simplifies the process considerably. This should reduce potential issues with stale cached artifacts.

---

`137-142`: **Consistent Firmware Retrieval in macOS Build**  
The macOS build job also fetches the firmware using the same strategy (lines 137–142). This consistency is good; just ensure that all platforms handle error cases similarly when the firmware cannot be found.

---

`252-260`: **Version Override in Linux AppImage Build**  
The Linux AppImage job sets its own `PYTHON_VERSION` (line 253) to 3.11.12. This override appears deliberate (as noted in the inline comment regarding AppImage availability). It would be beneficial to double-check that this variation doesn’t lead to incompatibilities between builds.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T14:28:21Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8abcb1c33bc47d0b6f2f621250dc07c1203329a3 and faf7a39155fae00b0dfa6b091bad35456e6a2a13.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 GitHub Actions: Build</summary>

<details>
<summary>.github/actions/init-environment/action.yml</summary>

[error] 44-44: Unrecognized named-value: 'secrets'. Located at position 1 within expression: secrets.GITHUB_TOKEN

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (9)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (9)</summary>

`2-2`: **Metadata Description Added Successfully**  
Adding the `description` field immediately after the `name` field clarifies the action's purpose and resolves previous metadata warnings.

---

`4-6`: **Clear Setup for the "do-release" Output Variable**  
The output variable `do-release` now has a clear description explaining that it is set to `'true'` if the Git reference matches a semantic versioning tag. This improves readability and maintainability.

---

`8-9`: **Improved "tag" Output Description**  
The updated description for the `tag` output ("Current Git tag from git describe") succinctly explains its purpose.

---

`11-11`: **Concise "python-minor" Output Explanation**  
The description for `python-minor` clearly indicates that it represents the Python version without the patch number, which is precise and useful.

---

`14-15`: **Descriptive "python-appimage" Output Variable**  
The `python-appimage` output now includes a clear description that indicates it represents the filename for the Python AppImage used in Linux builds.

---

`16-18`: **Well-Defined "firmware-url" Output Variable**  
The new `firmware-url` output variable, with its accompanying description, neatly encapsulates its purpose of providing a download URL for the firmware hex file.

---

`22-27`: **Aligned Python Setup Step**  
The step that sets up Python now leverages the environment variable `env.PYTHON_VERSION` for determining the Python version. This change standardizes the approach across workflows and simplifies configuration.

---

`32-34`: **Accurate Tag-Based Release Detection**  
The shell script condition using a regex on `$GITHUB_REF` to determine if the current ref is a release tag is well constructed. It sets the `do-release` output effectively when the condition matches.

---

`64-71`: **Effective PACKAGE_VERSION Setting**  
The "Set PACKAGE_VERSION" step extracts the semantic version from the Git tag and updates the `src/build/settings/base.json` file accordingly. This approach is neat and ensures that any suffixes in the tag (not supported by downstream tools) are removed. Just make sure that the placeholder `PACKAGE_VERSION` exists in the target file.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T14:46:42Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary><blockquote>

`41-59`: **Review of Firmware Version Retrieval Step**  
The "Get firmware version matching manifest" step is well structured with proper error handling. A couple of points to consider:  
- **Manifest Usage:** This step relies on `${{ steps.vars.outputs.manifest }}` (on lines 45 and 48) to determine the matching firmware tag. Ensure that this value is correctly populated (see the previous comment regarding declaring `manifest` as an output).  
- **Pattern Matching:** The grep command, as written, should match the exact firmware version. It may be beneficial to verify that the substitution of `${{ steps.vars.outputs.manifest }}` works as expected, especially if the manifest content could include unexpected characters or formatting.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between faf7a39155fae00b0dfa6b091bad35456e6a2a13 and 9a1f2b738588a2040ea8fd7a22dee671bc68b017.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (2)</summary>

`1-2`: **Add Action Description Metadata**  
The addition of a `description` field immediately after the `name` is excellent and helps document the action’s purpose clearly.

---

`60-67`: **Package Version Setting Is Clear and Functional**  
The final step properly writes the current Git tag into `package_version` and uses `sed` to remove any suffix from the semver tag (which is important for compatibility with downstream tools). This is straightforward and clear.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T14:53:54Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary><blockquote>

`60-67`: **Setting PACKAGE_VERSION Step: Implementation Review**  
The approach to output the current tag to a file and then derive a suffix-free version using sed is clear and straightforward. One possible improvement is to add error handling for the sed command to ensure that the file update succeeds under all circumstances.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9a1f2b738588a2040ea8fd7a22dee671bc68b017 and dea34f8f5b56c9d666e83f2d0844970b5a02b5b2.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (2)</summary>

`1-2`: **Metadata Update: Description Field Added**  
Adding the `description` field immediately after the `name` field improves clarity and documentation of the action’s purpose.

---

`22-27`: **Python Setup Step Looks Good**  
The step correctly uses `actions/setup-python@v5` and leverages the `env.PYTHON_VERSION` variable for consistency.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T14:59:00Z
user: login: jonathanperret
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T15:18:35Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T15:19:08Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (8)</summary><blockquote>

<details>
<summary>.github/workflows/build-multi-os.yml (8)</summary><blockquote>

`16-19`: **Workflow Trigger and Global Environment Variable Updated**  
The trigger mechanism now runs on `[push, pull_request]` which aligns with the PR objective to build on every code push rather than only on tag-based events. In addition, a global environment variable `PYTHON_VERSION: 3.11.9` is defined for the Windows and macOS jobs. Please verify that the Python version is intended to be unified across jobs or, if not, document the difference (see later in the Linux job).

---

`49-52`: **UI and Translation Files Conversion Step**  
The conversion step executes `bash setup-environment.ps1` to process UI and translation files. Although the command works, note that the extension `.ps1` typically denotes a PowerShell script. If this script is indeed cross-platform, consider adding documentation (or renaming, if appropriate) to clarify its usage via Bash.

---

`90-95`: **Installer Creation in Windows Build**  
Creating the installer with `python -m fbs installer` followed by renaming the generated file is clear. One point to verify: ensure that the expected file (`AYABSetup.exe`) is always present before executing the rename operation—this could help avoid intermittent failures.

---

`164-167`: **UI and Translation Files Conversion on macOS**  
The conversion step here repeats the Windows logic. As noted earlier, if a PowerShell script is being invoked by Bash, clarifying its cross-platform behavior may prevent future confusion.

---

`253-255`: **Linux Build Environment and Python Version**  
For the Linux AppImage job, the environment specifies `PYTHON_VERSION: 3.11.12`, which differs from the 3.11.9 used in Windows/macOS. Please verify that this version discrepancy is intentional (perhaps due to compatibility with the Python AppImage tool) and document the reasoning if necessary.

---

`279-282`: **UI and Translation Files Conversion on Linux**  
Again, the conversion step uses `bash setup-environment.ps1`. As noted in earlier steps, consider whether the `.ps1` extension might confuse future maintainers when invoked via Bash, and think about clarifying its usage.

---

`283-289`: **Repository Relocation for Linux Build**  
The relocation step uses shell features (e.g., `shopt`) to copy all files except the `git` folder into a new directory. Although clever, this approach can be brittle if shell behavior or directory structures change. It might be worth encapsulating this logic in a helper script or action for better maintainability.

---

`301-309`: **Installing Dependencies within AppImage**  
Within the extracted environment, dependencies are installed, and a hack is applied to work around a faulty include in `setup.py`. Although effective, consider addressing the root cause in the package configuration to eliminate the need for such hacks if possible.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between dea34f8f5b56c9d666e83f2d0844970b5a02b5b2 and 2803c9bdaf1535869968d63f6cfd610e43fcd498.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/workflows/build-multi-os.yml` (13 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (37)</summary><blockquote>

<details>
<summary>.github/workflows/build-multi-os.yml (37)</summary>

`26-31`: **Checkout Step and Caching Removal Verified**  
The checkout step now specifies `fetch-depth: 0` to support accurate versioning with `git describe` and clearly no caching steps remain. This reflects the intended removal of caching from the build process.

---

`32-34`: **Init Environment Step Consistency**  
The `uses: ./.github/actions/init-environment` step is correctly placed immediately after checkout. Please confirm that it now reliably sets all required outputs (e.g., `firmware-url`, `do-release`, etc.) given that caching has been removed from prior setups.

---

`35-40`: **Direct Firmware Version Retrieval**  
The new step uses a straightforward `curl --fail -O` command to download the firmware file from the URL provided by the environment. Using the `--fail` flag ensures the step will error out on HTTP failures, which is good for early detection of issues.

---

`41-48`: **Simplified Dependency Installation in Windows Build**  
The dependency installation for Windows is clear and streamlined without reliance on caching. Ensure that every run installs a consistent set of dependencies and that any potential transient network issues are handled upstream if necessary.

---

`53-58`: **File Cleanup for Windows Build**  
The removal of UI and resource files via `rm` commands is straightforward. Just make sure that these paths remain valid as the project structure evolves.

---

`59-69`: **CRLF Line Ending Adjustment**  
The script adjusts line endings on various UI Python files from Unix to CRLF, which is important for Windows-specific requirements. Confirm that the use of `ls` and shell globbing covers all intended files, as changes in directory structure could affect this logic.

---

`81-84`: **Disabling OpenSSL QtNetwork Backend**  
Removing the OpenSSL-based QtNetwork plugin via the `find` command ensures that the application falls back to native Windows libraries (schannel). This step is implemented clearly and aligns with best practices for dependency management in Windows builds.

---

`86-89`: **Building the Application**  
The build step invoking `python -m fbs freeze` is straightforward. With caching removed, be mindful that build times may increase; ensure that any changes here do not negatively impact the CI build duration.

---

`96-115`: **Conditional Release Attachment for Windows Installer**  
The step attaches the installer to a release only if `steps.vars.outputs.do-release == 'true'`, which is a smart safeguard for PR builds. Verify that the `init-environment` action reliably sets this output, and consider adding documentation for maintainers explaining this condition.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

102-102: property "sha" is not defined in object type {do-release: string; firmware-url: string; python-appimage: string; python-minor: string; tag: string}

(expression)

</details>

</details>

---

`128-133`: **macOS Checkout Step Consistency**  
The macOS job’s checkout step similarly includes `fetch-depth: 0` and submodule inclusion, keeping it consistent with the Windows job.

---

`137-141`: **Firmware Version Retrieval on macOS**  
Mirroring the Windows build, the macOS job retrieves the firmware file using `curl --fail -O`. As always, verify that the working directory is correct and that the variable substitution resolves properly on macOS.

---

`143-163`: **Dependency Installation on macOS**  
The macOS dependency installation includes tailored steps for handling wheels of packages like NumPy and Pillow for different architectures using `delocate-fuse`. This approach is practical for ensuring compatibility across architectures. Consider verifying that the separate downloads for the different platforms (e.g., macosx_10_09_x86_64 and macosx_11_0_arm64) are still necessary and correctly invoked.

---

`169-172`: **File Cleanup on macOS**  
Removing UI and QRC files in macOS follows the pattern established in the Windows job. This consistency should help in maintenance; ensure that file paths remain consistent with changes in project structure.

---

`173-179`: **Apple Certificate Import for macOS**  
The import of the Apple developer certificate is properly gated by a condition checking for `env.APPLE_CERTIFICATE_NAME`. Ensure that the secrets used (base64 and password) are stored securely and that any changes in certificate management are reflected in this step.

---

`180-182`: **macOS Application Build**  
The build command (`python -m fbs freeze`) is simple and mirrors the Windows job. No additional issues observed here.

---

`184-194`: **Application Signing on macOS**  
The signing step uses `codesign` with flags that ensure deep and timestamped signatures. The inline comments effectively describe the rationale behind special handling (e.g., signing `avrdude_mac` explicitly). This step appears correct; just make sure that any changes to the signing identity or certificate configuration are well tested on the current macOS version.

---

`195-202`: **Disk Image Creation**  
Creating the disk image via `python -m fbs installer` and renaming it is clear. It’s important that the tag and path handling here aligns exactly with later steps (such as notarization and release attachment).

---

`203-208`: **Disk Image Signing on macOS**  
The disk image signing step is conditional on both a release flag and the presence of an Apple certificate, which is a good safeguard. Check that the condition doesn’t inadvertently skip signing when it’s required.

---

`209-221`: **Notarization Submission for Disk Image**  
The combined submission and waiting step using `xcrun notarytool` simplifies the notarization process. Ensure that the environment variables for Apple Store Connect (issuer, key, etc.) are correctly provided and that the command’s exit code is handled appropriately by the workflow.

---

`225-230`: **Artifact Upload for Disk Image**  
Uploading the disk image as an artifact with `actions/upload-artifact` is implemented correctly. No issues noted.

---

`231-248`: **Release Attachment for Disk Image**  
The conditional attachment of the disk image to a release via `ncipollo/release-action` mirrors the Windows approach and is appropriately gated by the release flag. Confirm that all fields (e.g., tag, commit, artifact configurations) are accurate and consistent with the project's requirements.

---

`257-262`: **Linux Build: Repository Checkout**  
The checkout step for the Linux job follows the same pattern as the other platforms, with full depth for versioning. This consistency helps ensure reliable builds across platforms.

---

`263-265`: **Linux Init Environment Step**  
The reuse of the `init-environment` action is maintained in the Linux build. Confirm that its outputs are compatible with Linux-specific build logic.

---

`266-271`: **Firmware Version Retrieval in Linux Build**  
Retrieving the firmware using the same `curl` command as on other platforms ensures consistency. As with earlier steps, verify that error handling behaves as expected in the Linux environment.

---

`272-278`: **Installing Python Modules on Linux**  
The installation of Python modules via `apt-get` and `pip` is detailed and appears robust. Ensure that all necessary system packages (e.g., avrdude, libasound2-dev) are available in the build environment and that their versions meet the project’s requirements.

---

`290-292`: **Downloading Python AppImage for Linux**  
The command downloads a Python AppImage using dynamic variables from the environment. Validate that the URL is reliably generated and that network issues are appropriately retried or handled downstream if necessary.

---

`293-297`: **Extracting the Python AppImage**  
Marking the AppImage executable and extracting it is performed succinctly. This step should be stable as long as the downloaded AppImage conforms to expectations; any future changes in the AppImage format might necessitate a review here.

---

`298-300`: **Moving Repository into Extracted Structure**  
The repository is moved into the `squashfs-root` directory. This step is critical for the subsequent packaging, so please ensure no required files are inadvertently skipped during the copy.

---

`310-314`: **Updating PATH for AppDir**  
Appending the necessary subdirectories to `$GITHUB_PATH` ensures that binaries can be found during later steps. This is a neat solution and appears to be implemented correctly.

---

`315-321`: **Cleanup of Unneeded Files in Linux Build**  
Removing extraneous UI and QRC files mirrors the cleanup in other jobs. Keep an eye on these file paths to ensure they match any future restructuring of the repository.

---

`322-327`: **AppRun Replacement for Linux Build**  
Replacing the default `AppRun` with a custom version from `linux-build/appimage/AppRun` is a good way to ensure that the launcher behaves as expected. Confirm that this custom script is kept up-to-date with any changes in the AppImage tooling or application structure.

---

`328-336`: **Icon Addition for Linux Build**  
The steps to delete any existing icons and copy a new one into the proper location ensure that the correct icon is used. This process adheres to desktop environment norms and looks solid.

---

`337-345`: **Desktop File Creation for Linux**  
The creation and placement of the desktop file (e.g., `com.ayab_knitting.ayab.desktop`) is handled neatly. Verify that the file name and contents conform to the desktop standards expected by target environments.

---

`346-352`: **Adding Application Metadata for Linux Build**  
Placing the application metadata into `usr/share/metainfo/` is a standard approach for Linux apps. Ensure that the metadata file (`ayab.appdata.xml`) is updated whenever there are significant changes to the application.

---

`353-362`: **Conversion to AppImage**  
The conversion step downloads the latest `appimagetool`, adjusts permissions, runs the conversion, and then renames the resulting file. Everything appears to be in order; however, verify that the dynamic download (using `wget` and grep) continues to work as expected over time and that any dependency on external URLs is monitored for changes.

---

`363-382`: **Attaching AppImage to Release for Linux**  
The conditional attachment of the Linux AppImage artifact using `ncipollo/release-action` mimics the behavior seen in Windows and macOS. This consistency helps maintain the same release process across platforms.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

369-369: property "sha" is not defined in object type {do-release: string; firmware-url: string; python-appimage: string; python-minor: string; tag: string}

(expression)

</details>

</details>

---

`383-387`: **Artifact Upload for Linux AppImage**  
Uploading the AppImage artifact via `actions/upload-artifact` concludes the Linux job cleanly. This step is straightforward and performs as expected.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T15:20:16Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (2)</summary><blockquote>

`40-59`: **Firmware Version Retrieval: Error Handling and Robustness**

The "Get firmware version matching manifest" step (lines 40–59) implements a robust error handling mechanism by verifying that a matching firmware tag is found and aborting execution otherwise. The approach of scraping the releases page with `curl`, `grep`, and `sed` works; however, it may be brittle if the page structure changes.  
- **Suggestion:** Consider switching to the GitHub API for fetching releases, which would provide a more stable and maintainable solution.

---

`60-67`: **Setting Package Version Effectively**

The "Set PACKAGE_VERSION" step (lines 60–67) correctly writes the Git tag to a file and updates the JSON settings using a `sed` command.  
- **Recommendation:** Verify that the `sed` in-place editing (`-i -e`) is compatible with the intended execution environment. In cases of cross-platform usage (e.g., BSD vs. GNU sed), consider a platform-agnostic approach or add documentation about the required environment.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2803c9bdaf1535869968d63f6cfd610e43fcd498 and 53ac4015ca089c43557078561b6f393fb74fac4c.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary>

```
Learnt from: jonathanperret
PR: AllYarnsAreBeautiful/ayab-desktop#782
File: .github/actions/init-environment/action.yml:41-59
Timestamp: 2025-04-13T15:19:06.597Z
Learning: In GitHub Actions workflows, expressions like ${{ ... }} are expanded by GitHub Actions before the shell script executes. When using these expressions in shell commands, it's best to enclose them in single quotes to prevent any further expansion or interpretation by the shell.
```

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (4)</summary>

`1-2`: **Metadata Enhancement: Description Field Added**

The addition of the `description` field at line 2 improves documentation by clarifying the purpose of this GitHub Action. This addresses previous feedback regarding missing metadata.

---

`3-18`: **Improved Outputs Declarations**

The outputs now include clear, descriptive fields (`do-release`, `tag`, `python-minor`, `python-appimage`, and `firmware-url`), which enhances maintainability and clarity. Verify that the decision to remove the `manifest` output (while still echoing it in the firmware step) is intentional and does not affect downstream steps.

---

`22-26`: **Consistent Python Version Setup**

Leveraging the environment variable `${{ env.PYTHON_VERSION }}` for the Python setup (lines 22–26) ensures consistency across workflows. This change aligns with the objective of centralizing Python version configuration.

---

`28-39`: **Accurate Variable Extraction and Release Tag Detection**

The "Set variables" step (lines 28–39) properly checks if the current Git reference matches a semantic versioning pattern and extracts key variables (e.g., `sha-short`, `tag`, `python-minor`, and `python-appimage`).  
- **Note:** Ensure that the `sed` command used in line 37 for stripping the patch version functions as intended on all target environments (GNU vs. BSD `sed` differences).

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T15:28:59Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary><blockquote>

`60-67`: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Inconsistency with PACKAGE_VERSION Replacement**

The sed command on line 66 is intended to replace `"PACKAGE_VERSION"` in `src/build/settings/base.json`, but the file now contains `"version": ""` rather than the placeholder. As a result, the command may not update the version as expected. Please update the sed command to target the actual pattern in the JSON file or reconsider the change made to the JSON.

For example, you might change the replacement diff to:

```diff
- sed -i.bak -e "s/PACKAGE_VERSION/$version_without_suffix/" src/build/settings/base.json
+ sed -i.bak -e "s/\"version\": \"\"/\"version\": \"$version_without_suffix\"/" src/build/settings/base.json
```

---

**SED Command Update for Correct JSON Version Replacement**

The current sed command in `.github/actions/init-environment/action.yml` (line 66) targets the placeholder `"PACKAGE_VERSION"` in `src/build/settings/base.json`. However, the JSON file now contains `"version": ""`, meaning the sed command will not update the version as intended. Please update the command to search for `"version": ""` and replace it with the actual version value. For example:

```diff
- sed -i.bak -e "s/PACKAGE_VERSION/$version_without_suffix/" src/build/settings/base.json
+ sed -i.bak -e "s/\"version\": \"\"/\"version\": \"$version_without_suffix\"/" src/build/settings/base.json
```

This change will ensure the JSON file is updated properly with the correct version.

---

🏁 Script executed:

```shell
#!/bin/bash
echo "Checking for PACKAGE_VERSION placeholder in src/build/settings/base.json:"
grep -R "PACKAGE_VERSION" src/build/settings/base.json || echo "PACKAGE_VERSION not found"
echo "Checking for empty version key in src/build/settings/base.json:"
grep -R "\"version\": \"\"" src/build/settings/base.json || echo "\"version\": \"\" not found"
```

Length of output: 483

---



</details>

**Update SED Command for Accurate JSON Version Insertion**

The current sed command in `.github/actions/init-environment/action.yml` (line 66) is searching for `"PACKAGE_VERSION"`, which no longer exists in `src/build/settings/base.json`. As confirmed by the grep output, the file now contains a line with `"version": ""`. To ensure the correct version is inserted, please update the sed replacement to target the `"version": ""` pattern.

For example, modify the command as follows:

```diff
- sed -i.bak -e "s/PACKAGE_VERSION/$version_without_suffix/" src/build/settings/base.json
+ sed -i.bak -e "s/\"version\": \"\"/\"version\": \"$version_without_suffix\"/" src/build/settings/base.json
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (2)</summary><blockquote>

`28-38`: **Review Set Variables Step for Completeness**

The "Set variables" step correctly captures the Git reference and derives several outputs (like `do-release`, `tag`, `python-minor`, and `python-appimage`). Note that while `sha-short` is generated here, it is not declared as an output. Please confirm that this is acceptable and that no downstream step depends on it.

---

`39-59`: **Validate Firmware Version Retrieval Logic**

The step fetching firmware versions by reading the manifest file and then matching against available GitHub releases appears solid. For improved robustness:
- Consider adding an explicit check to ensure the manifest file exists before processing.
- Enhance error messaging or include additional logging to aid in debugging if no matching firmware release is found.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 53ac4015ca089c43557078561b6f393fb74fac4c and 0fb1bc58fc940b0b0e94ebb36f9e160943c185d5.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)
* `src/build/settings/base.json` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary>

```
Learnt from: jonathanperret
PR: AllYarnsAreBeautiful/ayab-desktop#782
File: .github/actions/init-environment/action.yml:41-59
Timestamp: 2025-04-13T15:19:06.597Z
Learning: In GitHub Actions workflows, expressions like ${{ ... }} are expanded by GitHub Actions before the shell script executes. When using these expressions in shell commands, it's best to enclose them in single quotes to prevent any further expansion or interpretation by the shell.
```

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>src/build/settings/base.json (1)</summary>

`1-8`: **Clarify Handling of the Version Field in Base Settings**

The `"version"` field is now set to an empty string, which appears to be intentional. Please verify that any downstream processes or tooling that previously relied on a non-empty version (or specifically on the placeholder `"PACKAGE_VERSION"`) are updated to handle an empty version appropriately.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

6-6: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>

</details>
<details>
<summary>.github/actions/init-environment/action.yml (3)</summary>

`1-2`: **Enhance Action Metadata with a Description**

Adding the `description` field immediately after the action name provides clear documentation of the action’s purpose. This is a great improvement for both maintainability and clarity.

---

`3-18`: **Well-Documented Output Variables**

The outputs—`do-release`, `tag`, `python-minor`, `python-appimage`, and `firmware-url`—now include descriptive texts that clarify their intended use. Ensure that any outputs removed from previous versions (such as `sha-short` and `manifest`) are not referenced later in the workflow.

---

`19-27`: **Consistent Python Version Setup**

Using the environment variable `env.PYTHON_VERSION` for configuring the Python setup step ensures consistency across workflows. This change aligns with similar updates in other parts of the project.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T15:41:32Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>.github/workflows/build-multi-os.yml (1)</summary><blockquote>

`59-69`: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Potential Path Issue in Line Endings Conversion**  
The script uses absolute paths (e.g., `/main/python/main/ayab/*_gui.py`) for converting line endings. Please verify that these paths correctly point to the intended files—if the files reside under `src/main/python/main/ayab`, consider updating the paths accordingly.

---

Below are shell scripts to search the repository for directories and files matching the pattern (i.e. “ayab” directories and *_gui.py files) so we can verify whether the workflow’s absolute paths (e.g. `/main/python/main/ayab/*_gui.py`) actually point to the correct locations or if they should instead reference paths like `src/main/python/main/ayab`. Please run these scripts and share the output for further verification.

---

🏁 Script executed:

```shell

#!/bin/bash
# List directories named "ayab" to see their locations:
find . -type d -name "ayab"

# List all *_gui.py files within any "ayab" directory:
find . -type f -name "*_gui.py" | grep -i "ayab"
```

Length of output: 257

---



</details>

**Path Correction Needed for CRLF Conversion**  
The workflow step is still using absolute paths (`/main/python/main/ayab/*_gui.py` and `/main/python/main/ayab/engine/*_gui.py`), while our repository search shows that the relevant files reside under `src/main/python/main/ayab`. Please update the file paths accordingly. If the `engine` subdirectory exists under this path, adjust its reference as well. Manual verification is advised to ensure all targeted files are correctly addressed.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary><blockquote>

`40-59`: **Firmware Version Retrieval Step**  
The step efficiently retrieves available firmware versions and selects the matching one. The error handling is clear. However, the echo of `manifest` on line 45 may be redundant since it is not declared as an output. Consider removing it if it is only meant for logging.

</blockquote></details>
<details>
<summary>.github/workflows/build-multi-os.yml (4)</summary><blockquote>

`258-260`: **Linux Build Python Version Override**  
The Linux AppImage job sets `PYTHON_VERSION` to 3.11.12, differing from the global version (3.11.9). Please confirm that this difference is intentional and required for Linux compatibility.

---

`288-294`: **Repository Relocation**  
This step relocates repository files into a temporary directory (`git`). Adding inline comments to clarify its purpose could aid future maintenance.

---

`303-305`: **Repository Relocation for Packaging**  
Moving files from the `git` directory into `squashfs-root` is simple; consider adding error handling in case the move fails.

---

`358-367`: **AppImage Conversion Process**  
Downloading the latest `appimagetool`, extracting the AppImage, and renaming it properly is well implemented. Consider adding error handling if the download fails.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 0fb1bc58fc940b0b0e94ebb36f9e160943c185d5 and e700193da4a6753473867e73764e200013974146.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)
* `.github/workflows/build-multi-os.yml` (13 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary>

```
Learnt from: jonathanperret
PR: AllYarnsAreBeautiful/ayab-desktop#782
File: .github/actions/init-environment/action.yml:41-59
Timestamp: 2025-04-13T15:19:06.597Z
Learning: In GitHub Actions workflows, expressions like ${{ ... }} are expanded by GitHub Actions before the shell script executes. When using these expressions in shell commands, it's best to enclose them in single quotes to prevent any further expansion or interpretation by the shell.
```

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (44)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (5)</summary>

`1-2`: **Metadata Description Added**  
The addition of a `description` field immediately following the `name` field enhances clarity and meets action metadata requirements.

---

`4-18`: **Improved Output Declarations**  
The output variables (`do-release`, `tag`, `python-minor`, `python-appimage`, and `firmware-url`) are now declared with clear and descriptive texts. This improves the readability and maintainability of the composite action.

---

`22-27`: **Python Setup Step**  
Using the global environment variable `PYTHON_VERSION` to set up Python with the official setup action ensures consistent configuration across jobs.

---

`28-38`: **Correct Handling of Variable Initialization**  
The `Set variables` step correctly assigns outputs such as `do-release`, `sha-short`, `tag`, `python-minor`, and `python-appimage`. The conditional check on the `GITHUB_REF` is implemented as expected.

---

`60-67`: **Setting Package Version**  
Capturing the tag into a file and normalizing its format with `sed` is a clean solution for setting the package version.

</details>
<details>
<summary>.github/workflows/build-multi-os.yml (39)</summary>

`16-17`: **Updated Workflow Trigger**  
Changing the trigger to run on both `push` and `pull_request` events ensures that builds initiate on every code push, reducing manual intervention.

---

`18-20`: **Global Python Version Declaration**  
The declaration of `PYTHON_VERSION: 3.11.9` as a global environment variable streamlines version consistency across the workflow.

---

`32-33`: **Usage of Composite Action for Environment Setup**  
Integrating the custom `.github/actions/init-environment` action (using `id: vars`) ensures that environment variables are set consistently across all jobs.

---

`35-40`: **Firmware Retrieval in Windows Job**  
This step uses the `firmware-url` output from the init action (enclosed in single quotes) to download the firmware file. The implementation is concise and consistent with best practices.

---

`41-48`: **Windows Dependencies Installation**  
Installing dependencies via Chocolatey and pip is straightforward. The explanatory comment on installing `vcredist-all` aids in understanding the necessity of this step.

---

`49-52`: **UI and Translation Files Conversion**  
The step runs `bash setup-environment.ps1` to process UI files. Verify that invoking a `.ps1` script with Bash is intentional and compatible with the Windows environment.

---

`53-59`: **Cleanup Step**  
Removing unneeded UI and resource files is clear and helps maintain a tidy build artifact.

---

`71-85`: **Removal of OpenSSL Backend**  
The step to remove the OpenSSL QtNetwork backend via `find` is well documented and effectively prevents unwanted DLL packaging.

---

`86-89`: **App Build Step**  
Triggering the build using `python -m fbs freeze` is clear and aligns with the expected application build process.

---

`90-95`: **Installer Creation**  
Creating the installer and renaming it to include the current Git tag improves traceability of build artifacts.

---

`96-115`: **Conditional Release Attachment (Windows)**  
Using `ncipollo/release-action@v1` with a condition based on `do-release` correctly ensures that the installer is attached to a release only when applicable.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

102-102: property "sha" is not defined in object type {do-release: string; firmware-url: string; python-appimage: string; python-minor: string; tag: string}

(expression)

</details>

</details>

---

`116-120`: **Installer Artifact Upload**  
Uploading the installer artifact with the dynamically generated name ensures that it is easily retrievable for further testing or distribution.

---

`137-142`: **Firmware Retrieval for macOS**  
The macOS job’s firmware retrieval step mirrors the Windows job, ensuring consistency. The use of the `firmware-url` output is correctly implemented.

---

`143-163`: **macOS Dependencies Installation**  
The step efficiently installs dependencies using `delocate` to handle wheel bundling for multiple platforms. Ensure that the platform-specific commands remain compatible with the target deployment environments.

---

`164-167`: **UI and Translation Files Conversion (macOS)**  
Similar to the Windows job, this step runs `bash setup-environment.ps1`. Please verify that invoking this PowerShell script with Bash on macOS yields the expected results.

---

`168-172`: **Cleanup Step (macOS)**  
The removal of unnecessary UI and resource files in the macOS build is consistently handled.

---

`173-179`: **Apple Certificate Import**  
Importing the Apple developer certificate using the dedicated action is done correctly, with conditions ensuring it only runs when the certificate name is provided.

---

`180-183`: **App Build Step (macOS)**  
The macOS build step invoking `python -m fbs freeze` is straightforward and consistent with other platform builds.

---

`184-199`: **App Signing Process**  
The app signing step is well documented and correctly differentiates between ad-hoc and certificate-based signing. Verify that the path to `avrdude_mac` is accurate.

---

`200-207`: **Disk Image Creation**  
The disk image is created, renamed to include the Git tag, and its details are output for subsequent steps, ensuring proper traceability.

---

`208-213`: **Conditional Disk Image Signing**  
The disk image is signed only if `do-release` is true and a valid certificate is available. The use of single quotes around the path preserves its integrity.

---

`214-229`: **Notarization Submission**  
Submitting the disk image for notarization using `xcrun notarytool` and then stapling the ticket is implemented securely and clearly, with sensitive credentials passed via environment variables.

---

`230-235`: **Disk Image Artifact Upload (macOS)**  
Uploading the disk image as an artifact is handled appropriately, ensuring it’s available for further release steps.

---

`236-253`: **Conditional Release Attachment (macOS)**  
Attaching the disk image to the release only when `do-release` is true ensures that draft releases are correctly managed. The configuration parameters are comprehensive.

---

`268-270`: **Environment Setup for Linux Build**  
Reusing the custom environment setup action ensures consistency in variable initialization for the Linux build job.

---

`271-276`: **Firmware Retrieval for Linux Build**  
The retrieval of the firmware file using the download URL is consistent with other jobs and correctly scoped via the working directory.

---

`277-283`: **Python Modules Installation for Linux**  
Installing the required Python modules and system libraries using apt and pip is clear and straightforward.

---

`284-287`: **UI Conversion in Linux Build**  
Invoking the `setup-environment.ps1` script via Bash on Linux merits verification to ensure cross-platform compatibility.

---

`295-297`: **Download Python AppImage**  
Downloading the Python AppImage using dynamic outputs (e.g. `${{steps.vars.outputs.python-minor}}` and `${{steps.vars.outputs.python-appimage}}`) is a neat integration that aligns with the build goals.

---

`298-302`: **AppImage Extraction**  
The extraction of the AppImage, coupled with permission updates, is clear and concise.

---

`306-314`: **Dependencies Installation in AppImage**  
Installing dependencies within the extracted AppImage environment is well structured. The documented workaround for the faulty include in `simpleaudio` is appreciated.

---

`315-319`: **Updating PATH for AppImage**  
Appending necessary directories to `$GITHUB_PATH` ensures that the app’s executables are properly located.

---

`320-326`: **Cleanup in AppImage**  
Removing redundant files (UI files and extra resource files) from the AppImage directory is handled consistently with previous cleanup steps.

---

`327-332`: **Replace AppRun Binary**  
Replacing the default `AppRun` with a custom version is standard in AppImage packaging and is implemented clearly.

---

`333-341`: **Add Application Icon**  
The process of removing obsolete icons and installing the new application icon in the correct directory structure is well executed.

---

`342-350`: **Desktop File Configuration**  
Creating and positioning the desktop file for the application ensures proper integration with desktop environments.

---

`351-357`: **Adding Metadata**  
Adding metadata files under `usr/share/metainfo/` enhances application discoverability and adheres to AppStream standards.

---

`368-387`: **Release Attachment for AppImage**  
Attaching the AppImage to the release using `ncipollo/release-action@v1` is configured consistently with other platforms, ensuring that the artifact is updated only when `do-release` is true.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

374-374: property "sha" is not defined in object type {do-release: string; firmware-url: string; python-appimage: string; python-minor: string; tag: string}

(expression)

</details>

</details>

---

`388-392`: **Artifact Upload for AppImage**  
Uploading the final AppImage artifact is handled cleanly, making it easily retrievable from the release.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T15:55:44Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (6)</summary><blockquote>

<details>
<summary>.github/workflows/build-multi-os.yml (6)</summary><blockquote>

`41-48`: **Dependency Installation in Windows Job**  
Dependencies are now installed using Chocolatey (for installing `vcredist2010`) and pip (for requirements). Consider adding error handling for the `choco install` command to gracefully catch installation failures.

---

`185-194`: **MacOS App Signing Improvements**  
The updated signing block conditionally sets `codesign_options` based on whether `APPLE_CERTIFICATE_NAME` is provided. For clarity and to avoid any potential unset variable issues, consider initializing `codesign_options` as an empty string before the conditional block.

---

`215-226`: **Notarization Process**  
The updated step submits the disk image using `xcrun notarytool` and staples the resulting ticket. As a security and hygiene measure, consider deleting the temporary key file (`apple-store-connect.key`) after notarization succeeds to prevent accidental exposure of sensitive data.

---

`306-314`: **Linux AppImage Dependency Installation**  
Within the `squashfs-root`, dependencies are installed and a hack is applied to fix issues with `setup.py`. It would be beneficial to document the reason for this hack in detail or consider a refactor for clarity and maintainability in future revisions.

---

`342-350`: **Desktop File Configuration**  
Creating and placing the desktop file in `usr/share/applications/` is handled here. Consider whether any stale desktop files might remain from previous runs and, if so, add a cleanup step.

---

`358-367`: **Conversion to AppImage**  
The conversion step dynamically downloads `appimagetool`, adjusts permissions, and uses it to build the AppImage. The process involves installing and later removing `appstream` via sudo. This approach works but may introduce overhead or transient state issues; consider using a containerized environment or caching the tool if performance becomes a concern.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between e700193da4a6753473867e73764e200013974146 and dbaaa5b721393757643367d3f4fcf91075016e20.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/workflows/build-multi-os.yml` (13 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: Create and upload Windows build
* GitHub Check: Create and upload Linux AppImage release
* GitHub Check: Create and upload Mac OSX build

</details>

<details>
<summary>🔇 Additional comments (27)</summary><blockquote>

<details>
<summary>.github/workflows/build-multi-os.yml (27)</summary>

`16-17`: **Trigger Update: Broaden Workflow Trigger**  
The trigger has been updated from a tag-only push to run on both push and pull_request events. This broader trigger will cause builds on every push and PR—which aligns with the PR objective of reducing manual test release triggers. Please verify that this change does not lead to unintended builds on branches not meant for release.

---

`18-19`: **Global Environment Variable for Python Version**  
A global environment variable `PYTHON_VERSION: 3.11.9` is now defined. This promotes consistency across jobs. Ensure that this version is supported on all target platforms and consider whether it needs periodic updating.

---

`22-24`: **Build-Windows Job Definition Update**  
The Windows build job is now defined with the revised job name and setup—removing caching and redundant setup steps. Confirm that all dependencies formerly provided via cache are now installed reliably during each run.

---

`29-31`: **Checkout Step: Full Git History via Fetch-Depth**  
The checkout step now sets `fetch-depth: 0` to enable commands like `git describe`. This ensures full repository history is available during the build and is consistent with the updated process.

---

`32-39`: **Firmware Version Fetch Using cURL**  
The step to fetch the firmware version now uses a direct `curl` command operating from the specified working directory. Please verify that the output variable `steps.vars.outputs.firmware-url` reliably supplies a valid URL in all build contexts.

---

`56-69`: **Change Line Endings to CRLF**  
The step converting line endings to CRLF uses a shell loop over files in `/main/python/main/ayab/*_gui.py`. Verify that the file paths (and any leading directory slashes) are accurate within the Windows environment, ensuring that the intended files are processed.

---

`86-97`: **Installer Creation and Conditional Release Attachment (Windows)**  
The installer is created by running `python -m fbs installer` and then renamed dynamically using the current tag. The subsequent attachment step uses a condition (`if: steps.vars.outputs.do-release == 'true'`) to ensure release assets are only published when appropriate. This approach is consistent with disabling release signing on non-release builds.

---

`128-133`: **MacOS Checkout Step Consistency**  
The macOS job now applies `fetch-depth: 0` similarly to the Windows build, ensuring full repository history for operations like `git describe`. This enhances consistency across platforms.

---

`137-141`: **MacOS Firmware Fetch Step**  
In macOS, the firmware is fetched via a `curl` command executed from the correct working directory. Please confirm that the directory exists in the macOS environment and that appropriate error handling is in place in case the file download fails.

---

`164-167`: **UI Conversion Step on macOS**  
The step converting UI and translation files now executes `bash setup-environment.ps1`. Verify that this PowerShell script is executable on macOS (or that an equivalent mechanism is in place) since cross-platform compatibility can be an issue here.

---

`208-212`: **Conditional Disk Image Signing**  
The disk image signing step now only runs when both `steps.vars.outputs.do-release` is `'true'` and `APPLE_CERTIFICATE_NAME` is available. This condition prevents unintended signing during PR builds.

---

`237-245`: **Release Attachment for Disk Image**  
Attaching the disk image to the release is now conditional (`if: steps.vars.outputs.do-release == 'true'`), which helps prevent mistakes during non-release builds. Ensure that the release metadata (like tag and artifact content type) is consistent with the other platforms.

---

`258-261`: **Linux Build: Python Version Specificity**  
The Linux AppImage job now specifies `PYTHON_VERSION: 3.11.12`, which differs from the global `3.11.9`. Please verify that this version difference is intentional to meet the requirements of `python-appimage` and that no compatibility issues arise.

---

`262-267`: **Linux Checkout: Full History Required**  
As in other jobs, the Linux build’s checkout step sets `fetch-depth: 0`. This is important for retrieving complete git history when needed.

---

`271-276`: **Linux Firmware Fetch Step**  
The Linux job fetches firmware using the same `curl` approach as Windows and macOS. Confirm that this method works reliably in the Ubuntu environment provided by the CI.

---

`277-283`: **Linux Dependency Installation**  
The installation step now installs system dependencies (via `apt-get`) and upgrades pip packages. Ensure that running these sudo commands works within the CI environment and consider adding error checks to handle potential failures gracefully.

---

`284-287`: **Linux UI Conversion Step**  
The conversion step executes `bash setup-environment.ps1` on Linux. Since `.ps1` scripts are typically for PowerShell, please verify that this script runs correctly on Linux or whether an alternative should be used.

---

`288-294`: **Repository Relocation for AppImage Build**  
The relocation step uses a shell pattern (`!(git)`) to copy all non-git files into a new directory. Confirm that this pattern behaves as expected under the shell in your CI environment.

---

`295-297`: **Downloading Python AppImage**  
The command to download the Python AppImage uses dynamic URL extraction via `wget`, `grep`, and `head`. Verify that the URL extraction reliably returns the intended AppImage asset, as changes on the external GitHub page could affect this step.

---

`298-305`: **AppImage Extraction and Repository Relocation**  
The steps to extract the AppImage and relocate repository content are straightforward. Ensure that file permissions and paths remain correct after extraction and moving files into `squashfs-root`.

---

`315-319`: **Append AppDir Subdirectories to PATH**  
Appending the `usr/bin` and `opt/.../bin` directories to `$GITHUB_PATH` is a neat solution to ensure the binaries are available later in the workflow.

---

`320-326`: **Removing Unneeded Files in Linux Build**  
The removal of various UI and resource files cleans up the build output. Please double-check that none of these files are required by downstream processes before removal.

---

`327-332`: **AppRun Replacement in Linux Build**  
Replacing `AppRun` with the version from `linux-build/appimage/AppRun` is a clear step. Ensure that the replacement file has the correct permissions and functionality.

---

`333-341`: **Icon Setup for AppImage**  
The steps to copy and position the application icon appear correct. Verify that `linux-build/appimage/ayab.png` exists and that the destination directory structure meets expectations for AppImage icons.

---

`351-357`: **Adding Metadata for Linux Build**  
The addition of metadata using `ayab.appdata.xml` is straightforward. Confirm that the metadata adheres to the AppImage standards required by the target distributions.

---

`368-376`: **Attaching AppImage to Release**  
The final release attachment for the AppImage is conditional on `do-release` and correctly packages the artifact with dynamic naming. This is consistent with the macOS and Windows release steps.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

374-374: property "sha" is not defined in object type {do-release: string; firmware-url: string; python-appimage: string; python-minor: string; tag: string}

(expression)

</details>

</details>

---

`388-392`: **Artifact Upload for AppImage**  
The upload-artifact step uses the standard action to archive the AppImage. Please verify that the artifact path is calculated correctly so that the expected file is uploaded.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T16:55:34Z
user: login: dl1com
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T17:28:56Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary><blockquote>

`40-59`: **Firmware Version Retrieval Step is Robust.**  
The newly added “Get firmware version matching manifest” step (lines 40–59) effectively reads the manifest file, retrieves available firmware releases via curl, and determines the matching release.  
  
*Suggestion:* Consider using `pushd`/`popd` instead of `cd` on line 52 in case subsequent steps depend on the original working directory.

</blockquote></details>
<details>
<summary>.github/workflows/build-multi-os.yml (1)</summary><blockquote>

`299-300`: **AppImage Download Command – Consider Quoting URL.**  
In the “Download AppImage of Python designed for manylinux” step (lines 299–300), the wget command formats the URL using GitHub Actions expressions. Although the expression expansion works correctly, it might improve robustness to quote the constructed URL in case of unexpected whitespace or special characters.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between dbaaa5b721393757643367d3f4fcf91075016e20 and 7bb088fe6d5151dab38b58d25b4286ef5e42841e.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `.github/actions/init-environment/action.yml` (1 hunks)
* `.github/workflows/build-multi-os.yml` (13 hunks)
* `.github/workflows/deploy-pages.yml` (1 hunks)
* `.github/workflows/python_tests.yml` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* .github/workflows/deploy-pages.yml
* .github/workflows/python_tests.yml

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>.github/actions/init-environment/action.yml (1)</summary>

```
Learnt from: jonathanperret
PR: AllYarnsAreBeautiful/ayab-desktop#782
File: .github/actions/init-environment/action.yml:41-59
Timestamp: 2025-04-13T15:19:06.597Z
Learning: In GitHub Actions workflows, expressions like ${{ ... }} are expanded by GitHub Actions before the shell script executes. When using these expressions in shell commands, it's best to enclose them in single quotes to prevent any further expansion or interpretation by the shell.
```

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Create and upload Windows build

</details>

<details>
<summary>🔇 Additional comments (12)</summary><blockquote>

<details>
<summary>.github/actions/init-environment/action.yml (5)</summary>

`1-2`: **Metadata Description Added and Clear.**  
The new `description` field on line 2 helps document the action’s purpose and resolves previous actionlint warnings.

---

`4-18`: **Well-Structured Outputs Update.**  
The new and updated outputs (such as `do-release`, `tag`, `python-minor`, `python-appimage`, and `firmware-url`) are clearly documented with descriptive text. This improves clarity for downstream steps.

---

`22-27`: **Python Setup Step is Correct.**  
The action correctly uses `actions/setup-python@v5` with the global environment variable `PYTHON_VERSION` to set up Python.

---

`28-38`: **Set Variables Step Implements Conditional Logic Effectively.**  
The conditional check on line 32 properly identifies a semantic-version tag to set `do-release`. The usage of `echo` commands to update `$GITHUB_OUTPUT` for various variables (including `sha-short` and `tag`) is clear and functional.

---

`60-67`: **PACKAGE_VERSION Update is Clear and Functional.**  
The step for setting the package version (lines 60–67) cleanly writes the tag value to a file and updates the JSON settings using sed.

</details>
<details>
<summary>.github/workflows/build-multi-os.yml (7)</summary>

`15-17`: **Updated Workflow Trigger Configuration.**  
Changing the trigger to `on: [push, pull_request]` (line 16) aligns with the PR objective to run builds on all code pushes, reducing the manual intervention needed.

---

`18-20`: **Global Python Version Environment Variable.**  
The declaration of `PYTHON_VERSION: 3.11.9` in the `env` block (line 18) is clear; note that while Windows and macOS jobs will inherit this, the Linux AppImage job overrides it with 3.11.12—ensure this discrepancy is intentional.

---

`32-40`: **Firmware URL Retrieval in Windows Build.**  
The Windows job’s step “Get firmware version matching manifest” (lines 35–40) uses a curl command with single quotes around the GitHub Actions output variable. This usage is appropriate and prevents unwanted shell expansion.

---

`90-95`: **Installer Creation and Release Attachment.**  
The steps for creating the installer and attaching it to a release are streamlined. The conditional check using `steps.vars.outputs.do-release == 'true'` ensures that signing and publishing only occur for release builds.

---

`137-142`: **Consistent Firmware Version Retrieval in macOS Job.**  
Mirroring the Windows build, the macOS job also invokes the “Get firmware version matching manifest” step with proper working directory context and shell quoting.

---

`275-280`: **Linux AppImage Job’s Firmware Retrieval is Consistent.**  
The Linux job repeats the firmware retrieval step (lines 275–280) consistently with the other jobs.

---

`372-391`: **Release Attachment in Linux Job is Well-Integrated.**  
The final steps attaching the AppImage to the release use conditional logic based on `do-release` and properly configure the release-action parameters.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

378-378: property "sha" is not defined in object type {do-release: string; firmware-url: string; python-appimage: string; python-minor: string; tag: string}

(expression)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T17:32:28Z

Review comments:
diff_hunk: @@ -1,5 +1,7 @@
 name: Init Environment
 outputs:
path: .github/actions/init-environment/action.yml
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Add metadata description for consistency.**

The action is missing a "description" field at the top (currently only the "name" is provided). Adding a description helps document the purpose of this action and satisfies metadata requirements (as flagged by actionlint).

---



</details>

**Action Required: Add a Metadata Description to the GitHub Action**

Please update the file `.github/actions/init-environment/action.yml` to include a `description` field immediately following the `name` field. For example:

```diff
 name: Init Environment
+description: "Provide a brief description of what this action does, e.g., initializes the environment for CI."
 outputs:
```

Adding this metadata clarifies the intent of the action and resolves the actionlint warning regarding missing documentation.  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
name: Init Environment
description: "Provide a brief description of what this action does, e.g., initializes the environment for CI."
outputs:
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 35ccfc5
created_at: 2025-04-12T22:18:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,40 +1,70 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
 runs:
   using: "composite"
   steps:
-    - name: Set up Python ${{ matrix.python-version }}
+    - name: Set up Python ${{ env.PYTHON_VERSION }}
       id: py
       uses: actions/setup-python@v5
       with:
-        python-version: ${{ matrix.python-version }}
-        cache: "pip"
+        python-version: ${{ env.PYTHON_VERSION }}
+
     - name: Set variables
       id: vars
       shell: bash
       run: |
+        if [[ "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+-?[-a-zA-Z0-9]*$ ]]; then
+            echo "do-release=true" >> $GITHUB_OUTPUT
+        fi
         echo "sha-short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
         echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
-        echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT
         echo "manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)" >> $GITHUB_OUTPUT
         echo "python-minor=$(echo '${{steps.py.outputs.python-version}}' | sed -e 's/\.[^.]*$//')" >> $GITHUB_OUTPUT
         echo "python-appimage=python${{steps.py.outputs.python-version}}-cp311-cp311-manylinux_2_28_x86_64.AppImage" >> $GITHUB_OUTPUT
+
+    - name: Get firmware version matching manifest
+      id: firmware
+      shell: bash
+      run: |
+        echo ${{ steps.vars.outputs.manifest }}
+        available=$(curl --fail --silent --show-error \
+          -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
+          -H "Accept: application/vnd.github.v3+json" \
+          "https://api.github.com/repos/AllYarnsAreBeautiful/ayab-firmware/releases" | \
+          jq -r '.[].tag_name')
+        echo "$available"
+        match=$(echo "$available" | grep '^${{ steps.vars.outputs.manifest }}$' | sort -r | head -1)
+        echo "$match"
+        if [[ $match ]]
+        then
+          cd src/main/resources/base/ayab/firmware/
+          url=https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases/download/$match/ayab_monolithic_uno.hex
+          echo "firmware-url=${url}" >> $GITHUB_OUTPUT
+        else
+          echo "Error: could not find firmware release matching manifest"
+          exit 1
+        fi
+
path: .github/actions/init-environment/action.yml
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Robust Firmware Version Retrieval with a Critical Caveat on Secrets Usage**  
The "Get firmware version matching manifest" step cleverly retrieves available firmware release tags via the GitHub API, matches them against the manifest, and sets the `firmware-url` output accordingly. The error handling—with a clear message and a non-zero exit on failure—is well implemented.  
  
However, the use of `${{ secrets.GITHUB_TOKEN }}` in the curl header (line 47) in a composite action can trigger issues (as indicated by the pipeline failure: *"Unrecognized named-value: 'secrets'"*). In composite actions, secrets must be passed explicitly (for example, as an input or environment variable) because they aren’t available by default in this context.  
  
Consider modifying the action to accept the token as an input (or via an environment variable) and then referencing that input instead of `${{ secrets.GITHUB_TOKEN }}`.

---



</details>

**Critical: Update Secrets Handling in Composite Action**

- In the composite action defined in `.github/actions/init-environment/action.yml` (lines 41–63), the curl command currently references `${{ secrets.GITHUB_TOKEN }}` directly. In composite actions, secrets aren’t available by default, which causes errors like "Unrecognized named-value: 'secrets'" during pipeline execution.
- **Resolution:** Update the action to accept the GitHub token explicitly—either as an input parameter (e.g., `token`) or by exposing it via an environment variable. Then modify the curl header to reference this input instead of `${{ secrets.GITHUB_TOKEN }}`.
  
This change ensures proper authentication when calling the GitHub API and adheres to best practices for composite actions.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Actions: Build</summary>

[error] 44-44: Unrecognized named-value: 'secrets'. Located at position 1 within expression: secrets.GITHUB_TOKEN

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-13T14:46:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,40 +1,66 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
 runs:
   using: "composite"
   steps:
-    - name: Set up Python ${{ matrix.python-version }}
+    - name: Set up Python ${{ env.PYTHON_VERSION }}
       id: py
       uses: actions/setup-python@v5
       with:
-        python-version: ${{ matrix.python-version }}
-        cache: "pip"
+        python-version: ${{ env.PYTHON_VERSION }}
+
     - name: Set variables
       id: vars
       shell: bash
       run: |
+        if [[ "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+-?[-a-zA-Z0-9]*$ ]]; then
+            echo "do-release=true" >> $GITHUB_OUTPUT
+        fi
         echo "sha-short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
         echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
-        echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT
         echo "manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)" >> $GITHUB_OUTPUT
         echo "python-minor=$(echo '${{steps.py.outputs.python-version}}' | sed -e 's/\.[^.]*$//')" >> $GITHUB_OUTPUT
         echo "python-appimage=python${{steps.py.outputs.python-version}}-cp311-cp311-manylinux_2_28_x86_64.AppImage" >> $GITHUB_OUTPUT
path: .github/actions/init-environment/action.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

_⚠️ Potential issue_

**Ensure Consistent Handling of the Manifest Value**  
Within the `Set variables` step, the command on line 37 echoes the manifest content:  
```bash
echo "manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)" >> $GITHUB_OUTPUT
```  
However, since `manifest` has been removed from the declared outputs, referencing it later (in the firmware retrieval step) may result in an empty value. Please either declare `manifest` as an output (as suggested above) or update the later steps to retrieve the manifest directly from the file.

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 53ac401
created_at: 2025-04-13T14:53:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,40 +1,66 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
path: .github/actions/init-environment/action.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Refined Outputs Declaration with a Caveat**  
The updated outputs now include `do-release`, `tag`, `python-minor`, `python-appimage`, and `firmware-url` with clear descriptions. This improves clarity and consistency across the workflow.  
**Note:** There is a potential issue regarding the `manifest` variable—while it is still echoed in the `Set variables` step, it is no longer declared as an output. This can lead to an empty value when later referenced in the firmware retrieval step. Consider either removing the echo of `manifest` from the `Set variables` step if it’s no longer needed or adding a new output for it. For example:  
```diff
 outputs:
   do-release:
     description: "'true' if the current ref is a release tag (matches semver pattern)"
     value: ${{steps.vars.outputs.do-release}}
   tag:
     description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
   python-minor:
     description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
     description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  manifest:
+    description: "Content of the firmware manifest file"
+    value: ${{steps.vars.outputs.manifest}}
   firmware-url:
     description: "Download URL for the firmware hex file"
     value: ${{steps.firmware.outputs.firmware-url}}
```  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
outputs:
  do-release:
    description: "'true' if the current ref is a release tag (matches semver pattern)"
    value: ${{steps.vars.outputs.do-release}}
  tag:
    description: "Current Git tag from git describe"
    value: ${{steps.vars.outputs.tag}}
  python-minor:
    description: "Python version without patch number (e.g. 3.11)"
    value: ${{steps.vars.outputs.python-minor}}
  python-appimage:
    description: "Python AppImage filename for Linux builds"
    value: ${{steps.vars.outputs.python-appimage}}
  manifest:
    description: "Content of the firmware manifest file"
    value: ${{steps.vars.outputs.manifest}}
  firmware-url:
    description: "Download URL for the firmware hex file"
    value: ${{steps.firmware.outputs.firmware-url}}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-13T14:53:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,40 +1,66 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
 runs:
   using: "composite"
   steps:
-    - name: Set up Python ${{ matrix.python-version }}
+    - name: Set up Python ${{ env.PYTHON_VERSION }}
       id: py
       uses: actions/setup-python@v5
       with:
-        python-version: ${{ matrix.python-version }}
-        cache: "pip"
+        python-version: ${{ env.PYTHON_VERSION }}
+
     - name: Set variables
       id: vars
       shell: bash
       run: |
+        if [[ "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+-?[-a-zA-Z0-9]*$ ]]; then
+            echo "do-release=true" >> $GITHUB_OUTPUT
+        fi
         echo "sha-short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
         echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
-        echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT
         echo "manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)" >> $GITHUB_OUTPUT
         echo "python-minor=$(echo '${{steps.py.outputs.python-version}}' | sed -e 's/\.[^.]*$//')" >> $GITHUB_OUTPUT
         echo "python-appimage=python${{steps.py.outputs.python-version}}-cp311-cp311-manylinux_2_28_x86_64.AppImage" >> $GITHUB_OUTPUT
+
path: .github/actions/init-environment/action.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Set Variables Step: Consistency Check**  
This step sets critical variables (e.g., `do-release`, `tag`, and `python-minor`). However, as mentioned earlier, it echoes the `manifest` value (line 37) without declaring it as an output. Make sure to address this to avoid unexpected empty values in downstream steps.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-13T14:58:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,40 +1,66 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
 runs:
path: .github/actions/init-environment/action.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Output Declarations: Missing Manifest Variable**  
The outputs now include `do-release`, `tag`, `python-minor`, `python-appimage`, and `firmware-url`, which is great. However, note that the `manifest` variable is still echoed in the "Set variables" step (line 37) and referenced later (line 45) but is not declared in the outputs section. Please either add a `manifest` output or remove its echo if it is no longer needed.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-13T14:58:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,40 +1,66 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
 runs:
   using: "composite"
   steps:
-    - name: Set up Python ${{ matrix.python-version }}
+    - name: Set up Python ${{ env.PYTHON_VERSION }}
       id: py
       uses: actions/setup-python@v5
       with:
-        python-version: ${{ matrix.python-version }}
-        cache: "pip"
+        python-version: ${{ env.PYTHON_VERSION }}
+
     - name: Set variables
       id: vars
       shell: bash
       run: |
+        if [[ "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+-?[-a-zA-Z0-9]*$ ]]; then
+            echo "do-release=true" >> $GITHUB_OUTPUT
+        fi
         echo "sha-short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
         echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
-        echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT
         echo "manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)" >> $GITHUB_OUTPUT
         echo "python-minor=$(echo '${{steps.py.outputs.python-version}}' | sed -e 's/\.[^.]*$//')" >> $GITHUB_OUTPUT
         echo "python-appimage=python${{steps.py.outputs.python-version}}-cp311-cp311-manylinux_2_28_x86_64.AppImage" >> $GITHUB_OUTPUT
+
+    - name: Get firmware version matching manifest
+      id: firmware
+      shell: bash
+      run: |
+        echo ${{ steps.vars.outputs.manifest }}
+        available=$(curl -s https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases | grep -oE '/tag/[^\"]+' | sed -E 's/\/tag\///')
+        echo $available
+        match=$(for x in $available; do echo $x; done | grep '^${{ steps.vars.outputs.manifest }}$' | sort -r | head -1)
+        echo $match
+        if [[ $match ]]
+        then
+          cd src/main/resources/base/ayab/firmware/
+          url=https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases/download/$match/ayab_monolithic_uno.hex
+          echo "firmware-url=${url}" >> $GITHUB_OUTPUT
+        else
+          echo "Error: could not find firmware release matching manifest"
+          exit 1
+        fi
+
path: .github/actions/init-environment/action.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

_⚠️ Potential issue_

**Variable Expansion Issue in Firmware Matching**  
In the "Get firmware version matching manifest" step, the grep pattern on line 48 is enclosed in single quotes, which prevents variable expansion. This will cause the match to fail. Please change the single quotes to double quotes so that the embedded expression is correctly substituted.  



Below is a suggested diff:
```diff
-        match=$(for x in $available; do echo $x; done | grep '^${{ steps.vars.outputs.manifest }}$' | sort -r | head -1)
+        match=$(for x in $available; do echo $x; done | grep "^${{ steps.vars.outputs.manifest }}$" | sort -r | head -1)
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    - name: Get firmware version matching manifest
      id: firmware
      shell: bash
      run: |
        echo ${{ steps.vars.outputs.manifest }}
        available=$(curl -s https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases | grep -oE '/tag/[^\"]+' | sed -E 's/\/tag\///')
        echo $available
        match=$(for x in $available; do echo $x; done | grep "^${{ steps.vars.outputs.manifest }}$" | sort -r | head -1)
        echo $match
        if [[ $match ]]
        then
          cd src/main/resources/base/ayab/firmware/
          url=https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases/download/$match/ayab_monolithic_uno.hex
          echo "firmware-url=${url}" >> $GITHUB_OUTPUT
        else
          echo "Error: could not find firmware release matching manifest"
          exit 1
        fi
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-13T14:59:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,40 +1,66 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
 runs:
   using: "composite"
   steps:
-    - name: Set up Python ${{ matrix.python-version }}
+    - name: Set up Python ${{ env.PYTHON_VERSION }}
       id: py
       uses: actions/setup-python@v5
       with:
-        python-version: ${{ matrix.python-version }}
-        cache: "pip"
+        python-version: ${{ env.PYTHON_VERSION }}
+
     - name: Set variables
       id: vars
       shell: bash
       run: |
+        if [[ "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+-?[-a-zA-Z0-9]*$ ]]; then
+            echo "do-release=true" >> $GITHUB_OUTPUT
+        fi
         echo "sha-short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
         echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
-        echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT
         echo "manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)" >> $GITHUB_OUTPUT
         echo "python-minor=$(echo '${{steps.py.outputs.python-version}}' | sed -e 's/\.[^.]*$//')" >> $GITHUB_OUTPUT
         echo "python-appimage=python${{steps.py.outputs.python-version}}-cp311-cp311-manylinux_2_28_x86_64.AppImage" >> $GITHUB_OUTPUT
+
+    - name: Get firmware version matching manifest
+      id: firmware
+      shell: bash
+      run: |
+        echo ${{ steps.vars.outputs.manifest }}
+        available=$(curl -s https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases | grep -oE '/tag/[^\"]+' | sed -E 's/\/tag\///')
+        echo $available
+        match=$(for x in $available; do echo $x; done | grep '^${{ steps.vars.outputs.manifest }}$' | sort -r | head -1)
+        echo $match
+        if [[ $match ]]
+        then
+          cd src/main/resources/base/ayab/firmware/
+          url=https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases/download/$match/ayab_monolithic_uno.hex
+          echo "firmware-url=${url}" >> $GITHUB_OUTPUT
+        else
+          echo "Error: could not find firmware release matching manifest"
+          exit 1
+        fi
+
path: .github/actions/init-environment/action.yml
user: login: jonathanperret
body: This is wrong, the embedded expression is expanded by GitHub actions before executing the script, so it is actually best to put it in simple quotes to prevent any further expansion by the shell.
created_at: 2025-04-13T15:18:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,40 +1,66 @@
 name: Init Environment
+description: "Sets up the environment and extracts various build-related variables"
 outputs:
-  sha-short:
-    value: ${{steps.vars.outputs.sha-short}}
+  do-release:
+    description: "'true' if the current ref is a release tag (matches semver pattern)"
+    value: ${{steps.vars.outputs.do-release}}
   tag:
+    description: "Current Git tag from git describe"
     value: ${{steps.vars.outputs.tag}}
-  draft:
-    value: ${{steps.vars.outputs.draft}}
-  manifest:
-    value: ${{steps.vars.outputs.manifest}}
   python-minor:
+    description: "Python version without patch number (e.g. 3.11)"
     value: ${{steps.vars.outputs.python-minor}}
   python-appimage:
+    description: "Python AppImage filename for Linux builds"
     value: ${{steps.vars.outputs.python-appimage}}
+  firmware-url:
+    description: "Download URL for the firmware hex file"
+    value: ${{steps.firmware.outputs.firmware-url}}
 runs:
   using: "composite"
   steps:
-    - name: Set up Python ${{ matrix.python-version }}
+    - name: Set up Python ${{ env.PYTHON_VERSION }}
       id: py
       uses: actions/setup-python@v5
       with:
-        python-version: ${{ matrix.python-version }}
-        cache: "pip"
+        python-version: ${{ env.PYTHON_VERSION }}
+
     - name: Set variables
       id: vars
       shell: bash
       run: |
+        if [[ "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+-?[-a-zA-Z0-9]*$ ]]; then
+            echo "do-release=true" >> $GITHUB_OUTPUT
+        fi
         echo "sha-short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
         echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
-        echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT
         echo "manifest=$(cat src/main/resources/base/ayab/firmware/manifest.txt)" >> $GITHUB_OUTPUT
         echo "python-minor=$(echo '${{steps.py.outputs.python-version}}' | sed -e 's/\.[^.]*$//')" >> $GITHUB_OUTPUT
         echo "python-appimage=python${{steps.py.outputs.python-version}}-cp311-cp311-manylinux_2_28_x86_64.AppImage" >> $GITHUB_OUTPUT
+
+    - name: Get firmware version matching manifest
+      id: firmware
+      shell: bash
+      run: |
+        echo ${{ steps.vars.outputs.manifest }}
+        available=$(curl -s https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases | grep -oE '/tag/[^\"]+' | sed -E 's/\/tag\///')
+        echo $available
+        match=$(for x in $available; do echo $x; done | grep '^${{ steps.vars.outputs.manifest }}$' | sort -r | head -1)
+        echo $match
+        if [[ $match ]]
+        then
+          cd src/main/resources/base/ayab/firmware/
+          url=https://github.com/AllYarnsAreBeautiful/ayab-firmware/releases/download/$match/ayab_monolithic_uno.hex
+          echo "firmware-url=${url}" >> $GITHUB_OUTPUT
+        else
+          echo "Error: could not find firmware release matching manifest"
+          exit 1
+        fi
+
path: .github/actions/init-environment/action.yml
user: login: coderabbitai[bot]
body: @jonathanperret You're absolutely right, and thank you for the correction. GitHub Actions does indeed expand the `${{ ... }}` expressions before the shell script executes, so using single quotes is the correct approach here. This prevents any special characters in the expanded value from being interpreted by the shell during runtime.
---
<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: jonathanperret
PR: AllYarnsAreBeautiful/ayab-desktop#782
File: .github/actions/init-environment/action.yml:41-59
Timestamp: 2025-04-13T15:19:06.597Z
Learning: In GitHub Actions workflows, expressions like ${{ ... }} are expanded by GitHub Actions before the shell script executes. When using these expressions in shell commands, it's best to enclose them in single quotes to prevent any further expansion or interpretation by the shell.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@jonathanperret You're absolutely right, and thank you for the correction. GitHub Actions does indeed expand the `${{ ... }}` expressions before the shell script executes, so using single quotes is the correct approach here. This prevents any special characters in the expanded value from being interpreted by the shell during runtime.
---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: jonathanperret
PR: AllYarnsAreBeautiful/ayab-desktop#782
File: .github/actions/init-environment/action.yml:41-59
Timestamp: 2025-04-13T15:19:06.597Z
Learning: In GitHub Actions workflows, expressions like ${{ ... }} are expanded by GitHub Actions before the shell script executes. When using these expressions in shell commands, it's best to enclose them in single quotes to prevent any further expansion or interpretation by the shell.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details></answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-13T15:19:08Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-12T21:30:21Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

The changes update multiple GitHub Actions workflows. The init-environment action now adds and updates output variables (including `do-release` and `firmware-url`) and introduces a new step to fetch firmware versions with error handling. The multi-OS build and Python tests workflows have been streamlined by removing caching and setup steps, replacing matrix strategies with a global `PYTHON_VERSION` environment variable (3.11.9), and simplifying job steps. Additionally, a new workflow has been added to automate deployment of documentation to GitHub Pages on pushes to the main branch.

## Changes

| File(s)                                                                                  | Change Summary                                                                                                                                                                                                                                             |
|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `.github/actions/init-environment/action.yml`                                            | Enhanced environment setup: added outputs `do-release` and `firmware-url`, removed deprecated variables (`sha-short`, `draft`, `manifest`), updated output descriptions, and added a new step to fetch firmware version with error handling.     |
| `.github/workflows/build-multi-os.yml`, `.github/workflows/python_tests.yml`               | Updated CI workflows: removed caching and the setup job, replaced matrix strategies with a global `PYTHON_VERSION` (3.11.9) environment variable, and streamlined job steps including firmware fetching, signing, and notarization logic.         |
| `.github/workflows/deploy-pages.yml`                                                     | Added a new workflow to automate deployment of documentation to GitHub Pages on pushes to the main branch, including steps for code checkout, dependency installation, `.nojekyll` creation, and documentation deployment.                        |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant CI as "CI Pipeline"
    participant Init as "Init Environment Action"
    participant Firmware as "Firmware Service"
    participant Build as "Build Job"
    participant Sign as "Signing Service"
    
    CI->>Init: Start workflow with Git tag info
    Note right of Init: Check if tag matches semver & set do-release
    Init->>Firmware: Fetch firmware versions matching manifest
    Firmware-->>Init: Return firmware data or error
    Init->>Build: Provide firmware-url output
    Build->>Sign: If do-release true, sign and notarize build
```

```mermaid
sequenceDiagram
    participant Main as "Main Branch Push"
    participant Deploy as "Deploy Pages Workflow"
    participant Checkout as "Checkout Code"
    participant Deps as "Install Dependencies"
    participant GHPages as "GitHub Pages"
    
    Main->>Deploy: Trigger deployment workflow
    Deploy->>Checkout: Checkout repository (including submodules)
    Deploy->>Deps: Install doxygen and graphviz
    Deploy->>GHPages: Create .nojekyll and deploy docs to gh-pages branch
```

## Assessment against linked issues

| Objective                                                   | Addressed | Explanation                                      |
|-------------------------------------------------------------|:---------:|--------------------------------------------------|
| Disable caching in the CI for the release builds (#774)     | ✅        |                                                  |

<!-- walkthrough_end -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡💬 Agentic Chat (Pro Plan, General Availability)</summary>
> 
> - We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
> 
> </details>

<!-- announcements_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpADK2VmgqyjcEj2wAbb5AokAI7Y0riQ4rjedJAARDYkzPhSjGgMCBhEkABmFCyQAtjw3rQxkADuaMiI2ALM6jT0cpDYiJSQQvgY1LCY3JQBYZj0qPBKGOJZ8NGV1nYYTgJtAOwAHABMGjCwnrzwzC7ygiJikp74WeEIyLYoyATotLQBiHfbt9WetPgMTuzR8FgzEslgAWfLyRK0eBZWQAzK4N4FIr0Mr4CgAayy3nwZXC+EgJG8ewB1E8CM8LTOFwYqXSRE2AEkMIgaGh6Od/ITYRl+FgaWlopMoogADSXTwBYLwAL0IWeUjkKjiTrlIp+DA4/gMH58VrcFyk7yHLAkWk8bzULJo5hisoINLobyIfGIPbcImTaTi/hSKi+fKFYo8XIMaSIDRGJkPKHKrD3AKJCRwlJpOFi8mzFDjXK0bCh5BoRg9DKeAHe3AUeBEUh8NhpTBIZjZNHepFB1EYrE4xlhVAa3GtMLx7BYFVof1MJReRDbUVZhjebBQnkCfAIyDYml+ARUDACgsYejcHx+SUhFnhraoNlCFq4NjjdB7O74uoYYkALzJb3I+dduHkK1a0wbBx3CStq0oZMORoFlOSiSppE2AAxFsARZTBQ3TN4dQCR8bnUVpvAuAF1HgUlXk8NsUTRTFsVxFVCPyXc0h7W4UGYbg0VwTAh3xDUaEuahvTQPAWGoeAGEgV0iHfHkhkgASXHgD8JJVXhvjDL0XE+JAVCiWUW2o5AFWUBpslyJtj39M9QnDIxUL4LJsAock+CUHiijnDMbhpLBFnQbUtPoYSMytXwcWTABVGwABkuAAbVgXBcG4RAOAAegyoh1FgGoNCYZgMoAQV8ABNFxmWKgIACFTTwaEfAytBZBUMAlEQdECG4DLrO8DLVjWABdAAKZLUvSrKcoRfLCpK8rKsQaqSDq0SJialq2o6rr8B6vqBvWABKCMDH0YxwCgMh2QuNbCFMpVokKh9OGDfhhFEcQpBkeRJ2UVR1C0HQzpMKA4BGA8cAIYgyDMx6WGergqAHJx9lccEFCUKh/s0bRdDAQxztMAwNGmvKBGak5OkQDLSNwMAyCTXIMGeinYw0WRmG8DgDBiXmDAsSBioZaHFVJehqmcNGOXrEtEHcHDi1IF9vQAcXUAAJGpBcp5lylortcTIYtQ29BnpU6Z7pJIXBsG4dBD34PBjzCCRlP0pDBcUkgGKdvBIFdyt3cgAADL4wACBDWmD9iAQrRQ8zoMUAShGlxB5aFvVw9hIDVsIAiySgyBN694NNVpwjQeEejCfZcH3dArf2cZJP9yhXU6ZN9RSygMDFcdOkyMpcobjqGErbhPs8C1Fm8TYPBDyYKGYCoAjAFzvGj/BfZdt2BCidjx2daNonuDSkynDMvjKDBsTZSAYti5s+DC6Vl50yBtgAD2yIoSDFQr3TW08EPdchZR7jzZpAeWngSCfyQGnTIW9Up+wDuRPeXpg4zjQGAGc3Fg5ilDlQLIuB8H23oMHJu0JQjRx6MkRYZBOSJkTtJN0HpuRVzONvaSFY8w2wCHPN4wceJEE3lw1BQd+zzkXB1Ee0gx7wAnvARih5JISXTnnEgvBpDsEoowFyeEwi5wrpkTGpxZSWRDtNSA4D4CLGDpsSMcY3gsk0VUD6Sje7ekHLbJ+1hZAIhVD0GQJAGGQmhFMeg9xKT2wJBgRmFts7iPQSHBmGgrBlWgOrAA8gAOQAPoADUACiNh7AMlydHdCrJrrei0UmLeyAKHUErJ/DQ3B/GwE6GAX07cMD2M9uQAcNA7YRAMrEFW1sf5LxXp4HpHjIC11TDyShBcWSlCCfkEJWA2RKFoLae0sBOQVimF9dArsihB0Xm/AIrcKC9OQDkPIhZc6awEJyLi/40SyDFIs2c4omyV20MyQYCyGyrNwH3B2g5dHByuTMteFAN6O2QYMbUaJlxECNAI1ALi7YAgXEuL0/QWzFloESHkCJhKwKYiAw5mACQUFyLWMMldSwXA1KCuudIpnXIlISMupYHlb0PJsYqjwyKdHHEabCMC4EsmTLi3xg4EH+13sKD+Mx6FYFtrQMWeIpGEobkwFRsYwICgYOiISYRoXelDoQCOArREovyIhdkTjPBGPzoXPcJATpZN9FKmVRZMBKxYbJcJflIjyCNphb8wD9b0QAOQPJHDrcc6h5ARz1fcOF785kqgGJWEgrs/AKRvHeb0VgOkqm8XbDSf4ToC1KjQJUHjlaX1EBaVtVN+AXFgVxVy0QWzHj3i3dgZFpBGCgFksRarPA7LoFwO14d+WIUqVgexpMaiszbTTd8dMzZMxZqkNmHMN6nUgDO51ST94LtoEu3Nq917rpDiTXK26T27tpvTOJ5tmbsB3Z0dmnNg4Xqvc7VVgdkk6rFku4RL7N3vvJp+qme71A/vif+8YgGMDAaRSNGxiixyPDoIdMDs6oP7xgw0Jd7SAkYDAG+NECG30zWQzram37D0JOwyh3DZ7o4EbkRA+Zd6yPToo2gqj3BdU0ZDnRzpDG0DcG4HsVlLGt3sdjJx/dGG/3Hp1nhwThHYzH1oGR3mMQp1E1Y2TDKHY6I4mptRRjPhxBgHwOGM93NLP80sELEWsNxYowOL24NstoF607PRBQGBJhEBcmpLAQEAzImTBmYqZVio1VLohHgqR0SsuQBskcmMiCdE8NUAQGFm5gTCZMVObaBFkggjWXxGYHMGw1VUBAxDBQWMLMIsAAhXXTkOfcQsiQbn4sXK6ZIxzIJ8BVKudcx4ZxkK8L4PJtk4LFp0c1q2Ns7YdDeRsrVsTxAR0zQkJIzD+48lpSgXABYXjfHIuZfk3LcVCqcq/GZG2VZRQZD/YUorICYsEGBbjWGd6Uc8Clny1asD5qwGdrZWY465lDLQE6UYMwAHVk5OdS0GE7QbvsaroejmS74Gu8SNNwgIaBOYAjoAdupSiWgpi+8Mn7PL/sKUB8DuUxW0BU4YYSYkXQGiQsiW8KpUqkthaUH0Q8Rcpii+CQw10nEPQRLB4M7hmjuubIYXe/VBcuXekfbMtu8yoQBDEAzloyZCw6j8E9IYYoAjulSOlt4HOGkbnwDlKSlLexxPwN4KQ9BzXomTClsX2hp77xt7l1ol554K98ErjkKurrq69JImbhKCzST6AwCNChnAO3uNn0tnIpQykgAUpAoE/AAGEADUXfIDxChCySsBQeLoJOvPfYDAsn2BJ/QE7JvD4unRxmBMSQwLS1pAq3nG3i97mkdpax0oPrZGtg6BHbw08o4OzT6CFxL5IEtWp0gG2qt1BePMlLSlKyqVM7Qqi6P6sRL6ol5TjGoxhtouqtBuoNyG5IIQY3qeDLoOproHaf4qRK71phgm7nY67ujhInwug1B1CDAOwVDqDtY/hrjKTf7zJliFiugZD7ye4iqRaxQAjYDfzFQqYMj7BP7UTtCCAm464XKIryCtAMLL43Ylphafab6uKy7ej1654XD55q57ga5YHo7Ub4EGpTg7ISpdB+D6gWpFYHa3Z+h+CD68IuSeBo6hJsieBTaeDGqV6tC2jDwyila8RG5pSMK3YhQOyFhWg/DIAqgO5H6wKiANQqgci/gspoxMG0D2QGD+rKC+BBoyyhr5xRBiANwzjQh8QryJENyOGM6mgs7kD+H0AkBZANZTCPidb0Te50B5jJgAJRBwIAToyS5vhqKZAyHyRQrWw+IU7h7lCFzBjFqc6IAM6xEvAHCNr+beAtpJbtpvBKALgGjaZhb9rcRDp8AjpEhSTjriCToXr44JqagLZtZaH3ohydCJRrawBih9TbZBDni4BDQaZIb2YXFlDOaBi0CuZLHwAeZeYgYXpFK/pHqJJzpmZLrpKZK5KFIlJlK5JcAADMGgAAjFiRoAAJxfFsY/HRZOYZQubMBuYgmeZGYXoABSAhwcLmQ8h4Tm0cNxXA8QTC5C5AdA6Uh2tshJdmDRpJ5JlJoJNJUA9JbyjJAJjGqQnmbJMmsGfekh0QwcPJiRXAtagp26wpfxZJspFJwJ4pAmdJDJLmymqmPBJAipsmi6KpXJIcGpfJ2pWYr6mmxJjm+popxp1Jppvmp0NmHpep1MKu2IsgYA+oSseGPmfMTaws90eqEsqMhw1IispxxUXsuILyWsxUHGUWXpIOngXQbA5CYZ+AEZUZSEAmGhDCscOYCckS+It0tcca1imi4Zlsee3wvw4wSu9wOZbyVgJhWw8aJJuIqAVxhcUBjxXo9wGYTSAI0cO4mEsAbExqroF4YWdBcI+8c+JZap5ZsgpCdokkhyFAI4IR2yWAUUBQ4w2AkAawGwAADGCNDs9AdnPsAV6K0AGhYbzlwEYLiZAAAFQgUd7bAWpIIYwkBgVcBgxVDDLNAZ62p8bUxx5IIAACEgII0cfG+qceyK3oPunm6gXyyaMFScu+S4CqhB8coOBgGwoFIFTIGE/oKhYwleXoKWXwn8sgCocFV4iFxu9euisxiAoWHFhec4iAFeEaUq8gdqfFCoeFDswcRAVA3AsASYH4pCLuFKAeBWrKoKXQNYEYmJzFHeTOgkGgGoIg6IsgvgglCF3hjA1l++9idlJADlvg0ccobpC5XwDA1MyUIGB+juBAaM9wZA1QNyoxcoB5yAj2pWbcTAzw6ANyGBLwcMjKH0DOTQg51gJhBgIImwYFAAIh2RWfqlWYgM5VcK5Q1ESF+DCpVXEpQB3ooJQFiRlLxfxWQMQEhpGUVmAHxthbiZiViXhTrPqked6ImeZEFb2TxKZvOYIkQLAMNUrMuSxE8eXqINCOwtblHpjLFp5HJBwtYj2c9ErgpBmMavFolqZnKGPm8HqdkH7kSCtXOThJ0GnNgEHkeV2coddewErlocrIVcOaGrbCqBkXOfiBmPsGWCuXuGueYIscsVsWtZ8J2pseARyDsYOuyPsTUIcRdhOnLBejkt7AWV1nekugeVwJVe6NVbVTqeTCGb1VVZWSYf6XzIGWAEYLZrqb8dTApp0HkrBM9jGTzHGf5gmTDA9MFpLKmeFkrJFvDcgGWB1r8bFo9d2sli2FWvRjAHZFmBIFHvNm8CvlITBG8LXC0ozqSEQIBC2LJQdTCP7p4CbYprcr0hthmPWfHDNRyPSu+TCXDrNdUazpWkjv7R4psPYHJXTr4N8raoPi7ceVbDNaMd+SFJyk7SlsHBLQxijolJNViZ8bWVgEoFEA0IyMCqaHsjEsHAzNHK0DNbYdsiRk2YdiHAidkvksUqUuUjktHPcMHJXfif0vPCMdXP3T4r7SqJIl6nhCbAiKgBHY+PAVmC4nfPbQ4c0vAN/PAQduSt+MJIHi0AzoOM0HbMvdqvQZkMHAACQADe79hdJ9bSSO3SduKoAAvoAzQpqujj7haNjqqOuG/Z/bEhIGkhkkPciaPbkpAMA7PQ1fDSwrrngbog9VWE9fMk0N0SSCqkjcfd/JnTQK7RtmEU7vIPpZkIESfdEI/QnUBhjYLEsWZOATje2RsYbSEX2p/AOuZMOmTWOs3CcVTVAJCZhpbLvQzQPUg0iSPaiePW6YhkSVzaXVLXZEZtA4ciWiECHNPQSXLVZoGQTCDLEjUrdIFsrdXgjP4GgMjKrejL9FjGoDjEDPjAYLY09OoHkqMIgK8UmN7HQHkhhK5HjDYxdOgAAGxLBYkACsiTIIWJDAz5iTDAWJIIyTiTWQRTqTeJawJASwDAKwqTtASwiTKgKwz5SwWQqT6wcTATCTBTiwtAiTawKwJAAgawAgjw6w2TSwawr5JA1TWQeJSwtAOTqTawPTSweJNI9AwMCTz5SzIIAgWQKwAgSwJA6JwzKw6JiTiTtAWJFzWQWTVTz5KwDAszaAz5eJWQAgDAII6J6J7Ttj6JqT2oWQDAqTBzjwGTOJFTgzQLiTeJVzawqTzzlTSgnz5zrzKwPzCTGTeJbIpz8LDA6JaAawfzgLeJszWJdTKTtAKwKwWQZzBcWJ+LJA5zqT6LEAkASwaArzwIBzIINTiwjTEzpz6JjzgLBzHzJLaAnzAgNTFTRzLLUA6JKwIIpzSwI2IIIIdTBcaA/zWJz5XzfTrTDzoIWTtAawlTqwpTzLGzrL/TizWJaACr5zKgDAMztAqgqT6Jz5TrWzT5UrJAprqTJAizDA7zcrkAKwTrAgWTXz7z6r8zAgRTawxTawWJcLz5tAYzeTEzerWL3zVrUAWQaAWQ7L6JMLqTqTBbJAz5z5AgabBbiTNbMLI2tAfzPLiTjLBLaA9LobWLWJWQQzSwCrBrBLr5z5po1LtTBLSzISyTWJ7ziT+zz5ZLobSg9rIIezLTUruTeJPT5zUz6Jfb8zirIIsz1b8LWzUrgzobfTurjzwzhbaTfzKw0LeJ87PT+7uTWQPTOrJAnzgLtAx7aLebkA7rqQIIi7/zzzKwqznzZbSwTT1TiTs7RTJb+73LBbHzUkQHz5bzs7QL1LjzYHNbNbJAeJIIAzAgtLeJJAVzLznzeT1TtAlr/jtjFTVbWJeJ6JuqIIaAyT7r6rDrhzA7dTZHEzbHJbRrBTy7I2aAWrBzybKHSwqTwnXzyTzbWQa7zrMLTTqTi7bbEzobKrNbVLBcFzqTaTWJuqFH+zrTJrwLIIfTbbLTP7fTmTngZ0HTrLQTuAITiR4TUwZQUTV0cTQAA -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=AllYarnsAreBeautiful/ayab-desktop&utm_content=782):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-04-13T17:29:44Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=AllYarnsAreBeautiful_ayab-desktop&pullRequest=782) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=AllYarnsAreBeautiful_ayab-desktop&pullRequest=782&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=AllYarnsAreBeautiful_ayab-desktop&pullRequest=782&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=AllYarnsAreBeautiful_ayab-desktop&pullRequest=782&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=AllYarnsAreBeautiful_ayab-desktop&pullRequest=782&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=AllYarnsAreBeautiful_ayab-desktop&pullRequest=782&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=AllYarnsAreBeautiful_ayab-desktop&pullRequest=782)


author_association: NONE
user: login: jonathanperret
created_at: 2025-04-13T17:34:10Z
body: Thanks @dl1com !

<img width="915" alt="image" src="https://github.com/user-attachments/assets/b771f262-4e65-4b45-b446-9f40953197f7" />

In case you didn't know, to fix the "required check" above (caused by the fact that I removed the single-entry build matrix, so `run-pytest (3.11)` is now just `run-pytest`) I think you need to go into the repository settings.
author_association: CONTRIBUTOR