meel-ayush commented on code in PR #76957:
URL: https://github.com/apache/airflow/pull/76957#discussion_r4557645050


##########
.github/workflows/test-providers-branch-tip.yml:
##########
@@ -0,0 +1,254 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+---
+# Runs the provider tests from main against Airflow built from the tips of the 
release branches, the
+# code of the next Airflow release before it is released. The compatibility 
tests of
+# `test-providers.yml` only cover released versions from PyPI.
+#
+# Each branch tip is resolved to one commit for the whole run, and built into 
wheels once, the way a
+# release is built (with the compiled UI). The test jobs install those wheels 
from `dist`, so the resolver
+# cannot replace them with a released Airflow of the same version number.
+name: Provider branch tip compatibility tests
+
+permissions:
+  contents: read
+on:  # yamllint disable-line rule:truthy
+  workflow_call:
+    inputs:
+      runners:
+        description: "The array of labels (in json form) determining runners."
+        required: true
+        type: string
+      platform:
+        description: "Platform for the build - 'linux/amd64' or 'linux/arm64'"
+        required: true
+        type: string
+      latest-release:
+        description: >
+          JSON object of the latest Airflow release in the compatibility 
matrix (airflow-version,
+          python-version, remove-providers). The vX-Y-test branches from its 
X.Y on are tested.
+        required: true
+        type: string
+      providers-test-types-list-as-strings-in-json:
+        description: "List of parallel provider test types as string"
+        required: true
+        type: string
+      use-uv:
+        description: "Whether to use uv to build the image (true/false)"
+        required: true
+        type: string
+
+jobs:
+  find-branch-tips:
+    name: "Find release branch tips"
+    runs-on: ["ubuntu-slim"]
+    outputs:
+      targets: ${{ steps.find.outputs.targets }}
+    steps:
+      - name: "Resolve the release branches from the latest release on to 
their current commits"
+        id: find
+        env:
+          LATEST_RELEASE: ${{ inputs.latest-release }}
+          GH_TOKEN: ${{ github.token }}
+          REPOSITORY: ${{ github.repository }}
+        run: |
+          if ! jq -e 'has("airflow-version")' <<< "${LATEST_RELEASE}" > 
/dev/null; then
+            echo "No released Airflow version to start from"
+            echo "targets=[]" >> "${GITHUB_OUTPUT}"
+            exit 0
+          fi
+          gh api --paginate 
"repos/${REPOSITORY}/git/matching-refs/heads/constraints-" \
+            --jq '.[].ref | ltrimstr("refs/heads/")' > 
"${RUNNER_TEMP}/constraints-branches.txt"
+          # Versions compare as numbers: the API lists v2-10-test before 
v2-9-test.
+          gh api --paginate "repos/${REPOSITORY}/git/matching-refs/heads/v" 
--jq '.[]' \
+            | jq -s -c --argjson release "${LATEST_RELEASE}" \
+                --rawfile constraints 
"${RUNNER_TEMP}/constraints-branches.txt" '
+                ($release["airflow-version"] | split(".")[:2] | map(tonumber)) 
as $floor
+                | ($constraints | split("\n")) as $constraint_branches
+                | [ .[]
+                    | (.ref | 
capture("^refs/heads/v(?<major>[0-9]+)-(?<minor>[0-9]+)-test$")) as $v
+                    | select([($v.major | tonumber), ($v.minor | tonumber)] >= 
$floor)
+                    | {
+                        branch: "v\($v.major)-\($v.minor)-test",
+                        sha: .object.sha,
+                        "airflow-constraints-reference": 
"constraints-\($v.major)-\($v.minor)",
+                        "python-version": $release["python-version"],
+                        "remove-providers": $release["remove-providers"]
+                      }
+                    | . + {"has-constraints": 
(."airflow-constraints-reference" | IN($constraint_branches[]))}
+                  ]' > "${RUNNER_TEMP}/branch-tips.json"
+          jq -r '.[] | select(."has-constraints") | "\(.branch): \(.sha)"' 
"${RUNNER_TEMP}/branch-tips.json"
+          # The constraints branch of a new release branch is created after 
the branch itself.
+          jq -r '.[] | select(."has-constraints" | not)
+            | "::notice::\(.branch): skipped, 
\(."airflow-constraints-reference") does not exist yet"' \
+            "${RUNNER_TEMP}/branch-tips.json"
+          echo "targets=$(jq -c '[.[] | select(."has-constraints") | 
del(."has-constraints")]' \
+            "${RUNNER_TEMP}/branch-tips.json")" >> "${GITHUB_OUTPUT}"
+
+  build-airflow:
+    timeout-minutes: 30
+    name: "Build Airflow from ${{ matrix.target.branch }}"
+    needs: [find-branch-tips]
+    if: needs.find-branch-tips.outputs.targets != '[]'
+    runs-on: ${{ format(fromJSON(inputs.runners)[0], '8+16', '32+64') }}
+    strategy:
+      fail-fast: false
+      matrix:
+        target: ${{ fromJSON(needs.find-branch-tips.outputs.targets) }}
+    env:
+      GITHUB_REPOSITORY: ${{ github.repository }}
+      VERBOSE: "true"
+    steps:
+      - name: "Cleanup repo"
+        shell: bash
+        run: sudo rm -rf ${GITHUB_WORKSPACE}/*
+      # The branch is checked out in place of main, so the steps below run its 
own breeze and build
+      # scripts, which match its sources.
+      - name: "Checkout ${{ matrix.target.branch }} ( ${{ matrix.target.sha }} 
)"
+        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1  # 
v7.0.1
+        with:
+          ref: ${{ matrix.target.sha }}
+          persist-credentials: false

Review Comment:
   ```suggestion
           with:
             repository: apache/airflow
             ref: ${{ matrix.target.sha }}
             persist-credentials: false
   ```
   When `repository:` is omitted from `actions/checkout`, it defaults to the 
runner repository (`github.repository`). 
   
   On fork CI under ADIP-12, the runner tries to check out `matrix.target.sha` 
from the contributor's fork repository. Because that SHA only exists on 
upstream `apache/airflow`, checkout immediately crashes with:
   `fatal: reference is not a tree: <sha>`.
   
   Explicitly setting `repository: apache/airflow` ensures git fetches the tree 
object from upstream.



##########
.github/workflows/test-providers-branch-tip.yml:
##########
@@ -0,0 +1,254 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+---
+# Runs the provider tests from main against Airflow built from the tips of the 
release branches, the
+# code of the next Airflow release before it is released. The compatibility 
tests of
+# `test-providers.yml` only cover released versions from PyPI.
+#
+# Each branch tip is resolved to one commit for the whole run, and built into 
wheels once, the way a
+# release is built (with the compiled UI). The test jobs install those wheels 
from `dist`, so the resolver
+# cannot replace them with a released Airflow of the same version number.
+name: Provider branch tip compatibility tests
+
+permissions:
+  contents: read
+on:  # yamllint disable-line rule:truthy
+  workflow_call:
+    inputs:
+      runners:
+        description: "The array of labels (in json form) determining runners."
+        required: true
+        type: string
+      platform:
+        description: "Platform for the build - 'linux/amd64' or 'linux/arm64'"
+        required: true
+        type: string
+      latest-release:
+        description: >
+          JSON object of the latest Airflow release in the compatibility 
matrix (airflow-version,
+          python-version, remove-providers). The vX-Y-test branches from its 
X.Y on are tested.
+        required: true
+        type: string
+      providers-test-types-list-as-strings-in-json:
+        description: "List of parallel provider test types as string"
+        required: true
+        type: string
+      use-uv:
+        description: "Whether to use uv to build the image (true/false)"
+        required: true
+        type: string
+
+jobs:
+  find-branch-tips:
+    name: "Find release branch tips"
+    runs-on: ["ubuntu-slim"]
+    outputs:
+      targets: ${{ steps.find.outputs.targets }}
+    steps:
+      - name: "Resolve the release branches from the latest release on to 
their current commits"
+        id: find
+        env:
+          LATEST_RELEASE: ${{ inputs.latest-release }}
+          GH_TOKEN: ${{ github.token }}
+          REPOSITORY: ${{ github.repository }}

Review Comment:
   ```suggestion
             REPOSITORY: "apache/airflow"
   ```
   Under ADIP-12 ("Your PR, Your CI"), workflows run on runners inside the 
contributor's fork repository where `${{ github.repository }}` evaluates to 
`<fork-owner>/airflow`. 
   
   GitHub only clones the default branch (`main`) on fork creation; maintenance 
branches (`vX-Y-test`) and constraint branches (`constraints-*`) are not 
replicated to forks. Querying `${REPOSITORY}` causes `gh api` to return an 
empty array `[]`, setting `targets=[]` and causing the compatibility checks to 
silently no-op on all fork CI runs.
   
   Because `apache/airflow` is a public repo, runner `GITHUB_TOKEN`s have read 
access to query its refs directly.



##########
.github/workflows/test-providers-branch-tip.yml:
##########
@@ -0,0 +1,254 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+---
+# Runs the provider tests from main against Airflow built from the tips of the 
release branches, the
+# code of the next Airflow release before it is released. The compatibility 
tests of
+# `test-providers.yml` only cover released versions from PyPI.
+#
+# Each branch tip is resolved to one commit for the whole run, and built into 
wheels once, the way a
+# release is built (with the compiled UI). The test jobs install those wheels 
from `dist`, so the resolver
+# cannot replace them with a released Airflow of the same version number.
+name: Provider branch tip compatibility tests
+
+permissions:
+  contents: read
+on:  # yamllint disable-line rule:truthy
+  workflow_call:
+    inputs:
+      runners:
+        description: "The array of labels (in json form) determining runners."
+        required: true
+        type: string
+      platform:
+        description: "Platform for the build - 'linux/amd64' or 'linux/arm64'"
+        required: true
+        type: string
+      latest-release:
+        description: >
+          JSON object of the latest Airflow release in the compatibility 
matrix (airflow-version,
+          python-version, remove-providers). The vX-Y-test branches from its 
X.Y on are tested.
+        required: true
+        type: string
+      providers-test-types-list-as-strings-in-json:
+        description: "List of parallel provider test types as string"
+        required: true
+        type: string
+      use-uv:
+        description: "Whether to use uv to build the image (true/false)"
+        required: true
+        type: string
+
+jobs:
+  find-branch-tips:
+    name: "Find release branch tips"
+    runs-on: ["ubuntu-slim"]
+    outputs:
+      targets: ${{ steps.find.outputs.targets }}
+    steps:
+      - name: "Resolve the release branches from the latest release on to 
their current commits"
+        id: find
+        env:
+          LATEST_RELEASE: ${{ inputs.latest-release }}
+          GH_TOKEN: ${{ github.token }}
+          REPOSITORY: ${{ github.repository }}
+        run: |
+          if ! jq -e 'has("airflow-version")' <<< "${LATEST_RELEASE}" > 
/dev/null; then
+            echo "No released Airflow version to start from"
+            echo "targets=[]" >> "${GITHUB_OUTPUT}"
+            exit 0
+          fi
+          gh api --paginate 
"repos/${REPOSITORY}/git/matching-refs/heads/constraints-" \
+            --jq '.[].ref | ltrimstr("refs/heads/")' > 
"${RUNNER_TEMP}/constraints-branches.txt"
+          # Versions compare as numbers: the API lists v2-10-test before 
v2-9-test.
+          gh api --paginate "repos/${REPOSITORY}/git/matching-refs/heads/v" 
--jq '.[]' \
+            | jq -s -c --argjson release "${LATEST_RELEASE}" \
+                --rawfile constraints 
"${RUNNER_TEMP}/constraints-branches.txt" '
+                ($release["airflow-version"] | split(".")[:2] | map(tonumber)) 
as $floor
+                | ($constraints | split("\n")) as $constraint_branches
+                | [ .[]
+                    | (.ref | 
capture("^refs/heads/v(?<major>[0-9]+)-(?<minor>[0-9]+)-test$")) as $v
+                    | select([($v.major | tonumber), ($v.minor | tonumber)] >= 
$floor)
+                    | {
+                        branch: "v\($v.major)-\($v.minor)-test",
+                        sha: .object.sha,
+                        "airflow-constraints-reference": 
"constraints-\($v.major)-\($v.minor)",
+                        "python-version": $release["python-version"],
+                        "remove-providers": $release["remove-providers"]
+                      }
+                    | . + {"has-constraints": 
(."airflow-constraints-reference" | IN($constraint_branches[]))}
+                  ]' > "${RUNNER_TEMP}/branch-tips.json"
+          jq -r '.[] | select(."has-constraints") | "\(.branch): \(.sha)"' 
"${RUNNER_TEMP}/branch-tips.json"
+          # The constraints branch of a new release branch is created after 
the branch itself.
+          jq -r '.[] | select(."has-constraints" | not)
+            | "::notice::\(.branch): skipped, 
\(."airflow-constraints-reference") does not exist yet"' \
+            "${RUNNER_TEMP}/branch-tips.json"
+          echo "targets=$(jq -c '[.[] | select(."has-constraints") | 
del(."has-constraints")]' \
+            "${RUNNER_TEMP}/branch-tips.json")" >> "${GITHUB_OUTPUT}"
+
+  build-airflow:
+    timeout-minutes: 30
+    name: "Build Airflow from ${{ matrix.target.branch }}"
+    needs: [find-branch-tips]
+    if: needs.find-branch-tips.outputs.targets != '[]'
+    runs-on: ${{ format(fromJSON(inputs.runners)[0], '8+16', '32+64') }}
+    strategy:
+      fail-fast: false
+      matrix:
+        target: ${{ fromJSON(needs.find-branch-tips.outputs.targets) }}
+    env:
+      GITHUB_REPOSITORY: ${{ github.repository }}
+      VERBOSE: "true"
+    steps:
+      - name: "Cleanup repo"
+        shell: bash
+        run: sudo rm -rf ${GITHUB_WORKSPACE}/*
+      # The branch is checked out in place of main, so the steps below run its 
own breeze and build
+      # scripts, which match its sources.
+      - name: "Checkout ${{ matrix.target.branch }} ( ${{ matrix.target.sha }} 
)"
+        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1  # 
v7.0.1
+        with:
+          ref: ${{ matrix.target.sha }}
+          persist-credentials: false
+      - name: "Install Breeze from ${{ matrix.target.branch }}"
+        uses: ./.github/actions/breeze
+      - name: "Prepare airflow and task-sdk distributions: wheel"
+        run: |
+          breeze release-management prepare-airflow-distributions 
--distribution-format wheel
+          breeze release-management prepare-task-sdk-distributions 
--distribution-format wheel
+      - name: "Check that the wheels were built from ${{ matrix.target.sha }}"
+        env:
+          SHA: ${{ matrix.target.sha }}
+        run: |
+          git_version=$(unzip -p dist/apache_airflow_core-*.whl 
airflow/git_version)
+          echo "git_version of the airflow-core wheel: ${git_version}"
+          if [[ "${git_version}" != ".release:${SHA}" ]]; then
+            echo "::error::Expected .release:${SHA}"
+            exit 1
+          fi
+      - name: "Upload airflow and task-sdk wheels"
+        uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 
 # v7.0.2
+        with:
+          name: "airflow-wheels-${{ matrix.target.branch }}"
+          path: ./dist/*.whl
+          retention-days: '7'
+          if-no-files-found: 'error'
+
+  providers-branch-tip-compatibility-tests:
+    timeout-minutes: 80
+    # yamllint disable rule:line-length
+    name: Compat ${{ matrix.target.branch }}:P${{ matrix.target.python-version 
}}:${{ matrix.test-types.description }}
+    needs: [find-branch-tips, build-airflow]
+    runs-on: ${{ format(fromJSON(inputs.runners)[0], '8+16', '32+64') }}
+    strategy:
+      fail-fast: false
+      matrix:
+        target: ${{ fromJSON(needs.find-branch-tips.outputs.targets) }}
+        test-types: ${{ 
fromJSON(inputs.providers-test-types-list-as-strings-in-json) }}
+    env:
+      GITHUB_REPOSITORY: ${{ github.repository }}
+      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      GITHUB_USERNAME: ${{ github.actor }}
+      INCLUDE_NOT_READY_PROVIDERS: "true"
+      PYTHON_MAJOR_MINOR_VERSION: "${{ matrix.target.python-version }}"
+      VERBOSE: "true"
+      CLEAN_AIRFLOW_INSTALLATION: "true"
+    steps:
+      - name: "Cleanup repo"
+        shell: bash
+        run: sudo rm -rf ${GITHUB_WORKSPACE}/*
+      - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1  # 
v7.0.1
+        with:
+          persist-credentials: false
+      - name: "Prepare breeze & CI image: ${{ matrix.target.python-version }}"
+        uses: ./.github/actions/prepare_breeze_and_image
+        with:
+          platform: ${{ inputs.platform }}
+          python: ${{ matrix.target.python-version }}
+          use-uv: ${{ inputs.use-uv }}
+          make-mnt-writeable-and-cleanup: true
+      - name: "Install prek"
+        uses: ./.github/actions/install-prek
+        id: prek
+        with:
+          platform: ${{ inputs.platform }}
+          save-cache: false
+          # The hatch_build.py files of the fab, edge3 and common.ai providers 
run these hooks.
+          hooks: compile-fab-assets compile-edge-assets 
compile-common-ai-provider-assets
+      - name: "Cleanup dist files"
+        run: rm -fv ./dist/*
+      - name: "Prepare provider distributions: wheel"
+        run: >
+          breeze release-management prepare-provider-distributions 
--include-not-ready-providers
+          --distribution-format wheel --skip-tag-check
+      - name: "Remove incompatible ${{ matrix.target.branch }} provider 
distributions"
+        env:
+          REMOVE_PROVIDERS: ${{ matrix.target.remove-providers }}
+        run: |
+          for provider in ${REMOVE_PROVIDERS}; do
+            echo "Removing incompatible provider: ${provider}"
+            rm -vf dist/apache_airflow_providers_${provider/./_}-*

Review Comment:
   ```suggestion
               rm -vf dist/apache_airflow_providers_${provider//./_}-*
   ```
   Bash parameter expansion `${provider/./_}` (single slash) only replaces the 
first occurrence of `.`. If a provider identifier contains multiple dots, 
subsequent dots remain unmodified, causing the glob to miss the wheel file in 
`dist/` and leaving the incompatible wheel installed.
   
   Using double-slash `${provider//./_}` ensures global replacement of all dots 
with underscores.



##########
.github/workflows/test-providers-branch-tip.yml:
##########
@@ -0,0 +1,254 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+---
+# Runs the provider tests from main against Airflow built from the tips of the 
release branches, the
+# code of the next Airflow release before it is released. The compatibility 
tests of
+# `test-providers.yml` only cover released versions from PyPI.
+#
+# Each branch tip is resolved to one commit for the whole run, and built into 
wheels once, the way a
+# release is built (with the compiled UI). The test jobs install those wheels 
from `dist`, so the resolver
+# cannot replace them with a released Airflow of the same version number.
+name: Provider branch tip compatibility tests
+
+permissions:
+  contents: read
+on:  # yamllint disable-line rule:truthy
+  workflow_call:
+    inputs:
+      runners:
+        description: "The array of labels (in json form) determining runners."
+        required: true
+        type: string
+      platform:
+        description: "Platform for the build - 'linux/amd64' or 'linux/arm64'"
+        required: true
+        type: string
+      latest-release:
+        description: >
+          JSON object of the latest Airflow release in the compatibility 
matrix (airflow-version,
+          python-version, remove-providers). The vX-Y-test branches from its 
X.Y on are tested.
+        required: true
+        type: string
+      providers-test-types-list-as-strings-in-json:
+        description: "List of parallel provider test types as string"
+        required: true
+        type: string
+      use-uv:
+        description: "Whether to use uv to build the image (true/false)"
+        required: true
+        type: string
+
+jobs:
+  find-branch-tips:
+    name: "Find release branch tips"
+    runs-on: ["ubuntu-slim"]
+    outputs:
+      targets: ${{ steps.find.outputs.targets }}
+    steps:
+      - name: "Resolve the release branches from the latest release on to 
their current commits"
+        id: find
+        env:
+          LATEST_RELEASE: ${{ inputs.latest-release }}
+          GH_TOKEN: ${{ github.token }}
+          REPOSITORY: ${{ github.repository }}
+        run: |
+          if ! jq -e 'has("airflow-version")' <<< "${LATEST_RELEASE}" > 
/dev/null; then
+            echo "No released Airflow version to start from"
+            echo "targets=[]" >> "${GITHUB_OUTPUT}"
+            exit 0
+          fi
+          gh api --paginate 
"repos/${REPOSITORY}/git/matching-refs/heads/constraints-" \
+            --jq '.[].ref | ltrimstr("refs/heads/")' > 
"${RUNNER_TEMP}/constraints-branches.txt"
+          # Versions compare as numbers: the API lists v2-10-test before 
v2-9-test.
+          gh api --paginate "repos/${REPOSITORY}/git/matching-refs/heads/v" 
--jq '.[]' \
+            | jq -s -c --argjson release "${LATEST_RELEASE}" \
+                --rawfile constraints 
"${RUNNER_TEMP}/constraints-branches.txt" '
+                ($release["airflow-version"] | split(".")[:2] | map(tonumber)) 
as $floor
+                | ($constraints | split("\n")) as $constraint_branches
+                | [ .[]
+                    | (.ref | 
capture("^refs/heads/v(?<major>[0-9]+)-(?<minor>[0-9]+)-test$")) as $v
+                    | select([($v.major | tonumber), ($v.minor | tonumber)] >= 
$floor)
+                    | {
+                        branch: "v\($v.major)-\($v.minor)-test",
+                        sha: .object.sha,
+                        "airflow-constraints-reference": 
"constraints-\($v.major)-\($v.minor)",
+                        "python-version": $release["python-version"],
+                        "remove-providers": $release["remove-providers"]
+                      }
+                    | . + {"has-constraints": 
(."airflow-constraints-reference" | IN($constraint_branches[]))}
+                  ]' > "${RUNNER_TEMP}/branch-tips.json"
+          jq -r '.[] | select(."has-constraints") | "\(.branch): \(.sha)"' 
"${RUNNER_TEMP}/branch-tips.json"
+          # The constraints branch of a new release branch is created after 
the branch itself.
+          jq -r '.[] | select(."has-constraints" | not)
+            | "::notice::\(.branch): skipped, 
\(."airflow-constraints-reference") does not exist yet"' \
+            "${RUNNER_TEMP}/branch-tips.json"
+          echo "targets=$(jq -c '[.[] | select(."has-constraints") | 
del(."has-constraints")]' \
+            "${RUNNER_TEMP}/branch-tips.json")" >> "${GITHUB_OUTPUT}"
+
+  build-airflow:
+    timeout-minutes: 30
+    name: "Build Airflow from ${{ matrix.target.branch }}"
+    needs: [find-branch-tips]
+    if: needs.find-branch-tips.outputs.targets != '[]'
+    runs-on: ${{ format(fromJSON(inputs.runners)[0], '8+16', '32+64') }}
+    strategy:
+      fail-fast: false
+      matrix:
+        target: ${{ fromJSON(needs.find-branch-tips.outputs.targets) }}
+    env:
+      GITHUB_REPOSITORY: ${{ github.repository }}
+      VERBOSE: "true"
+    steps:
+      - name: "Cleanup repo"
+        shell: bash
+        run: sudo rm -rf ${GITHUB_WORKSPACE}/*
+      # The branch is checked out in place of main, so the steps below run its 
own breeze and build
+      # scripts, which match its sources.
+      - name: "Checkout ${{ matrix.target.branch }} ( ${{ matrix.target.sha }} 
)"
+        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1  # 
v7.0.1
+        with:
+          ref: ${{ matrix.target.sha }}
+          persist-credentials: false
+      - name: "Install Breeze from ${{ matrix.target.branch }}"
+        uses: ./.github/actions/breeze
+      - name: "Prepare airflow and task-sdk distributions: wheel"
+        run: |
+          breeze release-management prepare-airflow-distributions 
--distribution-format wheel
+          breeze release-management prepare-task-sdk-distributions 
--distribution-format wheel
+      - name: "Check that the wheels were built from ${{ matrix.target.sha }}"
+        env:
+          SHA: ${{ matrix.target.sha }}
+        run: |
+          git_version=$(unzip -p dist/apache_airflow_core-*.whl 
airflow/git_version)
+          echo "git_version of the airflow-core wheel: ${git_version}"
+          if [[ "${git_version}" != ".release:${SHA}" ]]; then
+            echo "::error::Expected .release:${SHA}"
+            exit 1
+          fi
+      - name: "Upload airflow and task-sdk wheels"
+        uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 
 # v7.0.2
+        with:
+          name: "airflow-wheels-${{ matrix.target.branch }}"
+          path: ./dist/*.whl
+          retention-days: '7'
+          if-no-files-found: 'error'
+
+  providers-branch-tip-compatibility-tests:
+    timeout-minutes: 80
+    # yamllint disable rule:line-length
+    name: Compat ${{ matrix.target.branch }}:P${{ matrix.target.python-version 
}}:${{ matrix.test-types.description }}
+    needs: [find-branch-tips, build-airflow]

Review Comment:
   ```suggestion
       needs: [find-branch-tips, build-airflow]
       if: needs.find-branch-tips.outputs.targets != '[]' && 
needs.find-branch-tips.outputs.targets != ''
   ```
   `build-airflow` has an `if` guard (`if: 
needs.find-branch-tips.outputs.targets != '[]'`), but 
`providers-branch-tip-compatibility-tests` is missing it.
   
   In GitHub Actions, matrix expansion happens prior to step execution. If 
`targets` is empty (`[]`), `matrix.target: ${{ 
fromJSON(needs.find-branch-tips.outputs.targets) }}` receives an empty list, 
causing GitHub Actions to fail the workflow run with a syntax error:
   `The workflow is not valid. Matrix [target] cannot be empty.`
   
   Adding this job-level `if` ensures the job is cleanly skipped without error 
when no targets are resolved.



##########
.github/workflows/ci-amd.yml:
##########
@@ -1724,6 +1750,7 @@ jobs:
       - migration-round-trip
       - mypy-providers
       - providers
+      - providers-branch-tip

Review Comment:
   Please remove `providers-branch-tip` from `ci-passed`'s needs list (and from 
`check-timed-out-jobs`).
   
   `ci-passed` is the required status check gate for pull request merges. If 
`providers-branch-tip` is in `needs`, any unstable backport on upstream 
`v3-4-test` will cause `ci-passed` to fail and block all PRs on `main` that 
have the `full tests needed` label.
   
   As noted in the `selective_checks.py` docstring: "A release branch tip moves 
independently of the pull request, so a pull request can neither cause nor fix 
a failure there." Having failures on an external branch tip block unrelated PR 
merges on `main` breaks CI reliability. This check should run as an 
informational/canary check, but it should not be a blocking gate in `ci-passed`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to