[v3-3-test] Resolve the constraints a release ships instead of taggin… - #71081
Merged
Conversation
…g whatever exists (apache#71040) * Resolve the constraints a release ships instead of tagging whatever exists The constraints published with a version were whatever the constraints-X-Y branch happened to hold when the release ran - a resolution made by the last CI build, for the sources at that moment, rather than for the version being released. The candidate tagged that tip and the final release retagged the candidate, so no release ever resolved constraints of its own. A candidate now resolves them allowing pre-releases: the providers of the wave being voted on exist on PyPI only as rc versions, so constraints that refuse pre-releases cannot describe what a tester is asked to install. They land on a branch of the candidate's own, leaving the branch every other build reads where it was. The final release cannot promote those by retagging - a released version must never pin an rc - so it resolves the same set again, without pre-releases, and commits onto constraints-X-Y, which is what makes the released constraints the baseline everything downstream reads. Which of the two happens is derived from the version, so the stage cannot be set inconsistently with it. The work runs on CI runners rather than on the release manager's machine, which would otherwise need a CI image for every supported Python before it could cut a release, and is reachable on its own through `breeze workflow-run release-constraints` for redoing a candidate's constraints or producing them for a release cut before this existed. * Let only the providers answer with a pre-release `--pre` applies to the whole resolution, so a candidate's constraints could pin a pre-release of any dependency - a beta of some third-party library would end up in what a release ships, which is not what allowing rc providers was meant to permit. uv considers a pre-release for a package only when a requirement for it mentions one, so naming the providers with a pre-release lower bound confines the allowance to them and leaves every other package on the default policy. * State the pre-release scoping rather than leaning on uv's default The rc lower bounds already confined pre-releases to the providers, but only because uv's default strategy happens to permit them for explicitly marked packages. Naming `explicit` says that in the command instead of leaving it to a default that could change, and drops the `if-necessary` half of that default - the part that would let a package nobody marked resolve to a pre-release when no final version satisfies it. * Document what a release manager now sees at the constraints step The candidate half was undocumented - the release notes described only what the final release does, leaving a release manager to infer why a candidate suddenly grows a branch and a tag of its own, and why its constraints pin rc providers when nothing else in them is a pre-release. Both stages and the scope of the pre-release allowance are stated where each is reached. * Register the new constraints command where the docs checks look for it A command has to be grouped in its `*_commands_config.py` and embedded in one of the breeze docs, or the static checks reject it - `--allow-pre-releases` had no group and `workflow-run release-constraints` had a generated screenshot that nothing referenced. The two `setup` screenshots move because the command list they render is exactly what gained the new entry. (cherry picked from commit 26d53bd) Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
potiuk
requested review from
amoghrajesh,
ashb,
bugraoz93,
choo121600,
ephraimbuddy,
gopidesupavan,
jason810496,
jedcunningham,
jscheffl,
shahar1,
vatsrahul1001 and
vincbeck
as code owners
August 4, 2026 10:05
The cherry-pick created the test file in full, including the cases for the provider-downgrade check, which exists only on main - this branch has no check_providers_not_downgraded for them to exercise, so seven of the nine tests fail on an attribute that is not there. What the picked commit added here is the pre-release requirement builder, and that is what the file is left holding.
Merged
1 task
vatsrahul1001
pushed a commit
that referenced
this pull request
Aug 5, 2026
#71081) * [v3-3-test] Resolve the constraints a release ships instead of tagging whatever exists (#71040) * Resolve the constraints a release ships instead of tagging whatever exists The constraints published with a version were whatever the constraints-X-Y branch happened to hold when the release ran - a resolution made by the last CI build, for the sources at that moment, rather than for the version being released. The candidate tagged that tip and the final release retagged the candidate, so no release ever resolved constraints of its own. A candidate now resolves them allowing pre-releases: the providers of the wave being voted on exist on PyPI only as rc versions, so constraints that refuse pre-releases cannot describe what a tester is asked to install. They land on a branch of the candidate's own, leaving the branch every other build reads where it was. The final release cannot promote those by retagging - a released version must never pin an rc - so it resolves the same set again, without pre-releases, and commits onto constraints-X-Y, which is what makes the released constraints the baseline everything downstream reads. Which of the two happens is derived from the version, so the stage cannot be set inconsistently with it. The work runs on CI runners rather than on the release manager's machine, which would otherwise need a CI image for every supported Python before it could cut a release, and is reachable on its own through `breeze workflow-run release-constraints` for redoing a candidate's constraints or producing them for a release cut before this existed. * Let only the providers answer with a pre-release `--pre` applies to the whole resolution, so a candidate's constraints could pin a pre-release of any dependency - a beta of some third-party library would end up in what a release ships, which is not what allowing rc providers was meant to permit. uv considers a pre-release for a package only when a requirement for it mentions one, so naming the providers with a pre-release lower bound confines the allowance to them and leaves every other package on the default policy. * State the pre-release scoping rather than leaning on uv's default The rc lower bounds already confined pre-releases to the providers, but only because uv's default strategy happens to permit them for explicitly marked packages. Naming `explicit` says that in the command instead of leaving it to a default that could change, and drops the `if-necessary` half of that default - the part that would let a package nobody marked resolve to a pre-release when no final version satisfies it. * Document what a release manager now sees at the constraints step The candidate half was undocumented - the release notes described only what the final release does, leaving a release manager to infer why a candidate suddenly grows a branch and a tag of its own, and why its constraints pin rc providers when nothing else in them is a pre-release. Both stages and the scope of the pre-release allowance are stated where each is reached. * Register the new constraints command where the docs checks look for it A command has to be grouped in its `*_commands_config.py` and embedded in one of the breeze docs, or the static checks reject it - `--allow-pre-releases` had no group and `workflow-run release-constraints` had a generated screenshot that nothing referenced. The two `setup` screenshots move because the command list they render is exactly what gained the new entry. (cherry picked from commit 26d53bd) Co-authored-by: Jarek Potiuk <jarek@potiuk.com> * Trim the backported constraints tests to what this branch implements The cherry-pick created the test file in full, including the cases for the provider-downgrade check, which exists only on main - this branch has no check_providers_not_downgraded for them to exercise, so seven of the nine tests fail on an attribute that is not there. What the picked commit added here is the pre-release requirement builder, and that is what the file is left holding.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…g whatever exists (#71040)
The constraints published with a version were whatever the constraints-X-Y branch happened to hold when the release ran - a resolution made by the last CI build, for the sources at that moment, rather than for the version being released. The candidate tagged that tip and the final release retagged the candidate, so no release ever resolved constraints of its own.
A candidate now resolves them allowing pre-releases: the providers of the wave being voted on exist on PyPI only as rc versions, so constraints that refuse pre-releases cannot describe what a tester is asked to install. They land on a branch of the candidate's own, leaving the branch every other build reads where it was. The final release cannot promote those by retagging - a released version must never pin an rc - so it resolves the same set again, without pre-releases, and commits onto constraints-X-Y, which is what makes the released constraints the baseline everything downstream reads.
Which of the two happens is derived from the version, so the stage cannot be set inconsistently with it. The work runs on CI runners rather than on the release manager's machine, which would otherwise need a CI image for every supported Python before it could cut a release, and is reachable on its own through
breeze workflow-run release-constraintsfor redoing a candidate's constraints or producing them for a release cut before this existed.--preapplies to the whole resolution, so a candidate's constraints could pin a pre-release of any dependency - a beta of some third-party library would end up in what a release ships, which is not what allowing rc providers was meant to permit. uv considers a pre-release for a package only when a requirement for it mentions one, so naming the providers with a pre-release lower bound confines the allowance to them and leaves every other package on the default policy.The rc lower bounds already confined pre-releases to the providers, but only because uv's default strategy happens to permit them for explicitly marked packages. Naming
explicitsays that in the command instead of leaving it to a default that could change, and drops theif-necessaryhalf of that default - the part that would let a package nobody marked resolve to a pre-release when no final version satisfies it.The candidate half was undocumented - the release notes described only what the final release does, leaving a release manager to infer why a candidate suddenly grows a branch and a tag of its own, and why its constraints pin rc providers when nothing else in them is a pre-release. Both stages and the scope of the pre-release allowance are stated where each is reached.
A command has to be grouped in its
*_commands_config.pyand embedded in one of the breeze docs, or the static checks reject it ---allow-pre-releaseshad no group andworkflow-run release-constraintshad a generated screenshot that nothing referenced. The twosetupscreenshots move because the command list they render is exactly what gained the new entry.(cherry picked from commit 26d53bd)
Was generative AI tooling used to co-author this PR?
{pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.