This is an automated email from the ASF dual-hosted git repository.

vatsrahul1001 pushed a commit to branch v3-4-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-4-test by this push:
     new 864f1077ef2 [v3-4-test] Commit pre-release constraints onto the shared 
constraints-X-Y branch (#75329) (#75592)
864f1077ef2 is described below

commit 864f1077ef26b9ef7a307064cd3940189bef9771
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sun Oct 25 06:19:54 2026 +0000

    [v3-4-test] Commit pre-release constraints onto the shared constraints-X-Y 
branch (#75329) (#75592)
    
    * Commit pre-release constraints onto the shared constraints-X-Y branch
    
    A per-candidate constraints-<VERSION> branch shares its name with the
    constraints-<VERSION> tag, which makes the ref ambiguous for git and for
    anything resolving constraints by name. Keeping a single constraints-X-Y
    branch history for betas, rcs and finals removes the ambiguity, and a
    leftover per-candidate branch is now reported instead of silently kept.
    
    Generated-by: Claude Opus 5
    
    * Rebase-and-retry the shared-branch push; fix remote in stale-branch hint
    
    Pushing pre-release constraints onto the shared constraints-X-Y branch is a
    plain push, but that branch is also written by 
update-constraints-on-push.yml
    on every vX-Y-test uv.lock change -- which happens during the same beta/rc
    window this workflow runs in. A concurrent write makes the push a
    non-fast-forward and fails the job, forcing a manual re-run. Rebase onto the
    latest and retry (up to 5x) so a routine rolling-constraints commit no 
longer
    breaks the release run.
    
    The stale-branch error hint printed 'git push upstream --delete', but the
    workflow uses 'origin' throughout; align the hint to 'origin' so the pasted
    command targets the right remote in the RM checkout.
    
    ---------
    (cherry picked from commit fd52d8703fb3eca7bd9bdc08005e7b532097c49b)
    
    Co-authored-by: Jarek Potiuk <[email protected]>
    Co-authored-by: Rahul Vats <[email protected]>
---
 .github/workflows/release-constraints.yml | 46 +++++++++++++++++++------------
 dev/README_RELEASE_AIRFLOW.md             | 19 +++++++------
 2 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/.github/workflows/release-constraints.yml 
b/.github/workflows/release-constraints.yml
index c2e61fc9090..fe74f5527f7 100644
--- a/.github/workflows/release-constraints.yml
+++ b/.github/workflows/release-constraints.yml
@@ -118,15 +118,14 @@ jobs:
           constraints_branch="constraints-${major}-${minor}"
           echo "constraints-branch=${constraints_branch}" >> "${GITHUB_OUTPUT}"
           # A pre-release - beta or rc - pins the providers at the versions 
PyPI holds (rc provider
-          # waves included) and lands on a branch and tag of its own, so it 
never moves the shared
-          # constraints-X-Y branch. A final pins released providers and 
commits onto the shared branch.
+          # waves included); a final pins released providers. Both commit onto 
the shared
+          # constraints-X-Y branch and are tagged constraints-<VERSION>.
           if [[ "${VERSION}" =~ (b|rc)[0-9]+$ ]]; then
             echo "allow-pre-releases=true" >> "${GITHUB_OUTPUT}"
-            echo "target-branch=constraints-${VERSION}" >> "${GITHUB_OUTPUT}"
           else
             echo "allow-pre-releases=false" >> "${GITHUB_OUTPUT}"
-            echo "target-branch=${constraints_branch}" >> "${GITHUB_OUTPUT}"
           fi
+          echo "target-branch=${constraints_branch}" >> "${GITHUB_OUTPUT}"
       - name: "Parameters summary"
         shell: bash
         env:
@@ -231,30 +230,29 @@ jobs:
         with:
           pattern: constraints-*
           path: ./files
-      # A candidate's branch and tag belong to that candidate alone, so 
re-running for the same
-      # rc replaces them rather than adding to them: the branch would 
otherwise already hold the
-      # previous run's constraints (making the push a non-fast-forward) and 
the tag already exist.
-      # A final never gets this - it commits onto the shared constraints-X-Y 
branch, whose history
-      # every other build reads.
-      - name: "Delete the previous ${{ needs.build-info.outputs.target-branch 
}} branch and tag"
+      # Re-running for the same pre-release adds a commit on constraints-X-Y 
and moves its tag, so
+      # the previous run's tag is deleted first. A leftover 
constraints-<VERSION> branch (from when
+      # pre-releases had a branch of their own) would make that tag name 
ambiguous, so it fails fast.
+      - name: "Check for a stale constraints-${{ inputs.version }} branch and 
replace the tag"
         if: needs.build-info.outputs.allow-pre-releases == 'true'
         working-directory: "constraints"
         shell: bash
         run: |
-          if git ls-remote --exit-code origin "refs/heads/${TARGET_BRANCH}" > 
/dev/null; then
-            echo "Deleting the existing '${TARGET_BRANCH}' branch."
-            git push origin --delete "refs/heads/${TARGET_BRANCH}"
+          if git ls-remote --exit-code origin 
"refs/heads/constraints-${VERSION}" > /dev/null; then
+            echo "ERROR! Branch 'constraints-${VERSION}' must not exist -" \
+              "it would make the 'constraints-${VERSION}' tag ambiguous."
+            echo "Delete it first, e.g.: git push origin --delete 
'refs/heads/constraints-${VERSION}'"
+            exit 1
           fi
           if git ls-remote --exit-code origin 
"refs/tags/constraints-${VERSION}" > /dev/null; then
             echo "Deleting the existing 'constraints-${VERSION}' tag."
             git push origin --delete "refs/tags/constraints-${VERSION}"
           fi
           git tag --delete "constraints-${VERSION}" > /dev/null 2>&1 || true
-          git branch --delete --force "${TARGET_BRANCH}" > /dev/null 2>&1 || 
true
       - name: "Switch to ${{ needs.build-info.outputs.target-branch }}"
         working-directory: "constraints"
         shell: bash
-        run: git switch -c "${TARGET_BRANCH}" 2>/dev/null || git switch 
"${TARGET_BRANCH}"
+        run: git switch "${TARGET_BRANCH}"
       - name: "Diff in constraints for Python: ${{ 
needs.build-info.outputs.python-versions-list-as-string }}"
         run: ./scripts/ci/constraints/ci_diff_constraints.sh
       - name: "Commit changed constraint files"
