Repository navigation
forge: ship a licence with every build.sh wheel
#372
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Publish wheels | |
| on: | |
| push: | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| archs: | |
| description: | | |
| Architectures (comma-separated): | |
| required: false | |
| default: "android,iOS" | |
| packages: | |
| description: | | |
| Packages (comma-separated) or 'ALL' to select all available recipes: | |
| required: false | |
| default: "pydantic-core:,numpy:,pillow:" | |
| prebuild_recipes: | |
| description: | | |
| Recipes (comma-separated; typically flet-lib*) to build FIRST and seed into | |
| the matrix's dist/ for host-dep pip resolution (e.g. flet-libgdal -> gdal): | |
| required: false | |
| default: "" | |
| python_versions: | |
| description: | | |
| Python versions to fan the matrix across (comma-separated): | |
| required: false | |
| default: "3.12,3.13,3.14" | |
| mobile_test_pythons: | |
| description: | | |
| Python versions (comma-separated) whose recipe mobile tests should actually run. | |
| Versions in `python_versions` that aren't in this list still build wheels but skip the | |
| APK/iOS-simulator test stage. Use "ALL" to run tests for every entry in `python_versions`. | |
| Pass an empty string to build wheels WITHOUT any on-device tests (build-only deploy): | |
| required: false | |
| default: "3.12" | |
| python_build_run_id: | |
| description: | | |
| flet-dev/python-build Actions run-id whose artifacts to use as the | |
| python-build support tree, instead of the pinned date-keyed release tarball: | |
| required: false | |
| default: "" | |
| serious_python_ref: | |
| description: | | |
| Git ref (branch/tag/SHA) of flet-dev/serious-python to pin the | |
| recipe-tester's serious_python (+ platform impls) to, so on-device tests | |
| validate against an UNRELEASED sp fix. Empty = use the published | |
| serious_python. Replaces the old hardcoded override in the pyproject template: | |
| required: false | |
| default: "" | |
| publish: | |
| description: | | |
| Publish the built wheels to pypi.flet.dev at the end of the run. | |
| type: boolean | |
| required: false | |
| default: false | |
| # Reusable-workflow entry point for cross-repo callers. | |
| workflow_call: | |
| inputs: | |
| archs: | |
| type: string | |
| required: false | |
| default: "android,iOS" | |
| packages: | |
| type: string | |
| required: false | |
| default: "lru-dict:,pydantic-core:,numpy:" | |
| prebuild_recipes: | |
| type: string | |
| required: false | |
| default: "" | |
| python_versions: | |
| type: string | |
| required: false | |
| default: "3.12,3.13,3.14" | |
| mobile_test_pythons: | |
| type: string | |
| required: false | |
| default: "3.12" | |
| python_build_run_id: | |
| type: string | |
| required: false | |
| default: "" | |
| serious_python_ref: | |
| type: string | |
| required: false | |
| default: "" | |
| publish: | |
| type: boolean | |
| required: false | |
| default: false | |
| secrets: | |
| GEMFURY_TOKEN: | |
| required: false | |
| # Cancel in-flight runs when a newer event arrives for the same logical branch. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} | |
| cancel-in-progress: true | |
| env: | |
| DEFAULT_PYTHONS: "3.12,3.13,3.14" | |
| # Used as the fallback recipe set when `packages` input is empty | |
| # (workflow_dispatch/workflow_call) or when no `recipes/**` paths | |
| # changed in the triggering event (push/pull_request). | |
| SMOKE_TEST_PACKAGES: "lru-dict:,pydantic-core:,numpy:" | |
| permissions: | |
| contents: read | |
| jobs: | |
| detect: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| pythons_json: ${{ steps.detect-pythons.outputs.pythons_json }} | |
| canonical_python: ${{ steps.detect-pythons.outputs.canonical_python }} | |
| packages: ${{ steps.detect-packages.outputs.packages }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| persist-credentials: false | |
| - name: Get changed recipes | |
| id: changed-recipes | |
| uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6 | |
| with: | |
| files: recipes/** | |
| dir_names: true | |
| dir_names_max_depth: 2 | |
| - id: detect-pythons | |
| # Decide which Python versions this run fans out across. | |
| shell: bash | |
| env: | |
| INPUT_PYTHONS: ${{ inputs.python_versions }} | |
| run: | | |
| pythons="${INPUT_PYTHONS:-$DEFAULT_PYTHONS}" | |
| # Hand-built JSON array — no jq dep needed. | |
| json="[" | |
| first=true | |
| for py in $(echo "$pythons" | tr ',' ' '); do | |
| if [ "$first" = true ]; then first=false; else json+=","; fi | |
| json+="\"$py\"" | |
| done | |
| json+="]" | |
| echo "Detected pythons: $pythons -> $json" | |
| echo "pythons_json=$json" >> "$GITHUB_OUTPUT" | |
| # Canonical leg = first listed Python. build.sh (py3-none) recipes are | |
| # identical on every leg, so they build only on the canonical one. | |
| canonical="$(echo "$pythons" | tr ',' ' ' | awk '{print $1}' | cut -d. -f1-2)" | |
| echo "canonical_python=$canonical" >> "$GITHUB_OUTPUT" | |
| - id: detect-packages | |
| shell: bash | |
| env: | |
| GITHUB_EVENT_NAME: ${{ github.event_name }} | |
| INPUT_PACKAGES: ${{ inputs.packages }} | |
| CHANGED_DIRS: ${{ steps.changed-recipes.outputs.all_changed_files }} | |
| run: | | |
| if [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" || "$GITHUB_EVENT_NAME" == "workflow_call" ]]; then | |
| # The literal value "ALL" expands to every recipe with a meta.yaml under recipes/. | |
| if [[ "$INPUT_PACKAGES" == "ALL" ]]; then | |
| pkgs="" | |
| for dir in recipes/*/; do | |
| [[ -f "$dir/meta.yaml" ]] || continue | |
| pkg=$(basename "$dir") | |
| pkgs="${pkgs:+$pkgs,}${pkg}:" | |
| done | |
| else | |
| pkgs="${INPUT_PACKAGES:-$SMOKE_TEST_PACKAGES}" | |
| fi | |
| else | |
| pkgs="" | |
| for dir in $CHANGED_DIRS; do | |
| [[ -f "$dir/meta.yaml" ]] || continue # skip deleted recipes | |
| pkgs="${pkgs:+$pkgs,}${dir#recipes/}:" | |
| done | |
| pkgs="${pkgs:-$SMOKE_TEST_PACKAGES}" | |
| fi | |
| echo "Detected packages: $pkgs" | |
| echo "packages=$pkgs" >> "$GITHUB_OUTPUT" | |
| # One child workflow run per Python version. | |
| build: | |
| name: Python ${{ matrix.python_version }} | |
| needs: detect | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python_version: ${{ fromJson(needs.detect.outputs.pythons_json) }} | |
| uses: ./.github/workflows/build-wheels-version.yml | |
| with: | |
| python_version: ${{ matrix.python_version }} | |
| canonical_python: ${{ needs.detect.outputs.canonical_python }} | |
| archs: ${{ inputs.archs || 'android,iOS' }} | |
| packages: ${{ needs.detect.outputs.packages }} | |
| prebuild_recipes: ${{ inputs.prebuild_recipes || '' }} | |
| # A non-empty value is honored verbatim (list of test legs, or "ALL"). push/PR | |
| # carry no inputs, so those default to the 3.12 on-device test. On | |
| # workflow_dispatch/workflow_call an EXPLICIT empty string disables all mobile | |
| # tests — mapped to the `none` sentinel so it survives the reusable-workflow | |
| # boundary and never matches a python in the child's gate (`none` works too). | |
| mobile_test_pythons: >- | |
| ${{ inputs.mobile_test_pythons != '' && inputs.mobile_test_pythons | |
| || ((github.event_name == 'push' || github.event_name == 'pull_request') && '3.12') | |
| || 'none' }} | |
| python_build_run_id: ${{ inputs.python_build_run_id || '' }} | |
| # No `|| default` here: an explicitly-passed empty string must survive so a | |
| # caller can disable the override and test against the published sp. | |
| serious_python_ref: ${{ inputs.serious_python_ref }} | |
| publish: ${{ inputs.publish || false }} | |
| secrets: | |
| GEMFURY_TOKEN: ${{ secrets.GEMFURY_TOKEN }} |