Skip to content

Move Flet client binaries from PyPI wheels to GitHub releases#6309

Merged
FeodorFitsner merged 2 commits intomainfrom
flet-client-binaries
Mar 16, 2026
Merged

Move Flet client binaries from PyPI wheels to GitHub releases#6309
FeodorFitsner merged 2 commits intomainfrom
flet-client-binaries

Conversation

@FeodorFitsner
Copy link
Contributor

@FeodorFitsner FeodorFitsner commented Mar 13, 2026

Close #6290

Flet desktop client binaries (compiled Flutter app) are currently bundled into flet-desktop and flet-desktop-light platform-specific wheels. This makes wheels huge and each release consumes significant PyPI space. Previously (before commit 9d21f5b94), binaries were downloaded from GitHub Releases on first run. The goal is to restore that behavior: remove binaries from wheels, publish them to GitHub Releases for both dev and tag builds, and download on first run.

Additionally, since binaries are no longer in the wheel, we unify flet-desktop and flet-desktop-light into a single flet-desktop package. The light/full choice becomes a runtime configuration ([tool.flet] in user's pyproject.toml) that determines which binary to download.

Decisions

  • Dev builds: Create a new GitHub Release for every dev build from main (tag v0.83.0.dev6045)
  • Linux binary selection: Detect system glibc version and pick the best matching binary
  • Wheel format: Single universal py3-none-any flet-desktop wheel (eliminate flet-desktop-light)
  • Release tag: Always v{version} — existing version.py patching is sufficient
  • Light/Full toggle: [tool.flet] in user's pyproject.toml with FLET_DESKTOP_FLAVOR env var override; default is light on Linux, full on Windows/macOS

Step 1: Add download logic to flet_desktop/__init__.py

File: sdk/python/packages/flet-desktop/src/flet_desktop/__init__.py

1a. Add imports

Add back urllib.request, zipfile (removed in 9d21f5b94). Add ctypes for glibc detection.

1b. Add glibc-based Linux binary selection

__get_linux_distro_id() -> str:

  • Check FLET_LINUX_DISTRO env var override first
  • Detect system glibc version using ctypes (ctypes.CDLL("libc.so.6") -> gnu_get_libc_version())
  • Pick the best matching distro (highest glibc requirement <= system glibc):
glibc version distro_id manylinux tag
2.28 debian10 manylinux_2_28
2.31 ubuntu20.04 manylinux_2_31
2.35 ubuntu22.04 manylinux_2_35
2.36 debian12 manylinux_2_36
2.39 ubuntu24.04 manylinux_2_39

1c. Add desktop flavor detection

__get_desktop_flavor() -> str (returns "full" or "light"):

  1. Check FLET_DESKTOP_FLAVOR env var (explicit override)
  2. Read pyproject.toml from os.getcwd() -> [tool.flet].desktop_flavor
  3. Default: "light" on Linux, "full" on Windows/macOS

Use stdlib tomllib (Python 3.11+) with tomli fallback for 3.10 compatibility. Wrap in try/except — missing file or parse errors silently fall back to default.

1d. Add artifact filename helper

__get_artifact_filename() -> str:

  • Windows: "flet-windows.zip"
  • macOS: "flet-macos.tar.gz"
  • Linux full: "flet-linux-{distro_id}-{arch}.tar.gz"
  • Linux light: "flet-linux-{distro_id}-light-{arch}.tar.gz"

Uses __get_linux_distro_id() + get_arch() + __get_desktop_flavor().

1e. Revive __download_flet_client(file_name) -> str

def __download_flet_client(file_name):
    ver = flet_desktop.version.version
    flet_url = f"https://github.com/flet-dev/flet/releases/download/v{ver}/{file_name}"
    flet_url = os.environ.get("FLET_CLIENT_URL", flet_url)
    logger.info(f"Downloading Flet v{ver} from {flet_url}")
    print(f"Preparing Flet v{ver} for the first use. This is a one-time operation...")
    temp_arch = Path(tempfile.gettempdir()).joinpath(f"{file_name}.{random_string(8)}")
    urllib.request.urlretrieve(flet_url, str(temp_arch))
    final_path = Path(tempfile.gettempdir()).joinpath(file_name)
    temp_arch.rename(final_path)
    return str(final_path)

1f. Restructure __locate_and_unpack_flet_view() resolution order

New order per platform:

  1. Check build/{platform}/ dir (local flet build output) — unchanged
  2. Check FLET_VIEW_PATH env var — moved up
  3. Check cached binary at __get_client_storage_dir() — reuse if already extracted
  4. Check packaged binaries at get_package_bin_dir() — for PyInstaller bundles
  5. Download from GitHub Releases -> extract to cache dir

Windows: Download flet-windows.zip, extract with zipfile.
macOS: Download flet-macos.tar.gz, extract with tarfile.
Linux: Download flet-linux-{distro}[-light]-{arch}.tar.gz, extract with tarfile.

1g. Update __get_client_storage_dir()

Replace __get_desktop_distribution_name() (no longer needed) with flavor-aware cache path:
~/.flet/client/flet-desktop-{flavor}-{version}/


Step 2: Eliminate flet-desktop-light package

2a. Delete sdk/python/packages/flet-desktop-light/ entirely

2b. Update flet-desktop/pyproject.toml

File: sdk/python/packages/flet-desktop/pyproject.toml

  • Remove [tool.setuptools.package-data] section

2c. Update flet/utils/pip.py

File: sdk/python/packages/flet/src/flet/utils/pip.py

  • ensure_flet_desktop_package_installed(): Remove flet-desktop-light branch. Always install flet-desktop:
def ensure_flet_desktop_package_installed():
    try:
        import flet_desktop.version
        if flet_desktop.version.version and flet_desktop.version.version != flet.version.flet_version:
            raise RuntimeError("flet-desktop version mismatch")
    except Exception:
        install_flet_package("flet-desktop")

Step 3: Update CI workflow

File: .github/workflows/ci.yml

3a. Stop bundling binaries into wheels

build_windows job:

  • Keep Flutter build and flet-windows.zip creation
  • Remove: copying flet/ dir into flet_desktop/app/, building flet-desktop wheel, wheel retagging
  • Remove: version patching step (no longer building Python package here)
  • Only upload client/flet-windows.zip

build_macos job:

  • Keep Flutter build and flet-macos.tar.gz creation
  • Remove: copying tar.gz into flet_desktop/app/, building flet-desktop wheel, wheel retagging
  • Only upload client/flet-macos.tar.gz

build_linux job:

  • Keep Flutter build and all flet-linux-*.tar.gz creation (both full and light variants)
  • Remove: the entire "Build flet-desktop and flet-desktop-light Python packages" step
  • Only upload client/flet-linux*.tar.gz

3b. Move wheel builds to build_flet_cli_desktop

Change from building only --sdist to full build:

uv build --package flet-cli
uv build --package flet
uv build --package flet-desktop  # wheel + sdist, now universal py3-none-any

Remove all flet-desktop-light references.

3c. Add dev release job

dev_release:
  name: Publish dev GitHub Release
  runs-on: ubuntu-latest
  if: github.ref == 'refs/heads/main'
  needs: [build_flet_package, build_windows, build_macos, build_linux]
  steps:
    - uses: actions/download-artifact@v4
      with:
        path: dist
        merge-multiple: true
    - uses: softprops/action-gh-release@v2
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: v${{ needs.build_flet_package.outputs.PYPI_VER }}
        name: v${{ needs.build_flet_package.outputs.PYPI_VER }}
        prerelease: true
        generate_release_notes: false
        files: |
          dist/**/flet-windows.zip
          dist/**/flet-macos.tar.gz
          dist/**/flet-linux*.tar.gz

3d. Update py_publish dependencies

Remove dependencies on build_windows, build_macos, build_linux. Remove flet_desktop_light from publish list.

3e. Remove flet-desktop-light from CI entirely

  • common.sh: Remove from patch_python_package_versions() loop
  • ci.yml py_publish: Remove flet_desktop_light from package list
  • ci.yml build_linux: Keep building both full and light Flutter clients (they produce different archives), but remove flet-desktop-light wheel building

Step 4: Update PyInstaller hook

File: sdk/python/packages/flet-cli/src/flet_cli/__pyinstaller/utils.py

Update get_flet_bin_path():

  1. Check get_package_bin_dir() — if has content, return it
  2. Check cache dir — if binaries exist, return that
  3. Trigger download, return cache path

Step 5: Environment variables

  • FLET_DESKTOP_FLAVOR"full" or "light" (default: "light" on Linux, "full" elsewhere)
  • FLET_LINUX_DISTRO — override glibc-based distro detection (e.g., debian12)
  • FLET_CLIENT_URL — override full download URL (mirrors/air-gapped)

Summary by Sourcery

Move Flet desktop client distribution from wheel-bundled binaries to on-demand downloads from GitHub Releases, while unifying desktop packages and updating tooling to support the new flow.

New Features:

  • Support runtime selection of Flet desktop client flavor (full or light) via environment variable or pyproject.toml configuration.
  • Add glibc-based Linux distro detection to choose the most appropriate desktop client binary per system.
  • Introduce automatic download and caching of Flet desktop client artifacts from GitHub Releases when no bundled binaries are present.
  • Add a GitHub workflow job to publish dev GitHub Releases with platform-specific desktop client archives.

Enhancements:

  • Simplify desktop packaging by replacing separate flet-desktop and flet-desktop-light wheels with a single universal flet-desktop package used on all platforms.
  • Refine Flet desktop client resolution to prefer local build outputs, then FLET_VIEW_PATH, then cached/downloaded clients in a versioned user cache directory.
  • Update the PyInstaller integration to reuse bundled binaries when present or trigger the same download-and-cache mechanism used at runtime.
  • Adjust CI build and publish workflows to stop embedding desktop binaries into wheels, centralize wheel building in the flet CLI/desktop job, and wire tagged releases to include desktop client archives.
  • Streamline dependency declarations, version patching scripts, and example projects to remove all references to the deprecated flet-desktop-light package.

Build:

  • Change flet-desktop to build as a universal py3-none-any wheel without bundled client binaries, relying on runtime downloads instead.

Summary by Sourcery

Move Flet desktop runtime distribution from wheel-bundled binaries to on-demand downloads from GitHub Releases, while unifying desktop packaging and updating tooling to support the new flow.

New Features:

  • Support runtime selection of Flet desktop client flavor (full or light) via environment variable or pyproject.toml configuration.
  • Add glibc-based Linux distro detection to choose the most appropriate desktop client binary per system.
  • Introduce automatic download, extraction, and caching of Flet desktop client artifacts from GitHub Releases when no bundled binaries are present.
  • Expose a helper for ensuring the desktop client is cached so PyInstaller builds can reuse the same download flow.
  • Add a CI job to publish dev GitHub Releases with platform-specific desktop client archives.

Enhancements:

  • Simplify desktop packaging by replacing separate flet-desktop and flet-desktop-light wheels with a single universal flet-desktop package across platforms.
  • Refine desktop client resolution order to prefer local build outputs, then FLET_VIEW_PATH, then cached/downloaded clients in a versioned per-user cache directory.
  • Update PyInstaller integration to prefer bundled binaries when present and otherwise fall back to the shared download-and-cache mechanism.
  • Adjust CI workflows to stop embedding desktop binaries into wheels and centralize Python package builds in the desktop/CLI build job.
  • Streamline version patching scripts, dependency declarations, and example projects by removing all references to the deprecated flet-desktop-light package.

Build:

  • Change flet-desktop to build as a universal py3-none-any wheel without bundled client binaries, relying on runtime downloads instead.

CI:

  • Remove wheel-building steps from platform client build jobs and rely on artifacts-only uploads for desktop binaries.
  • Update release workflows so tagged and dev releases both collect platform-specific client archives from CI artifacts for GitHub Releases.

Documentation:

  • Update internal package index and example configuration to drop flet-desktop-light and rely on the unified flet-desktop package.

Chores:

  • Remove the flet-desktop-light package, its PyPI cleanup, and related tooling entries from the repository.

Remove the flet-desktop-light package and all references across scripts, packaging and docs; delete its README and pyproject. Consolidate desktop packaging to a single flet-desktop artifact and simplify CI (remove builds/packaging for the light variant, update artifact uploads, and add a dev_release job).

Enhance flet-desktop runtime: add logic to determine Linux distro by glibc, choose desktop flavor via env/pyproject/default, compute artifact filenames, download GitHub release archives, extract into a versioned per-user cache, and ensure a cached client is used when bundled binaries are absent. Update flet-cli utils to prefer bundled binaries then fall back to the cached/downloaded client. Update pip utils to always target flet-desktop. Misc: remove package-data entry from flet-desktop pyproject and update various pyproject files and macros to drop flet-desktop-light where applicable.
@FeodorFitsner FeodorFitsner marked this pull request as ready for review March 13, 2026 23:37
@FeodorFitsner FeodorFitsner added this to the 0.83.0 milestone Mar 13, 2026
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Restores the previous “download desktop client on first run” distribution model by removing bundled Flet desktop client binaries from PyPI wheels, publishing the binaries to GitHub Releases, and unifying flet-desktop / flet-desktop-light into a single flet-desktop package with runtime flavor selection.

Changes:

  • Add runtime client selection + download/extract caching logic to flet_desktop, including glibc-based Linux artifact selection and flavor config via env/pyproject.toml.
  • Remove flet-desktop-light across the Python workspace (deps, extras, scripts, docs) and simplify installation logic to always use flet-desktop.
  • Update CI to stop embedding client binaries into wheels, upload client archives as workflow artifacts, and publish them on GitHub Releases (including dev releases from main).

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
sdk/python/pyproject.toml Removes flet-desktop-light from workspace dependencies.
sdk/python/packages/flet/src/flet/utils/pip.py Simplifies desktop runtime installation to always install flet-desktop.
sdk/python/packages/flet/pyproject.toml Unifies extras to depend on flet-desktop on all platforms.
sdk/python/packages/flet/docs/extras/macros/pypi_index.py Removes flet-desktop-light from docs package index set.
sdk/python/packages/flet-desktop/src/flet_desktop/init.py Implements flavor selection, Linux distro selection, download + cache extraction, and updated view resolution order.
sdk/python/packages/flet-desktop/pyproject.toml Stops shipping bundled client binaries in the wheel.
sdk/python/packages/flet-desktop-light/pyproject.toml Deletes deprecated flet-desktop-light package metadata.
sdk/python/packages/flet-desktop-light/README.md Deletes deprecated flet-desktop-light documentation.
sdk/python/packages/flet-cli/src/flet_cli/__pyinstaller/utils.py Updates PyInstaller integration to use bundled binaries, cache, or trigger downloads.
sdk/python/examples/apps/flet_build_test/pyproject.toml Removes flet-desktop-light from example app deps.
.github/workflows/ci.yml Stops bundling clients into wheels; publishes client archives to GitHub Releases (tag + dev).
.github/scripts/patch_toml_versions.py Removes flet-desktop-light from version patching list.
.github/scripts/common.sh Removes flet-desktop-light from version patch loop.
.github/scripts/clean-pypi.sh Removes PyPI cleanup step for flet-desktop-light.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Introduce safe_zip_extractall (flet.utils.files) to validate zip member paths and prevent path traversal, and export it via flet.utils.__init__.py. Update flet_desktop to use a temporary extraction directory and atomic rename into the cache, add cleanup on failure (shutil.rmtree), and use safe_zip_extractall for .zip archives. Other changes: increase randomness length for temp download names, return the temp download path (avoid in-place rename), log a warning when glibc detection falls back to a default, and improve handling of FLET_VIEW_PATH by checking for the actual executable and emitting informative warnings if not found.
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 16, 2026

Deploying flet-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7d1ec1b
Status: ✅  Deploy successful!
Preview URL: https://c3f5a270.flet-docs.pages.dev
Branch Preview URL: https://flet-client-binaries.flet-docs.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link

Deploying flet-examples with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7d1ec1b
Status: ✅  Deploy successful!
Preview URL: https://e557622e.flet-examples.pages.dev
Branch Preview URL: https://flet-client-binaries.flet-examples.pages.dev

View logs

@FeodorFitsner FeodorFitsner merged commit ad0b9b8 into main Mar 16, 2026
28 of 97 checks passed
@FeodorFitsner FeodorFitsner deleted the flet-client-binaries branch March 16, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Download Flet desktop client binaries from GitHub Releases on demand

2 participants