Repository navigation
Python: coordinate release batches with Azure DevOps - #9821
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Release batches can omit untracked packages, misidentify moved or renamed distributions, validate the wrong revision, or reuse an existing release tag.
4 open issues
What changed in this PR
This PR adds the GitHub-side preparation and validation for coordinated Python release batches, supporting the Azure DevOps release pipeline planned in #2661. Production publishing moves to the separately coordinated Azure DevOps consumer; no package versions change here.
Changes:
- Generate and validate a reviewed release manifest containing selected versions and public smoke imports.
- Replace GitHub release asset building with read-only checks and retire local publish tasks.
- Document the protected publisher handoff, recovery procedures, and rollout order.
| File | Description |
|---|---|
python/shared_tasks.toml |
Removes the shared local publish task. |
python/scripts/tests/test_prepare_release.py |
Adds selection, manifest validation, and smoke-import inventory tests. |
python/scripts/prepare_release.py |
Generates and validates release batch manifests. |
python/pyproject.toml |
Adds the preparation task and removes root publishing. |
python/DEV_SETUP.md |
Documents the revised release preparation commands. |
python/.github/skills/agent-framework-py-release/SKILL.md |
Defines batch preparation, handoff, recovery, and rollout procedures. |
docs/decisions/0046-python-coordinated-release-batches.md |
Proposes the coordinated single-publisher release design. |
.github/workflows/python-release.yml |
Replaces asset publishing with read-only PR and release-tag validation. |
Review effort: Balanced
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: Findings reported
Scope: full PR (2 commit(s)): a1773d4d9b5f, 2b1a1efbd8cc
Model: gpt-5.6-sol
Overview
This PR moves Python release selection into a reviewed manifest and leaves GitHub with read-only validation while Azure DevOps owns publication. Exact-tag checkout, manifest/package equality, canonical-name checks, smoke-import coverage, and focused tests provide strong guardrails. Two uncommon selection states can still omit a distribution that the reviewed batch must contain: the documented root/Core coupling and a renamed distribution identity.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
2 verified findings remained after source verification (2 medium) across 1 file. Details are attached to the affected lines below.
Affected areas: python/scripts/prepare_release.py
There was a problem hiding this comment.
MAF Automated Review — Iteration 2
Result: Findings reported
Scope: 3 net-new commit(s): 3ce39b089edb, b5a5412f537d, 208bcb06dc6d
Model: gpt-5.6-sol
Overview
The incremental update replaces the fixed manifest with an exact per-tag path and adds strong guards against fallback lookup, malformed paths, historical edits, and filename/content mismatches. The read-only workflow and focused tests provide good protection for those invariants. One remaining selection gate blocks ordinary new-package PRs by treating package creation as immediate release intent.
Reviewed the supplied incremental change set across correctness, security/reliability, architecture, and failure behavior.
1 verified finding remained after source verification (1 medium) across 1 file. Details are attached to the affected lines below.
Affected areas: python/scripts/prepare_release.py

Motivation & Context
Python release preparation selects independently versioned distributions, but the existing GitHub workflow builds and uploads assets only after a release is public. Hand that reviewed batch to one protected Azure DevOps publisher instead, without granting GitHub Azure DevOps API credentials or federated queue permission.
Description & Review Guide
prepare-python-releaseto generatepython/.github/release-<fulltag>.jsonin the version-bump PR from the existing changed-metadata selection, retaining actual version increases and new workspace packages only. For example,python-1.24.0usespython/.github/release-python-1.24.0.json. Earlier per-tag files remain unchanged and browsable onmain; CI requires one new manifest, rejects historical edits/deletions/renames, and validates only the new batch against current package metadata. Versions come frompyproject.toml, not a duplicate manual list or PyPI absence. Generate reviewed publicmodule:exportsmoke imports for all selected distributions; cover the current workspace inventory and reject unknown distributions, invalid names/versions, per-package tags, filename/content tag mismatches, and missing selected packages. Replace the old asset-building/uploading release workflow with read-only PR and exact-tag validation. Retire root/shared local production publish tasks. Keep release procedures in the release skill, remove obsolete publication guidance from developer setup. Producer and consumer derive the exact manifest filename from the validated expected full tag, with no fixed/root/latest-file fallback.python-*tag plus an existing maintainer-created draft initiates one Azure DevOps run for the whole batch. Azure DevOps owns build-once artifacts, isolated checks, protected ESRP approval/publication, post-publication verification, exact asset upload to the existing draft, and finaldraft:false, preserving title/body/prerelease metadata. GitHub only validates. Historical source manifests record reviewed intended batches, not proof of publication; the verified artifact manifest on the published release records what shipped. Dependency-only maintenance remains supported without adding a manifest or revalidating old versions. This infrastructure PR does not change package versions or generate an actual production batch, tag, or draft.Focused checks completed locally:
cd python && uv run --no-project --python 3.12 --with packaging==26.3 --with rich --with pytest==9.1.1 python -m pytest -c /dev/null -p no:cacheprovider scripts/tests/test_prepare_release.py scripts/dependencies/tests/test_dependency_bounds_release.py -q- passed, 64 tests, including exact per-tag paths, historical preservation, edit/delete/rename rejection, filename/content mismatch, multiple-batch rejection, and no fixed/root/other-tag fallback.cd python && uv run --no-project --with-requirements tooling/requirements-quality.txt ruff check --isolated --select E,F,I,UP --line-length 120 scripts/prepare_release.py scripts/tests/test_prepare_release.py- passed; both files also formatted with the same Ruff bundle.go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 .github/workflows/python-release.yml- passed.cd python && uv lock --check- passed, lockfile unchanged.cd python && uv run --no-project --with pygments==2.21.0 python -m scripts.check_md_code_blocks --no-glob .github/skills/agent-framework-py-release/SKILL.md- passed.cd python && uv run --no-project --python 3.12 --with packaging==26.3 --with rich python -m scripts.prepare_release --check --ci --base-ref origin/main- passed, unrelated metadata-only PR correctly skips release-batch validation.cd python && uv run --no-project --with packaging==26.3 --with rich --with poethepoet==0.49.0 poe -d prepare-python-release --base-ref origin/main --tag python-1.24.0- passed before the manifest filename update; the generator's CLI arguments are unchanged.The full runtime suite and real Azure DevOps/ESRP/publication flow were not run. No production tags/drafts, package publication, Azure resource changes, or discovery activation were performed.
Related Issue
Related to #2661. This PR implements the GitHub producer and retirement of the old asset path; the Azure DevOps consumer and operator activation are separate. No competing open PR was found for #2661. The issue has no
ready-for-implementationlabel or agreement comment yet, maintainer confirmation and coordinated review remain required.AI Assistance
AI assistance details: Copilot assisted with implementation, focused tests, workflow changes, documentation and this PR description.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after a language prefix) — a workflow keeps the label and title prefix in sync automatically.