Skip to content
Open
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
8 changes: 7 additions & 1 deletion .github/workflows/realapps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,14 @@ jobs:
done

- name: Validate the generated crate
# rocrate-validator needs rich<14, which current Flower cannot share, so it
# gets its own virtual environment. The federation has finished by now.
# offline=True only reads the validator's cache, so fill it first.
run: |
python tests/e2e/validate_crate.py \
python -m venv /tmp/validator
/tmp/validator/bin/pip install "roc-validator>=0.13"
/tmp/validator/bin/rocrate-validator cache warm -p ro-crate-1.2 -p process-run-crate-0.5
/tmp/validator/bin/python tests/e2e/validate_crate.py \
/tmp/flcrate_out/ro-crate/ro-crate-metadata.json \
"${{ matrix.strategy }}" "${{ matrix.framework }}"

Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ jobs:
# works without a Flower install.
run: |
python -m pip install --upgrade pip
pip install pytest pytest-cov "rocrate>=0.13" "tomli>=2.0; python_version < '3.11'"
pip install pytest pytest-cov "rocrate>=0.15" "roc-validator>=0.13" "tomli>=2.0; python_version < '3.11'"
pip install -e . --no-deps

- name: Cache the validator's profile resources
# The tests validate with offline=True, which only reads rocrate-validator's
# cache. A fresh runner's cache is empty, so fill it first.
run: rocrate-validator cache warm -p ro-crate-1.2 -p process-run-crate-0.5

- name: Run tests with coverage
run: pytest -q --cov=flwrcrate --cov-report=term-missing --cov-fail-under=85
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ grep -rn "flwr.serverapp\|strategy.start\|server_fn\|ServerAppComponents" <app>/
- `flwr.serverapp` **and** `strategy.start` → ✅ compatible
- `server_fn` or `ServerAppComponents` → ❌ classic API, not supported (yet)

Other requirements: Python ≥ 3.11, `rocrate ≥ 0.13`.
Other requirements: Python ≥ 3.11, `rocrate ≥ 0.15`.

## Install

Expand Down Expand Up @@ -243,11 +243,15 @@ series.

### Validation

Crates validate against the official
[`rocrate-validator`](https://github.com/crs4/rocrate-validator). Note:
`ro-crate-py` ≥ 0.15 writes RO-Crate **1.2**, while `rocrate-validator` 0.10
ships only a **1.1** profile, producing a single false-positive `MUST 5.3`
(`conformsTo` version). All other REQUIRED checks pass.
Crates declare and validate against **RO-Crate 1.2**: flwrCrate sets the
version explicitly, so the output does not depend on which `ro-crate-py` is
installed. The test suite and the end-to-end workflow check generated crates
with [`rocrate-validator`](https://github.com/crs4/rocrate-validator) at the
REQUIRED level, against the `ro-crate-1.2` and `process-run-crate-0.5`
profiles. Process Run Crate 0.5 is based on RO-Crate 1.1, so its inherited
checks are not reported; the RO-Crate 1.2 check covers the base rules.
The validator's opt-in extra checks are enabled too; they flag likely mistakes,
such as a plain string where a link to another entity was meant.

## Tested with

Expand Down Expand Up @@ -294,7 +298,8 @@ it produced.
## Development

```bash
pip install -e ".[dev]" # installs pytest + pytest-cov
pip install -e ".[dev]" # installs pytest + pytest-cov and roc-validator
rocrate-validator cache warm -p ro-crate-1.2 -p process-run-crate-0.5 # once, for the validation tests
pytest # run the full unit + integration suite
pytest --cov=flwrcrate --cov-report=term-missing # with a coverage report
```
Expand Down
2 changes: 1 addition & 1 deletion flwrcrate/crate_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def build_crate(captured: dict, crate_dir, metrics_log_path=None, model_path=Non
"""Assemble and write an RO-Crate. Returns the crate directory path."""
uri_map = uri_map or {}
crate_dir = Path(crate_dir)
crate = ROCrate()
crate = ROCrate(version="1.2")

crate.name = captured.get("app_name") or "Federated learning run"
crate.description = (
Expand Down
Loading
Loading