Skip to content

ci: pre-clone flet shallowly; surface package-command progress #228

ci: pre-clone flet shallowly; surface package-command progress

ci: pre-clone flet shallowly; surface package-command progress #228

Workflow file for this run

name: CI
on:
push:
branches: ['**']
tags: ['*']
pull_request:
workflow_dispatch:
# Auto-cancel in-flight runs when a new push lands on the same ref.
# Tag builds (refs/tags/*) get a unique-per-run group so release runs
# never cancel each other.
concurrency:
group: ${{ github.workflow }}-${{ startsWith(github.ref, 'refs/tags/') && github.run_id || github.ref }}
cancel-in-progress: true
env:
ROOT: "${{ github.workspace }}"
SCRIPTS: "${{ github.workspace }}/.github/scripts"
SERIOUS_PYTHON_SITE_PACKAGES: "${{ github.workspace }}/site-packages"
UV_PYTHON: "3.12"
# Pin flet so the Python side matches the Dart-side flet version. With
# `--only-binary :all:`, pip would otherwise silently downgrade to an
# older flet whose transitive deps (e.g. msgpack) have wheels for the
# target python_version / platform, leaving the two halves mismatched.
FLET_VERSION: "0.85.3"
# Python flet for the FFI-transport example is pinned to a git ref —
# FletDartBridgeServer isn't on PyPI yet. The git URL is given to pip via
# --requirements, which would normally clone the whole flet repo (large)
# inside pip itself. On Windows this can take 30+ minutes and looks like
# a hang because pip emits no progress during git clone. So the FFI jobs
# first do an explicit `git clone --depth 1` into ${{ runner.temp }}/flet
# and then pass the local subpath as the requirement.
FLET_GIT_REF: "dart-bridge"
FLET_GIT_URL: "https://github.com/flet-dev/flet.git"
# Source installs additionally require SERIOUS_PYTHON_ALLOW_SOURCE_DISTRIBUTIONS=flet
# on mobile targets to bypass --only-binary :all:; see package_command.dart.
jobs:
macos:
name: Test Flet example on macOS (Python ${{ matrix.python_version }})
runs-on: macos-26
# Temporarily disabled — focusing CI on flet_ffi_example while the
# dart_bridge transport stabilises. Flip back on before merging the
# flet PR to confirm the socket transport still works.
if: false
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Run tests
working-directory: "src/serious_python/example/flet_example"
run: |
dart run serious_python:main package app/src --platform Darwin --python-version ${{ matrix.python_version }} --requirements flet==${{ env.FLET_VERSION }}
flutter test integration_test --device-id macos --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
ios:
name: Test Flet example on iOS (Python ${{ matrix.python_version }})
runs-on: macos-26
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
# 3.13/3.14 disabled until msgpack 1.x ships iOS arm64 wheels for
# those Python versions on pypi.flet.dev — with `--only-binary :all:`
# pip otherwise silently downgrades flet to an older version,
# leaving Python/Dart out of sync.
python_version: ['3.12']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Setup iOS Simulator
id: simulator
uses: futureware-tech/simulator-action@v4
with:
# https://github.com/futureware-tech/simulator-action/wiki/Devices-macos-latest
model: 'iPhone 17 Pro Max'
os: "iOS"
os_version: "26.5"
shutdown_after_job: true
wait_for_boot: true
- name: Run tests
working-directory: "src/serious_python/example/flet_example"
run: |
dart run serious_python:main package app/src --platform iOS --python-version ${{ matrix.python_version }} --requirements flet==${{ env.FLET_VERSION }}
flutter test integration_test --device-id ${{ steps.simulator.outputs.udid }} --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
android:
name: Test Flet example on Android (Python ${{ matrix.python_version }})
runs-on: ubuntu-latest
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12'] # see ios job for the 3.13/3.14 gate
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Gradle cache
uses: gradle/actions/setup-gradle@v3
- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd
- name: Setup Android Emulator + Run tests
uses: reactivecircus/android-emulator-runner@v2
env:
EMULATOR_PORT: 5554
with:
avd-name: android_emulator
api-level: 33
target: google_atd
arch: x86_64
profile: pixel_5
sdcard-path-or-size: 128M
ram-size: 2048M
disk-size: 4096M
emulator-port: ${{ env.EMULATOR_PORT }}
disable-animations: true
emulator-options: -no-window -noaudio -no-boot-anim -wipe-data -cache-size 1000 -partition-size 8192
pre-emulator-launch-script: |
sdkmanager --list_installed
script: |
cd src/serious_python/example/flet_example && dart run serious_python:main package app/src --platform Android --python-version ${{ matrix.python_version }} --requirements flet==${{ env.FLET_VERSION }}
cd src/serious_python/example/flet_example && flutter test integration_test --device-id emulator-${{ env.EMULATOR_PORT }} --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
windows:
name: Test Flet example on Windows (Python ${{ matrix.python_version }})
runs-on: windows-latest
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Run tests
working-directory: "src/serious_python/example/flet_example"
run: |
dart run serious_python:main package app/src --platform Windows --python-version ${{ matrix.python_version }} --requirements flet==${{ env.FLET_VERSION }}
flutter test integration_test -d windows --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
linux:
name: Test Flet example on Linux ${{ matrix.title }} (Python ${{ matrix.python_version }})
runs-on: ${{ matrix.runner }}
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
arch: [arm64, amd64]
include:
- arch: arm64
runner: ubuntu-24.04-arm
title: ARM64
- arch: amd64
runner: ubuntu-24.04
title: AMD64
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup uv
uses: astral-sh/setup-uv@v6
- name: Get Flutter version from ".fvmrc"
uses: kuhnroyal/flutter-fvm-config-action/config@v3
id: fvm-config-action
with:
path: '.fvmrc'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }}
channel: ${{ matrix.arch == 'arm64' && 'master' || 'stable' }} # https://github.com/subosito/flutter-action/issues/345#issuecomment-2657332687
cache: true
- name: Install dependencies
run: |
sudo apt-get update --allow-releaseinfo-change
sudo apt-get install -y xvfb libgtk-3-dev
if [ "${{ matrix.arch }}" = "amd64" ]; then
sudo apt-get install -y \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libgstreamer-plugins-bad1.0-dev \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
gstreamer1.0-tools \
gstreamer1.0-x \
gstreamer1.0-alsa \
gstreamer1.0-gl \
gstreamer1.0-gtk3 \
gstreamer1.0-qt5 \
gstreamer1.0-pulseaudio
else
sudo apt-get install -y \
clang \
ninja-build \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav
fi
- name: Run tests
working-directory: src/serious_python/example/flet_example
run: |
flutter pub get
dart run serious_python:main package app/src --platform Linux --python-version ${{ matrix.python_version }} --requirements flet==${{ env.FLET_VERSION }}
xvfb-run flutter test integration_test -d linux --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
flet_ffi_macos:
name: Test Flet FFI example on macOS (Python ${{ matrix.python_version }})
runs-on: macos-26
# Temporarily gated off while we debug the Windows hang — re-enable after.
if: false
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
SERIOUS_PYTHON_ALLOW_SOURCE_DISTRIBUTIONS: flet
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Shallow-clone flet (dart-bridge)
run: |
git clone --depth 1 --branch "${FLET_GIT_REF}" "${FLET_GIT_URL}" "${{ runner.temp }}/flet-src"
- name: Run tests
working-directory: "src/serious_python/example/flet_ffi_example"
run: |
dart run serious_python:main package app/src --platform Darwin --python-version ${{ matrix.python_version }} --requirements "${{ runner.temp }}/flet-src/sdk/python/packages/flet"
flutter test integration_test --device-id macos --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
flet_ffi_ios:
name: Test Flet FFI example on iOS (Python ${{ matrix.python_version }})
runs-on: macos-26
if: false # see `flet_ffi_macos:` rationale
strategy:
fail-fast: false
matrix:
# 3.13/3.14 gated on msgpack iOS arm64 wheels landing on pypi.flet.dev
# — see the flet_example ios job for the same rationale.
python_version: ['3.12']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
SERIOUS_PYTHON_ALLOW_SOURCE_DISTRIBUTIONS: flet
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Setup iOS Simulator
id: simulator
uses: futureware-tech/simulator-action@v4
with:
model: 'iPhone 17 Pro Max'
os: "iOS"
os_version: "26.5"
shutdown_after_job: true
wait_for_boot: true
- name: Shallow-clone flet (dart-bridge)
run: |
git clone --depth 1 --branch "${FLET_GIT_REF}" "${FLET_GIT_URL}" "${{ runner.temp }}/flet-src"
- name: Run tests
working-directory: "src/serious_python/example/flet_ffi_example"
run: |
dart run serious_python:main package app/src --platform iOS --python-version ${{ matrix.python_version }} --requirements "${{ runner.temp }}/flet-src/sdk/python/packages/flet"
flutter test integration_test --device-id ${{ steps.simulator.outputs.udid }} --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
flet_ffi_android:
name: Test Flet FFI example on Android (Python ${{ matrix.python_version }})
runs-on: ubuntu-latest
if: false # see `flet_ffi_macos:` rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12'] # see ios job for the 3.13/3.14 gate
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
SERIOUS_PYTHON_ALLOW_SOURCE_DISTRIBUTIONS: flet
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Gradle cache
uses: gradle/actions/setup-gradle@v3
- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-ffi
- name: Shallow-clone flet (dart-bridge)
run: |
git clone --depth 1 --branch "${FLET_GIT_REF}" "${FLET_GIT_URL}" "${{ runner.temp }}/flet-src"
- name: Setup Android Emulator + Run tests
uses: reactivecircus/android-emulator-runner@v2
env:
EMULATOR_PORT: 5554
with:
avd-name: android_emulator
api-level: 33
target: google_atd
arch: x86_64
profile: pixel_5
sdcard-path-or-size: 128M
ram-size: 2048M
disk-size: 4096M
emulator-port: ${{ env.EMULATOR_PORT }}
disable-animations: true
emulator-options: -no-window -noaudio -no-boot-anim -wipe-data -cache-size 1000 -partition-size 8192
pre-emulator-launch-script: |
sdkmanager --list_installed
script: |
cd src/serious_python/example/flet_ffi_example && dart run serious_python:main package app/src --platform Android --python-version ${{ matrix.python_version }} --requirements "${{ runner.temp }}/flet-src/sdk/python/packages/flet"
cd src/serious_python/example/flet_ffi_example && flutter test integration_test --device-id emulator-${{ env.EMULATOR_PORT }} --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
flet_ffi_windows:
name: Test Flet FFI example on Windows (Python ${{ matrix.python_version }})
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
SERIOUS_PYTHON_ALLOW_SOURCE_DISTRIBUTIONS: flet
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Shallow-clone flet (dart-bridge)
shell: bash
run: |
git clone --depth 1 --branch "${FLET_GIT_REF}" "${FLET_GIT_URL}" "${RUNNER_TEMP}/flet-src"
- name: Run tests
working-directory: "src/serious_python/example/flet_ffi_example"
shell: bash
run: |
dart run serious_python:main package app/src --platform Windows --python-version ${{ matrix.python_version }} --requirements "${RUNNER_TEMP}/flet-src/sdk/python/packages/flet"
flutter test integration_test -d windows --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
flet_ffi_linux:
name: Test Flet FFI example on Linux ${{ matrix.title }} (Python ${{ matrix.python_version }})
runs-on: ${{ matrix.runner }}
if: false # see `flet_ffi_macos:` rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
arch: [arm64, amd64]
include:
- arch: arm64
runner: ubuntu-24.04-arm
title: ARM64
- arch: amd64
runner: ubuntu-24.04
title: AMD64
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
SERIOUS_PYTHON_ALLOW_SOURCE_DISTRIBUTIONS: flet
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup uv
uses: astral-sh/setup-uv@v6
- name: Get Flutter version from ".fvmrc"
uses: kuhnroyal/flutter-fvm-config-action/config@v3
id: fvm-config-action
with:
path: '.fvmrc'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }}
channel: ${{ matrix.arch == 'arm64' && 'master' || 'stable' }}
cache: true
- name: Install dependencies
run: |
sudo apt-get update --allow-releaseinfo-change
sudo apt-get install -y xvfb libgtk-3-dev
if [ "${{ matrix.arch }}" = "amd64" ]; then
sudo apt-get install -y \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libgstreamer-plugins-bad1.0-dev \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
gstreamer1.0-tools \
gstreamer1.0-x \
gstreamer1.0-alsa \
gstreamer1.0-gl \
gstreamer1.0-gtk3 \
gstreamer1.0-qt5 \
gstreamer1.0-pulseaudio
else
sudo apt-get install -y \
clang \
ninja-build \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav
fi
- name: Shallow-clone flet (dart-bridge)
run: |
git clone --depth 1 --branch "${FLET_GIT_REF}" "${FLET_GIT_URL}" "${{ runner.temp }}/flet-src"
- name: Run tests
working-directory: src/serious_python/example/flet_ffi_example
run: |
flutter pub get
dart run serious_python:main package app/src --platform Linux --python-version ${{ matrix.python_version }} --requirements "${{ runner.temp }}/flet-src/sdk/python/packages/flet"
xvfb-run flutter test integration_test -d linux --dart-define=EXPECTED_PYTHON_VERSION=${{ matrix.python_version }}
bridge_example_macos:
name: Test Bridge example on macOS (Python ${{ matrix.python_version }})
runs-on: macos-26
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Package + run integration test
working-directory: "src/serious_python/example/bridge_example"
run: |
dart run serious_python:main package app/src --platform Darwin --python-version ${{ matrix.python_version }}
flutter test integration_test -d macos
bridge_example_ios:
name: Test Bridge example on iOS (Python ${{ matrix.python_version }})
runs-on: macos-26
timeout-minutes: 25
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
# serious_python_darwin's prepare_ios.sh downloads python-ios-dart-<ver>.tar.gz
# (~100MB) into src/serious_python_darwin/darwin/dist_ios/ and skips the
# download if the directory already exists. Cache it so reruns and
# subsequent matrix jobs don't re-fetch from GitHub Releases.
- name: Cache iOS Python framework
uses: actions/cache@v4
with:
path: src/serious_python_darwin/darwin/dist_ios
key: ios-python-dist-${{ matrix.python_version }}-v2
- name: Setup iOS Simulator
id: simulator
uses: futureware-tech/simulator-action@v4
with:
model: 'iPhone 17 Pro Max'
os: "iOS"
os_version: "26.5"
shutdown_after_job: true
wait_for_boot: true
- name: Package + run integration test
working-directory: "src/serious_python/example/bridge_example"
run: |
ts() { date '+%H:%M:%S'; }
echo "[$(ts)] >>> dart run serious_python:main package"
# certifi is a placeholder requirement: serious_python_darwin's
# sync_site_packages.sh only populates dist_ios/site-xcframeworks
# (which bundle-python-frameworks-ios.sh then requires at build
# time) when iOS-specific site-packages subdirs exist. Empty
# --requirements skips that branch and the build fails.
dart run serious_python:main package app/src --platform iOS --python-version ${{ matrix.python_version }} --requirements certifi
echo "[$(ts)] >>> flutter test integration_test"
flutter test integration_test --device-id ${{ steps.simulator.outputs.udid }}
echo "[$(ts)] >>> done"
bridge_example_android:
name: Test Bridge example on Android (Python ${{ matrix.python_version }})
runs-on: ubuntu-latest
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
# x86_64 matches the emulator architecture; only build/install for
# that ABI to keep CI fast.
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Gradle cache
uses: gradle/actions/setup-gradle@v3
- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-bridge
- name: Setup Android Emulator + Run tests
uses: reactivecircus/android-emulator-runner@v2
env:
EMULATOR_PORT: 5554
with:
avd-name: android_emulator
api-level: 33
target: google_atd
arch: x86_64
profile: pixel_5
sdcard-path-or-size: 128M
ram-size: 2048M
disk-size: 4096M
emulator-port: ${{ env.EMULATOR_PORT }}
disable-animations: true
emulator-options: -no-window -noaudio -no-boot-anim -wipe-data -cache-size 1000 -partition-size 8192
pre-emulator-launch-script: |
sdkmanager --list_installed
script: |
cd src/serious_python/example/bridge_example && dart run serious_python:main package app/src --platform Android --python-version ${{ matrix.python_version }}
cd src/serious_python/example/bridge_example && flutter test integration_test --device-id emulator-${{ env.EMULATOR_PORT }}
- name: Diagnostics on failure
if: failure()
shell: bash
run: |
set +e
REPO="$GITHUB_WORKSPACE"
ABI=x86_64
echo "=== serious_python_android/android/src/main/jniLibs/$ABI/ ==="
ls -la "$REPO/src/serious_python_android/android/src/main/jniLibs/$ABI/" 2>/dev/null || echo "(not found)"
echo
echo "=== example/build/app/outputs/apk/debug/*.apk ==="
APK=$(find "$REPO/src/serious_python/example/bridge_example/build" -name "*-debug.apk" 2>/dev/null | head -n1)
echo "APK: $APK"
if [ -n "$APK" ]; then
echo "Native libs inside APK:"
unzip -l "$APK" | grep -E "lib/$ABI/" || echo "(no lib/$ABI/ entries)"
fi
bridge_example_windows:
name: Test Bridge example on Windows (Python ${{ matrix.python_version }})
runs-on: windows-latest
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Package + run integration test
working-directory: "src/serious_python/example/bridge_example"
shell: bash
run: |
dart run serious_python:main package app/src --platform Windows --python-version ${{ matrix.python_version }}
# bash + pipefail so the test step actually fails when flutter fails
# (default PowerShell shell on windows runners eats the failure when
# piping into tail).
set -o pipefail
flutter test integration_test -d windows -v 2>&1 | tail -300
- name: Diagnostics on failure
if: failure()
shell: bash
working-directory: "src/serious_python/example/bridge_example"
run: |
set +e
DBG_DIR=build/windows/x64/runner/Debug
echo "=== runner/Debug dir ==="
ls -la $DBG_DIR/ || true
echo
echo "=== dart_bridge*.dll bundled? ==="
ls -la $DBG_DIR/dart_bridge*.dll || echo "(no dart_bridge dll bundled)"
echo
echo "=== runner/Debug/Lib (Python stdlib) ==="
ls $DBG_DIR/Lib | head -20 || true
echo
echo "=== runner/Debug/site-packages ==="
ls -la $DBG_DIR/site-packages/ || true
bridge_example_linux:
name: Test Bridge example on Linux ${{ matrix.title }} (Python ${{ matrix.python_version }})
runs-on: ${{ matrix.runner }}
if: false # see `macos:` for rationale
strategy:
fail-fast: false
matrix:
python_version: ['3.12', '3.13', '3.14']
arch: [amd64, arm64]
include:
- arch: amd64
runner: ubuntu-24.04
title: AMD64
- arch: arm64
runner: ubuntu-24.04-arm
title: ARM64
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Get Flutter version from .fvmrc
uses: kuhnroyal/flutter-fvm-config-action/config@v3
id: fvm-config-action
with:
path: '.fvmrc'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }}
channel: ${{ matrix.arch == 'arm64' && 'master' || 'stable' }}
cache: true
- name: Install Linux desktop build deps
run: |
sudo apt-get update --allow-releaseinfo-change
sudo apt-get install -y xvfb libgtk-3-dev
if [ "${{ matrix.arch }}" = "amd64" ]; then
sudo apt-get install -y \
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly gstreamer1.0-libav
else
sudo apt-get install -y \
clang ninja-build gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly gstreamer1.0-libav
fi
- name: Package + run integration test
working-directory: src/serious_python/example/bridge_example
run: |
flutter pub get
dart run serious_python:main package app/src \
--platform Linux \
--python-version ${{ matrix.python_version }}
set -o pipefail
xvfb-run flutter test integration_test -d linux -v 2>&1 | tail -300
- name: Diagnostics on failure
if: failure()
working-directory: src/serious_python/example/bridge_example
run: |
set +e
DBG_DIR=build/linux/${{ matrix.arch == 'arm64' && 'arm64' || 'x64' }}/debug/bundle
echo "=== bundle dir ==="
ls -la $DBG_DIR/ 2>/dev/null
echo
echo "=== bundle/lib (bundled shared libs) ==="
ls -la $DBG_DIR/lib/ 2>/dev/null
echo
echo "=== readelf -d on libdart_bridge.so ==="
readelf -d $DBG_DIR/lib/libdart_bridge.so 2>/dev/null | grep -E "NEEDED|libpython" || echo "(libdart_bridge.so not found)"
echo
echo "=== bundle data/flutter_assets/native_assets/linux/ ==="
ls -la $DBG_DIR/data/flutter_assets/native_assets/linux/ 2>/dev/null
echo
echo "=== Python stdlib dir ==="
ls -d $DBG_DIR/python3.* 2>/dev/null | head -5
publish:
name: Publish to pub.dev
needs:
- macos
- ios
- android
- windows
- linux
- bridge_example_macos
- bridge_example_ios
- bridge_example_android
- bridge_example_linux
- bridge_example_windows
runs-on: ubuntu-22.04
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup uv
uses: astral-sh/setup-uv@v6
- name: Setup Flutter
uses: kuhnroyal/flutter-fvm-config-action/setup@v3
with:
path: '.fvmrc'
cache: true
- name: Compute PKG_VER
run: |
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
# Extract the tag name
tag="${GITHUB_REF#refs/tags/}"
# Remove leading "v" if present
PKG_VER="${tag#v}"
else
# Get the latest tag, or fall back to "v0.0.0" if none exist
cv=$(git describe --abbrev=0 2>/dev/null || echo "v0.0.0")
# Remove leading "v" if present
cv=${cv#v}
# Split into major/minor components
major=$(echo "$cv" | cut -d. -f1)
minor=$(echo "$cv" | cut -d. -f2)
# Construct the package version
PKG_VER="${major}.${minor}.${GITHUB_RUN_NUMBER}"
fi
export PKG_VER
echo "PKG_VER=$PKG_VER" | tee -a "$GITHUB_ENV"
- name: Configure pub.dev credentials
run: |
mkdir -p $HOME/.config/dart
echo "${{ secrets.PUB_DEV_TOKEN }}" | base64 --decode > $HOME/.config/dart/pub-credentials.json
- name: Patch pubspec versions
working-directory: "src"
run: |
for pkg in \
"serious_python" \
"serious_python_platform_interface" \
"serious_python_android" \
"serious_python_darwin" \
"serious_python_windows" \
"serious_python_linux"; do
uv run "$SCRIPTS/patch_pubspec.py" "$pkg/pubspec.yaml" "$PKG_VER"
done
- name: Publish packages
run: |
publish_pkg () {
pushd "$1" >/dev/null
dart pub publish --force
popd >/dev/null
}
publish_pkg src/serious_python_platform_interface
sleep 600
publish_pkg src/serious_python_android
publish_pkg src/serious_python_darwin
publish_pkg src/serious_python_windows
publish_pkg src/serious_python_linux
sleep 600
publish_pkg src/serious_python