Skip to content
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
922aa44
ci(framework): Migrate pyproject.toml to use [project]
danieljanes Feb 28, 2026
f68d3c8
Fix formatting
danieljanes Mar 1, 2026
6157afd
Make E2E pyproject less ambiguous
danieljanes Mar 1, 2026
9a02d2b
Add license classifier
danieljanes Mar 1, 2026
0e83d22
Add simulation extra when installing flwr from artifact store
danieljanes Mar 1, 2026
0ffabc4
Remove --with dev
danieljanes Mar 1, 2026
2640290
ci(*:skip): Improve CI pipelines
danieljanes Mar 1, 2026
9dac122
Merge branch 'main' into improve-ci-pipelines
danieljanes Mar 1, 2026
91ff810
Update docs
danieljanes Mar 1, 2026
eb2734a
Revert changes in intelligence-docs.yml
danieljanes Mar 1, 2026
2f738bb
ci(framework): Migrate pyproject.toml to use [project]
danieljanes Feb 28, 2026
e013b9a
Make E2E pyproject less ambiguous
danieljanes Mar 1, 2026
8815e69
Add license classifier
danieljanes Mar 1, 2026
0130843
Remove --with dev
danieljanes Mar 1, 2026
7d4256b
Merge remote-tracking branch 'refs/remotes/origin/migrate-pyproject' …
danieljanes Mar 1, 2026
ff24e2d
ci(framework): Migrate pyproject.toml to use [project]
danieljanes Feb 28, 2026
8d067fe
Add license classifier
danieljanes Mar 1, 2026
e24eb82
Remove --with dev
danieljanes Mar 1, 2026
7a6667b
Merge remote-tracking branch 'refs/remotes/origin/migrate-pyproject' …
danieljanes Mar 1, 2026
a217f2d
Merge branch 'main' into migrate-pyproject
danieljanes Mar 2, 2026
1cbe331
Move pyproject_meta into devtool
danieljanes Mar 2, 2026
7e02a17
Merge branch 'main' into migrate-pyproject
danieljanes Mar 3, 2026
5e86859
Delete project_meta Python helper
danieljanes Mar 3, 2026
885c892
Merge branch 'main' into migrate-pyproject
danieljanes Mar 3, 2026
e78a434
ci(framework): Add uv support
danieljanes Mar 3, 2026
889913e
Merge branch 'main' into migrate-add-uv
danieljanes Mar 3, 2026
79f5bfe
Add instructions
danieljanes Mar 3, 2026
c1e9d35
Fix test
danieljanes Mar 3, 2026
eb11b59
Merge branch 'main' into migrate-add-uv
danieljanes Mar 4, 2026
6220b13
Update framework/uv.md
danieljanes Mar 4, 2026
b329a05
Merge branch 'main' into migrate-add-uv
danieljanes Mar 4, 2026
acf99f0
Merge branch 'main' into migrate-add-uv
danieljanes Mar 4, 2026
f4c61de
ci(*:skip): Migrate CI to uv
danieljanes Mar 4, 2026
f820d56
Merge branch 'main' into migrate-ci-to-uv
danieljanes Mar 4, 2026
85bf792
Update pip usage
danieljanes Mar 4, 2026
b6ac113
Merge remote-tracking branch 'refs/remotes/origin/migrate-ci-to-uv' i…
danieljanes Mar 4, 2026
8075d32
Improve uv usage with --locked
danieljanes Mar 5, 2026
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
20 changes: 0 additions & 20 deletions .github/actions/bootstrap/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,9 @@ inputs:
setuptools-version:
description: "Version of setuptools to be installed using pip"
default: 82.0.0
poetry-version:
description: "Version of poetry to be installed using pip"
default: 2.3.2
poetry-skip:
description: "Option to skip the poetry installation"
required: false
default: "false"
uv-version:
description: "Version of uv to install"
default: "0.10.7"
uv-skip:
description: "Option to skip the uv installation"
required: false
default: "true"
outputs:
python-version:
description: "Version range or exact version of Python or PyPy"
Expand All @@ -34,9 +23,6 @@ outputs:
setuptools-version:
description: "Installed version of setuptools"
value: ${{ steps.versions.outputs.setuptools-version }}
poetry-version:
description: "Requested version of poetry"
value: ${{ steps.versions.outputs.poetry-version }}
uv-version:
description: "Requested version of uv"
value: ${{ steps.versions.outputs.uv-version }}
Expand All @@ -48,24 +34,18 @@ runs:
with:
python-version: ${{ inputs.python-version }}
- name: Set up uv
if: ${{ inputs.uv-skip == 'false' }}
uses: astral-sh/setup-uv@v7
with:
version: ${{ inputs.uv-version }}
- name: Install build tools
run: |
python -m pip install -U pip==${{ inputs.pip-version }}
python -m pip install -U setuptools==${{ inputs.setuptools-version }}
if ${{ inputs.poetry-skip == 'false' }}; then
python -m pip install -U poetry==${{ inputs.poetry-version }}
python -m poetry config virtualenvs.create false
fi
shell: bash
- id: versions
shell: bash
run: |
echo "python-version=$(echo ${{ inputs.python-version }})" >> $GITHUB_OUTPUT
echo "pip-version=$(echo ${{ inputs.pip-version }})" >> $GITHUB_OUTPUT
echo "setuptools-version=$(echo ${{ inputs.setuptools-version }})" >> $GITHUB_OUTPUT
echo "poetry-version=$(echo ${{ inputs.poetry-version }})" >> $GITHUB_OUTPUT
echo "uv-version=$(echo ${{ inputs.uv-version }})" >> $GITHUB_OUTPUT
14 changes: 8 additions & 6 deletions .github/workflows/build-deploy-non-framework-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@ jobs:
run: ./dev/test-copyright.sh
- name: Bootstrap
uses: ./.github/actions/bootstrap
with:
uv-skip: "false"
- name: Install pandoc
run: sudo apt install pandoc
- name: Install docs dependencies
run: |
cd framework
python -m poetry install
python -m pip install -e ../datasets
uv sync --frozen --all-groups
uv pip install -e ../datasets
- name: Install devtool dependencies
run: |
cd dev
Expand All @@ -45,13 +43,17 @@ jobs:
cd dev
uv run python -m devtool.update_html_themes
- name: Build baselines docs
run: ./dev/build-baseline-docs.sh
run: |
cd framework
uv run --no-sync ../dev/build-baseline-docs.sh
- name: Build examples docs
run: |
cd dev
uv run python -m devtool.build_example_docs
- name: Build datasets docs
run: ./datasets/dev/build-flwr-datasets-docs.sh
run: |
cd framework
uv run --no-sync ../datasets/dev/build-flwr-datasets-docs.sh
- name: Deploy docs
if: ${{ github.ref == 'refs/heads/main' && github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork }}
env:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/datasets-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ jobs:
uses: ./.github/actions/bootstrap
with:
python-version: 3.10.19
uv-skip: "false"
poetry-skip: "true"
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@v1.3.1
with:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/datasets-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ jobs:
uses: ./.github/actions/bootstrap
with:
python-version: ${{ matrix.python }}
uv-skip: "false"
poetry-skip: "true"
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@v1.3.1
with:
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/framework-devtools.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
- name: Install dependencies (mandatory + optional)
run: |
cd framework
python -m poetry install
uv sync --frozen --all-groups
- name: Lint + Test (isort/black/mypy/pylint/pytest)
run: ./framework/dev/test-tool.sh
run: |
cd framework
uv run --no-sync ./dev/test-tool.sh
10 changes: 5 additions & 5 deletions .github/workflows/framework-docs-update-translations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@ jobs:
- name: Install dependencies
run: |
cd framework
python -m poetry install
uv sync --frozen --all-groups

