Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions .github/workflows/build-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand All @@ -44,17 +57,26 @@ 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:
pattern: python-*
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:
Expand Down
66 changes: 65 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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/`.
27 changes: 27 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -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
}
}
}
Loading