From 93462d01072745634f58b44dedee73d9fca1acd4 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 11 Jun 2026 11:58:01 -0700 Subject: [PATCH 1/3] Date-keyed releases (PBS-style): full version in filenames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructures the publish step so that a manually triggered workflow_dispatch with a `release_date` input (YYYYMMDD) produces a single GitHub release tagged by that date, containing every per-platform tarball from every matrix entry. Mirrors what astral-sh/python-build-standalone already does and what we already consume in flet-dev/serious-python's package_command via _release.standaloneReleaseDate. Why move away from one-release-per-python-minor: * Re-cutting a release for a build fix (e.g. the Python.app strip we just landed) currently has to clobber an existing tag, which breaks reproducibility for any downstream that pinned to it. * Several platform fixes in the past month had to wait for a coordinated "all minor versions get a fresh tarball" moment; date tags decouple that — we just cut a new date once everything we care about builds. * Symmetric with how flet-dev/serious-python's package_command resolves its astral-sh CPython tarball: pin a date, not a minor. Changes: * build-python.yml: - workflow_dispatch gains a `release_date` input (YYYYMMDD). - New publish-release job downloads ALL matrix artifacts and publishes one release tagged ${release_date}. - Publish only fires on workflow_dispatch with a non-empty release_date; pushes still exercise the matrix (artifacts left for inspection) but don't touch releases. * build-python-version.yml: - Removed the per-version publish-release job (moved to parent). - Matrix artifact upload names now include the full Python version (e.g. python-darwin-3.14.6 instead of python-darwin-3.14) so the parent workflow can ingest multiple patch versions of the same minor without artifact-name collisions. - Darwin packagers receive the full version directly so their tarball filenames carry it verbatim. * Per-platform packagers (darwin/ios, android, linux, windows): - Tarball/zip filenames switch from $PYTHON_VERSION_SHORT to the full $PYTHON_VERSION (e.g. python-macos-dart-3.14.6.tar.gz). The internal lookups that need the short version derive it inline. - mobile-forge artifacts follow the same naming convention. Consumer side (serious-python's prepare_*.sh, build.gradle, CMakeLists) still needs a follow-up to: - Read a new PYTHON_BUILD_RELEASE (YYYYMMDD) env var instead of using "v$PYTHON_VERSION" as the release tag. - Reference tarballs by full Python version in the URL. - Lay them out as $FLET_CACHE_DIR/python-build//. That migration is independent of this PR and will land separately. --- .github/workflows/build-python-version.yml | 59 ++++++---------------- .github/workflows/build-python.yml | 41 +++++++++++++++ android/package-for-dart.sh | 6 ++- darwin/package-ios-for-dart.sh | 6 ++- linux/package-for-linux.sh | 6 ++- windows/package-for-dart.ps1 | 6 ++- 6 files changed, 73 insertions(+), 51 deletions(-) diff --git a/.github/workflows/build-python-version.yml b/.github/workflows/build-python-version.yml index 57135fe..ca47722 100644 --- a/.github/workflows/build-python-version.yml +++ b/.github/workflows/build-python-version.yml @@ -58,18 +58,23 @@ jobs: # mobile-forge artifact: iOS-only install+support tree (same structure as before). # Captured before the macOS build also writes into ./support / ./install. - tar -czf dist/python-ios-mobile-forge-$PYTHON_VERSION_SHORT.tar.gz install support + tar -czf dist/python-ios-mobile-forge-$PYTHON_VERSION.tar.gz install support # macOS: universal2 framework built from source (all versions). python build_macos.py "$PYTHON_VERSION" - bash ./package-ios-for-dart.sh . "$PYTHON_VERSION_SHORT" - bash ./package-macos-for-dart.sh . "$PYTHON_VERSION_SHORT" + # Package scripts receive the FULL Python version: the tarball name + # carries it verbatim so a date-keyed release can host multiple + # patches of the same minor (e.g. 3.14.5 + 3.14.6) side by side. + # Internal lookups inside the scripts derive the short version + # themselves where they need it. + bash ./package-ios-for-dart.sh . "$PYTHON_VERSION" + bash ./package-macos-for-dart.sh . "$PYTHON_VERSION" - name: Upload Darwin build artifacts uses: actions/upload-artifact@v4 with: - name: python-darwin-${{ env.PYTHON_VERSION_SHORT }} + name: python-darwin-${{ env.PYTHON_VERSION }} path: darwin/dist/python-*.tar.gz if-no-files-found: error @@ -102,7 +107,7 @@ jobs: run: | bash ./build-all.sh "$PYTHON_VERSION" mkdir -p dist - tar -czf dist/python-android-mobile-forge-$PYTHON_VERSION_SHORT.tar.gz install support + tar -czf dist/python-android-mobile-forge-$PYTHON_VERSION.tar.gz install support bash ./package-for-dart.sh install "$PYTHON_VERSION" arm64-v8a bash ./package-for-dart.sh install "$PYTHON_VERSION" x86_64 read version_major version_minor < <(echo "$PYTHON_VERSION" | sed -E 's/^([0-9]+)\.([0-9]+).*/\1 \2/') @@ -122,7 +127,7 @@ jobs: - name: Upload build artifacts uses: actions/upload-artifact@v4 with: - name: python-android-${{ env.PYTHON_VERSION_SHORT }} + name: python-android-${{ env.PYTHON_VERSION }} path: android/dist/python-android-*.tar.gz if-no-files-found: error @@ -155,7 +160,7 @@ jobs: - name: Upload build artifacts uses: actions/upload-artifact@v4 with: - name: python-linux-${{ env.PYTHON_VERSION_SHORT }} + name: python-linux-${{ env.PYTHON_VERSION }} path: linux/python-linux-dart-*.tar.gz if-no-files-found: error @@ -186,42 +191,10 @@ jobs: - name: Upload build artifacts uses: actions/upload-artifact@v4 with: - name: python-windows-${{ env.PYTHON_VERSION_SHORT }} + name: python-windows-${{ env.PYTHON_VERSION }} path: windows/python-windows-for-dart-*.zip if-no-files-found: error - publish-release: - name: Publish Release Assets - runs-on: ubuntu-latest - # Only publish GitHub release assets from the main branch; other branches still - # build (and upload per-job artifacts) but don't touch releases. - if: github.ref == 'refs/heads/main' - needs: - - build-darwin - - build-android - - build-linux - - build-windows - permissions: - contents: write - steps: - - name: Derive short Python version - shell: bash - run: | - echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV" - - - name: Download all build artifacts - uses: actions/download-artifact@v4 - with: - pattern: python-*-${{ env.PYTHON_VERSION_SHORT }} - path: release-artifacts - merge-multiple: true - - - name: Publish all artifacts to release - uses: softprops/action-gh-release@v2 - with: - tag_name: v${{ env.PYTHON_VERSION_SHORT }} - files: release-artifacts/* - fail_on_unmatched_files: true - generate_release_notes: false - draft: false - prerelease: false + # The publish-release job lives in the parent workflow (build-python.yml): + # date-keyed releases collect tarballs from every matrix entry into one + # release, so the publish step has to run after the full matrix completes. diff --git a/.github/workflows/build-python.yml b/.github/workflows/build-python.yml index 746203f..46df25d 100644 --- a/.github/workflows/build-python.yml +++ b/.github/workflows/build-python.yml @@ -4,6 +4,16 @@ on: push: pull_request: workflow_dispatch: + inputs: + release_date: + description: > + Release tag (YYYYMMDD). When set, a single GitHub release with that + tag is created and all per-platform tarballs from every matrix entry + are published as assets. Leave empty for a build-only run that uploads + per-job artifacts but does not publish a release. + required: false + type: string + default: "" # Cancel in-flight runs when a newer event arrives for the same logical branch. concurrency: @@ -24,3 +34,34 @@ jobs: with: python_version: ${{ matrix.python_version }} secrets: inherit + + publish-release: + name: Publish Release Assets + runs-on: ubuntu-latest + # Date-keyed releases (PBS-style): only publish when an operator explicitly + # triggers via workflow_dispatch with a `release_date` input. Pushes still + # exercise the matrix but leave per-job artifacts for inspection and do + # not touch GitHub releases. + if: github.event_name == 'workflow_dispatch' && inputs.release_date != '' + needs: + - build-matrix + permissions: + contents: write + steps: + - name: Download all build artifacts + uses: actions/download-artifact@v4 + with: + pattern: python-* + path: release-artifacts + merge-multiple: true + + - name: Publish all artifacts to release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ inputs.release_date }} + name: ${{ inputs.release_date }} + files: release-artifacts/* + fail_on_unmatched_files: true + generate_release_notes: false + draft: false + prerelease: false diff --git a/android/package-for-dart.sh b/android/package-for-dart.sh index eb100a9..92ac6c1 100755 --- a/android/package-for-dart.sh +++ b/android/package-for-dart.sh @@ -121,5 +121,7 @@ done rm -rf $build_dir/lib -# final archive -tar -czf dist/python-android-dart-$python_version_short-$abi.tar.gz -C $build_dir . +# final archive — filename uses the FULL python version (e.g. 3.14.6, not +# 3.14) so a single date-keyed release can host multiple patches of the +# same minor side by side. +tar -czf dist/python-android-dart-$python_version-$abi.tar.gz -C $build_dir . diff --git a/darwin/package-ios-for-dart.sh b/darwin/package-ios-for-dart.sh index 542d0e0..10d0212 100755 --- a/darwin/package-ios-for-dart.sh +++ b/darwin/package-ios-for-dart.sh @@ -82,5 +82,7 @@ rm -rf __pycache__ rm -rf **/__pycache__ cd - -# final archive -tar -czf dist/python-ios-dart-$python_version_short.tar.gz -C $build_dir . +# final archive — filename uses the FULL python version (e.g. 3.14.6, not +# 3.14) so a single date-keyed release can host multiple patches of the +# same minor side by side. +tar -czf dist/python-ios-dart-$python_version.tar.gz -C $build_dir . diff --git a/linux/package-for-linux.sh b/linux/package-for-linux.sh index 416cc4d..437a50f 100755 --- a/linux/package-for-linux.sh +++ b/linux/package-for-linux.sh @@ -47,5 +47,7 @@ fi mkdir -p $PYTHON_ARCH/dist rsync -av --exclude-from=python-linux-dart.exclude $PYTHON_ARCH/build/python/* $PYTHON_ARCH/dist -# archive -tar -czf "python-linux-dart-$PYTHON_VERSION_SHORT-$PYTHON_ARCH.tar.gz" -C "$PYTHON_ARCH/dist" . +# archive — filename uses the FULL python version (e.g. 3.14.6, not 3.14) +# so a single date-keyed release can host multiple patches of the same +# minor side by side. +tar -czf "python-linux-dart-$PYTHON_VERSION-$PYTHON_ARCH.tar.gz" -C "$PYTHON_ARCH/dist" . diff --git a/windows/package-for-dart.ps1 b/windows/package-for-dart.ps1 index fd81a30..124f286 100644 --- a/windows/package-for-dart.ps1 +++ b/windows/package-for-dart.ps1 @@ -20,8 +20,10 @@ $srcDir = Join-Path $srcRoot "Python-$PythonVersion" $pcbuildDir = Join-Path $srcDir "PCbuild\amd64" $pythonTag = $PythonVersionShort -replace '\.', '' -$packageRoot = Join-Path $workspace "windows\python-windows-for-dart-$PythonVersionShort" -$zipPath = Join-Path $workspace "windows\python-windows-for-dart-$PythonVersionShort.zip" +# Filename uses the FULL python version (e.g. 3.14.6, not 3.14) so a single +# date-keyed release can host multiple patches of the same minor side by side. +$packageRoot = Join-Path $workspace "windows\python-windows-for-dart-$PythonVersion" +$zipPath = Join-Path $workspace "windows\python-windows-for-dart-$PythonVersion.zip" $excludeListPath = Join-Path $workspace "windows\python-windows-dart.exclude" $keepImportLibs = @("python3.lib", "python3_d.lib", "python$pythonTag.lib", "python${pythonTag}_d.lib") From 079d67ee0aec79f2b7a6858ebcd14d86f3c040cd Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 11 Jun 2026 12:06:45 -0700 Subject: [PATCH 2/3] ci: bump actions/{checkout,upload-artifact,download-artifact} v4 -> v5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous releases bundled Node.js 20 runtimes; GitHub deprecated Node 20 in actions on 2026-06-16 with full removal on 2026-09-16, and the workflow now emits a "Node.js 20 actions are deprecated" warning on every matrix entry. v5 ships on Node 24 across all three actions and is otherwise drop-in compatible with our usage. setup-python is already on v6 (Node 24 native). softprops/action-gh- release@v2 still runs on Node 20 — leaving it pending an upstream v3 since it only fires on the new workflow_dispatch publish path and won't add warning noise to push-driven runs. --- .github/workflows/build-python-version.yml | 16 ++++++++-------- .github/workflows/build-python.yml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-python-version.yml b/.github/workflows/build-python-version.yml index ca47722..ed30879 100644 --- a/.github/workflows/build-python-version.yml +++ b/.github/workflows/build-python-version.yml @@ -34,7 +34,7 @@ jobs: runs-on: macos-26 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Derive short Python version shell: bash @@ -72,7 +72,7 @@ jobs: bash ./package-macos-for-dart.sh . "$PYTHON_VERSION" - name: Upload Darwin build artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: python-darwin-${{ env.PYTHON_VERSION }} path: darwin/dist/python-*.tar.gz @@ -83,7 +83,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Derive short Python version shell: bash @@ -125,7 +125,7 @@ jobs: run: python3 -m unittest discover -s android/tests -t android/tests -v - name: Upload build artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: python-android-${{ env.PYTHON_VERSION }} path: android/dist/python-android-*.tar.gz @@ -136,7 +136,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Derive short Python version shell: bash @@ -158,7 +158,7 @@ jobs: bash ./package-for-linux.sh aarch64 "" - name: Upload build artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: python-linux-${{ env.PYTHON_VERSION }} path: linux/python-linux-dart-*.tar.gz @@ -168,7 +168,7 @@ jobs: name: Build Python for Windows runs-on: windows-2022 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Derive short Python version shell: pwsh @@ -189,7 +189,7 @@ jobs: -PythonVersionShort "${{ env.PYTHON_VERSION_SHORT }}" - name: Upload build artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: python-windows-${{ env.PYTHON_VERSION }} path: windows/python-windows-for-dart-*.zip diff --git a/.github/workflows/build-python.yml b/.github/workflows/build-python.yml index 46df25d..4157f94 100644 --- a/.github/workflows/build-python.yml +++ b/.github/workflows/build-python.yml @@ -49,7 +49,7 @@ jobs: contents: write steps: - name: Download all build artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: pattern: python-* path: release-artifacts From 44743b4f3cf3d578daddb23fcadceef3eb55dcf0 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 11 Jun 2026 12:50:09 -0700 Subject: [PATCH 3/3] ci: bump actions to latest majors (Node 24) The earlier v4->v5 bump didn't silence the Node 20 deprecation warnings: actions/upload-artifact@v5 and actions/download-artifact@v5 only have "preliminary" Node 24 support and still default to Node 20. The runtime default flips to Node 24 only at v6+. Move every action to its current latest major (all node24): actions/checkout v5 -> v6 actions/upload-artifact v5 -> v7 actions/download-artifact v5 -> v8 softprops/action-gh-release v2 -> v3 actions/setup-python v6 (already latest, node24) All inputs in use remain supported; artifacts stay zipped so upload v7 / download v8 (direct-upload/decompress changes) and download v8's default digest-mismatch=error don't affect this workflow. --- .github/workflows/build-python-version.yml | 16 ++++++++-------- .github/workflows/build-python.yml | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-python-version.yml b/.github/workflows/build-python-version.yml index ed30879..7bf4568 100644 --- a/.github/workflows/build-python-version.yml +++ b/.github/workflows/build-python-version.yml @@ -34,7 +34,7 @@ jobs: runs-on: macos-26 steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Derive short Python version shell: bash @@ -72,7 +72,7 @@ jobs: bash ./package-macos-for-dart.sh . "$PYTHON_VERSION" - name: Upload Darwin build artifacts - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: python-darwin-${{ env.PYTHON_VERSION }} path: darwin/dist/python-*.tar.gz @@ -83,7 +83,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Derive short Python version shell: bash @@ -125,7 +125,7 @@ jobs: run: python3 -m unittest discover -s android/tests -t android/tests -v - name: Upload build artifacts - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: python-android-${{ env.PYTHON_VERSION }} path: android/dist/python-android-*.tar.gz @@ -136,7 +136,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Derive short Python version shell: bash @@ -158,7 +158,7 @@ jobs: bash ./package-for-linux.sh aarch64 "" - name: Upload build artifacts - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: python-linux-${{ env.PYTHON_VERSION }} path: linux/python-linux-dart-*.tar.gz @@ -168,7 +168,7 @@ jobs: name: Build Python for Windows runs-on: windows-2022 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Derive short Python version shell: pwsh @@ -189,7 +189,7 @@ jobs: -PythonVersionShort "${{ env.PYTHON_VERSION_SHORT }}" - name: Upload build artifacts - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: python-windows-${{ env.PYTHON_VERSION }} path: windows/python-windows-for-dart-*.zip diff --git a/.github/workflows/build-python.yml b/.github/workflows/build-python.yml index 4157f94..28a156a 100644 --- a/.github/workflows/build-python.yml +++ b/.github/workflows/build-python.yml @@ -49,14 +49,14 @@ jobs: contents: write steps: - name: Download all build artifacts - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v8 with: pattern: python-* path: release-artifacts merge-multiple: true - name: Publish all artifacts to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: tag_name: ${{ inputs.release_date }} name: ${{ inputs.release_date }}