@@ -262,9 +260,21 @@ jobs:
       - name: "Push ${{ needs.build-info.outputs.target-branch }}"
         working-directory: "constraints"
         shell: bash
-        # Qualify as refs/heads/ -- for a release candidate the branch and the 
tag share a name
-        # (both constraints-<VERSION>), so a bare refspec is ambiguous 
("matches more than one").
-        run: git push origin "refs/heads/${TARGET_BRANCH}"
+        # constraints-X-Y is also written by update-constraints-on-push.yml on 
every vX-Y-test
+        # uv.lock change, which can land during the beta/rc window this 
workflow runs in. A
+        # concurrent write makes this push a non-fast-forward, so rebase onto 
the latest and retry.
+        # Qualify as refs/heads/ so the push never resolves to a same-named 
tag.
+        run: |
+          for attempt in $(seq 1 5); do
+            if git push origin "refs/heads/${TARGET_BRANCH}"; then
+              exit 0
+            fi
+            echo "Push of '${TARGET_BRANCH}' rejected (it moved underneath 
us);" \
+              "rebasing onto the latest and retrying (attempt ${attempt}/5)."
+            git pull --rebase origin "${TARGET_BRANCH}"
+          done
+          echo "ERROR! Could not push '${TARGET_BRANCH}' after 5 attempts."
+          exit 1
       - name: "Tag constraints-${{ inputs.version }}"
         working-directory: "constraints"
         shell: bash
diff --git a/dev/README_RELEASE_AIRFLOW.md b/dev/README_RELEASE_AIRFLOW.md
index 5c81a5f8461..be218b3f6eb 100644
--- a/dev/README_RELEASE_AIRFLOW.md
+++ b/dev/README_RELEASE_AIRFLOW.md
@@ -182,8 +182,8 @@ no vote.
 
    It validates that `vX-Y-test` exists, checks out its tip, tags the beta 
there, builds and signs
    the artifacts, resolves constraints through the `release-constraints` 
workflow from `vX-Y-test`
-   (exactly like an `rc`: provider rc waves are allowed and the result lands 
on its own
-   `constraints-X.Y.0bN` branch and tag, leaving the shared `constraints-X-Y` 
untouched), uploads to
+   (exactly like an `rc`: provider rc waves are allowed, the result is 
committed onto the shared
+   `constraints-X-Y` branch and tagged `constraints-X.Y.0bN`), uploads to
    SVN dev and PyPI, and pushes the tags. Everything downstream of the tag is 
the same as an `rc`;
    only the branch/sync/vote handling differs.
 
@@ -722,9 +722,9 @@ still works but is no longer recommended.
    allowance is scoped to `apache-airflow-providers-*`; no other package can 
resolve to a
    pre-release, so a beta of some third-party library cannot slip into what 
the candidate ships.
 
-   The result lands on a branch of its own (`constraints-${VERSION_RC}`) and 
is tagged
-   `constraints-${VERSION_RC}`. The shared `constraints-X-Y` branch is left 
where it was — only
-   the final release moves it.
+   The result is committed onto the shared `constraints-X-Y` branch and tagged
+   `constraints-${VERSION_RC}`. There is no `constraints-${VERSION_RC}` branch 
— a branch with the
+   same name as the tag would make the name ambiguous, so the workflow fails 
if it finds one.
 
    **Testing the start-rc-process command:**
    Before running the actual release command, you can safely test it using:
@@ -1557,7 +1557,7 @@ disagree with the version:
 
 | `--version` | Provider pins | Lands on | Tagged |
 |---|---|---|---|
-| `3.3.1rc1` | newest in PyPI, `rcN` included | `constraints-3.3.1rc1`, 
branched off `constraints-3-3` | `constraints-3.3.1rc1` |
+| `3.3.1rc1` | newest in PyPI, `rcN` included | `constraints-3-3` (commit) | 
`constraints-3.3.1rc1` |
 | `3.3.1` | newest final in PyPI | `constraints-3-3` (commit) | 
`constraints-3.3.1` |
 
 The providers are pinned rather than resolved: every 
`apache-airflow-providers-*` is named with
@@ -1568,9 +1568,10 @@ candidate in the wave keeps its release. A final ignores 
candidates entirely, wh
 it impossible for a released constraints file to carry an `rc` pin. Nothing 
else in the dependency
 graph can resolve to a pre-release, since no other requirement mentions one.
 
-Re-running the workflow for the same candidate deletes and re-creates that 
candidate's branch and
-tag, so redoing a candidate's constraints just works. A final is never treated 
this way - it commits
-onto the shared `constraints-X-Y` branch, whose history everything downstream 
reads.
+Re-running the workflow for the same candidate adds another commit onto 
`constraints-X-Y` and
+re-creates the candidate's tag on it, so redoing a candidate's constraints 
just works. If a
+leftover `constraints-${VERSION}` branch exists (from when candidates had a 
branch of their own),
+the workflow stops and asks for it to be deleted first.
 
 
 4. Make sure to update Airflow version in ``v3-*-test`` branch after 
cherry-picking to X.Y.1 in

Reply via email to