From 5983916ec72c2bdd5dc31aef4c1cb5255031b97c Mon Sep 17 00:00:00 2001 From: Martin Koerner Date: Fri, 20 Mar 2026 07:47:23 +0100 Subject: [PATCH 1/3] Fix cache for Windows GitHub actions --- .github/workflows/ci.yml | 32 ++++++++++++++++++++ .github/workflows/ci/skiplist_os_linux.txt | 4 +-- .github/workflows/ci/skiplist_os_macos.txt | 4 +-- .github/workflows/ci/skiplist_os_windows.txt | 4 +-- .github/workflows/ci/workflow_template.yml | 2 ++ 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6affa57f0..546f63000 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,6 +63,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_linux_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_linux_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (macOS) uses: actions/cache@v5 @@ -71,6 +72,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_macos_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_macos_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (Windows) uses: actions/cache@v5 @@ -79,6 +81,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_windows_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_windows_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (Python Latest Supported) uses: actions/cache@v5 @@ -87,6 +90,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_python_latest_supported_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_python_latest_supported_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (Python 3.12) uses: actions/cache@v5 @@ -95,6 +99,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_python_312_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_python_312_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (Python 3.11) uses: actions/cache@v5 @@ -103,6 +108,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_python_311_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_python_311_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (Python 3.10) uses: actions/cache@v5 @@ -111,6 +117,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_python_310_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_python_310_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (Qt GUI) uses: actions/cache@v5 @@ -119,6 +126,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_qt_gui_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_qt_gui_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (Packaging) uses: actions/cache@v5 @@ -127,6 +135,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_packaging_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_packaging_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Test (Code Quality) uses: actions/cache@v5 @@ -135,6 +144,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.test_code_quality_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.test_code_quality_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Build (Linux) uses: actions/cache@v5 @@ -143,6 +153,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.build_linux_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.build_linux_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Build (macOS App) uses: actions/cache@v5 @@ -151,6 +162,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.build_macos_app_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.build_macos_app_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Notarize (macOS App) uses: actions/cache@v5 @@ -159,6 +171,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.notarize_macos_app_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.notarize_macos_app_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Build (macOS DMG) uses: actions/cache@v5 @@ -167,6 +180,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.build_macos_dmg_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.build_macos_dmg_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Notarize (macOS DMG) uses: actions/cache@v5 @@ -175,6 +189,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.notarize_macos_dmg_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.notarize_macos_dmg_skip_cache_key }} + enableCrossOsArchive: true - name: Check skip cache for Build (Windows) uses: actions/cache@v5 @@ -183,6 +198,7 @@ jobs: key: 0_check_${{ steps.set_cache.outputs.build_windows_skip_cache_key }}_${{ github.run_id }} restore-keys: 0_${{ steps.set_cache.outputs.build_windows_skip_cache_key }} + enableCrossOsArchive: true - name: Set outputs id: set_ouputs @@ -293,6 +309,7 @@ jobs: with: path: .skip_cache_test_linux key: 0_${{ needs.analyze.outputs.test_linux_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_linux'" @@ -346,6 +363,7 @@ jobs: with: path: .skip_cache_test_macos key: 0_${{ needs.analyze.outputs.test_macos_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_macos'" @@ -405,6 +423,7 @@ jobs: with: path: .skip_cache_test_windows key: 0_${{ needs.analyze.outputs.test_windows_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_windows'" @@ -463,6 +482,7 @@ jobs: with: path: .skip_cache_test_python_latest_supported key: 0_${{ needs.analyze.outputs.test_python_latest_supported_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_python_latest_supported'" @@ -521,6 +541,7 @@ jobs: with: path: .skip_cache_test_python_312 key: 0_${{ needs.analyze.outputs.test_python_312_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_python_312'" @@ -579,6 +600,7 @@ jobs: with: path: .skip_cache_test_python_311 key: 0_${{ needs.analyze.outputs.test_python_311_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_python_311'" @@ -637,6 +659,7 @@ jobs: with: path: .skip_cache_test_python_310 key: 0_${{ needs.analyze.outputs.test_python_310_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_python_310'" @@ -697,6 +720,7 @@ jobs: with: path: .skip_cache_test_qt_gui key: 0_${{ needs.analyze.outputs.test_qt_gui_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_qt_gui'" @@ -788,6 +812,7 @@ jobs: with: path: .skip_cache_test_packaging key: 0_${{ needs.analyze.outputs.test_packaging_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_packaging'" @@ -847,6 +872,7 @@ jobs: with: path: .skip_cache_test_code_quality key: 0_${{ needs.analyze.outputs.test_code_quality_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_test_code_quality'" @@ -918,6 +944,7 @@ jobs: with: path: .skip_cache_build_linux key: 0_${{ needs.analyze.outputs.build_linux_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_build_linux'" @@ -990,6 +1017,7 @@ jobs: with: path: .skip_cache_build_macos_app key: 0_${{ needs.analyze.outputs.build_macos_app_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_build_macos_app'" @@ -1085,6 +1113,7 @@ jobs: with: path: .skip_cache_notarize_macos_app key: 0_${{ needs.analyze.outputs.notarize_macos_app_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_notarize_macos_app'" @@ -1170,6 +1199,7 @@ jobs: with: path: .skip_cache_build_macos_dmg key: 0_${{ needs.analyze.outputs.build_macos_dmg_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_build_macos_dmg'" @@ -1256,6 +1286,7 @@ jobs: with: path: .skip_cache_notarize_macos_dmg key: 0_${{ needs.analyze.outputs.notarize_macos_dmg_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_notarize_macos_dmg'" @@ -1338,6 +1369,7 @@ jobs: with: path: .skip_cache_build_windows key: 0_${{ needs.analyze.outputs.build_windows_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'.skip_cache_build_windows'" diff --git a/.github/workflows/ci/skiplist_os_linux.txt b/.github/workflows/ci/skiplist_os_linux.txt index 3d82cce45..a6bb5aedc 100644 --- a/.github/workflows/ci/skiplist_os_linux.txt +++ b/.github/workflows/ci/skiplist_os_linux.txt @@ -1,5 +1,5 @@ -.github/workflows/ci/skiplist_os_Windows.txt -.github/workflows/ci/skiplist_os_macOS.txt +.github/workflows/ci/skiplist_os_windows.txt +.github/workflows/ci/skiplist_os_macos.txt osx/* plover/oslayer/osx/* plover/oslayer/windows/* diff --git a/.github/workflows/ci/skiplist_os_macos.txt b/.github/workflows/ci/skiplist_os_macos.txt index f71f08207..3b683e5bf 100644 --- a/.github/workflows/ci/skiplist_os_macos.txt +++ b/.github/workflows/ci/skiplist_os_macos.txt @@ -1,5 +1,5 @@ -.github/workflows/ci/skiplist_os_Linux.txt -.github/workflows/ci/skiplist_os_Windows.txt +.github/workflows/ci/skiplist_os_linux.txt +.github/workflows/ci/skiplist_os_windows.txt linux/* plover/oslayer/linux/* plover/oslayer/windows/* diff --git a/.github/workflows/ci/skiplist_os_windows.txt b/.github/workflows/ci/skiplist_os_windows.txt index 5c1363214..fa93cf8b5 100644 --- a/.github/workflows/ci/skiplist_os_windows.txt +++ b/.github/workflows/ci/skiplist_os_windows.txt @@ -1,5 +1,5 @@ -.github/workflows/ci/skiplist_os_Linux.txt -.github/workflows/ci/skiplist_os_macOS.txt +.github/workflows/ci/skiplist_os_linux.txt +.github/workflows/ci/skiplist_os_macos.txt linux/* osx/* plover/oslayer/linux/* diff --git a/.github/workflows/ci/workflow_template.yml b/.github/workflows/ci/workflow_template.yml index 714dbe848..a3f0f24e1 100644 --- a/.github/workflows/ci/workflow_template.yml +++ b/.github/workflows/ci/workflow_template.yml @@ -47,6 +47,7 @@ jobs: key: <@ cache_epoch @>_check_${{ steps.set_cache.outputs.<@ j.id @>_skip_cache_key }}_${{ github.run_id }} restore-keys: <@ cache_epoch @>_${{ steps.set_cache.outputs.<@ j.id @>_skip_cache_key }} + enableCrossOsArchive: true <% endfor %> <% endif %> @@ -393,6 +394,7 @@ jobs: with: path: <@ j.skip_cache_path @> key: <@ cache_epoch @>_${{ needs.analyze.outputs.<@ j.id @>_skip_cache_key }} + enableCrossOsArchive: true - name: Update skip cache 2 run: run_eval "echo 'https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID' >'<@ j.skip_cache_path @>'" From 704d5b1a7324a6d16a2b26fe6016f1f1f4db900e Mon Sep 17 00:00:00 2001 From: Martin Koerner Date: Fri, 20 Mar 2026 07:53:27 +0100 Subject: [PATCH 2/3] Test skip logic From 8271dca25fad5a101455f553f5342d167f4aca7f Mon Sep 17 00:00:00 2001 From: Martin Koerner Date: Fri, 20 Mar 2026 08:22:50 +0100 Subject: [PATCH 3/3] Update CI doc - also to test job skip --- doc/ci.md | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/doc/ci.md b/doc/ci.md index e188cabac..b69b8ea0a 100644 --- a/doc/ci.md +++ b/doc/ci.md @@ -25,15 +25,18 @@ actions), in order to reduce duplications, that file is currently generated: The current workflow consists of: -- 1 pre-processing job: "Analyze", all other jobs depend on it -- 3 "platform tests" jobs: Linux, macOS, and Windows -- 3 "platform build" jobs, again: Linux, macOS and Windows, dependent on their - respective "platform tests" job (so if the `Test (macOS)` job fails, the +- **Analyze**: a pre-processing job, all other jobs depend on it. +- **Platform tests**: jobs for Linux, macOS, and Windows. +- **Qt GUI test**: specifically for testing the Qt interface. +- **Python tests**: for checking compatibility across all supported versions of Python. +- **Code quality**: runs linting and formatting checks. +- **Packaging**: runs a number of packaging related checks. +- **Platform build**: jobs for Linux, macOS and Windows, dependent on their + respective platform tests job (so if the `Test (macOS)` job fails, the `Build (macOS)` job is skipped). -- 1 "packaging" job that run a number of packaging related checks -- 3 "Python tests" jobs: for checking support for older/newer versions of Python - (other than the version currently used for the distributions) -- 1 final, optional, "release" job +- **macOS notarization**: handles code signing and Apple notarization for + the macOS application and disk image. +- **Release**: a final, optional job. ## Analyze job @@ -105,6 +108,22 @@ If the key changes, the cache is cleared/reset, and the Python environment will be recreated, wheel and extra dependencies re-downloaded, etc... +## macOS Notarization + +To ensure that Plover can be run on modern macOS versions without being blocked +by Gatekeeper, the macOS app and DMG are code-signed and notarized by Apple. + +This process involves: +- Importing a Developer ID certificate into a temporary keychain. +- Signing the application bundle and the disk image. +- Submitting the artifacts to Apple's notarization service. +- Stapling the notarization ticket to the artifacts. + +Because this requires access to sensitive credentials, notarization is only +performed for commits on the `main` branch and `maintenance/*` branches. These +jobs are automatically skipped for all other branches and pull requests from forks. + + ## Packaging job This job will run a number of packaging-related checks. See @@ -138,8 +157,4 @@ The release notes are automatically generated from the last release section in ## Limitations -- The artifact upload action [always wraps artifacts in a - zip](https://github.com/actions/upload-artifact/issues/39), - even if they are a single file such as an exe or a dmg. - Artifacts can only be downloaded when logged-in. -- Artifacts are only accessible once all the jobs of a workflow have completed.