diff --git a/.github/workflows/build-python.yml b/.github/workflows/build-python.yml index 28a156a..40a43ac 100644 --- a/.github/workflows/build-python.yml +++ b/.github/workflows/build-python.yml @@ -21,15 +21,28 @@ concurrency: cancel-in-progress: true jobs: + setup: + name: Read build matrix from manifest + runs-on: ubuntu-latest + outputs: + versions: ${{ steps.read.outputs.versions }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + - name: Extract Python versions from manifest.json + id: read + # manifest.json is the single source of truth: it both selects which + # CPython versions are built here and is published as a release asset + # (see publish-release) for serious_python / flet to consume. + run: echo "versions=$(jq -c '[.pythons[].full_version]' manifest.json)" >> "$GITHUB_OUTPUT" + build-matrix: name: Build Python ${{ matrix.python_version }} + needs: setup strategy: fail-fast: false matrix: - python_version: - - 3.12.13 - - 3.13.14 - - 3.14.6 + python_version: ${{ fromJSON(needs.setup.outputs.versions) }} uses: ./.github/workflows/build-python-version.yml with: python_version: ${{ matrix.python_version }} @@ -44,10 +57,14 @@ jobs: # not touch GitHub releases. if: github.event_name == 'workflow_dispatch' && inputs.release_date != '' needs: + - setup - build-matrix permissions: contents: write steps: + - name: Checkout repository + uses: actions/checkout@v6 + - name: Download all build artifacts uses: actions/download-artifact@v8 with: @@ -55,6 +72,11 @@ jobs: path: release-artifacts merge-multiple: true + - name: Add runtime manifest (with release date) to the release + # Publish the same manifest.json that drove this build, with the release + # date injected, so consumers can fetch a consistent version set by date. + run: jq '.release = "${{ inputs.release_date }}"' manifest.json > release-artifacts/manifest.json + - name: Publish all artifacts to release uses: softprops/action-gh-release@v3 with: diff --git a/README.md b/README.md index ec7f0c6..a2193fc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,66 @@ # python-build -Building Python for Android and iOS + +Builds the embedded CPython runtimes (Android, iOS, macOS, Linux, Windows) that +[serious_python](https://github.com/flet-dev/serious-python) and +[flet](https://github.com/flet-dev/flet) bundle into apps. + +## `manifest.json` — the runtime source of truth + +[`manifest.json`](manifest.json) is the single source of truth for a runtime +release. It is used **both** ways: + +- **Drives the build.** CI reads it to decide which CPython versions to build + (the build matrix), so what gets built is exactly what the manifest lists. +- **Is published.** Each release uploads the same `manifest.json` as a release + asset (with the `release` date injected), so downstream tools fetch a single, + consistent version set by date instead of hand-mirroring versions. + +Schema: + +```json +{ + "release": "20260611", // injected at publish (= release tag) + "default_python_version": "3.14", + "dart_bridge_version": "1.2.3", + "pythons": { + "3.14": { + "full_version": "3.14.6", + "standalone_release_date": "20260610", + "pyodide_version": "314.0.0", + "pyodide_platform_tag": "pyemscripten-2026.0-wasm32", + "prerelease": false + } + } +} +``` + +The committed file omits `release`; the publish step injects it. + +### Adding or bumping a Python / Pyodide / dart_bridge version + +Edit [`manifest.json`](manifest.json) and open a PR. The CI matrix updates +automatically from it; per-version build specifics (ABIs, the 3.12 vs 3.13+ build +method) live in the platform build scripts. + +## Releases + +Releases are date-keyed (`YYYYMMDD`) and cut manually: + +1. Run the **Build Python Packages** workflow via `workflow_dispatch` with a + `release_date` of `YYYYMMDD`. +2. CI builds every Python in the manifest matrix, then publishes all per-platform + tarballs **and** `manifest.json` (with `release` set) to a GitHub release tagged + with that date. + +A push without a `release_date` still exercises the full matrix but publishes no +release (per-job artifacts only). + +## Consumers + +- **serious_python** pins a release date, fetches that release's `manifest.json`, + and generates committed per-platform version tables from it. +- **flet** fetches the manifest by date for commands that run without serious_python + (e.g. `flet publish`). + +See platform-specific notes under [`android/`](android/README.md), +[`darwin/`](darwin/README.rst), `linux/`, and `windows/`. diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..4b2117b --- /dev/null +++ b/manifest.json @@ -0,0 +1,27 @@ +{ + "default_python_version": "3.14", + "dart_bridge_version": "1.2.3", + "pythons": { + "3.12": { + "full_version": "3.12.13", + "standalone_release_date": "20260610", + "pyodide_version": "0.27.7", + "pyodide_platform_tag": "pyodide-2024.0-wasm32", + "prerelease": false + }, + "3.13": { + "full_version": "3.13.14", + "standalone_release_date": "20260610", + "pyodide_version": "0.29.4", + "pyodide_platform_tag": "pyemscripten-2025.0-wasm32", + "prerelease": false + }, + "3.14": { + "full_version": "3.14.6", + "standalone_release_date": "20260610", + "pyodide_version": "314.0.0", + "pyodide_platform_tag": "pyemscripten-2026.0-wasm32", + "prerelease": false + } + } +}