From 8f729764b33b178c967502ebed5ff790c81398f1 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 2 Jul 2026 10:20:06 +0800 Subject: [PATCH 01/13] Allow for using a non-framework Python library. --- cookiecutter.json | 1 + .../{{ cookiecutter.class_name }}/main.m | 8 ++ .../project.pbxproj | 87 ++++++++++++++++++- 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/cookiecutter.json b/cookiecutter.json index 6831353..b978087 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -16,6 +16,7 @@ "universal_build": true, "host_arch": "arm64", "min_os_version": "11.0", + "use_framework": true, "_extensions": [ "briefcase.integrations.cookiecutter.PythonVersionExtension", "briefcase.integrations.cookiecutter.PListExtension" diff --git a/{{ cookiecutter.format }}/{{ cookiecutter.class_name }}/main.m b/{{ cookiecutter.format }}/{{ cookiecutter.class_name }}/main.m index 7120d66..79301c2 100644 --- a/{{ cookiecutter.format }}/{{ cookiecutter.class_name }}/main.m +++ b/{{ cookiecutter.format }}/{{ cookiecutter.class_name }}/main.m @@ -5,7 +5,11 @@ #import #import #import +{%- if cookiecutter.use_framework %} #import +{%- else %} +#import +{%- endif %} #include #include #include @@ -96,7 +100,11 @@ int main(int argc, char *argv[]) { // Set the home for the Python interpreter python_tag = @"{{ cookiecutter.python_version|py_tag }}"; +{%- if cookiecutter.use_framework %} python_home = [NSString stringWithFormat:@"%@/Python.framework/Versions/%@", frameworksPath, python_tag, nil]; +{%- else %} + python_home = [NSString stringWithFormat:@"%@/python/", resourcePath, nil]; +{%- endif %} debug_log(@"PythonHome: %@", python_home); wtmp_str = Py_DecodeLocale([python_home UTF8String], NULL); status = PyConfig_SetString(&config, &config.home, wtmp_str); diff --git a/{{ cookiecutter.format }}/{{ cookiecutter.formal_name }}.xcodeproj/project.pbxproj b/{{ cookiecutter.format }}/{{ cookiecutter.formal_name }}.xcodeproj/project.pbxproj index 7e39d34..1bbea80 100644 --- a/{{ cookiecutter.format }}/{{ cookiecutter.formal_name }}.xcodeproj/project.pbxproj +++ b/{{ cookiecutter.format }}/{{ cookiecutter.formal_name }}.xcodeproj/project.pbxproj @@ -14,8 +14,12 @@ 0D354FEF2551C249009178D1 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D354FEE2551C249009178D1 /* Cocoa.framework */; }; 0D7B44A82555E01500CBC44B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D7B44A72555E01500CBC44B /* Foundation.framework */; }; 0D7B44DA2556C84100CBC44B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D354FD72551BFBD009178D1 /* main.m */; }; +{%- if cookiecutter.use_framework %} 6060E7722AF0B40500C04AE0 /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6060E76F2AF0B14D00C04AE0 /* Python.xcframework */; }; 6060E7732AF0B40500C04AE0 /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6060E76F2AF0B14D00C04AE0 /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; +{%- else %} + AA0000022AF0B40500C04AE0 /* libpython{{ cookiecutter.python_version|py_tag }}.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AA0000012AF0B14D00C04AE0 /* libpython{{ cookiecutter.python_version|py_tag }}.dylib */; }; +{%- endif %} /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -29,6 +33,7 @@ name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; }; +{%- if cookiecutter.use_framework %} 6060E7742AF0B40500C04AE0 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -40,6 +45,7 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; +{%- endif %} /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -53,7 +59,11 @@ 0D354FE52551C1E1009178D1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 0D354FEE2551C249009178D1 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 0D7B44A72555E01500CBC44B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; +{%- if cookiecutter.use_framework %} 6060E76F2AF0B14D00C04AE0 /* Python.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python.xcframework; sourceTree = ""; }; +{%- else %} + AA0000012AF0B14D00C04AE0 /* libpython{{ cookiecutter.python_version|py_tag }}.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpython{{ cookiecutter.python_version|py_tag }}.dylib; path = Python/lib/libpython{{ cookiecutter.python_version|py_tag }}.dylib; sourceTree = ""; }; +{%- endif %} /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,7 +74,11 @@ 0D354FE62551C1E1009178D1 /* AppKit.framework in Frameworks */, 0D354FEF2551C249009178D1 /* Cocoa.framework in Frameworks */, 0D7B44A82555E01500CBC44B /* Foundation.framework in Frameworks */, +{%- if cookiecutter.use_framework %} 6060E7722AF0B40500C04AE0 /* Python.xcframework in Frameworks */, +{%- else %} + AA0000022AF0B40500C04AE0 /* libpython{{ cookiecutter.python_version|py_tag }}.dylib in Frameworks */, +{%- endif %} ); runOnlyForDeploymentPostprocessing = 0; }; @@ -115,7 +129,11 @@ 60A04BBB28AF5E1000DAA9E5 /* Support */ = { isa = PBXGroup; children = ( +{%- if cookiecutter.use_framework %} 6060E76F2AF0B14D00C04AE0 /* Python.xcframework */, +{%- else %} + AA0000012AF0B14D00C04AE0 /* libpython{{ cookiecutter.python_version|py_tag }}.dylib */, +{%- endif %} ); path = Support; sourceTree = ""; @@ -131,7 +149,11 @@ 0D354FC52551BFBA009178D1 /* Frameworks */, 0D354FC62551BFBA009178D1 /* Resources */, 0D7B44EB2556C8B800CBC44B /* Embed Foundation Extensions */, +{%- if cookiecutter.use_framework %} 6060E7742AF0B40500C04AE0 /* Embed Frameworks */, +{%- else %} + AA0000032AF0B40500C04AE0 /* Embed Python lib */, +{%- endif %} 60A04BC128AF640400DAA9E5 /* Sign Python Binary Modules */, ); buildRules = ( @@ -150,7 +172,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1540; + LastUpgradeCheck = 2660; ORGANIZATIONNAME = "{{ cookiecutter.author }}"; TargetAttributes = { 0D354FC72551BFBA009178D1 = { @@ -190,6 +212,27 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ +{%- if not cookiecutter.use_framework %} + AA0000032AF0B40500C04AE0 /* Embed Python lib */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Embed Python lib"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\nDEST=\"$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/python\"\necho \"Embedding Python lib into $DEST\"\nmkdir -p \"$DEST\"\n# Copy the entire lib/ tree, preserving symlinks. Exclude static archives\n# and pkgconfig metadata that are not needed at runtime.\nrsync -a --delete --copy-unsafe-links \\\n --exclude='*.a' \\\n --exclude='pkgconfig' \\\n \"$PROJECT_DIR/Support/Python/lib/\" \"$DEST/lib/\"\n"; + }; +{%- endif %} 60A04BC128AF640400DAA9E5 /* Sign Python Binary Modules */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -286,6 +329,7 @@ ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "{{ cookiecutter.formal_name }}"; SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; }; name = Debug; }; @@ -345,6 +389,7 @@ MTL_FAST_MATH = YES; PRODUCT_NAME = "{{ cookiecutter.formal_name }}"; SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; }; name = Release; }; @@ -363,17 +408,37 @@ COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; ENABLE_HARDENED_RUNTIME = YES; +{%- if cookiecutter.use_framework %} FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(PROJECT_DIR)/Support\"", ); +{%- else %} + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; +{%- endif %} GCC_C_LANGUAGE_STANDARD = gnu99; +{%- if cookiecutter.use_framework %} HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; +{%- else %} + HEADER_SEARCH_PATHS = "\"$(PROJECT_DIR)/Support/Python/include/python{{ cookiecutter.python_version|py_tag }}\""; +{%- endif %} INFOPLIST_FILE = "{{ cookiecutter.class_name }}/Info.plist"; +{%- if cookiecutter.use_framework %} LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); +{%- else %} + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../Resources/python/lib", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(PROJECT_DIR)/Support/Python/lib\"", + ); +{%- endif %} MACOSX_DEPLOYMENT_TARGET = {{ cookiecutter.min_os_version }}; PRODUCT_BUNDLE_IDENTIFIER = "{{ cookiecutter.bundle }}.{{ cookiecutter.app_name }}"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -396,17 +461,37 @@ DEAD_CODE_STRIPPING = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_TESTABILITY = YES; +{%- if cookiecutter.use_framework %} FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(PROJECT_DIR)/Support\"", ); +{%- else %} + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; +{%- endif %} GCC_C_LANGUAGE_STANDARD = gnu99; +{%- if cookiecutter.use_framework %} HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; +{%- else %} + HEADER_SEARCH_PATHS = "\"$(PROJECT_DIR)/Support/Python/include/python{{ cookiecutter.python_version|py_tag }}\""; +{%- endif %} INFOPLIST_FILE = "{{ cookiecutter.class_name }}/Info.plist"; +{%- if cookiecutter.use_framework %} LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); +{%- else %} + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../Resources/python/lib", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(PROJECT_DIR)/Support/Python/lib\"", + ); +{%- endif %} MACOSX_DEPLOYMENT_TARGET = {{ cookiecutter.min_os_version }}; PRODUCT_BUNDLE_IDENTIFIER = "{{ cookiecutter.bundle }}.{{ cookiecutter.app_name }}"; }; From 7cadcf29d50bd5df5c4033bc0556f50fc068f2d1 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 09:49:16 +0800 Subject: [PATCH 02/13] Add workflow to build non-framework binaries. --- .github/workflows/update-binary.yml | 38 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index 25cae37..5c4e4a9 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -11,6 +11,7 @@ jobs: strategy: matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] + framework: [true, false] outputs: BUILD_NUMBER: ${{ steps.build-vars.outputs.BUILD_NUMBER }} @@ -22,39 +23,52 @@ jobs: run: | export BUILD_NUMBER=$(basename $TAG_NAME) export PYTHON_TAG=$(python -c "print('${{ matrix.python-version }}'.split('-')[0])") + export STUB_PREFIX=${{ matrix.framework && "L" else "" }} echo "PYTHON_TAG=${PYTHON_TAG}" | tee -a $GITHUB_ENV echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a $GITHUB_ENV + echo "STUB_PREFIX=${STUB_PREFIX}" | tee -a $GITHUB_ENV - name: Checkout Template uses: actions/checkout@v6.0.3 - name: Setup Python ${{ matrix.python-version }} + if: ${{ matrix.framework }} uses: actions/setup-python@v6.2.0 with: python-version: ${{ matrix.python-version }} allow-prereleases: true + - name: Setup Miniconda + if: ${{ !matrix.framework }} + uses: conda-incubator/setup-miniconda@v3 + with: + python-version: ${{ matrix.python-version }} + auto-update-conda: true + activate-environment: briefcase-env + - name: Install Dependencies run: | python -m pip install --upgrade pip - python -m pip install git+https://github.com/beeware/briefcase.git + # TEMP: use the WIP branch to build + python -m pip install git+https://github.com/freakboy3742/briefcase.git@alt-env-support - name: Generate Xcode App Template run: | # Generate the stub app cd stub + briefcase create macOS Xcode -C env_manager=${{ !matrix.framework && "conda" || "pip" }} briefcase build macOS Xcode - echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} console stub artefact" - mv "./build/console-stub/macos/xcode/build/Release/Console Stub.app/Contents/MacOS/Console Stub" Stub - codesign --remove-signature Stub - zip Console-Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip Stub + echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && "non-framework" || "framework" }} console stub artefact" + mv "./build/console-stub/macos/xcode/build/Release/Console Stub.app/Contents/MacOS/Console Stub" ${{ env.STUB_PREFIX }}Stub + codesign --remove-signature ${{ env.STUB_PREFIX }}Stub + zip Console-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip ${{ env.STUB_PREFIX }}Stub - echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} GUI stub artefact" - mv "./build/gui-stub/macos/xcode/build/Release/GUI Stub.app/Contents/MacOS/GUI Stub" Stub - codesign --remove-signature Stub - zip GUI-Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip Stub + echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && "non-framework" || "framework" }} GUI stub artefact" + mv "./build/gui-stub/macos/xcode/build/Release/GUI Stub.app/Contents/MacOS/GUI Stub" ${{ env.STUB_PREFIX }}Stub + codesign --remove-signature ${{ env.STUB_PREFIX }}Stub + zip GUI-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip ${{ env.STUB_PREFIX }}Stub echo "Stub binaries:" ls -1 *.zip @@ -62,7 +76,7 @@ jobs: - name: Upload build artefacts uses: actions/upload-artifact@v7.0.1 with: - name: ${{ env.PYTHON_TAG }}-stubs + name: ${{ env.PYTHON_TAG }}-${{ env.STUB_PREFIX }}Stubs path: stub/*.zip - name: Upload Release Asset to S3 @@ -74,8 +88,8 @@ jobs: python -m pip install -U setuptools python -m pip install awscli - aws s3 cp stub/Console-Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip s3://briefcase-support/python/${{ env.PYTHON_TAG }}/macOS/Console-Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip - aws s3 cp stub/GUI-Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip s3://briefcase-support/python/${{ env.PYTHON_TAG }}/macOS/GUI-Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip + aws s3 cp stub/Console-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip s3://briefcase-support/python/${{ env.PYTHON_TAG }}/macOS/Console-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip + aws s3 cp stub/GUI-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip s3://briefcase-support/python/${{ env.PYTHON_TAG }}/macOS/GUI-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip make-release: name: Make Release From 1347daca79f8ec09e3ad8576dbf2d9464e7dbe59 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 09:55:11 +0800 Subject: [PATCH 03/13] Correct matrix variable usage. --- .github/workflows/update-binary.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index 5c4e4a9..057fe08 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -23,7 +23,7 @@ jobs: run: | export BUILD_NUMBER=$(basename $TAG_NAME) export PYTHON_TAG=$(python -c "print('${{ matrix.python-version }}'.split('-')[0])") - export STUB_PREFIX=${{ matrix.framework && "L" else "" }} + export STUB_PREFIX=${{ matrix.framework && 'L' || '' }} echo "PYTHON_TAG=${PYTHON_TAG}" | tee -a $GITHUB_ENV echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a $GITHUB_ENV @@ -57,15 +57,15 @@ jobs: run: | # Generate the stub app cd stub - briefcase create macOS Xcode -C env_manager=${{ !matrix.framework && "conda" || "pip" }} + briefcase create macOS Xcode -C env_manager=${{ !matrix.framework && 'conda' || 'pip' }} briefcase build macOS Xcode - echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && "non-framework" || "framework" }} console stub artefact" + echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && 'non-framework' || 'framework' }} console stub artefact" mv "./build/console-stub/macos/xcode/build/Release/Console Stub.app/Contents/MacOS/Console Stub" ${{ env.STUB_PREFIX }}Stub codesign --remove-signature ${{ env.STUB_PREFIX }}Stub zip Console-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip ${{ env.STUB_PREFIX }}Stub - echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && "non-framework" || "framework" }} GUI stub artefact" + echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && 'non-framework' || 'framework' }} GUI stub artefact" mv "./build/gui-stub/macos/xcode/build/Release/GUI Stub.app/Contents/MacOS/GUI Stub" ${{ env.STUB_PREFIX }}Stub codesign --remove-signature ${{ env.STUB_PREFIX }}Stub zip GUI-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip ${{ env.STUB_PREFIX }}Stub From 1453ceaeb5dc6d1dcf4341069621bd88cf4f14e2 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 10:08:42 +0800 Subject: [PATCH 04/13] Add quotes to config value. --- .github/workflows/update-binary.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index 057fe08..6b00afe 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -57,7 +57,7 @@ jobs: run: | # Generate the stub app cd stub - briefcase create macOS Xcode -C env_manager=${{ !matrix.framework && 'conda' || 'pip' }} + briefcase create macOS Xcode -C env_manager=\"${{ !matrix.framework && 'conda' || 'pip' }}\" briefcase build macOS Xcode echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && 'non-framework' || 'framework' }} console stub artefact" From 730d781b8c2d380d66f62cf82fce52e36af726f7 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 10:08:56 +0800 Subject: [PATCH 05/13] Shorten description. --- stub/pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stub/pyproject.toml b/stub/pyproject.toml index 2ea0289..af1f818 100644 --- a/stub/pyproject.toml +++ b/stub/pyproject.toml @@ -10,11 +10,11 @@ template = ".." [tool.briefcase.app.gui-stub] formal_name = "GUI Stub" -description = "A stub binary for GUI apps that can be integrated into the macOS app template" +description = "A stub binary for macOS GUI apps" sources = ['src/gui_stub'] [tool.briefcase.app.console-stub] formal_name = "Console Stub" -description = "A stub binary for console apps that can be integrated into the macOS app template" +description = "A stub binary for macOS console apps" sources = ['src/console_stub'] console_app = true From a89e3d0780912bfb11cebb6b11f601f9668e696b Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 10:09:34 +0800 Subject: [PATCH 06/13] Disable fail-fast on build matrix. --- .github/workflows/update-binary.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index 6b00afe..17429ee 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -9,6 +9,7 @@ jobs: name: Build stub binaries runs-on: macos-26 strategy: + fail-fast: false matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] framework: [true, false] From 4bb6fb80916c6778d988b0fb007262aa21cc93b5 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 10:18:33 +0800 Subject: [PATCH 07/13] Use separate create paths. --- .github/workflows/update-binary.yml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index 17429ee..fdd4116 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -24,7 +24,7 @@ jobs: run: | export BUILD_NUMBER=$(basename $TAG_NAME) export PYTHON_TAG=$(python -c "print('${{ matrix.python-version }}'.split('-')[0])") - export STUB_PREFIX=${{ matrix.framework && 'L' || '' }} + export STUB_PREFIX=${{ !matrix.framework && 'L' || '' }} echo "PYTHON_TAG=${PYTHON_TAG}" | tee -a $GITHUB_ENV echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a $GITHUB_ENV @@ -54,11 +54,24 @@ jobs: # TEMP: use the WIP branch to build python -m pip install git+https://github.com/freakboy3742/briefcase.git@alt-env-support - - name: Generate Xcode App Template + - name: Generate Framework stub app + if: ${{ !matrix.framework }} + run: | + # Generate the stub app + cd stub + briefcase create macOS Xcode + + - name: Create Non-framework stub app + if: ${{ !matrix.framework }} + run: | + # Generate the stub app + cd stub + briefcase create macOS Xcode -C env_manager=\"conda\" -C universal_build=false + + - name: Build Stub App run: | # Generate the stub app cd stub - briefcase create macOS Xcode -C env_manager=\"${{ !matrix.framework && 'conda' || 'pip' }}\" briefcase build macOS Xcode echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && 'non-framework' || 'framework' }} console stub artefact" From be1ccc04bd04fdc0789ac8425e1107da89ac5b85 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 10:21:20 +0800 Subject: [PATCH 08/13] Correct logic for create paths --- .github/workflows/update-binary.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index fdd4116..e16bbe7 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -54,8 +54,8 @@ jobs: # TEMP: use the WIP branch to build python -m pip install git+https://github.com/freakboy3742/briefcase.git@alt-env-support - - name: Generate Framework stub app - if: ${{ !matrix.framework }} + - name: Create Framework stub app + if: ${{ matrix.framework }} run: | # Generate the stub app cd stub @@ -70,7 +70,6 @@ jobs: - name: Build Stub App run: | - # Generate the stub app cd stub briefcase build macOS Xcode From c2d30891d545c14f3a44e087539e8c7fbab97c65 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 10:41:33 +0800 Subject: [PATCH 09/13] Only include stub prefix on archive name. --- .github/workflows/update-binary.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index e16bbe7..34f9145 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -74,14 +74,14 @@ jobs: briefcase build macOS Xcode echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && 'non-framework' || 'framework' }} console stub artefact" - mv "./build/console-stub/macos/xcode/build/Release/Console Stub.app/Contents/MacOS/Console Stub" ${{ env.STUB_PREFIX }}Stub - codesign --remove-signature ${{ env.STUB_PREFIX }}Stub - zip Console-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip ${{ env.STUB_PREFIX }}Stub + mv "./build/console-stub/macos/xcode/build/Release/Console Stub.app/Contents/MacOS/Console Stub" Stub + codesign --remove-signature Stub + zip Console-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip Stub echo "Build ${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }} ${{ !matrix.framework && 'non-framework' || 'framework' }} GUI stub artefact" - mv "./build/gui-stub/macos/xcode/build/Release/GUI Stub.app/Contents/MacOS/GUI Stub" ${{ env.STUB_PREFIX }}Stub - codesign --remove-signature ${{ env.STUB_PREFIX }}Stub - zip GUI-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip ${{ env.STUB_PREFIX }}Stub + mv "./build/gui-stub/macos/xcode/build/Release/GUI Stub.app/Contents/MacOS/GUI Stub" Stub + codesign --remove-signature Stub + zip GUI-${{ env.STUB_PREFIX }}Stub-${{ env.PYTHON_TAG }}-${{ env.BUILD_NUMBER }}.zip Stub echo "Stub binaries:" ls -1 *.zip From bb1dd02e8729f8dcb689bc073e7aeacc22aca798 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 13 Jul 2026 11:08:39 +0800 Subject: [PATCH 10/13] Ensure build number is available as an output. --- .github/workflows/update-binary.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index 53ffe79..f12d01a 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -34,6 +34,9 @@ jobs: echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a $GITHUB_ENV echo "STUB_PREFIX=${STUB_PREFIX}" | tee -a $GITHUB_ENV + # Expose BUILD_NUMBER as a step output so it can be consumed as a job output + echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a $GITHUB_OUTPUT + - name: Checkout Template uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: From 9571d7ec772276511ebb88c62de449593e88ec76 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 14 Jul 2026 11:40:39 +0800 Subject: [PATCH 11/13] Bump hashes now that zizmor is enabled upstream. --- .github/workflows/check-pr-template.yml | 2 +- .github/workflows/ci.yml | 6 ++++-- .github/workflows/update-binary.yml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-pr-template.yml b/.github/workflows/check-pr-template.yml index ddf0895..bd2ae75 100644 --- a/.github/workflows/check-pr-template.yml +++ b/.github/workflows/check-pr-template.yml @@ -9,4 +9,4 @@ permissions: {} jobs: check-pr-template: name: Check PR template - uses: beeware/.github/.github/workflows/pr-checklist.yml@43aab4a46c7db630ef1bfe817c120677ffa5548e # main + uses: beeware/.github/.github/workflows/pr-checklist.yml@741cc5a311012ee0ee195938889a337449d01eeb # main diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e2380d..58e03b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,14 +23,16 @@ permissions: {} jobs: pre-commit: name: Pre-commit checks - uses: beeware/.github/.github/workflows/pre-commit-run.yml@43aab4a46c7db630ef1bfe817c120677ffa5548e # main + uses: beeware/.github/.github/workflows/pre-commit-run.yml@741cc5a311012ee0ee195938889a337449d01eeb # main with: pre-commit-source: pre-commit verify-apps: name: Build apps needs: pre-commit - uses: beeware/.github/.github/workflows/app-build-verify.yml@43aab4a46c7db630ef1bfe817c120677ffa5548e # main + uses: beeware/.github/.github/workflows/app-build-verify.yml@741cc5a311012ee0ee195938889a337449d01eeb # main + permissions: + contents: read with: python-version: ${{ matrix.python-version }} runner-os: macos-15 diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index f12d01a..49d0af6 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -115,7 +115,7 @@ jobs: make-release: name: Make Release - runs-on: macOS-latest + runs-on: macos-26 needs: [ build-stubs ] permissions: contents: write From 92c0cca5c59062b2791099874861bdc51eb97a75 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 14 Jul 2026 12:03:38 +0800 Subject: [PATCH 12/13] Simplify permissions. --- .github/workflows/update-binary.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index 49d0af6..2517bff 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -10,8 +10,6 @@ jobs: build-stubs: name: Build stub binaries runs-on: macos-26 - permissions: - contents: read strategy: fail-fast: false matrix: @@ -60,7 +58,7 @@ jobs: - name: Install Dependencies run: | python -m pip install --upgrade pip - # TEMP: use the WIP branch to build + # TODO: use the WIP branch to build until python -m pip install git+https://github.com/freakboy3742/briefcase.git@alt-env-support - name: Create Framework stub app From 0c06671d5c52ab8d24b0638dc1c265ed4da5cd3e Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 14 Jul 2026 12:18:13 +0800 Subject: [PATCH 13/13] More permission tweaks. --- .github/workflows/ci.yml | 2 ++ .github/workflows/update-binary.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58e03b1..d848060 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,8 @@ jobs: pre-commit: name: Pre-commit checks uses: beeware/.github/.github/workflows/pre-commit-run.yml@741cc5a311012ee0ee195938889a337449d01eeb # main + permissions: + contents: read with: pre-commit-source: pre-commit diff --git a/.github/workflows/update-binary.yml b/.github/workflows/update-binary.yml index 2517bff..7da28f4 100644 --- a/.github/workflows/update-binary.yml +++ b/.github/workflows/update-binary.yml @@ -58,7 +58,7 @@ jobs: - name: Install Dependencies run: | python -m pip install --upgrade pip - # TODO: use the WIP branch to build until + # TODO: use the WIP branch to build until the feature is finalized. python -m pip install git+https://github.com/freakboy3742/briefcase.git@alt-env-support - name: Create Framework stub app