From 8a755df167162f38817f89252efd3589bf3d6cad Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Thu, 29 Oct 2026 11:20:31 +0100 Subject: [PATCH] Refuse to publish constraints when the branch moved during generation A regular constraints refresh resolves its pins against the constraints branch as it is when the run starts, then commits them on top of the branch as it is when the run ends. When Release constraints commits a release candidate's pins in between, the refresh overwrote them with pins resolved against the older baseline, and the push still succeeded because it was an ordinary fast-forward. The two workflows run in different concurrency groups, so nothing serialised them. The publish now fails instead and asks for a re-run, which then starts from the candidate's constraints. Generated-by: Claude Opus 5 --- .../workflows/update-constraints-on-push.yml | 28 +++++++++++++++++++ ..._GENERATING_IMAGE_CACHE_AND_CONSTRAINTS.md | 6 ++++ 2 files changed, 34 insertions(+) diff --git a/.github/workflows/update-constraints-on-push.yml b/.github/workflows/update-constraints-on-push.yml index ba55e09d9eb2e..4c84567e23db5 100644 --- a/.github/workflows/update-constraints-on-push.yml +++ b/.github/workflows/update-constraints-on-push.yml @@ -99,6 +99,7 @@ jobs: default-python-version: ${{ steps.selective-checks.outputs.default-python-version }} python-versions: ${{ steps.selective-checks.outputs.python-versions }} python-versions-list-as-string: ${{ steps.selective-checks.outputs.python-versions-list-as-string }} + constraints-baseline-sha: ${{ steps.constraints-baseline.outputs.sha }} steps: - name: "Cleanup repo" shell: bash @@ -129,6 +130,19 @@ jobs: VERBOSE: "false" GITHUB_CONTEXT_INPUT: "${{ runner.temp }}/github_context.json" run: breeze ci selective-check 2>> ${GITHUB_OUTPUT} + # Recorded before the constraints are generated, so any commit landing on the branch while + # this run works - a release candidate's constraints above all - stops the publish below + # instead of being overwritten by pins resolved against the older baseline. + - name: "Record the constraints baseline" + id: constraints-baseline + shell: bash + env: + CONSTRAINTS_BRANCH: ${{ steps.selective-checks.outputs.default-constraints-branch }} + run: | + sha="$(git ls-remote "https://github.com/${GITHUB_REPOSITORY}" \ + "refs/heads/${CONSTRAINTS_BRANCH}" | cut -f1)" + echo "sha=${sha}" >> "${GITHUB_OUTPUT}" + echo "Constraints baseline: ${CONSTRAINTS_BRANCH} @ ${sha:-}" - name: "Parameters summary" shell: bash env: @@ -217,6 +231,20 @@ jobs: ref: ${{ env.CONSTRAINTS_BRANCH }} persist-credentials: true fetch-depth: 0 + - name: "Check ${{ env.CONSTRAINTS_BRANCH }} did not move while the constraints were generated" + working-directory: "constraints" + env: + BASELINE_SHA: ${{ needs.build-info.outputs.constraints-baseline-sha }} + run: | + current_sha="$(git rev-parse HEAD)" + if [[ -n "${BASELINE_SHA}" && "${current_sha}" != "${BASELINE_SHA}" ]]; then + echo "::error::${CONSTRAINTS_BRANCH} moved from ${BASELINE_SHA} to ${current_sha}" \ + "while this run generated its constraints. Publishing would overwrite those commits" \ + "with pins resolved against the older baseline. Re-run the workflow so it starts" \ + "from the current branch." + git log --oneline "${BASELINE_SHA}..${current_sha}" || true + exit 1 + fi - name: "Download constraints from the generate-constraints job" uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: diff --git a/dev/MANUALLY_GENERATING_IMAGE_CACHE_AND_CONSTRAINTS.md b/dev/MANUALLY_GENERATING_IMAGE_CACHE_AND_CONSTRAINTS.md index cd07deec80bed..b40f1f59c1d33 100644 --- a/dev/MANUALLY_GENERATING_IMAGE_CACHE_AND_CONSTRAINTS.md +++ b/dev/MANUALLY_GENERATING_IMAGE_CACHE_AND_CONSTRAINTS.md @@ -284,6 +284,12 @@ To run it: https://github.com/apache/airflow/commits/constraints--/ + If the run instead fails with "moved ... while this run generated its constraints", something + else committed to that branch while it was working - typically the `Release constraints` + workflow pinning a release candidate. The run refuses to overwrite that commit with pins + resolved against the older baseline; run it again so it starts from the current branch. + Automatic `uv.lock`-push runs behave the same way. + > [!NOTE] > Because `v3-3-test` and `v3-3-stable` can diverge while RCs are being voted on (fixes are > cherry-picked to `v3-3-test`), be deliberate about which `ref` you refresh from. Refresh from