-
Notifications
You must be signed in to change notification settings - Fork 49
[RFE] Add graph check command for pre-rebuild conflict detection #998
Description
Problem
When a set of requirements has incompatible version constraints, fromager
discovers this only after the full bootstrap completes — during
write_constraints_file(). On large dependency trees this means hours of
build work before the run fails with "no single version meets all
requirements."
The typical workflow is iterative: bootstrap fails with conflicts, the user
edits constraints, re-runs bootstrap. Each iteration costs hours. There is
no cheap way to check the previous build's graph for structural issues or
classify which version conflicts are resolvable before committing to another
full run.
What exists today
-
graph explain-duplicatesreports which packages have multiple
versions and which parents require them. It shows the specifier detail
but doesn't classify conflicts or provide exit codes for scripting. -
write_constraints_fileresolves conflicts by cascade: process
packages alphabetically, skip edges from already-resolved parent
versions, pick the highest feasible version. This runs post-build
and discovers conflicts only after all wheels are built.
Neither checks graph structure (dangling edges, cycles) or answers the
pre-rebuild question: which conflicts can be resolved by pinning, and
which will cause write_constraints_file to fail?
Proposal
Add a graph check command that checks a previous build's graph.json
in seconds. It performs three checks:
| Check | What it catches |
|---|---|
| Well-formed | Dangling edges — targets referenced but not in graph (would crash from_dict) |
| Acyclic | Self-loops and cycles in raw JSON (absorbed by from_dict, invisible after construction) |
| Version-unique | Multiple versions of the same package — extra builds, potential conflicts |
When version-unique fails, the command classifies each multi-version
package using the same specifier.filter logic as show_explain_duplicates
and write_constraints_file:
- Collapsible: one version satisfies all consumer specifiers. The extra
version was an unnecessary build. Reports the feasible pin and binding
parent. - Required: no single version satisfies all consumers.
write_constraints_filewill fail for this package.
The classification is conservative relative to write_constraints_file:
it checks specifiers from ALL parent versions, while the resolver cascades
(skips edges from already-resolved parents). So:
- Collapsible here guarantees
write_constraints_filesucceeds - Required here may overcount — the resolver's cascade may resolve some
This is the right trade-off for a pre-rebuild gate: false positives for
"required" are safe (the maintainer investigates), false negatives for
"collapsible" would be dangerous (silent build failure).
Output modes
- Human-readable (default): three-check summary, build efficiency, conflict
detail with binding parents and specifiers --json: machine-readable for CI integration--constraints: collapsible pins inconstraints.txtformat
Exit codes
- 0: all checks pass
- 1: any check fails (dangling edges, cycles, or version conflicts)
Background
This work comes from fromager-analyze,
an external analysis tool that checks graph.json for structural properties
and version conflicts. The tool was validated against real e2e graphs:
| Graph | Nodes | Well-formed | Acyclic | Version-unique | Conflicts |
|---|---|---|---|---|---|
| build-parallel | 16 | PASS | PASS | PASS | 0 |
| conflict-graph | 301 | PASS | PASS | FAIL | 24 (20 collapsible, 4 required) |
| old-graph | 219 | FAIL (4 dangling) | FAIL (self-loops) | FAIL | 12 |
The accompanying PR brings the core validation into fromager proper, where it has access
to DependencyGraph and packaging directly rather than reimplementing
them.
Scope
The PR will add:
_check_well_formed()— dangling edge detection on raw graph dict_check_acyclicity()— cycle and self-loop detection on raw graph dict_classify_conflicts()— collapsible/required classification via
DependencyGraph_print_check()— human-readable, JSON, and constraints outputcheckCLI command underfromager graph- 25 tests covering all checks, output modes, and edge cases
Follow on RFE/PR will add the maintainer skill to use this tool.