Skip to content

Release plan

release_plan

Build a deterministic, read-only workspace release plan.

plan_releases(root, ref='HEAD')

Plan every actual member at a pinned revision without any Git mutation.

Inventory/tag discovery runs once; manifests use one cat-file batch. Only changed packages query scoped history. Optional extras are reported intact rather than introducing plugin cycles into the mandatory order. Conditional mandatory requirements are conservatively included across target platforms.

Source code in packages/axm-git/src/axm_git/core/release_plan.py
Python
def plan_releases(root: Path, ref: str = "HEAD") -> dict[str, object]:
    """Plan every actual member at a pinned revision without any Git mutation.

    Inventory/tag discovery runs once; manifests use one cat-file batch. Only
    changed packages query scoped history. Optional extras are reported intact
    rather than introducing plugin cycles into the mandatory order. Conditional
    mandatory requirements are conservatively included across target platforms.
    """
    inventory = read_inventory(root, ref)
    order = release_order(inventory.packages)
    by_name = {p.name: p for p in inventory.packages}
    entries = [_entry(inventory, by_name[name]) for name in order]
    return {
        "ref": inventory.ref,
        "order": order,
        "packages": entries,
        "excluded": list(inventory.excluded),
        "ready": True,
        "warnings": [
            "Optional requirements need index availability checks before publication.",
            "Only local tags are inspected; verify relevant remote tag identities.",
        ],
    }

release_order(packages)

Order mandatory prerequisites first, with stable independent-node ties.

Source code in packages/axm-git/src/axm_git/core/release_plan.py
Python
def release_order(packages: tuple[Package, ...]) -> list[str]:
    """Order mandatory prerequisites first, with stable independent-node ties."""
    names = {p.name for p in packages}
    graph = {
        p.name: {canonicalize_name(Requirement(r).name) for r in p.required} & names
        for p in packages
    }
    try:
        sorter = TopologicalSorter(graph)
        sorter.prepare()
    except CycleError as exc:
        raise ValueError(f"Mandatory release dependency cycle: {exc.args[1]}") from exc
    order = []
    while sorter.is_active():
        ready = sorted(sorter.get_ready())
        order.extend(ready)
        sorter.done(*ready)
    return order