- name: Install pandoc
uses: nikeee/setup-pandoc@v1

- name: Update text and translations for all locales
run: |
cd framework/docs
make update-text
for langDir in locales/*; do
cd framework
uv run --no-sync make -C docs update-text
for langDir in docs/locales/*; do
if [ -d "$langDir" ]; then
lang=$(basename $langDir)
echo "Updating language $lang"
make update-lang lang=$lang
uv run --no-sync make -C docs update-lang lang=$lang
fi
done

Expand Down
14 changes: 8 additions & 6 deletions .github/workflows/framework-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
- name: Install Flower Framework
run: |
cd framework
python -m poetry install
uv sync --frozen --all-groups
- name: Sync required docs build assets from main for release branches
if: ${{ startsWith(github.ref, 'refs/heads/release/framework-') || (github.event_name == 'pull_request' && startsWith(github.base_ref, 'release/framework-')) || (github.event_name == 'release' && startsWith(github.ref, 'refs/tags/framework-')) }}
run: |
Expand Down Expand Up @@ -87,7 +87,8 @@ jobs:
DOC_VERSION: ${{ steps.doc_version.outputs.version }}
run: |
echo "Building docs for version: ${DOC_VERSION}"
./framework/dev/build-docs.sh full
cd framework
uv run --no-sync ./dev/build-docs.sh full
- name: Determine if this is the latest stable version
if: ${{ github.repository == 'adap/flower' && ((startsWith(github.ref, 'refs/heads/release/framework-') && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')) || (github.event_name == 'release' && startsWith(github.ref, 'refs/tags/framework-'))) }}
id: latest_check
Expand Down Expand Up @@ -141,8 +142,9 @@ jobs:
git checkout origin/main
fi

python ./framework/docs/generate_docs_ui_metadata.py \
--docs-ui-config ./dev/docs-ui-config.yml \
--output ./framework/docs/build/docs-ui-metadata.json
cd framework
uv run --no-sync python ./docs/generate_docs_ui_metadata.py \
--docs-ui-config ../dev/docs-ui-config.yml \
--output ./docs/build/docs-ui-metadata.json

aws s3 cp --cache-control "no-cache" ./framework/docs/build/docs-ui-metadata.json s3://${{ secrets.DOCS_AWS_BUCKET_NAME }}/docs/framework/docs-ui-metadata.json
aws s3 cp --cache-control "no-cache" ./docs/build/docs-ui-metadata.json s3://${{ secrets.DOCS_AWS_BUCKET_NAME }}/docs/framework/docs-ui-metadata.json
15 changes: 7 additions & 8 deletions .github/workflows/framework-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,15 @@ jobs:
- name: Install dependencies
run: |
cd framework
python -m poetry install --all-extras
uv sync --frozen --all-extras --all-groups
- name: Build wheel
run: ./framework/dev/build.sh
run: |
cd framework
uv run --no-sync ./dev/build.sh
- name: Test wheel
run: ./framework/dev/test-wheel.sh
run: |
cd framework
uv run --no-sync ./dev/test-wheel.sh
- name: Upload wheel
if: ${{ github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }}
id: upload
Expand Down Expand Up @@ -104,7 +108,6 @@ jobs:
uses: ./.github/actions/bootstrap
with:
python-version: ${{ matrix.python-version }}
poetry-skip: 'true'
- name: Install Flower from repo
if: ${{ needs.changes.outputs.framework == 'true' && (github.repository != 'adap/flower' || github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]') }}
working-directory: ./framework
Expand Down Expand Up @@ -282,8 +285,6 @@ jobs:
- name: Bootstrap
if: ${{ needs.changes.outputs.framework == 'true' }}
uses: ./.github/actions/bootstrap
with:
poetry-skip: 'true'
- name: Install dependencies
if: ${{ needs.changes.outputs.framework == 'true' }}
run: |
Expand Down Expand Up @@ -421,7 +422,6 @@ jobs:
uses: ./.github/actions/bootstrap
with:
python-version: ${{ matrix.python-version }}
poetry-skip: 'true'
- name: Install Flower from repo
if: ${{ needs.changes.outputs.framework == 'true' && (github.repository != 'adap/flower' || github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]') }}
run: |
Expand Down Expand Up @@ -469,7 +469,6 @@ jobs:
uses: ./.github/actions/bootstrap
with:
python-version: ${{ matrix.python-version }}
poetry-skip: 'true'
- name: Install Flower from repo
if: ${{ needs.changes.outputs.framework == 'true' && (github.repository != 'adap/flower' || github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]') }}
working-directory: ./framework
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/framework-release-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ jobs:
echo "pip-version=${{ steps.bootstrap.outputs.pip-version }}" >> "$GITHUB_OUTPUT"
echo "setuptools-version=${{ steps.bootstrap.outputs.setuptools-version }}" >> "$GITHUB_OUTPUT"

NAME=$(poetry version | awk {'print $1'})
VERSION=$(poetry version -s)
NAME=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['name'])")
VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
python dev/build-docker-image-matrix.py --flwr-version "${VERSION}" --matrix nightly --flwr-package "${NAME}" > matrix.json
echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/framework-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
curl $wheel_url --output dist/$wheel_name
curl $tar_url --output dist/$tar_name

python -m poetry publish -u __token__ -p ${{ secrets.PYPI_TOKEN_RELEASE_FLWR }}
uv publish --token ${{ secrets.PYPI_TOKEN_RELEASE_FLWR }}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The --token argument in uv publish --token ${{ secrets.PYPI_TOKEN_RELEASE_FLWR }} is not quoted. In GitHub Actions, ${{ secrets.PYPI_TOKEN_RELEASE_FLWR }} is inlined directly into the shell command, so the token value should be quoted to prevent word splitting and other shell issues. The token should be passed as --token "${{ secrets.PYPI_TOKEN_RELEASE_FLWR }}" or, better yet, provided via an environment variable that is then referenced as a quoted shell variable.

Suggested change
uv publish --token ${{ secrets.PYPI_TOKEN_RELEASE_FLWR }}
uv publish --token "${{ secrets.PYPI_TOKEN_RELEASE_FLWR }}"

Copilot uses AI. Check for mistakes.

parameters:
if: ${{ github.repository == 'adap/flower' }}
Expand Down
16 changes: 11 additions & 5 deletions .github/workflows/framework-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,20 @@ jobs:
- name: Install dependencies
if: ${{ needs.changes.outputs.framework == 'true' || needs.changes.outputs.ex_bench == 'true' }}
run: |
cd framework
python -m poetry install --all-extras
cd framework
uv sync --python=${{ matrix.python }} --frozen --all-extras --all-groups
- name: Check if protos need recompilation
if: ${{ needs.changes.outputs.framework == 'true' }}
run: ./framework/dev/check-protos.sh
run: |
cd framework
uv run --no-sync ./dev/check-protos.sh
- name: Lint + Test (isort/black/docformatter/mypy/pylint/flake8/pytest)
if: ${{ needs.changes.outputs.framework == 'true' }}
run: ./framework/dev/test.sh
run: |
cd framework
uv run --no-sync ./dev/test.sh
- name: Check benchmarks and examples
if: ${{ needs.changes.outputs.ex_bench == 'true' }}
run: ./dev/test.sh
run: |
cd framework
uv run --no-sync ../dev/test.sh
9 changes: 3 additions & 6 deletions .github/workflows/intelligence-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ jobs:
- uses: actions/checkout@v5
- name: Bootstrap
uses: ./.github/actions/bootstrap
with:
uv-skip: "false"
poetry-skip: "true"
- name: Install dependencies
run: |
cd dev
Expand Down Expand Up @@ -146,7 +143,7 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' && github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork }}
run: |
cd framework
python -m poetry install --extras "simulation"
uv sync --frozen --all-groups --extra simulation
- name: Download TS docs
if: ${{ github.ref == 'refs/heads/main' && github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork }}
uses: actions/download-artifact@v4
Expand All @@ -168,8 +165,8 @@ jobs:
- name: Build final docs
if: ${{ github.ref == 'refs/heads/main' && github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork }}
run: |
cd intelligence/docs
make html
cd framework
uv run --no-sync make -C ../intelligence/docs html
- name: Deploy docs
if: ${{ github.ref == 'refs/heads/main' && github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork }}
env:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/repo-check-pr-title.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ jobs:
uses: ./.github/actions/bootstrap
with:
python-version: 3.13
poetry-skip: 'true'
- name: Check PR title format
env:
PR_TITLE: ${{ github.event.pull_request.title }}
Expand Down
4 changes: 2 additions & 2 deletions dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This directory provides developer tooling used across the repository (for exampl
formatting, docs helpers, and repository checks).

`devtool` uses `uv` for dependency management and command execution.
The Flower `framework` project remains Poetry-based.
The Flower `framework` project also uses `uv` for CI and local developer workflows.

## Prerequisites

Expand Down Expand Up @@ -72,4 +72,4 @@ uv sync --frozen

- CI jobs that use `devtool` should run `uv sync --frozen` and execute commands with
`uv run`.
- CI jobs that install `framework` still use Poetry.
- CI jobs that install `framework` should use `uv sync` and `uv run`.
2 changes: 1 addition & 1 deletion framework/dev/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
set -e
cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"/../

python -m poetry build
uv build --clear
4 changes: 2 additions & 2 deletions framework/dev/publish-nightly.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/../
if [[ $(git log --since="24 hours ago" --pretty=oneline) ]]; then
sed -i -E "s/^name = \"(.+)\"/name = \"\1-nightly\"/" pyproject.toml
sed -i -E "s/^version = \"(.+)\"/version = \"\1.dev$(date '+%Y%m%d')\"/" pyproject.toml
python -m poetry build
python -m poetry publish -u __token__ -p $PYPI_TOKEN
uv build --clear
uv publish --token "$PYPI_TOKEN"
else
echo "There were no commits in the last 24 hours."
fi
3 changes: 2 additions & 1 deletion framework/dev/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ python -m pylint --ignore=py/flwr/proto py/flwr
echo "- pylint: done"

echo "- pytest: start"
python -m pytest --cov=py/flwr
# Ray's uv runtime-env hook can stall under `uv run` during pytest.
RAY_ENABLE_UV_RUN_RUNTIME_ENV=0 python -m pytest --cov=py/flwr
echo "- pytest: done"

echo "- All Python checks passed"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
Install development versions of Flower
****************************************

Using Poetry (recommended)
==========================
Using uv (recommended)
======================

Install a ``flwr`` pre-release from PyPI: update the ``flwr`` dependency in
``pyproject.toml`` and then reinstall (ensure to delete ``poetry.lock`` via ``rm
poetry.lock`` before running ``python -m poetry install``).
``pyproject.toml`` and then reinstall with ``uv sync``.

- ``flwr = { version = "1.0.0a0", allow-prereleases = true }`` (without extras)
- ``flwr = { version = "1.0.0a0", allow-prereleases = true, extras = ["simulation"] }``
Expand All @@ -28,8 +27,8 @@ Install ``flwr`` from a local wheel file via ``pyproject.toml``:
- ``flwr = { path = "../../dist/flwr-1.8.0-py3-none-any.whl", extras = ["simulation"]
}`` (with extras)

Please refer to the Poetry documentation for further details: `Poetry Dependency
Specification <https://python-poetry.org/docs/dependency-specification/>`_
Please refer to the uv documentation for further details: `Managing dependencies with uv
<https://docs.astral.sh/uv/concepts/projects/dependencies/>`_

Using pip (recommended on Colab)
================================
Expand Down
Loading