From 8925eb22e98cddf72f71080c6506efd04c231b76 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Fri, 8 May 2026 01:07:54 +0200 Subject: [PATCH] [Experimental] Split ci-amd-arm.yml into ARM canary and AMD per-PR workflows (#66348) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Split ci-amd-arm.yml into ci-arm.yml (canary) and ci-amd.yml (per-PR) wrappers Replaces the combined ci-amd-arm.yml workflow with two thin wrappers carrying the full pipeline inline: - ci-arm.yml: schedule (canary cron) + workflow_dispatch only; runs on linux/arm64. - ci-amd.yml: pull_request + push (to v3-N-test etc) + workflow_dispatch; runs on linux/amd64. No schedule for now; ARM keeps the canary slot. Each wrapper carries the full pipeline jobs identically except for platform / runner-type / triggers, so per-job UI grouping is preserved on the GitHub Actions page. The runtime cross-mapping in selective_checks.runner_type is left in place because is_disabled_integration still consumes it; the API lookup against the now-removed ci-amd-arm.yml falls back to AMD harmlessly. References to the old file name are updated in: README.md, dev/update_github_branch_config.py, ci-notification.yml, e2e-flaky-tests-report.yml, scripts/ci/analyze_e2e_flaky_tests.py, dev/README_AIRFLOW3_DEV.md, dev/README_RELEASE_AIRFLOW.md, generated/PYPI_README.md, update-constraints-on-push*.yml, release_dockerhub_image.yml. * Add prek hook that asserts ci-arm.yml and ci-amd.yml stay in sync The two CI workflow files are physical copies of each other (GH Actions has no cross-file YAML include) — they should differ only in: - header intro comment - workflow name (ARM vs AMD) - triggers (schedule vs pull_request+push) - concurrency group prefix - build-info platform / runner-type outputs - print-platform job name + echo Drift outside this set is a bug. The new `scripts/ci/prek/check_ci_workflows_in_sync.py` normalizes both files against the documented divergences (regex line rules + arch-only block removals) and asserts the rest matches byte-for-byte. Wired up as a local prek hook gated on either workflow file changing. Local UX: when run interactively, the script also diffs each file against `upstream/main` (falls back to `origin/main`, then `main`) and attributes the drift — "only ci-arm.yml changed since baseline; mirror to ci-amd.yml" with the exact diff to copy, OR "add to LINE_RULES / ARM_ONLY_BLOCK in this script if intentional". Falls back to the non-attribution view in CI / non-TTY runs. Set `FORCE_INTERACTIVE=1` to opt in from a non-TTY shell. (cherry picked from commit 8f9363715516dd5b8c5c1bafe007a84fa5122390) --- .../workflows/{ci-amd-arm.yml => ci-amd.yml} | 31 +- .github/workflows/ci-arm.yml | 1159 +++++++++++++++++ .github/workflows/ci-notification.yml | 4 +- .github/workflows/e2e-flaky-tests-report.yml | 5 +- .github/workflows/release_dockerhub_image.yml | 2 +- .../update-constraints-on-push-stable.yml | 2 +- .../workflows/update-constraints-on-push.yml | 2 +- .pre-commit-config.yaml | 7 + README.md | 28 +- dev/README_AIRFLOW3_DEV.md | 2 +- dev/README_RELEASE_AIRFLOW.md | 2 +- dev/breeze/doc/images/output_build-docs.txt | 2 +- .../doc/images/output_ci-image_build.txt | 2 +- .../output_ci-image_export-mount-cache.txt | 2 +- .../output_ci-image_import-mount-cache.txt | 2 +- .../doc/images/output_ci-image_load.txt | 2 +- .../doc/images/output_ci-image_pull.txt | 2 +- .../doc/images/output_ci-image_save.txt | 2 +- .../doc/images/output_ci-image_verify.txt | 2 +- .../doc/images/output_ci_fix-ownership.txt | 2 +- .../doc/images/output_ci_free-space.txt | 2 +- .../images/output_ci_get-workflow-info.txt | 2 +- .../doc/images/output_ci_resource-check.txt | 2 +- .../doc/images/output_ci_selective-check.txt | 2 +- .../doc/images/output_ci_set-milestone.txt | 2 +- dev/breeze/doc/images/output_ci_upgrade.txt | 2 +- dev/breeze/doc/images/output_cleanup.txt | 2 +- dev/breeze/doc/images/output_doctor.txt | 2 +- dev/breeze/doc/images/output_down.txt | 2 +- dev/breeze/doc/images/output_exec.txt | 2 +- .../images/output_generate-migration-file.txt | 2 +- .../doc/images/output_issues_unassign.txt | 2 +- .../doc/images/output_k8s_build-k8s-image.txt | 2 +- .../images/output_k8s_configure-cluster.txt | 2 +- .../doc/images/output_k8s_create-cluster.txt | 2 +- .../doc/images/output_k8s_delete-cluster.txt | 2 +- .../doc/images/output_k8s_deploy-airflow.txt | 2 +- .../doc/images/output_k8s_deploy-cluster.txt | 2 +- dev/breeze/doc/images/output_k8s_dev.txt | 2 +- dev/breeze/doc/images/output_k8s_k9s.txt | 2 +- dev/breeze/doc/images/output_k8s_logs.txt | 2 +- .../images/output_k8s_run-complete-tests.txt | 2 +- .../doc/images/output_k8s_setup-env.txt | 2 +- dev/breeze/doc/images/output_k8s_shell.txt | 2 +- dev/breeze/doc/images/output_k8s_status.txt | 2 +- dev/breeze/doc/images/output_k8s_tests.txt | 2 +- .../images/output_k8s_upload-k8s-image.txt | 2 +- .../doc/images/output_pr_auto-triage.txt | 2 +- .../doc/images/output_prod-image_build.txt | 2 +- .../doc/images/output_prod-image_load.txt | 2 +- .../doc/images/output_prod-image_pull.txt | 2 +- .../doc/images/output_prod-image_save.txt | 2 +- .../doc/images/output_prod-image_verify.txt | 2 +- .../doc/images/output_registry_backfill.txt | 2 +- .../images/output_registry_extract-data.txt | 2 +- .../output_registry_publish-versions.txt | 2 +- ...release-management_add-back-references.txt | 2 +- ...release-management_check-release-files.txt | 2 +- ...anagement_clean-old-provider-artifacts.txt | 2 +- ...e-management_constraints-version-check.txt | 2 +- ...release-management_create-minor-branch.txt | 2 +- ...elease-management_generate-constraints.txt | 2 +- ...management_generate-issue-content-core.txt | 2 +- ...ment_generate-issue-content-helm-chart.txt | 2 +- ...ement_generate-issue-content-providers.txt | 2 +- ...management_generate-providers-metadata.txt | 2 +- ...agement_install-provider-distributions.txt | 2 +- ...t_release-management_merge-prod-images.txt | 2 +- ...ment_prepare-airflow-ctl-distributions.txt | 2 +- ...nagement_prepare-airflow-distributions.txt | 2 +- ...-management_prepare-helm-chart-package.txt | 2 +- ...-management_prepare-helm-chart-tarball.txt | 2 +- ...-management_prepare-mypy-distributions.txt | 2 +- ...agement_prepare-provider-distributions.txt | 2 +- ...agement_prepare-provider-documentation.txt | 2 +- ...lease-management_prepare-python-client.txt | 2 +- ...put_release-management_prepare-tarball.txt | 2 +- ...agement_prepare-task-sdk-distributions.txt | 2 +- ..._release-management_publish-docs-to-s3.txt | 2 +- ...output_release-management_publish-docs.txt | 2 +- ...release-management_release-prod-images.txt | 2 +- ...ut_release-management_start-rc-process.txt | 2 +- ...utput_release-management_start-release.txt | 2 +- ...utput_release-management_tag-providers.txt | 2 +- ..._release-management_update-constraints.txt | 2 +- ...nagement_update-providers-next-version.txt | 2 +- ...nagement_verify-provider-distributions.txt | 2 +- ...ut_release-management_verify-rc-by-pmc.txt | 2 +- dev/breeze/doc/images/output_run.txt | 2 +- .../output_sbom_build-all-airflow-images.txt | 2 +- ...put_sbom_export-dependency-information.txt | 2 +- ...t_sbom_generate-providers-requirements.txt | 2 +- .../output_sbom_update-sbom-information.txt | 2 +- .../doc/images/output_setup_autocomplete.txt | 2 +- ...utput_setup_check-all-params-in-groups.txt | 2 +- dev/breeze/doc/images/output_setup_config.txt | 2 +- ...output_setup_regenerate-command-images.txt | 2 +- .../output_setup_synchronize-local-mounts.txt | 2 +- .../doc/images/output_setup_version.txt | 2 +- dev/breeze/doc/images/output_shell.svg | 2 +- dev/breeze/doc/images/output_shell.txt | 2 +- .../doc/images/output_start-airflow.svg | 2 +- .../doc/images/output_start-airflow.txt | 2 +- ..._testing_airflow-ctl-integration-tests.txt | 2 +- .../output_testing_airflow-ctl-tests.txt | 2 +- .../output_testing_airflow-e2e-tests.txt | 2 +- .../output_testing_core-integration-tests.txt | 2 +- .../doc/images/output_testing_core-tests.txt | 2 +- .../output_testing_docker-compose-tests.txt | 2 +- .../doc/images/output_testing_helm-tests.txt | 2 +- ...ut_testing_providers-integration-tests.txt | 2 +- .../images/output_testing_providers-tests.txt | 2 +- ...output_testing_python-api-client-tests.txt | 2 +- .../images/output_testing_system-tests.txt | 2 +- ...put_testing_task-sdk-integration-tests.txt | 2 +- .../images/output_testing_task-sdk-tests.txt | 2 +- .../images/output_testing_ui-e2e-tests.txt | 2 +- ...tput_ui_check-translation-completeness.txt | 2 +- .../doc/images/output_ui_compile-assets.txt | 2 +- .../output_workflow-run_publish-docs.txt | 2 +- .../airflow_breeze/utils/selective_checks.py | 6 + generated/PYPI_README.md | 28 +- scripts/ci/analyze_e2e_flaky_tests.py | 4 +- scripts/ci/prek/check_ci_workflows_in_sync.py | 375 ++++++ 124 files changed, 1712 insertions(+), 163 deletions(-) rename .github/workflows/{ci-amd-arm.yml => ci-amd.yml} (98%) create mode 100644 .github/workflows/ci-arm.yml create mode 100755 scripts/ci/prek/check_ci_workflows_in_sync.py diff --git a/.github/workflows/ci-amd-arm.yml b/.github/workflows/ci-amd.yml similarity index 98% rename from .github/workflows/ci-amd-arm.yml rename to .github/workflows/ci-amd.yml index ed11af2ca82c5..350575c848b86 100644 --- a/.github/workflows/ci-amd-arm.yml +++ b/.github/workflows/ci-amd.yml @@ -16,10 +16,15 @@ # under the License. # --- -name: Tests +# AMD CI workflow. Triggered on every PR and on push to release branches. +# Companion to `ci-arm.yml`, which runs the same pipeline on ARM as the +# scheduled canary. The two workflows are physical copies of each other +# (GitHub Actions has no cross-file YAML include), differing only in their +# trigger surface, the hardcoded `runner-type` / `platform` values in +# `build-info`'s outputs, and the architecture-specific print-platform job. +# Edit both files together when changing pipeline shape. +name: Tests (AMD) on: # yamllint disable-line rule:truthy - schedule: - - cron: '28 1,3,7,9,13,15,19,21 * * *' push: branches: - v[0-9]+-[0-9]+-test @@ -43,7 +48,7 @@ env: VERBOSE: "true" concurrency: - group: ci-amd-arm-${{ github.event.pull_request.number || github.ref }} + group: ci-amd-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: @@ -90,7 +95,9 @@ jobs: latest-versions-only: ${{ steps.selective-checks.outputs.latest-versions-only }} mysql-exclude: ${{ steps.selective-checks.outputs.mysql-exclude }} mysql-versions: ${{ steps.selective-checks.outputs.mysql-versions }} - platform: ${{ steps.selective-checks.outputs.platform }} + # platform / runner-type are hardcoded per workflow file (this is the + # AMD copy). The matching ARM copy lives in ci-arm.yml. + platform: "linux/amd64" postgres-exclude: ${{ steps.selective-checks.outputs.postgres-exclude }} postgres-versions: ${{ steps.selective-checks.outputs.postgres-versions }} prod-image-build: ${{ steps.selective-checks.outputs.prod-image-build }} @@ -119,7 +126,7 @@ jobs: run-task-sdk-integration-tests: ${{ steps.selective-checks.outputs.run-task-sdk-integration-tests }} run-breeze-integration-tests: ${{ steps.selective-checks.outputs.run-breeze-integration-tests }} run-scripts-tests: ${{ steps.selective-checks.outputs.run-scripts-tests }} - runner-type: ${{ steps.selective-checks.outputs.runner-type }} + runner-type: '["ubuntu-22.04"]' run-ui-tests: ${{ steps.selective-checks.outputs.run-ui-tests }} run-ui-e2e-tests: ${{ steps.selective-checks.outputs.run-ui-e2e-tests }} run-unit-tests: ${{ steps.selective-checks.outputs.run-unit-tests }} @@ -197,20 +204,10 @@ jobs: env: PR_LABELS: ${{ steps.source-run-info.outputs.pr-labels }} - print-platform-arm: - name: "Platform: ARM" - needs: [build-info] - runs-on: ["ubuntu-22.04"] - if: needs.build-info.outputs.platform == 'linux/arm64' - steps: - - name: "Print architecture" - run: "echo '## Architecture: ARM' >> $GITHUB_STEP_SUMMARY" - - print-platform-amd: + print-platform: name: "Platform: AMD" needs: [build-info] runs-on: ["ubuntu-22.04"] - if: needs.build-info.outputs.platform == 'linux/amd64' steps: - name: "Print architecture" run: "echo '## Architecture: AMD' >> $GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/ci-arm.yml b/.github/workflows/ci-arm.yml new file mode 100644 index 0000000000000..4addb776950c1 --- /dev/null +++ b/.github/workflows/ci-arm.yml @@ -0,0 +1,1159 @@ +# 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. +# +--- +# ARM canary CI workflow. Triggered on the canary cron only — ARM runners are +# reserved for the scheduled slot. Companion to `ci-amd.yml`, which runs the +# same pipeline on AMD for every PR and push. The two workflows are physical +# copies of each other (GitHub Actions has no cross-file YAML include), +# differing only in their trigger surface, the hardcoded `runner-type` / +# `platform` values in `build-info`'s outputs, and the architecture-specific +# print-platform job. Edit both files together when changing pipeline shape. +name: Tests (ARM) +on: # yamllint disable-line rule:truthy + schedule: + - cron: '28 1,3,7,9,13,15,19,21 * * *' + workflow_dispatch: +permissions: + # All other permissions are set to none by default + contents: read +env: + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_USERNAME: ${{ github.actor }} + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + VERBOSE: "true" + +concurrency: + group: ci-arm-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build-info: + name: "Build info" + # At build-info stage we do not yet have outputs so we need to hard-code the runs-on to public runners + runs-on: ["ubuntu-22.04"] + outputs: + all-python-versions-list-as-string: >- + ${{ steps.selective-checks.outputs.all-python-versions-list-as-string }} + arm-runners: ${{ steps.selective-checks.outputs.arm-runners }} + basic-checks-only: ${{ steps.selective-checks.outputs.basic-checks-only }} + canary-run: ${{ steps.source-run-info.outputs.canary-run }} + ci-image-build: ${{ steps.selective-checks.outputs.ci-image-build }} + core-test-types-list-as-strings-in-json: >- + ${{ steps.selective-checks.outputs.core-test-types-list-as-strings-in-json }} + debug-resources: ${{ steps.selective-checks.outputs.debug-resources }} + default-branch: ${{ steps.selective-checks.outputs.default-branch }} + default-constraints-branch: ${{ steps.selective-checks.outputs.default-constraints-branch }} + default-helm-version: ${{ steps.selective-checks.outputs.default-helm-version }} + default-kind-version: ${{ steps.selective-checks.outputs.default-kind-version }} + default-kubernetes-version: ${{ steps.selective-checks.outputs.default-kubernetes-version }} + default-mysql-version: ${{ steps.selective-checks.outputs.default-mysql-version }} + default-postgres-version: ${{ steps.selective-checks.outputs.default-postgres-version }} + default-python-version: ${{ steps.selective-checks.outputs.default-python-version }} + disable-airflow-repo-cache: ${{ steps.selective-checks.outputs.disable-airflow-repo-cache }} + docker-cache: ${{ steps.selective-checks.outputs.docker-cache }} + docs-build: ${{ steps.selective-checks.outputs.docs-build }} + docs-list-as-string: ${{ steps.selective-checks.outputs.docs-list-as-string }} + excluded-providers-as-string: ${{ steps.selective-checks.outputs.excluded-providers-as-string }} + force-pip: ${{ steps.selective-checks.outputs.force-pip }} + full-tests-needed: ${{ steps.selective-checks.outputs.full-tests-needed }} + has-migrations: ${{ steps.selective-checks.outputs.has-migrations }} + helm-test-packages: ${{ steps.selective-checks.outputs.helm-test-packages }} + helm-test-kubernetes-versions: ${{ steps.selective-checks.outputs.helm-test-kubernetes-versions }} + include-success-outputs: ${{ steps.selective-checks.outputs.include-success-outputs }} + individual-providers-test-types-list-as-strings-in-json: >- + ${{ steps.selective-checks.outputs.individual-providers-test-types-list-as-strings-in-json }} + kubernetes-combos: ${{ steps.selective-checks.outputs.kubernetes-combos }} + kubernetes-combos-list-as-string: >- + ${{ steps.selective-checks.outputs.kubernetes-combos-list-as-string }} + kubernetes-versions-list-as-string: >- + ${{ steps.selective-checks.outputs.kubernetes-versions-list-as-string }} + latest-versions-only: ${{ steps.selective-checks.outputs.latest-versions-only }} + mysql-exclude: ${{ steps.selective-checks.outputs.mysql-exclude }} + mysql-versions: ${{ steps.selective-checks.outputs.mysql-versions }} + # platform / runner-type are hardcoded per workflow file (this is the + # ARM copy). The matching AMD copy lives in ci-amd.yml. + platform: "linux/arm64" + postgres-exclude: ${{ steps.selective-checks.outputs.postgres-exclude }} + postgres-versions: ${{ steps.selective-checks.outputs.postgres-versions }} + prod-image-build: ${{ steps.selective-checks.outputs.prod-image-build }} + # yamllint disable rule:line-length + providers-compatibility-tests-matrix: > + ${{ steps.selective-checks.outputs.providers-compatibility-tests-matrix }} + providers-test-types-list-as-strings-in-json: >- + ${{ steps.selective-checks.outputs.providers-test-types-list-as-strings-in-json }} + pull-request-labels: ${{ steps.source-run-info.outputs.pr-labels }} + python-versions-list-as-string: ${{ steps.selective-checks.outputs.python-versions-list-as-string }} + python-versions: ${{ steps.selective-checks.outputs.python-versions }} + run-airflow-ctl-tests: ${{ steps.selective-checks.outputs.run-airflow-ctl-tests }} + run-airflow-ctl-integration-tests: ${{ steps.selective-checks.outputs.run-airflow-ctl-integration-tests }} + run-amazon-tests: ${{ steps.selective-checks.outputs.run-amazon-tests }} + run-api-codegen: ${{ steps.selective-checks.outputs.run-api-codegen }} + run-api-tests: ${{ steps.selective-checks.outputs.run-api-tests }} + run-coverage: ${{ steps.source-run-info.outputs.run-coverage }} + run-go-sdk-tests: ${{ steps.selective-checks.outputs.run-go-sdk-tests }} + run-helm-tests: ${{ steps.selective-checks.outputs.run-helm-tests }} + run-kubernetes-tests: ${{ steps.selective-checks.outputs.run-kubernetes-tests }} + run-mypy-providers: ${{ steps.selective-checks.outputs.run-mypy-providers }} + run-remote-logging-elasticsearch-e2e-tests: ${{ steps.selective-checks.outputs.run-remote-logging-elasticsearch-e2e-tests }} + run-remote-logging-s3-e2e-tests: ${{ steps.selective-checks.outputs.run-remote-logging-s3-e2e-tests }} + run-system-tests: ${{ steps.selective-checks.outputs.run-system-tests }} + run-task-sdk-tests: ${{ steps.selective-checks.outputs.run-task-sdk-tests }} + run-task-sdk-integration-tests: ${{ steps.selective-checks.outputs.run-task-sdk-integration-tests }} + run-breeze-integration-tests: ${{ steps.selective-checks.outputs.run-breeze-integration-tests }} + run-scripts-tests: ${{ steps.selective-checks.outputs.run-scripts-tests }} + runner-type: '["ubuntu-22.04-arm"]' + run-ui-tests: ${{ steps.selective-checks.outputs.run-ui-tests }} + run-ui-e2e-tests: ${{ steps.selective-checks.outputs.run-ui-e2e-tests }} + run-unit-tests: ${{ steps.selective-checks.outputs.run-unit-tests }} + run-www-tests: ${{ steps.selective-checks.outputs.run-www-tests }} + selected-providers-list-as-string: >- + ${{ steps.selective-checks.outputs.selected-providers-list-as-string }} + shared-distributions-as-json: ${{ steps.selective-checks.outputs.shared-distributions-as-json }} + skip-prek-hooks: ${{ steps.selective-checks.outputs.skip-prek-hooks }} + skip-providers-tests: ${{ steps.selective-checks.outputs.skip-providers-tests }} + source-head-repo: ${{ steps.source-run-info.outputs.head-repo }} + source-head-ref: ${{ steps.source-run-info.outputs.head-ref }} + sqlite-exclude: ${{ steps.selective-checks.outputs.sqlite-exclude }} + testable-core-integrations: ${{ steps.selective-checks.outputs.testable-core-integrations }} + testable-providers-integrations: ${{ steps.selective-checks.outputs.testable-providers-integrations }} + use-uv: ${{ steps.selective-checks.outputs.force-pip == 'true' && 'false' || 'true' }} + upgrade-to-newer-dependencies: ${{ steps.selective-checks.outputs.upgrade-to-newer-dependencies }} + is-uv-lock-update: ${{ steps.selective-checks.outputs.is-uv-lock-update }} + steps: + - name: "Cleanup repo" + shell: bash + run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Fetch incoming commit ${{ github.sha }} with its parent + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.sha }} + fetch-depth: 2 + persist-credentials: false + - name: "Install Breeze" + uses: ./.github/actions/breeze + id: breeze + - name: "Save github context to file" + # The github context can be very large for PRs that touch many files (e.g. Dependabot + # bumps with dozens of packages). Passing it as an env var would exceed ARG_MAX and + # prevent subsequent steps from starting bash, so we write it to a file once here and + # let downstream breeze invocations read it via GITHUB_CONTEXT_INPUT. + # + # Zizmor flags this as template-injection because attacker-controllable fields in the + # github context (PR title, body, branch names) are pasted into a `run:` script. It is + # a false positive in this specific shape: + # * the substituted JSON sits inside a SINGLE-QUOTED heredoc (`<< '__GITHUB_CONTEXT_END__'`), + # which disables ALL bash expansion -- $(...), `...`, ${...}, and even `\` are literal, + # so no shell metacharacter in the JSON can be evaluated; + # * the only remaining escape is the delimiter `__GITHUB_CONTEXT_END__` appearing on a + # line by itself in the JSON. `toJson` escapes newlines inside string values as `\n` + # (so they are NOT real newlines in the script source), and the delimiter is unique + # enough that github will never produce it as a structural line of the JSON output; + # * `cat` writes the bytes verbatim to a file -- it is not eval'd. + # Whatever junk a malicious PR puts in title/body therefore lands inside a JSON file + # consumed by breeze, never executed as shell. + shell: bash + run: | # zizmor: ignore[template-injection] + cat > "${RUNNER_TEMP}/github_context.json" << '__GITHUB_CONTEXT_END__' + ${{ toJson(github) }} + __GITHUB_CONTEXT_END__ + - name: "Get information about the Workflow" + id: source-run-info + run: breeze ci get-workflow-info 2>> ${GITHUB_OUTPUT} + env: + SKIP_BREEZE_SELF_UPGRADE_CHECK: "true" + GITHUB_CONTEXT_INPUT: "${{ runner.temp }}/github_context.json" + - name: Selective checks + id: selective-checks + env: + PR_LABELS: "${{ steps.source-run-info.outputs.pr-labels }}" + COMMIT_REF: "${{ github.sha }}" + VERBOSE: "false" + GITHUB_CONTEXT_INPUT: "${{ runner.temp }}/github_context.json" + run: breeze ci selective-check 2>> ${GITHUB_OUTPUT} + - name: env + run: printenv + env: + PR_LABELS: ${{ steps.source-run-info.outputs.pr-labels }} + + print-platform: + name: "Platform: ARM" + needs: [build-info] + runs-on: ["ubuntu-22.04"] + steps: + - name: "Print architecture" + run: "echo '## Architecture: ARM' >> $GITHUB_STEP_SUMMARY" + + basic-tests: + name: "Basic tests" + needs: [build-info] + uses: ./.github/workflows/basic-tests.yml + with: + runners: ${{ needs.build-info.outputs.runner-type }} + run-ui-tests: ${{needs.build-info.outputs.run-ui-tests}} + run-www-tests: ${{needs.build-info.outputs.run-www-tests}} + run-api-codegen: ${{needs.build-info.outputs.run-api-codegen}} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + basic-checks-only: ${{ needs.build-info.outputs.basic-checks-only }} + skip-prek-hooks: ${{ needs.build-info.outputs.skip-prek-hooks }} + canary-run: ${{needs.build-info.outputs.canary-run}} + run-breeze-integration-tests: ${{needs.build-info.outputs.run-breeze-integration-tests}} + run-scripts-tests: ${{needs.build-info.outputs.run-scripts-tests}} + latest-versions-only: ${{needs.build-info.outputs.latest-versions-only}} + use-uv: ${{needs.build-info.outputs.use-uv}} + platform: ${{ needs.build-info.outputs.platform }} + shared-distributions-as-json: ${{needs.build-info.outputs.shared-distributions-as-json}} + + build-ci-images: + name: Build CI images + needs: [build-info] + uses: ./.github/workflows/ci-image-build.yml + permissions: + contents: read + # This write is only given here for `push` events from "apache/airflow" repo. It is not given for PRs + # from forks. This is to prevent malicious PRs from creating images in the "apache/airflow" repo. + packages: write + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + push-image: "false" + upload-image-artifact: "true" + upload-mount-cache-artifact: ${{ needs.build-info.outputs.canary-run }} + python-versions: ${{ needs.build-info.outputs.python-versions }} + branch: ${{ needs.build-info.outputs.default-branch }} + constraints-branch: ${{ needs.build-info.outputs.default-constraints-branch }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + upgrade-to-newer-dependencies: ${{ needs.build-info.outputs.upgrade-to-newer-dependencies }} + docker-cache: ${{ needs.build-info.outputs.docker-cache }} + disable-airflow-repo-cache: ${{ needs.build-info.outputs.disable-airflow-repo-cache }} + if: needs.build-info.outputs.ci-image-build == 'true' + + additional-ci-image-checks: + name: "Additional CI image checks" + needs: [build-info, build-ci-images] + uses: ./.github/workflows/additional-ci-image-checks.yml + permissions: + contents: read + packages: write + id-token: write + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + python-versions: ${{ needs.build-info.outputs.python-versions }} + branch: ${{ needs.build-info.outputs.default-branch }} + constraints-branch: ${{ needs.build-info.outputs.default-constraints-branch }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + upgrade-to-newer-dependencies: ${{ needs.build-info.outputs.upgrade-to-newer-dependencies }} + skip-prek-hooks: ${{ needs.build-info.outputs.skip-prek-hooks }} + docker-cache: ${{ needs.build-info.outputs.docker-cache }} + disable-airflow-repo-cache: ${{ needs.build-info.outputs.disable-airflow-repo-cache }} + canary-run: ${{ needs.build-info.outputs.canary-run }} + latest-versions-only: ${{ needs.build-info.outputs.latest-versions-only }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + + generate-constraints: + name: "Generate constraints" + needs: [build-info, build-ci-images] + uses: ./.github/workflows/generate-constraints.yml + if: needs.build-info.outputs.ci-image-build == 'true' + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + python-versions-list-as-string: ${{ needs.build-info.outputs.python-versions-list-as-string }} + python-versions: ${{ needs.build-info.outputs.python-versions }} + generate-pypi-constraints: "true" + # generate no providers constraints only in canary builds - they take quite some time to generate + # they are not needed for regular builds, they are only needed to update constraints in canaries + generate-no-providers-constraints: ${{ needs.build-info.outputs.canary-run }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + + ci-image-checks: + name: "CI image checks" + needs: [build-info, build-ci-images] + uses: ./.github/workflows/ci-image-checks.yml + permissions: + id-token: write + contents: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + python-versions-list-as-string: ${{ needs.build-info.outputs.python-versions-list-as-string }} + branch: ${{ needs.build-info.outputs.default-branch }} + canary-run: ${{ needs.build-info.outputs.canary-run }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + docs-list-as-string: ${{ needs.build-info.outputs.docs-list-as-string }} + latest-versions-only: ${{ needs.build-info.outputs.latest-versions-only }} + basic-checks-only: ${{ needs.build-info.outputs.basic-checks-only }} + upgrade-to-newer-dependencies: ${{ needs.build-info.outputs.upgrade-to-newer-dependencies }} + skip-prek-hooks: ${{ needs.build-info.outputs.skip-prek-hooks }} + ci-image-build: ${{ needs.build-info.outputs.ci-image-build }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + docs-build: ${{ needs.build-info.outputs.docs-build }} + run-api-codegen: ${{ needs.build-info.outputs.run-api-codegen }} + default-postgres-version: ${{ needs.build-info.outputs.default-postgres-version }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + source-head-repo: ${{ needs.build-info.outputs.source-head-repo }} + source-head-ref: ${{ needs.build-info.outputs.source-head-ref }} + secrets: + DOCS_AWS_ACCESS_KEY_ID: ${{ secrets.DOCS_AWS_ACCESS_KEY_ID }} + DOCS_AWS_SECRET_ACCESS_KEY: ${{ secrets.DOCS_AWS_SECRET_ACCESS_KEY }} + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + + mypy-providers: + timeout-minutes: 45 + name: "MyPy providers checks" + needs: [build-info, build-ci-images] + runs-on: ${{ fromJSON(needs.build-info.outputs.runner-type) }} + if: needs.build-info.outputs.run-mypy-providers == 'true' + env: + PYTHON_MAJOR_MINOR_VERSION: "${{ needs.build-info.outputs.default-python-version }}" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: "Cleanup repo" + shell: bash + run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: "Prepare breeze & CI image: ${{ needs.build-info.outputs.default-python-version }}" + uses: ./.github/actions/prepare_breeze_and_image + with: + platform: ${{ needs.build-info.outputs.platform }} + python: "${{ needs.build-info.outputs.default-python-version }}" + use-uv: ${{ needs.build-info.outputs.use-uv }} + make-mnt-writeable-and-cleanup: true + id: breeze + - name: "Install prek" + uses: ./.github/actions/install-prek + id: prek + with: + python-version: ${{steps.breeze.outputs.host-python-version}} + platform: ${{ needs.build-info.outputs.platform }} + save-cache: false + - name: "MyPy checks for providers" + run: prek --color always --verbose --stage manual mypy-providers --all-files + env: + VERBOSE: "false" + COLUMNS: "202" + SKIP_GROUP_OUTPUT: "true" + DEFAULT_BRANCH: ${{ needs.build-info.outputs.default-branch }} + RUFF_FORMAT: "github" + INCLUDE_MYPY_VOLUME: "false" + + migration-round-trip: + timeout-minutes: 20 + name: "Migration round-trip check" + needs: [build-info, build-ci-images] + runs-on: ${{ fromJSON(needs.build-info.outputs.runner-type) }} + if: needs.build-info.outputs.has-migrations == 'true' + env: + PYTHON_MAJOR_MINOR_VERSION: "${{ needs.build-info.outputs.default-python-version }}" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: "Cleanup repo" + shell: bash + run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: "Prepare breeze & CI image: ${{ needs.build-info.outputs.default-python-version }}" + uses: ./.github/actions/prepare_breeze_and_image + with: + platform: ${{ needs.build-info.outputs.platform }} + python: "${{ needs.build-info.outputs.default-python-version }}" + use-uv: ${{ needs.build-info.outputs.use-uv }} + make-mnt-writeable-and-cleanup: true + id: breeze + - name: "Install prek" + uses: ./.github/actions/install-prek + id: prek + with: + python-version: ${{steps.breeze.outputs.host-python-version}} + platform: ${{ needs.build-info.outputs.platform }} + save-cache: false + - name: "Migration round-trip check" + run: prek --color always --verbose --stage manual migration-round-trip --all-files + env: + VERBOSE: "false" + COLUMNS: "202" + SKIP_GROUP_OUTPUT: "true" + DEFAULT_BRANCH: ${{ needs.build-info.outputs.default-branch }} + + providers: + name: "provider distributions tests" + uses: ./.github/workflows/test-providers.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + if: > + needs.build-info.outputs.skip-providers-tests != 'true' && + needs.build-info.outputs.latest-versions-only != 'true' && + needs.build-info.outputs.run-unit-tests == 'true' + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + canary-run: ${{ needs.build-info.outputs.canary-run }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + upgrade-to-newer-dependencies: ${{ needs.build-info.outputs.upgrade-to-newer-dependencies }} + selected-providers-list-as-string: ${{ needs.build-info.outputs.selected-providers-list-as-string }} + # yamllint disable rule:line-length + providers-compatibility-tests-matrix: > + ${{ needs.build-info.outputs.providers-compatibility-tests-matrix }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + python-versions: ${{ needs.build-info.outputs.python-versions }} + providers-test-types-list-as-strings-in-json: > + ${{ needs.build-info.outputs.providers-test-types-list-as-strings-in-json }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + + tests-helm: + name: "Helm tests" + uses: ./.github/workflows/helm-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + helm-test-packages: ${{ needs.build-info.outputs.helm-test-packages }} + helm-test-kubernetes-versions: ${{ needs.build-info.outputs.helm-test-kubernetes-versions }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + use-uv: ${{ needs.build-info.outputs.use-uv }} + if: > + needs.build-info.outputs.run-helm-tests == 'true' && + needs.build-info.outputs.default-branch == 'main' && + needs.build-info.outputs.latest-versions-only != 'true' + + + tests-postgres-core: + name: "Postgres tests: core" + uses: ./.github/workflows/run-unit-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + backend: "postgres" + test-name: "Postgres" + test-scope: "DB" + test-group: "core" + python-versions: ${{ needs.build-info.outputs.python-versions }} + backend-versions: ${{ needs.build-info.outputs.postgres-versions }} + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: ${{ needs.build-info.outputs.postgres-exclude }} + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.core-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-migration-tests: "true" + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + if: needs.build-info.outputs.run-unit-tests == 'true' + + tests-postgres-providers: + name: "Postgres tests: providers" + uses: ./.github/workflows/run-unit-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + backend: "postgres" + test-name: "Postgres" + test-scope: "DB" + test-group: "providers" + python-versions: ${{ needs.build-info.outputs.python-versions }} + backend-versions: ${{ needs.build-info.outputs.postgres-versions }} + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: ${{ needs.build-info.outputs.postgres-exclude }} + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.providers-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-migration-tests: "true" + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + if: needs.build-info.outputs.run-unit-tests == 'true' + + tests-mysql-core: + name: "MySQL tests: core" + uses: ./.github/workflows/run-unit-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + backend: "mysql" + test-name: "MySQL" + test-scope: "DB" + test-group: "core" + python-versions: ${{ needs.build-info.outputs.python-versions }} + backend-versions: ${{ needs.build-info.outputs.mysql-versions }} + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: ${{ needs.build-info.outputs.mysql-exclude }} + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.core-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + run-migration-tests: "true" + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + if: needs.build-info.outputs.run-unit-tests == 'true' && needs.build-info.outputs.platform == 'linux/amd64' + + tests-mysql-providers: + name: "MySQL tests: providers" + uses: ./.github/workflows/run-unit-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + backend: "mysql" + test-name: "MySQL" + test-scope: "DB" + test-group: "providers" + python-versions: ${{ needs.build-info.outputs.python-versions }} + backend-versions: ${{ needs.build-info.outputs.mysql-versions }} + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: ${{ needs.build-info.outputs.mysql-exclude }} + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.providers-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + run-migration-tests: "true" + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + if: needs.build-info.outputs.run-unit-tests == 'true' && needs.build-info.outputs.platform == 'linux/amd64' + + tests-sqlite-core: + name: "Sqlite tests: core" + uses: ./.github/workflows/run-unit-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + backend: "sqlite" + test-name: "Sqlite" + test-name-separator: "" + test-scope: "DB" + test-group: "core" + python-versions: ${{ needs.build-info.outputs.python-versions }} + # No versions for sqlite + backend-versions: "['']" + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: ${{ needs.build-info.outputs.sqlite-exclude }} + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.core-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + run-migration-tests: "true" + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + if: needs.build-info.outputs.run-unit-tests == 'true' + + tests-sqlite-providers: + name: "Sqlite tests: providers" + uses: ./.github/workflows/run-unit-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + backend: "sqlite" + test-name: "Sqlite" + test-name-separator: "" + test-scope: "DB" + test-group: "providers" + python-versions: ${{ needs.build-info.outputs.python-versions }} + # No versions for sqlite + backend-versions: "['']" + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: ${{ needs.build-info.outputs.sqlite-exclude }} + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.providers-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + run-migration-tests: "true" + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + if: needs.build-info.outputs.run-unit-tests == 'true' + + tests-non-db-core: + name: "Non-DB tests: core" + uses: ./.github/workflows/run-unit-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + backend: "sqlite" + test-name: "" + test-name-separator: "" + test-scope: "Non-DB" + test-group: "core" + python-versions: ${{ needs.build-info.outputs.python-versions }} + # No versions for non-db + backend-versions: "['']" + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: ${{ needs.build-info.outputs.sqlite-exclude }} + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.core-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + if: needs.build-info.outputs.run-unit-tests == 'true' + + tests-non-db-providers: + name: "Non-DB tests: providers" + uses: ./.github/workflows/run-unit-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + backend: "sqlite" + test-name: "" + test-name-separator: "" + test-scope: "Non-DB" + test-group: "providers" + python-versions: ${{ needs.build-info.outputs.python-versions }} + # No versions for non-db + backend-versions: "['']" + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: ${{ needs.build-info.outputs.sqlite-exclude }} + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.providers-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + if: needs.build-info.outputs.run-unit-tests == 'true' + + tests-special: + name: "Special tests" + uses: ./.github/workflows/special-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + if: > + needs.build-info.outputs.run-unit-tests == 'true' && + (needs.build-info.outputs.canary-run == 'true' || + needs.build-info.outputs.upgrade-to-newer-dependencies != 'false' || + needs.build-info.outputs.full-tests-needed == 'true') + with: + default-branch: ${{ needs.build-info.outputs.default-branch }} + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + core-test-types-list-as-strings-in-json: > + ${{ needs.build-info.outputs.core-test-types-list-as-strings-in-json }} + providers-test-types-list-as-strings-in-json: > + ${{ needs.build-info.outputs.providers-test-types-list-as-strings-in-json }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + python-versions: ${{ needs.build-info.outputs.python-versions }} + default-postgres-version: ${{ needs.build-info.outputs.default-postgres-version }} + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + canary-run: ${{ needs.build-info.outputs.canary-run }} + upgrade-to-newer-dependencies: ${{ needs.build-info.outputs.upgrade-to-newer-dependencies }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + + tests-integration-system: + name: Integration and System Tests + needs: [build-info, build-ci-images] + uses: ./.github/workflows/integration-system-tests.yml + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + testable-core-integrations: ${{ needs.build-info.outputs.testable-core-integrations }} + testable-providers-integrations: ${{ needs.build-info.outputs.testable-providers-integrations }} + run-system-tests: ${{ needs.build-info.outputs.run-system-tests }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + default-postgres-version: ${{ needs.build-info.outputs.default-postgres-version }} + default-mysql-version: ${{ needs.build-info.outputs.default-mysql-version }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + if: needs.build-info.outputs.run-unit-tests == 'true' + + tests-with-lowest-direct-resolution-core: + name: "Low dep tests:core" + needs: [build-info, build-ci-images] + uses: ./.github/workflows/run-unit-tests.yml + permissions: + contents: read + packages: read + if: > + needs.build-info.outputs.run-unit-tests == 'true' + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + test-name: "LowestDeps" + force-lowest-dependencies: "true" + test-scope: "All" + test-group: "core" + backend: "sqlite" + python-versions: ${{ needs.build-info.outputs.python-versions }} + backend-versions: "['${{ needs.build-info.outputs.default-postgres-version }}']" + excluded-providers-as-string: "" + excludes: "[]" + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.core-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + monitor-delay-time-in-seconds: 120 + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + + tests-with-lowest-direct-resolution-providers: + name: "Low dep tests: providers" + needs: [build-info, build-ci-images] + uses: ./.github/workflows/run-unit-tests.yml + permissions: + contents: read + packages: read + if: needs.build-info.outputs.run-unit-tests == 'true' + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + test-name: "LowestDeps" + force-lowest-dependencies: "true" + test-scope: "All" + test-group: "providers" + backend: "sqlite" + python-versions: ${{ needs.build-info.outputs.python-versions }} + backend-versions: "['${{ needs.build-info.outputs.default-postgres-version }}']" + excluded-providers-as-string: ${{ needs.build-info.outputs.excluded-providers-as-string }} + excludes: "[]" + test-types-as-strings-in-json: > + ${{ needs.build-info.outputs.individual-providers-test-types-list-as-strings-in-json }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + run-coverage: ${{ needs.build-info.outputs.run-coverage }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + monitor-delay-time-in-seconds: 120 + skip-providers-tests: ${{ needs.build-info.outputs.skip-providers-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + + build-prod-images: + name: Build PROD images + needs: [build-info, build-ci-images, generate-constraints] + uses: ./.github/workflows/prod-image-build.yml + permissions: + contents: read + # This write is only given here for `push` events from "apache/airflow" repo. It is not given for PRs + # from forks. This is to prevent malicious PRs from creating images in the "apache/airflow" repo. + packages: write + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + build-type: "Regular" + push-image: "false" + upload-image-artifact: "true" + upload-package-artifact: "true" + python-versions: ${{ needs.build-info.outputs.python-versions }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + branch: ${{ needs.build-info.outputs.default-branch }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + upgrade-to-newer-dependencies: ${{ needs.build-info.outputs.upgrade-to-newer-dependencies }} + constraints-branch: ${{ needs.build-info.outputs.default-constraints-branch }} + docker-cache: ${{ needs.build-info.outputs.docker-cache }} + disable-airflow-repo-cache: ${{ needs.build-info.outputs.disable-airflow-repo-cache }} + prod-image-build: ${{ needs.build-info.outputs.prod-image-build }} + + additional-prod-image-tests: + name: "Additional PROD image tests" + needs: [build-info, build-prod-images, generate-constraints] + uses: ./.github/workflows/additional-prod-image-tests.yml + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + default-branch: ${{ needs.build-info.outputs.default-branch }} + constraints-branch: ${{ needs.build-info.outputs.default-constraints-branch }} + upgrade-to-newer-dependencies: ${{ needs.build-info.outputs.upgrade-to-newer-dependencies }} + docker-cache: ${{ needs.build-info.outputs.docker-cache }} + disable-airflow-repo-cache: ${{ needs.build-info.outputs.disable-airflow-repo-cache }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + run-task-sdk-integration-tests: ${{ needs.build-info.outputs.run-task-sdk-integration-tests }} + canary-run: ${{ needs.build-info.outputs.canary-run }} + run-remote-logging-elasticsearch-e2e-tests: ${{ needs.build-info.outputs.run-remote-logging-elasticsearch-e2e-tests }} + run-remote-logging-s3-e2e-tests: ${{ needs.build-info.outputs.run-remote-logging-s3-e2e-tests }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + run-ui-e2e-tests: ${{ needs.build-info.outputs.run-ui-e2e-tests }} + run-airflow-ctl-integration-tests: ${{ needs.build-info.outputs.run-airflow-ctl-integration-tests }} + if: needs.build-info.outputs.prod-image-build == 'true' + + tests-kubernetes: + name: "Kubernetes tests" + uses: ./.github/workflows/k8s-tests.yml + needs: [build-info, build-prod-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + python-versions-list-as-string: ${{ needs.build-info.outputs.python-versions-list-as-string }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + kubernetes-combos: ${{ needs.build-info.outputs.kubernetes-combos }} + if: > + ( needs.build-info.outputs.run-kubernetes-tests == 'true' || + needs.build-info.outputs.run-helm-tests == 'true') + + + tests-task-sdk: + name: "Task SDK tests" + uses: ./.github/workflows/airflow-distributions-tests.yml + needs: [build-info, build-ci-images] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + python-versions: ${{ needs.build-info.outputs.python-versions }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + canary-run: ${{ needs.build-info.outputs.canary-run }} + distribution-name: "task-sdk" + distribution-cmd-format: "prepare-task-sdk-distributions" + test-type: "task-sdk-tests" + use-local-venv: 'false' + test-timeout: 20 + if: needs.build-info.outputs.run-task-sdk-tests == 'true' + + tests-go-sdk: + name: "Go SDK tests" + needs: [build-info] + runs-on: ${{ fromJSON(needs.build-info.outputs.runner-type) }} + timeout-minutes: 15 + permissions: + contents: read + packages: read + if: needs.build-info.outputs.run-go-sdk-tests == 'true' + env: + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_USERNAME: ${{ github.actor }} + VERBOSE: "true" + steps: + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + # keep this in sync with go.mod in go-sdk/ + - name: Setup Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: 1.24 + cache-dependency-path: go-sdk/go.sum + # keep this in sync with go.mod in go-sdk/ + - name: Setup Gotestsum + shell: bash + run: | + go install gotest.tools/gotestsum@c4a0df2e75a225d979a444342dd3db752b53619f # v1.13.0 + gotestsum --version + - name: "Cleanup dist files" + run: rm -fv ./dist/* + - name: Run Go tests + working-directory: ./go-sdk + run: gotestsum --format github-actions ./... + + tests-airflow-ctl: + name: "Airflow CTL tests" + uses: ./.github/workflows/airflow-distributions-tests.yml + needs: [build-info] + permissions: + contents: read + packages: read + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + python-versions: ${{ needs.build-info.outputs.python-versions }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + canary-run: ${{ needs.build-info.outputs.canary-run }} + distribution-name: "airflow-ctl" + distribution-cmd-format: "prepare-airflow-ctl-distributions" + test-type: "airflow-ctl-tests" + use-local-venv: 'true' + test-timeout: 20 + if: needs.build-info.outputs.run-airflow-ctl-tests == 'true' + + finalize-tests: + name: Finalize tests + permissions: + contents: write + packages: write + # This will fire when all the jobs from "needs" are either successful or skipped + if: always() && !failure() && !cancelled() + needs: + - additional-ci-image-checks + - additional-prod-image-tests + - basic-tests + - build-info + - build-prod-images + - ci-image-checks + - generate-constraints + - migration-round-trip + - mypy-providers + - providers + - tests-helm + - tests-integration-system + - tests-kubernetes + - tests-mysql-core + - tests-mysql-providers + - tests-non-db-core + - tests-non-db-providers + - tests-postgres-core + - tests-postgres-providers + - tests-sqlite-core + - tests-sqlite-providers + - tests-task-sdk + - tests-airflow-ctl + - tests-go-sdk + - tests-with-lowest-direct-resolution-core + - tests-with-lowest-direct-resolution-providers + uses: ./.github/workflows/finalize-tests.yml + with: + runners: ${{ needs.build-info.outputs.runner-type }} + platform: ${{ needs.build-info.outputs.platform }} + python-versions: ${{ needs.build-info.outputs.python-versions }} + python-versions-list-as-string: ${{ needs.build-info.outputs.python-versions-list-as-string }} + branch: ${{ needs.build-info.outputs.default-branch }} + constraints-branch: ${{ needs.build-info.outputs.default-constraints-branch }} + default-python-version: "${{ needs.build-info.outputs.default-python-version }}" + upgrade-to-newer-dependencies: ${{ needs.build-info.outputs.upgrade-to-newer-dependencies }} + include-success-outputs: ${{ needs.build-info.outputs.include-success-outputs }} + docker-cache: ${{ needs.build-info.outputs.docker-cache }} + disable-airflow-repo-cache: ${{ needs.build-info.outputs.disable-airflow-repo-cache }} + canary-run: ${{ needs.build-info.outputs.canary-run }} + use-uv: ${{ needs.build-info.outputs.use-uv }} + debug-resources: ${{ needs.build-info.outputs.debug-resources }} + + notify-slack: + name: "Notify Slack" + needs: + - build-info + - finalize-tests + if: >- + always() && + !cancelled() && + github.event_name == 'schedule' && + github.run_attempt == 1 + runs-on: ["ubuntu-22.04"] + steps: + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: "Get failing jobs" + id: get-failures + shell: bash + run: | + FAILED_JOBS=$(gh run view "${{ github.run_id }}" \ + --repo "${{ github.repository }}" \ + --json jobs \ + --jq '[.jobs[] | select(.conclusion == "failure") | .name] | sort | .[]') + echo "failed-jobs<> "${GITHUB_OUTPUT}" + echo "${FAILED_JOBS}" >> "${GITHUB_OUTPUT}" + echo "EOF" >> "${GITHUB_OUTPUT}" + if [[ -n "${FAILED_JOBS}" ]]; then + echo "has-failures=true" >> "${GITHUB_OUTPUT}" + else + echo "has-failures=false" >> "${GITHUB_OUTPUT}" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: "Determine notification action" + id: notification + shell: bash + run: | + command -v gh >/dev/null 2>&1 || { echo "::error::gh CLI is not installed"; exit 1; } + gh auth status || gh auth login --with-token <<< "${GITHUB_TOKEN}" + python3 scripts/ci/slack_notification_state.py + env: + ARTIFACT_NAME: "slack-state-tests-${{ github.ref_name }}" + CURRENT_FAILURES: "${{ steps.get-failures.outputs.failed-jobs }}" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: "Upload notification state" + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: "slack-state-tests-${{ github.ref_name }}" + path: ./slack-state/ + retention-days: 7 + overwrite: true + - name: "Notify Slack (new/changed failures)" + if: steps.notification.outputs.action == 'notify_new' + uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3 + with: + method: chat.postMessage + token: ${{ env.SLACK_BOT_TOKEN }} + # yamllint disable rule:line-length + payload: | + channel: "internal-airflow-ci-cd" + text: "🚨 Failure Alert: Scheduled CI (${{ needs.build-info.outputs.platform }}) on branch *${{ github.ref_name }}*\n\nFailing jobs:\n${{ steps.get-failures.outputs.failed-jobs }}\n\n*Details:* " + blocks: + - type: "section" + text: + type: "mrkdwn" + text: "🚨 Failure Alert: Scheduled CI (${{ needs.build-info.outputs.platform }}) on *${{ github.ref_name }}*\n\nFailing jobs:\n${{ steps.get-failures.outputs.failed-jobs }}\n\n*Details:* " + # yamllint enable rule:line-length + - name: "Notify Slack (still not fixed)" + if: steps.notification.outputs.action == 'notify_reminder' + uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3 + with: + method: chat.postMessage + token: ${{ env.SLACK_BOT_TOKEN }} + # yamllint disable rule:line-length + payload: | + channel: "internal-airflow-ci-cd" + text: "🚨🔁 Still not fixed: Scheduled CI (${{ needs.build-info.outputs.platform }}) on branch *${{ github.ref_name }}*\n\nFailing jobs:\n${{ steps.get-failures.outputs.failed-jobs }}\n\n*Details:* " + blocks: + - type: "section" + text: + type: "mrkdwn" + text: "🚨🔁 Still not fixed: Scheduled CI (${{ needs.build-info.outputs.platform }}) on *${{ github.ref_name }}*\n\nFailing jobs:\n${{ steps.get-failures.outputs.failed-jobs }}\n\n*Details:* " + # yamllint enable rule:line-length + - name: "Notify Slack (all tests passing)" + if: steps.notification.outputs.action == 'notify_recovery' + uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3 + with: + method: chat.postMessage + token: ${{ env.SLACK_BOT_TOKEN }} + # yamllint disable rule:line-length + payload: | + channel: "internal-airflow-ci-cd" + text: "✅ All tests passing: Scheduled CI (${{ needs.build-info.outputs.platform }}) on branch *${{ github.ref_name }}*\n\n*Details:* " + blocks: + - type: "section" + text: + type: "mrkdwn" + text: "✅ All tests passing: Scheduled CI (${{ needs.build-info.outputs.platform }}) on *${{ github.ref_name }}*\n\n*Details:* " + # yamllint enable rule:line-length + + summarize-warnings: + timeout-minutes: 15 + name: "Summarize warnings" + needs: + - build-info + - tests-mysql-core + - tests-mysql-providers + - tests-non-db-core + - tests-non-db-providers + - tests-postgres-core + - tests-postgres-providers + - tests-sqlite-core + - tests-sqlite-providers + - tests-task-sdk + - tests-airflow-ctl + - tests-special + - tests-with-lowest-direct-resolution-core + - tests-with-lowest-direct-resolution-providers + runs-on: ${{ fromJSON(needs.build-info.outputs.runner-type) }} + if: needs.build-info.outputs.run-unit-tests == 'true' + steps: + - name: "Cleanup repo" + shell: bash + run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: "Free up disk space" + shell: bash + run: ./scripts/tools/free_up_disk_space.sh + - name: "Download all test warning artifacts from the current build" + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + path: ./artifacts + pattern: test-warnings-* + - name: "Setup python" + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "${{ inputs.default-python-version }}" + - name: "Summarize all warnings" + run: | + ./scripts/ci/testing/summarize_captured_warnings.py ./artifacts \ + --pattern "**/warnings-*.txt" \ + --output ./files + - name: "Upload artifact for summarized warnings" + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: "test-summarized-warnings" + path: ./files/warn-summary-*.txt + retention-days: 7 + if-no-files-found: ignore + overwrite: true diff --git a/.github/workflows/ci-notification.yml b/.github/workflows/ci-notification.yml index 6bb7b830a7888..b59cabc8b25ed 100644 --- a/.github/workflows/ci-notification.yml +++ b/.github/workflows/ci-notification.yml @@ -37,7 +37,9 @@ jobs: strategy: matrix: branch: ["v3-2-test"] - workflow-id: ["ci-amd-arm.yml"] + # Track AMD; ARM is the canary slot and is reported separately by + # `ci-arm.yml`'s notify-slack job on schedule events. + workflow-id: ["ci-amd.yml"] runs-on: ubuntu-latest steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" diff --git a/.github/workflows/e2e-flaky-tests-report.yml b/.github/workflows/e2e-flaky-tests-report.yml index 7eb2cdf954243..caa27063468b3 100644 --- a/.github/workflows/e2e-flaky-tests-report.yml +++ b/.github/workflows/e2e-flaky-tests-report.yml @@ -46,7 +46,10 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MAX_RUNS: "10" - WORKFLOW_NAME: "ci-amd-arm.yml" + # E2E test runs come from the AMD workflow (every PR / push to main + # goes through it). The ARM canary is too sparse to drive flakiness + # analysis, so we keep the report tied to AMD. + WORKFLOW_NAME: "ci-amd.yml" BRANCH: "main" OUTPUT_FILE: "slack-message.json" diff --git a/.github/workflows/release_dockerhub_image.yml b/.github/workflows/release_dockerhub_image.yml index a1326e74d7642..dbff0e42201ce 100644 --- a/.github/workflows/release_dockerhub_image.yml +++ b/.github/workflows/release_dockerhub_image.yml @@ -92,7 +92,7 @@ jobs: - name: "Install Breeze" uses: ./.github/actions/breeze - name: "Save github context to file" - # See ci-amd-arm.yml for the full rationale: avoids ARG_MAX on big PRs by writing the + # See ci-amd.yml for the full rationale: avoids ARG_MAX on big PRs by writing the # github context to a file, and the single-quoted heredoc makes the zizmor # template-injection finding a false positive (no bash expansion happens inside it). shell: bash diff --git a/.github/workflows/update-constraints-on-push-stable.yml b/.github/workflows/update-constraints-on-push-stable.yml index 0fe7d6d544566..389c153c5b7f2 100644 --- a/.github/workflows/update-constraints-on-push-stable.yml +++ b/.github/workflows/update-constraints-on-push-stable.yml @@ -60,7 +60,7 @@ jobs: uses: ./.github/actions/breeze id: breeze - name: "Save github context to file" - # See ci-amd-arm.yml for the full rationale: avoids ARG_MAX on big PRs by writing the + # See ci-amd.yml for the full rationale: avoids ARG_MAX on big PRs by writing the # github context to a file, and the single-quoted heredoc makes the zizmor # template-injection finding a false positive (no bash expansion happens inside it). shell: bash diff --git a/.github/workflows/update-constraints-on-push.yml b/.github/workflows/update-constraints-on-push.yml index eb9b202e581cf..f8aee69246736 100644 --- a/.github/workflows/update-constraints-on-push.yml +++ b/.github/workflows/update-constraints-on-push.yml @@ -63,7 +63,7 @@ jobs: uses: ./.github/actions/breeze id: breeze - name: "Save github context to file" - # See ci-amd-arm.yml for the full rationale: avoids ARG_MAX on big PRs by writing the + # See ci-amd.yml for the full rationale: avoids ARG_MAX on big PRs by writing the # github context to a file, and the single-quoted heredoc makes the zizmor # template-injection finding a false positive (no bash expansion happens inside it). shell: bash diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0b913692a4c4a..cc1f41c4685b3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -235,6 +235,13 @@ repos: ^pyproject\.toml$ pass_filenames: false require_serial: true + - id: check-ci-workflows-in-sync + name: Check ci-arm.yml and ci-amd.yml stay in sync + entry: ./scripts/ci/prek/check_ci_workflows_in_sync.py + language: python + files: ^\.github/workflows/ci-(arm|amd)\.yml$ + pass_filenames: false + require_serial: true - id: sync-uv-min-version-markers name: Sync `# sync-uv-min-version` markers with [tool.uv] required-version entry: ./scripts/ci/prek/sync_uv_min_version_markers.py diff --git a/README.md b/README.md index 9e45b8907b850..a659243961629 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ | Version | Build Status | |---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Main | [![GitHub Build main](https://github.com/apache/airflow/actions/workflows/ci-amd-arm.yml/badge.svg)](https://github.com/apache/airflow/actions) | -| 3.x | [![GitHub Build 3.1](https://github.com/apache/airflow/actions/workflows/ci-amd-arm.yml/badge.svg?branch=v3-1-test)](https://github.com/apache/airflow/actions) | +| Main | [![GitHub Build main](https://github.com/apache/airflow/actions/workflows/ci-amd.yml/badge.svg)](https://github.com/apache/airflow/actions) | +| 3.x | [![GitHub Build 3.2](https://github.com/apache/airflow/actions/workflows/ci-amd.yml/badge.svg?branch=v3-2-test)](https://github.com/apache/airflow/actions) | | 2.x | [![GitHub Build 2.11](https://github.com/apache/airflow/actions/workflows/ci.yml/badge.svg?branch=v2-11-test)](https://github.com/apache/airflow/actions) | @@ -98,14 +98,14 @@ Airflow is not a streaming solution, but it is often used to process real-time d Apache Airflow is tested with: -| | Main version (dev) | Stable version (3.2.1) | Stable version (2.11.2) | -|------------|-----------------------------------|------------------------------|------------------------------| -| Python | 3.10, 3.11, 3.12, 3.13, 3.14 | 3.10, 3.11, 3.12, 3.13, 3.14 | 3.10, 3.11, 3.12 | -| Platform | AMD64/ARM64 | AMD64/ARM64 | AMD64/ARM64(\*) | -| Kubernetes | 1.30, 1.31, 1.32, 1.33, 1.34, 1.35 | 1.30, 1.31, 1.32, 1.33 | 1.26, 1.27, 1.28, 1.29, 1.30 | -| PostgreSQL | 14, 15, 16, 17, 18 | 13, 14, 15, 16, 17 | 12, 13, 14, 15, 16 | -| MySQL | 8.0, 8.4, Innovation | 8.0, 8.4, Innovation | 8.0, Innovation | -| SQLite | 3.15.0+ | 3.15.0+ | 3.15.0+ | +| | Main version (dev) | Stable version (3.2.0) | Stable version (2.11.2) | +|------------|------------------------------------|-------------------------------------|------------------------------| +| Python | 3.10, 3.11, 3.12, 3.13, 3.14 | 3.10, 3.11, 3.12, 3.13, 3.14 | 3.10, 3.11, 3.12 | +| Platform | AMD64/ARM64 | AMD64/ARM64 | AMD64/ARM64(\*) | +| Kubernetes | 1.30, 1.31, 1.32, 1.33, 1.34, 1.35 | 1.30, 1.31, 1.32, 1.33, 1.34, 1.35 | 1.26, 1.27, 1.28, 1.29, 1.30 | +| PostgreSQL | 14, 15, 16, 17, 18 | 14, 15, 16, 17, 18 | 12, 13, 14, 15, 16 | +| MySQL | 8.0, 8.4, Innovation | 8.0, 8.4, Innovation | 8.0, Innovation | +| SQLite | 3.15.0+ | 3.15.0+ | 3.15.0+ | \* Experimental @@ -171,15 +171,15 @@ them to the appropriate format and workflow that your tool requires. ```bash -pip install 'apache-airflow==3.2.1' \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.2.1/constraints-3.10.txt" +pip install 'apache-airflow==3.2.0' \ + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.2.0/constraints-3.10.txt" ``` 2. Installing with extras (i.e., postgres, google) ```bash -pip install 'apache-airflow[postgres,google]==3.2.1' \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.2.1/constraints-3.10.txt" +pip install 'apache-airflow[postgres,google]==3.2.0' \ + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.2.0/constraints-3.10.txt" ``` For information on installing provider distributions, check diff --git a/dev/README_AIRFLOW3_DEV.md b/dev/README_AIRFLOW3_DEV.md index 3c19a28cf6c75..17de81521cbfd 100644 --- a/dev/README_AIRFLOW3_DEV.md +++ b/dev/README_AIRFLOW3_DEV.md @@ -72,7 +72,7 @@ PRs should **never** target `v3-1-stable` directly unless explicitly instructed > likely need additional changes before GA. However, when using this shortcut, the release manager **must** > verify that the `v3-X-test` push CI action ("Tests" workflow) has succeeded before cutting the RC. You can > check this at: -> https://github.com/apache/airflow/actions/workflows/ci-amd-arm.yml?query=event%3Apush+branch%3Av3-2-test +> https://github.com/apache/airflow/actions/workflows/ci-amd.yml?query=event%3Apush+branch%3Av3-2-test > (adjust the branch filter for the relevant `v3-X-test` branch). ## Developing for Airflow 3 diff --git a/dev/README_RELEASE_AIRFLOW.md b/dev/README_RELEASE_AIRFLOW.md index a7c508e554cd1..36ef4c331dff8 100644 --- a/dev/README_RELEASE_AIRFLOW.md +++ b/dev/README_RELEASE_AIRFLOW.md @@ -533,7 +533,7 @@ still works but is no longer recommended. > likely need additional changes before GA. However, when using this shortcut, the release manager **must** > verify that the `v3-X-test` push CI action ("Tests" workflow) has succeeded before cutting the RC. You can > check this at: -> https://github.com/apache/airflow/actions/workflows/ci-amd-arm.yml?query=event%3Apush+branch%3Av3-2-test +> https://github.com/apache/airflow/actions/workflows/ci-amd.yml?query=event%3Apush+branch%3Av3-2-test > (adjust the branch filter for the relevant `v3-X-test` branch). - When the PR is approved (or when using the shortcut above), install `dev/breeze` in a virtualenv: diff --git a/dev/breeze/doc/images/output_build-docs.txt b/dev/breeze/doc/images/output_build-docs.txt index b94beee13bebf..ea24111dadf71 100644 --- a/dev/breeze/doc/images/output_build-docs.txt +++ b/dev/breeze/doc/images/output_build-docs.txt @@ -1 +1 @@ -773708c31df1241d861ccd24c4f9d850 +5023b820002e3f33104ae46d617645c4 diff --git a/dev/breeze/doc/images/output_ci-image_build.txt b/dev/breeze/doc/images/output_ci-image_build.txt index 0d5f5e8b8edb7..4d06edb479b8f 100644 --- a/dev/breeze/doc/images/output_ci-image_build.txt +++ b/dev/breeze/doc/images/output_ci-image_build.txt @@ -1 +1 @@ -7798356a133bc45002b2d00dea58a174 +6f9021a610b04f0853dcb38f80059cc2 diff --git a/dev/breeze/doc/images/output_ci-image_export-mount-cache.txt b/dev/breeze/doc/images/output_ci-image_export-mount-cache.txt index 32ac052a83fea..f9bae543c4323 100644 --- a/dev/breeze/doc/images/output_ci-image_export-mount-cache.txt +++ b/dev/breeze/doc/images/output_ci-image_export-mount-cache.txt @@ -1 +1 @@ -dca0cd678dae89b1e35317bbc130a106 +390efb28399cac005e2fe192c2c8fa3c diff --git a/dev/breeze/doc/images/output_ci-image_import-mount-cache.txt b/dev/breeze/doc/images/output_ci-image_import-mount-cache.txt index d6f503d06e548..6f7766e809abf 100644 --- a/dev/breeze/doc/images/output_ci-image_import-mount-cache.txt +++ b/dev/breeze/doc/images/output_ci-image_import-mount-cache.txt @@ -1 +1 @@ -f9ca33618f97321e3e5a410474d84420 +b2e325b92a7dda14681676c6bf050191 diff --git a/dev/breeze/doc/images/output_ci-image_load.txt b/dev/breeze/doc/images/output_ci-image_load.txt index 7e10a45f2474a..2f2f4d04205c0 100644 --- a/dev/breeze/doc/images/output_ci-image_load.txt +++ b/dev/breeze/doc/images/output_ci-image_load.txt @@ -1 +1 @@ -d919d32cd79055fbb8ed65c33a3f047d +baf0bfe0e270b6982bbfbfd97707a1ba diff --git a/dev/breeze/doc/images/output_ci-image_pull.txt b/dev/breeze/doc/images/output_ci-image_pull.txt index ef0884ededa64..fb2ef908512cc 100644 --- a/dev/breeze/doc/images/output_ci-image_pull.txt +++ b/dev/breeze/doc/images/output_ci-image_pull.txt @@ -1 +1 @@ -3251ba2079b1e67c196db34289a7b980 +fc42909eb684d7821ff2a3575a7e1073 diff --git a/dev/breeze/doc/images/output_ci-image_save.txt b/dev/breeze/doc/images/output_ci-image_save.txt index 0480e0b4a8aed..5c490055adbfa 100644 --- a/dev/breeze/doc/images/output_ci-image_save.txt +++ b/dev/breeze/doc/images/output_ci-image_save.txt @@ -1 +1 @@ -b8db67fe0fb1717432c68048b783038d +b2ccfc3115708e08a384ff6852145485 diff --git a/dev/breeze/doc/images/output_ci-image_verify.txt b/dev/breeze/doc/images/output_ci-image_verify.txt index 1e2a2241916de..d62405260cc9d 100644 --- a/dev/breeze/doc/images/output_ci-image_verify.txt +++ b/dev/breeze/doc/images/output_ci-image_verify.txt @@ -1 +1 @@ -b1a6deb8e99fc88f9ee887b07982abb9 +59daf613dc467f3f1f923bcf7d24eb88 diff --git a/dev/breeze/doc/images/output_ci_fix-ownership.txt b/dev/breeze/doc/images/output_ci_fix-ownership.txt index 744858849d1fe..195b864d2d0b9 100644 --- a/dev/breeze/doc/images/output_ci_fix-ownership.txt +++ b/dev/breeze/doc/images/output_ci_fix-ownership.txt @@ -1 +1 @@ -9a350b9a01617c0d91b74895c471998d +3cb498e57408220f1e519fd87b3591fd diff --git a/dev/breeze/doc/images/output_ci_free-space.txt b/dev/breeze/doc/images/output_ci_free-space.txt index fcd3e8380ae56..6d05cae2891b8 100644 --- a/dev/breeze/doc/images/output_ci_free-space.txt +++ b/dev/breeze/doc/images/output_ci_free-space.txt @@ -1 +1 @@ -5463f176d0f234b70c339a6327b04fc1 +f09f3a00b5184fc32f8f2a83e2b2d85e diff --git a/dev/breeze/doc/images/output_ci_get-workflow-info.txt b/dev/breeze/doc/images/output_ci_get-workflow-info.txt index 9215605ee86d7..cb32fa3aba57a 100644 --- a/dev/breeze/doc/images/output_ci_get-workflow-info.txt +++ b/dev/breeze/doc/images/output_ci_get-workflow-info.txt @@ -1 +1 @@ -b356e9aec5dc0c6b7a6748aa944a9097 +31cc2b4c6d1a1aafaf748d35d156dd05 diff --git a/dev/breeze/doc/images/output_ci_resource-check.txt b/dev/breeze/doc/images/output_ci_resource-check.txt index 133407b13abed..3acf87fec0de7 100644 --- a/dev/breeze/doc/images/output_ci_resource-check.txt +++ b/dev/breeze/doc/images/output_ci_resource-check.txt @@ -1 +1 @@ -78faaccb656e7115091c3eb33e1db52e +aba60bb91a07cb067da939e93308ed07 diff --git a/dev/breeze/doc/images/output_ci_selective-check.txt b/dev/breeze/doc/images/output_ci_selective-check.txt index 5c3f254d10c24..49fcc692fa57e 100644 --- a/dev/breeze/doc/images/output_ci_selective-check.txt +++ b/dev/breeze/doc/images/output_ci_selective-check.txt @@ -1 +1 @@ -07f0b9236b55157c0c48349d1e7fc716 +dece9e901b05dabcb3af55c27b61410d diff --git a/dev/breeze/doc/images/output_ci_set-milestone.txt b/dev/breeze/doc/images/output_ci_set-milestone.txt index 0e7e7b794517f..2333f8006209d 100644 --- a/dev/breeze/doc/images/output_ci_set-milestone.txt +++ b/dev/breeze/doc/images/output_ci_set-milestone.txt @@ -1 +1 @@ -da6dcbf0c7c951081f6ed7082a849024 +7e6437d4c374aba8a6c9f459d3237ae0 diff --git a/dev/breeze/doc/images/output_ci_upgrade.txt b/dev/breeze/doc/images/output_ci_upgrade.txt index 446a9b367ccdf..b4279b39938e2 100644 --- a/dev/breeze/doc/images/output_ci_upgrade.txt +++ b/dev/breeze/doc/images/output_ci_upgrade.txt @@ -1 +1 @@ -cd82673ad278d0e427562e69237116e6 +98c7d919cdbf65fa4a8f774650c007e4 diff --git a/dev/breeze/doc/images/output_cleanup.txt b/dev/breeze/doc/images/output_cleanup.txt index 8e5b3135835a4..24d8db6ddc91b 100644 --- a/dev/breeze/doc/images/output_cleanup.txt +++ b/dev/breeze/doc/images/output_cleanup.txt @@ -1 +1 @@ -c48fa924ab93157f3782106db4e4c564 +0a2dfb9e5d5e65d602ff2399a0949925 diff --git a/dev/breeze/doc/images/output_doctor.txt b/dev/breeze/doc/images/output_doctor.txt index 848ff3a141bfd..6f3c5acf19407 100644 --- a/dev/breeze/doc/images/output_doctor.txt +++ b/dev/breeze/doc/images/output_doctor.txt @@ -1 +1 @@ -0062c127f9be56656573a21d3ca22ed1 +d79232c4903a1ffaacb5eb3b944f354e diff --git a/dev/breeze/doc/images/output_down.txt b/dev/breeze/doc/images/output_down.txt index 9ffc1b9234d8b..c0200cc3228e1 100644 --- a/dev/breeze/doc/images/output_down.txt +++ b/dev/breeze/doc/images/output_down.txt @@ -1 +1 @@ -c0823111aee5a9b4832219380463cbea +5c5712f40f3397d077afce24bc6b5d4d diff --git a/dev/breeze/doc/images/output_exec.txt b/dev/breeze/doc/images/output_exec.txt index fb30562c12694..b3ad835922b46 100644 --- a/dev/breeze/doc/images/output_exec.txt +++ b/dev/breeze/doc/images/output_exec.txt @@ -1 +1 @@ -b7253a38538f0d76fa005c4aa1ee2730 +0c19dd1538b155da498dd37640c9327e diff --git a/dev/breeze/doc/images/output_generate-migration-file.txt b/dev/breeze/doc/images/output_generate-migration-file.txt index 465ee6e2c8f57..bc99ac073a20a 100644 --- a/dev/breeze/doc/images/output_generate-migration-file.txt +++ b/dev/breeze/doc/images/output_generate-migration-file.txt @@ -1 +1 @@ -17abdd8a6f454801c5d7a62f108e4af0 +af32528c0276154a8b806a7c31e129dc diff --git a/dev/breeze/doc/images/output_issues_unassign.txt b/dev/breeze/doc/images/output_issues_unassign.txt index f068eeb8ac899..f876d66b1894f 100644 --- a/dev/breeze/doc/images/output_issues_unassign.txt +++ b/dev/breeze/doc/images/output_issues_unassign.txt @@ -1 +1 @@ -0980c196ed32f8a4d18adaee0c1d4e2b +acac77b3df954d6b8aff4d11fafedee6 diff --git a/dev/breeze/doc/images/output_k8s_build-k8s-image.txt b/dev/breeze/doc/images/output_k8s_build-k8s-image.txt index f8d906e6b89ca..e3c40f12db5c3 100644 --- a/dev/breeze/doc/images/output_k8s_build-k8s-image.txt +++ b/dev/breeze/doc/images/output_k8s_build-k8s-image.txt @@ -1 +1 @@ -b0aad03ecd34c29f7a4dcb228c80f52e +72bed3d7d7894504f270fe40239e1b9b diff --git a/dev/breeze/doc/images/output_k8s_configure-cluster.txt b/dev/breeze/doc/images/output_k8s_configure-cluster.txt index 93a8fd7719af1..73ef5f5decd35 100644 --- a/dev/breeze/doc/images/output_k8s_configure-cluster.txt +++ b/dev/breeze/doc/images/output_k8s_configure-cluster.txt @@ -1 +1 @@ -cd279fe254076d65388174b6a3d7f91a +f2b5ff2738e80212ec1afb4fd0a3b1d5 diff --git a/dev/breeze/doc/images/output_k8s_create-cluster.txt b/dev/breeze/doc/images/output_k8s_create-cluster.txt index 33331013c1741..257f2e33b7ecf 100644 --- a/dev/breeze/doc/images/output_k8s_create-cluster.txt +++ b/dev/breeze/doc/images/output_k8s_create-cluster.txt @@ -1 +1 @@ -0e5b77c6711ca067ef42651e2303d4ac +bda47ffc8ebdaf681ed2bdec16574ec3 diff --git a/dev/breeze/doc/images/output_k8s_delete-cluster.txt b/dev/breeze/doc/images/output_k8s_delete-cluster.txt index c4325b42571cc..cf72922b112f4 100644 --- a/dev/breeze/doc/images/output_k8s_delete-cluster.txt +++ b/dev/breeze/doc/images/output_k8s_delete-cluster.txt @@ -1 +1 @@ -fee7401ccb099fa284ef144654c4b2c6 +ad00903ae7f5ff3cb8f21bc2e4cf1387 diff --git a/dev/breeze/doc/images/output_k8s_deploy-airflow.txt b/dev/breeze/doc/images/output_k8s_deploy-airflow.txt index ea0bdf6c51d8d..f4c4c5620afd0 100644 --- a/dev/breeze/doc/images/output_k8s_deploy-airflow.txt +++ b/dev/breeze/doc/images/output_k8s_deploy-airflow.txt @@ -1 +1 @@ -ff2638b43ba5c3be45c1b684c6240a69 +3ce1a62e91cffceefefd09619cb6eb52 diff --git a/dev/breeze/doc/images/output_k8s_deploy-cluster.txt b/dev/breeze/doc/images/output_k8s_deploy-cluster.txt index c78f9e0f0bb0a..fa099647e20fb 100644 --- a/dev/breeze/doc/images/output_k8s_deploy-cluster.txt +++ b/dev/breeze/doc/images/output_k8s_deploy-cluster.txt @@ -1 +1 @@ -d2d591b44c79354f83acc1cd5f7618d1 +6b82815ccbac7e68a900d84d9b2be1cd diff --git a/dev/breeze/doc/images/output_k8s_dev.txt b/dev/breeze/doc/images/output_k8s_dev.txt index 07332651c42ea..e111aa2516d39 100644 --- a/dev/breeze/doc/images/output_k8s_dev.txt +++ b/dev/breeze/doc/images/output_k8s_dev.txt @@ -1 +1 @@ -4357e08b16b300332ddb4dbf9789f9f6 +a5232fad87953eb4ddfe6344b5080b2f diff --git a/dev/breeze/doc/images/output_k8s_k9s.txt b/dev/breeze/doc/images/output_k8s_k9s.txt index f42a27e5ab481..eb49e665e9243 100644 --- a/dev/breeze/doc/images/output_k8s_k9s.txt +++ b/dev/breeze/doc/images/output_k8s_k9s.txt @@ -1 +1 @@ -642687535a9bd119c4b18fb853615640 +81eeaa4e9ab9ab7ec358057d6e4e0968 diff --git a/dev/breeze/doc/images/output_k8s_logs.txt b/dev/breeze/doc/images/output_k8s_logs.txt index 7ca19863f89fb..92c22fe0ca632 100644 --- a/dev/breeze/doc/images/output_k8s_logs.txt +++ b/dev/breeze/doc/images/output_k8s_logs.txt @@ -1 +1 @@ -9c1b08ff80101f04d3b35660005f326c +efc8b5f82c4b23809d8e692f0a62dbad diff --git a/dev/breeze/doc/images/output_k8s_run-complete-tests.txt b/dev/breeze/doc/images/output_k8s_run-complete-tests.txt index d6ef9cf230db4..68b2b5a33198a 100644 --- a/dev/breeze/doc/images/output_k8s_run-complete-tests.txt +++ b/dev/breeze/doc/images/output_k8s_run-complete-tests.txt @@ -1 +1 @@ -d527256816eeaad37919aea33b4aa0b6 +7cc20839aa0a13776ae3b70c48b5a522 diff --git a/dev/breeze/doc/images/output_k8s_setup-env.txt b/dev/breeze/doc/images/output_k8s_setup-env.txt index 3ff7701f59c63..a7859612ac114 100644 --- a/dev/breeze/doc/images/output_k8s_setup-env.txt +++ b/dev/breeze/doc/images/output_k8s_setup-env.txt @@ -1 +1 @@ -fa874dd017a7904593f8c33e31380c79 +df0eb05952e6885c632edc7a0624506e diff --git a/dev/breeze/doc/images/output_k8s_shell.txt b/dev/breeze/doc/images/output_k8s_shell.txt index 9ad213f0d3fc0..84c5b435e6f32 100644 --- a/dev/breeze/doc/images/output_k8s_shell.txt +++ b/dev/breeze/doc/images/output_k8s_shell.txt @@ -1 +1 @@ -e73ff34e57ab87fd9da11c82e8bc75d2 +2b3987215e9ca3cf742199fba144c0e2 diff --git a/dev/breeze/doc/images/output_k8s_status.txt b/dev/breeze/doc/images/output_k8s_status.txt index aeb8fc2666051..4494c25300b79 100644 --- a/dev/breeze/doc/images/output_k8s_status.txt +++ b/dev/breeze/doc/images/output_k8s_status.txt @@ -1 +1 @@ -58c22a8b2da6ef1406751793398ca8b4 +3acd959fabaea5b0e6b08d11e2f98be5 diff --git a/dev/breeze/doc/images/output_k8s_tests.txt b/dev/breeze/doc/images/output_k8s_tests.txt index def266501c720..459e3cd1d2df1 100644 --- a/dev/breeze/doc/images/output_k8s_tests.txt +++ b/dev/breeze/doc/images/output_k8s_tests.txt @@ -1 +1 @@ -9d43b6a388f1a1d27a4b9a7882d480e8 +7a1170264859cd3fc078681755907622 diff --git a/dev/breeze/doc/images/output_k8s_upload-k8s-image.txt b/dev/breeze/doc/images/output_k8s_upload-k8s-image.txt index c745aa99b8822..bf42134049f0a 100644 --- a/dev/breeze/doc/images/output_k8s_upload-k8s-image.txt +++ b/dev/breeze/doc/images/output_k8s_upload-k8s-image.txt @@ -1 +1 @@ -d3df7bfd0a00839583a6ba8a14ab1626 +3309c346f42feddbf81134a844fd84a5 diff --git a/dev/breeze/doc/images/output_pr_auto-triage.txt b/dev/breeze/doc/images/output_pr_auto-triage.txt index fe8684a66c3ef..9083b3855757d 100644 --- a/dev/breeze/doc/images/output_pr_auto-triage.txt +++ b/dev/breeze/doc/images/output_pr_auto-triage.txt @@ -1 +1 @@ -640d7f0c5dfb6d651727247974229425 +0dbf8ae00f0620d12477ece9fda0ab6d diff --git a/dev/breeze/doc/images/output_prod-image_build.txt b/dev/breeze/doc/images/output_prod-image_build.txt index ca70c4faa312c..d7e65161edde2 100644 --- a/dev/breeze/doc/images/output_prod-image_build.txt +++ b/dev/breeze/doc/images/output_prod-image_build.txt @@ -1 +1 @@ -5e9c8c08d742ffa088519b84cdcd12ea +9e7d3206e8ca56abb72cae9ec1342822 diff --git a/dev/breeze/doc/images/output_prod-image_load.txt b/dev/breeze/doc/images/output_prod-image_load.txt index f53600a7886c3..2fe778125069c 100644 --- a/dev/breeze/doc/images/output_prod-image_load.txt +++ b/dev/breeze/doc/images/output_prod-image_load.txt @@ -1 +1 @@ -f27e839e0922eca043c6685150d309a5 +63c87a78c6a0ef9bd1172b0099cf3351 diff --git a/dev/breeze/doc/images/output_prod-image_pull.txt b/dev/breeze/doc/images/output_prod-image_pull.txt index 2cf1b3b03f388..fa188f44b6160 100644 --- a/dev/breeze/doc/images/output_prod-image_pull.txt +++ b/dev/breeze/doc/images/output_prod-image_pull.txt @@ -1 +1 @@ -354d53de69f66f13ca75c97154e78acf +943b61b60f81476638e74ab0e5ba451e diff --git a/dev/breeze/doc/images/output_prod-image_save.txt b/dev/breeze/doc/images/output_prod-image_save.txt index cd074a47eebe1..b2e74c178e614 100644 --- a/dev/breeze/doc/images/output_prod-image_save.txt +++ b/dev/breeze/doc/images/output_prod-image_save.txt @@ -1 +1 @@ -75b76351fd6e0b9c9b15f95f8320580e +501704529422b306b8cfc28ee28d3f55 diff --git a/dev/breeze/doc/images/output_prod-image_verify.txt b/dev/breeze/doc/images/output_prod-image_verify.txt index 77a49bbf22d81..f431e6eae9daa 100644 --- a/dev/breeze/doc/images/output_prod-image_verify.txt +++ b/dev/breeze/doc/images/output_prod-image_verify.txt @@ -1 +1 @@ -e9aa872361d9d782fb489f390df32349 +f95887aff9ae25fe203629e01c2fe25d diff --git a/dev/breeze/doc/images/output_registry_backfill.txt b/dev/breeze/doc/images/output_registry_backfill.txt index baa713f381a34..a6c2643c30355 100644 --- a/dev/breeze/doc/images/output_registry_backfill.txt +++ b/dev/breeze/doc/images/output_registry_backfill.txt @@ -1 +1 @@ -c7ec8adadd6e4f0cfd792a00c428e8e3 +ae5a02b96d38958e1b732eef27e22743 diff --git a/dev/breeze/doc/images/output_registry_extract-data.txt b/dev/breeze/doc/images/output_registry_extract-data.txt index 01f0685f69351..a5b0e70c052a4 100644 --- a/dev/breeze/doc/images/output_registry_extract-data.txt +++ b/dev/breeze/doc/images/output_registry_extract-data.txt @@ -1 +1 @@ -8d49c8fa1983d39f05a5add21b1e7172 +602ea508f9bcf0d5c2f97a220f5ee6d2 diff --git a/dev/breeze/doc/images/output_registry_publish-versions.txt b/dev/breeze/doc/images/output_registry_publish-versions.txt index 87ec90bfa1303..b3bf16f2409c1 100644 --- a/dev/breeze/doc/images/output_registry_publish-versions.txt +++ b/dev/breeze/doc/images/output_registry_publish-versions.txt @@ -1 +1 @@ -b26208c9d3432eaf1d11bce4a287d82b +60aa5a1adc37e2165177e7881a838707 diff --git a/dev/breeze/doc/images/output_release-management_add-back-references.txt b/dev/breeze/doc/images/output_release-management_add-back-references.txt index 6138108703315..1738c0ec0c0fc 100644 --- a/dev/breeze/doc/images/output_release-management_add-back-references.txt +++ b/dev/breeze/doc/images/output_release-management_add-back-references.txt @@ -1 +1 @@ -b4654ebd46094a96811efaec9cef0b80 +057958044be14599b5b0039ec507b6ca diff --git a/dev/breeze/doc/images/output_release-management_check-release-files.txt b/dev/breeze/doc/images/output_release-management_check-release-files.txt index 7229b27512752..e3b08d31a5e3e 100644 --- a/dev/breeze/doc/images/output_release-management_check-release-files.txt +++ b/dev/breeze/doc/images/output_release-management_check-release-files.txt @@ -1 +1 @@ -648165a2800b8651d176d9778ecd96a3 +4d7d540413a5955a51eaf7d035ff31bc diff --git a/dev/breeze/doc/images/output_release-management_clean-old-provider-artifacts.txt b/dev/breeze/doc/images/output_release-management_clean-old-provider-artifacts.txt index 4edf34897dc3c..a7826a4a7a549 100644 --- a/dev/breeze/doc/images/output_release-management_clean-old-provider-artifacts.txt +++ b/dev/breeze/doc/images/output_release-management_clean-old-provider-artifacts.txt @@ -1 +1 @@ -2be42faedac6e0807d5ff895850350b1 +0d6898918777adbd6576972fe59dc2f7 diff --git a/dev/breeze/doc/images/output_release-management_constraints-version-check.txt b/dev/breeze/doc/images/output_release-management_constraints-version-check.txt index 6959bc944dd9e..5f4e91344580c 100644 --- a/dev/breeze/doc/images/output_release-management_constraints-version-check.txt +++ b/dev/breeze/doc/images/output_release-management_constraints-version-check.txt @@ -1 +1 @@ -333b3097d268808466dd5d33e88dada4 +69595e717626710cce603db050e76a21 diff --git a/dev/breeze/doc/images/output_release-management_create-minor-branch.txt b/dev/breeze/doc/images/output_release-management_create-minor-branch.txt index 049d17b9f1425..95896eb6a4f3e 100644 --- a/dev/breeze/doc/images/output_release-management_create-minor-branch.txt +++ b/dev/breeze/doc/images/output_release-management_create-minor-branch.txt @@ -1 +1 @@ -01495a0ad3c811a4d54d12de34818bbb +72d85ebed1d067a94eace68825d55848 diff --git a/dev/breeze/doc/images/output_release-management_generate-constraints.txt b/dev/breeze/doc/images/output_release-management_generate-constraints.txt index 3bd12bcce163b..6b4ef06da4a35 100644 --- a/dev/breeze/doc/images/output_release-management_generate-constraints.txt +++ b/dev/breeze/doc/images/output_release-management_generate-constraints.txt @@ -1 +1 @@ -1e05462af1f8749ae02ccc79f9d40422 +8f5434ddc6564b1a2b026a63424eecea diff --git a/dev/breeze/doc/images/output_release-management_generate-issue-content-core.txt b/dev/breeze/doc/images/output_release-management_generate-issue-content-core.txt index 96c77b3f300c1..d0a9e0a1cb09a 100644 --- a/dev/breeze/doc/images/output_release-management_generate-issue-content-core.txt +++ b/dev/breeze/doc/images/output_release-management_generate-issue-content-core.txt @@ -1 +1 @@ -e8e5a148b595f092733ecd1de8d5ff83 +80bb575675cea0b47b61d6ac65dec28f diff --git a/dev/breeze/doc/images/output_release-management_generate-issue-content-helm-chart.txt b/dev/breeze/doc/images/output_release-management_generate-issue-content-helm-chart.txt index b0b4f20c1bd40..d4cd28e21cbcf 100644 --- a/dev/breeze/doc/images/output_release-management_generate-issue-content-helm-chart.txt +++ b/dev/breeze/doc/images/output_release-management_generate-issue-content-helm-chart.txt @@ -1 +1 @@ -8b831c945a031adf581c10d056f2f8cb +ddb64b2373109f1f7bee6abc2d62d636 diff --git a/dev/breeze/doc/images/output_release-management_generate-issue-content-providers.txt b/dev/breeze/doc/images/output_release-management_generate-issue-content-providers.txt index e6e491130d472..0a88b97dfc405 100644 --- a/dev/breeze/doc/images/output_release-management_generate-issue-content-providers.txt +++ b/dev/breeze/doc/images/output_release-management_generate-issue-content-providers.txt @@ -1 +1 @@ -3784a30daef839c40d1728db89d14eec +20f849b3a6098cf813098a97bf220006 diff --git a/dev/breeze/doc/images/output_release-management_generate-providers-metadata.txt b/dev/breeze/doc/images/output_release-management_generate-providers-metadata.txt index 69b019acadb03..8424582464120 100644 --- a/dev/breeze/doc/images/output_release-management_generate-providers-metadata.txt +++ b/dev/breeze/doc/images/output_release-management_generate-providers-metadata.txt @@ -1 +1 @@ -8032b4cd7d4700fad274499dc09600a2 +a9a87df8382a9faa57e6b79356f4295f diff --git a/dev/breeze/doc/images/output_release-management_install-provider-distributions.txt b/dev/breeze/doc/images/output_release-management_install-provider-distributions.txt index 8522b5eed0998..e80b971b250e7 100644 --- a/dev/breeze/doc/images/output_release-management_install-provider-distributions.txt +++ b/dev/breeze/doc/images/output_release-management_install-provider-distributions.txt @@ -1 +1 @@ -50d5237415adf86e0305d8f9a7101622 +e27a6e759f82c1fb8639a32f8f6ef1ff diff --git a/dev/breeze/doc/images/output_release-management_merge-prod-images.txt b/dev/breeze/doc/images/output_release-management_merge-prod-images.txt index 5b3dad52ab703..0c477d4b585d0 100644 --- a/dev/breeze/doc/images/output_release-management_merge-prod-images.txt +++ b/dev/breeze/doc/images/output_release-management_merge-prod-images.txt @@ -1 +1 @@ -fdffd3058df3b2fa320ff1cc1451ec17 +f7bc7460a2910c50776b6f702ecb2bc8 diff --git a/dev/breeze/doc/images/output_release-management_prepare-airflow-ctl-distributions.txt b/dev/breeze/doc/images/output_release-management_prepare-airflow-ctl-distributions.txt index be56ef03f8c64..f4299494cc4eb 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-airflow-ctl-distributions.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-airflow-ctl-distributions.txt @@ -1 +1 @@ -78b65572bc4eae79e93da71d792164fe +b40148a43101cec687cce3c378c52c50 diff --git a/dev/breeze/doc/images/output_release-management_prepare-airflow-distributions.txt b/dev/breeze/doc/images/output_release-management_prepare-airflow-distributions.txt index 5abdcb474858f..57792ecf073b2 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-airflow-distributions.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-airflow-distributions.txt @@ -1 +1 @@ -183d19e51977a7ffd727580bdf6ea8ef +2ef5b359a3cc686b973f408aef6b5803 diff --git a/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.txt b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.txt index bc3fe5f3e6086..675e69663de44 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.txt @@ -1 +1 @@ -4820cdc0da993867f28caab6ab5fc7dc +535e58ad4fd6139c86bd3b89fcec1964 diff --git a/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.txt b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.txt index 70249d65b3c19..0f74190a7444a 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.txt @@ -1 +1 @@ -cfb2d856454f9e86bea23396118c5e30 +465b09b0f0fd9898cdc3ff006ef86b61 diff --git a/dev/breeze/doc/images/output_release-management_prepare-mypy-distributions.txt b/dev/breeze/doc/images/output_release-management_prepare-mypy-distributions.txt index 65abb49b363a3..5c480ad616e13 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-mypy-distributions.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-mypy-distributions.txt @@ -1 +1 @@ -648c4d643abdb60f82e1afced6cfd6d5 +6a78a6708d57916b90df21bd8a035e8d diff --git a/dev/breeze/doc/images/output_release-management_prepare-provider-distributions.txt b/dev/breeze/doc/images/output_release-management_prepare-provider-distributions.txt index 6c7d65448ee8d..416151822b1fc 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-provider-distributions.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-provider-distributions.txt @@ -1 +1 @@ -2939956d3bf1154f772da9d8a1bf1647 +8e9317e44788c0b820f3a461da6df58a diff --git a/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.txt b/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.txt index 32b1109fb35da..25496ff5fe2a2 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.txt @@ -1 +1 @@ -926fc875638e2cb79e4f9df1acbd846b +75517e0fd3d48cbc5cf85c50812753df diff --git a/dev/breeze/doc/images/output_release-management_prepare-python-client.txt b/dev/breeze/doc/images/output_release-management_prepare-python-client.txt index 57dd5f1ed3a36..77e308e2a3857 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-python-client.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-python-client.txt @@ -1 +1 @@ -2501eff9b78bd0c1e8154150d37fbe30 +404fc48b3968c34a8ad53443dfce8980 diff --git a/dev/breeze/doc/images/output_release-management_prepare-tarball.txt b/dev/breeze/doc/images/output_release-management_prepare-tarball.txt index 36e25bbd08c1f..7cc646fca25ed 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-tarball.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-tarball.txt @@ -1 +1 @@ -529d01caf3eb57088d7df671f80b4bdb +921cee73b360da76bab70bd424293e20 diff --git a/dev/breeze/doc/images/output_release-management_prepare-task-sdk-distributions.txt b/dev/breeze/doc/images/output_release-management_prepare-task-sdk-distributions.txt index f41ed008535d9..f1b9ee42e4573 100644 --- a/dev/breeze/doc/images/output_release-management_prepare-task-sdk-distributions.txt +++ b/dev/breeze/doc/images/output_release-management_prepare-task-sdk-distributions.txt @@ -1 +1 @@ -40d4bc2a1d656d4e0f7373a90b549e94 +e7dd67a233f4c0b5ea0ae75e95c859fa diff --git a/dev/breeze/doc/images/output_release-management_publish-docs-to-s3.txt b/dev/breeze/doc/images/output_release-management_publish-docs-to-s3.txt index 822ce77242d59..bfad2d6f5eba3 100644 --- a/dev/breeze/doc/images/output_release-management_publish-docs-to-s3.txt +++ b/dev/breeze/doc/images/output_release-management_publish-docs-to-s3.txt @@ -1 +1 @@ -41787acc1ee74ac0d86bf981678956e8 +b11847cc9e7091d948597ac5823c98d3 diff --git a/dev/breeze/doc/images/output_release-management_publish-docs.txt b/dev/breeze/doc/images/output_release-management_publish-docs.txt index 396fda7d61166..12e06cfa472c4 100644 --- a/dev/breeze/doc/images/output_release-management_publish-docs.txt +++ b/dev/breeze/doc/images/output_release-management_publish-docs.txt @@ -1 +1 @@ -82288cd2badfc7241e8e6e46620c0280 +7967a912265c05eb878af2ba3ddf2057 diff --git a/dev/breeze/doc/images/output_release-management_release-prod-images.txt b/dev/breeze/doc/images/output_release-management_release-prod-images.txt index 1ea13efce800e..e7a2563b7e97b 100644 --- a/dev/breeze/doc/images/output_release-management_release-prod-images.txt +++ b/dev/breeze/doc/images/output_release-management_release-prod-images.txt @@ -1 +1 @@ -c29e3146509fc796313a8b201d16d7ef +66ee560be7b29389cb7f46d104eb92ec diff --git a/dev/breeze/doc/images/output_release-management_start-rc-process.txt b/dev/breeze/doc/images/output_release-management_start-rc-process.txt index 5489f0a06e95b..7026b7fdecceb 100644 --- a/dev/breeze/doc/images/output_release-management_start-rc-process.txt +++ b/dev/breeze/doc/images/output_release-management_start-rc-process.txt @@ -1 +1 @@ -549da0be0cb515c2300c8f099b0543ca +59523e169ffeaf7e5f01b40986de7951 diff --git a/dev/breeze/doc/images/output_release-management_start-release.txt b/dev/breeze/doc/images/output_release-management_start-release.txt index 590311afbc23c..50d1444010638 100644 --- a/dev/breeze/doc/images/output_release-management_start-release.txt +++ b/dev/breeze/doc/images/output_release-management_start-release.txt @@ -1 +1 @@ -cfab7b5f470357cdb11fcfea04641a1d +353deb3db7e1ef5cfe5aa3b897211f4c diff --git a/dev/breeze/doc/images/output_release-management_tag-providers.txt b/dev/breeze/doc/images/output_release-management_tag-providers.txt index d98a7c6f08f5e..1520dccffc554 100644 --- a/dev/breeze/doc/images/output_release-management_tag-providers.txt +++ b/dev/breeze/doc/images/output_release-management_tag-providers.txt @@ -1 +1 @@ -8a985738a87fb8c51c90448b20f418c9 +95035a072198cd13edf4108c2d4dedae diff --git a/dev/breeze/doc/images/output_release-management_update-constraints.txt b/dev/breeze/doc/images/output_release-management_update-constraints.txt index c3d786b4891f0..f85cfa6d1493c 100644 --- a/dev/breeze/doc/images/output_release-management_update-constraints.txt +++ b/dev/breeze/doc/images/output_release-management_update-constraints.txt @@ -1 +1 @@ -2abc0886ad0977e0a91f579c3f0ac3ce +1ef2866635f42330fe813b8dc2121f6f diff --git a/dev/breeze/doc/images/output_release-management_update-providers-next-version.txt b/dev/breeze/doc/images/output_release-management_update-providers-next-version.txt index a916bab6a5734..7eafa92405b1c 100644 --- a/dev/breeze/doc/images/output_release-management_update-providers-next-version.txt +++ b/dev/breeze/doc/images/output_release-management_update-providers-next-version.txt @@ -1 +1 @@ -49953c2a602e2fb6b9c8c9e12ce1de0a +822bfe3d040b5b0e2052582cea5fa2f7 diff --git a/dev/breeze/doc/images/output_release-management_verify-provider-distributions.txt b/dev/breeze/doc/images/output_release-management_verify-provider-distributions.txt index ee06584a4fbb6..d8467d376021d 100644 --- a/dev/breeze/doc/images/output_release-management_verify-provider-distributions.txt +++ b/dev/breeze/doc/images/output_release-management_verify-provider-distributions.txt @@ -1 +1 @@ -51d8f9f4993e6569a523ea6b049d3de8 +6f38f05b84f4aa4a5e41e2f7e7ee4318 diff --git a/dev/breeze/doc/images/output_release-management_verify-rc-by-pmc.txt b/dev/breeze/doc/images/output_release-management_verify-rc-by-pmc.txt index 1cdcdfc8d6e1e..d1dcea6926cbe 100644 --- a/dev/breeze/doc/images/output_release-management_verify-rc-by-pmc.txt +++ b/dev/breeze/doc/images/output_release-management_verify-rc-by-pmc.txt @@ -1 +1 @@ -2c62c11595f22d4fdf7e9c9a7aefb998 +7026ac9fe494c008d46607532a603105 diff --git a/dev/breeze/doc/images/output_run.txt b/dev/breeze/doc/images/output_run.txt index a6ec3736b4cc3..5d3b86b5069aa 100644 --- a/dev/breeze/doc/images/output_run.txt +++ b/dev/breeze/doc/images/output_run.txt @@ -1 +1 @@ -d2879ca7680ce6396b118b3e42bfd62d +54d7d635ab887d0f556a9cebcab7f63f diff --git a/dev/breeze/doc/images/output_sbom_build-all-airflow-images.txt b/dev/breeze/doc/images/output_sbom_build-all-airflow-images.txt index a549f772080a7..97a73d6d30072 100644 --- a/dev/breeze/doc/images/output_sbom_build-all-airflow-images.txt +++ b/dev/breeze/doc/images/output_sbom_build-all-airflow-images.txt @@ -1 +1 @@ -93c3e4001d46207d0b1026768f4cb4c0 +a1857855ca7836fb77e7d49d59452c98 diff --git a/dev/breeze/doc/images/output_sbom_export-dependency-information.txt b/dev/breeze/doc/images/output_sbom_export-dependency-information.txt index ae661bd335990..21c6d97139bff 100644 --- a/dev/breeze/doc/images/output_sbom_export-dependency-information.txt +++ b/dev/breeze/doc/images/output_sbom_export-dependency-information.txt @@ -1 +1 @@ -d1782d0498b05c41c04ebe4703af7843 +e374f5b74d0f817f6915a8417ba0cda4 diff --git a/dev/breeze/doc/images/output_sbom_generate-providers-requirements.txt b/dev/breeze/doc/images/output_sbom_generate-providers-requirements.txt index af3b18bac68d0..0c39f82ba3755 100644 --- a/dev/breeze/doc/images/output_sbom_generate-providers-requirements.txt +++ b/dev/breeze/doc/images/output_sbom_generate-providers-requirements.txt @@ -1 +1 @@ -32e515c6d22a49190410280d16eb3398 +cb4611abc6764a8d7c1aacad63da03e3 diff --git a/dev/breeze/doc/images/output_sbom_update-sbom-information.txt b/dev/breeze/doc/images/output_sbom_update-sbom-information.txt index 6ab41cc9f19e3..cfdc44468b5fd 100644 --- a/dev/breeze/doc/images/output_sbom_update-sbom-information.txt +++ b/dev/breeze/doc/images/output_sbom_update-sbom-information.txt @@ -1 +1 @@ -fb99f661fec72e46d73d5de124f56fe7 +1c4a91a95b45910314f3596b0a84ac02 diff --git a/dev/breeze/doc/images/output_setup_autocomplete.txt b/dev/breeze/doc/images/output_setup_autocomplete.txt index cfe326723abfe..7886a97f75416 100644 --- a/dev/breeze/doc/images/output_setup_autocomplete.txt +++ b/dev/breeze/doc/images/output_setup_autocomplete.txt @@ -1 +1 @@ -993887cc456374d1a10ffb62d5133154 +c34f64dff5e77995d13ccee0a29a5408 diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt index e31c6cb3d1130..47183c1981ec7 100644 --- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt +++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt @@ -1 +1 @@ -ea835758cd03dda882551c07b051daa8 +17c3b9d51cdd33b71a3ef495edc7297f diff --git a/dev/breeze/doc/images/output_setup_config.txt b/dev/breeze/doc/images/output_setup_config.txt index 5d1e4e5dfac02..4bed9f321beca 100644 --- a/dev/breeze/doc/images/output_setup_config.txt +++ b/dev/breeze/doc/images/output_setup_config.txt @@ -1 +1 @@ -c04c7d721a48bf54ff269e0c403853e1 +4fc5026be69f9e924d243365bdaa993d diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt index e8bd48f0167b1..f171b07e731c1 100644 --- a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt +++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt @@ -1 +1 @@ -2cc5a3c1f8cf474ed99999e62f59fd72 +d94f428c2c56dd453d3c5f02ae3442af diff --git a/dev/breeze/doc/images/output_setup_synchronize-local-mounts.txt b/dev/breeze/doc/images/output_setup_synchronize-local-mounts.txt index e7c8a46e3f876..8d20c67ea650b 100644 --- a/dev/breeze/doc/images/output_setup_synchronize-local-mounts.txt +++ b/dev/breeze/doc/images/output_setup_synchronize-local-mounts.txt @@ -1 +1 @@ -20b6427e7e7faa4b9b5676fccd31bb5d +f2fe62f152bdbe41956fa1d6a9bf719a diff --git a/dev/breeze/doc/images/output_setup_version.txt b/dev/breeze/doc/images/output_setup_version.txt index 2fe696e64d804..18a4093aec818 100644 --- a/dev/breeze/doc/images/output_setup_version.txt +++ b/dev/breeze/doc/images/output_setup_version.txt @@ -1 +1 @@ -6752d695b7db5fdea208095797fed2fa +f9dfcf32db12ce914dd00b0542a40e2f diff --git a/dev/breeze/doc/images/output_shell.svg b/dev/breeze/doc/images/output_shell.svg index 1a74a0392f59e..8289228729836 100644 --- a/dev/breeze/doc/images/output_shell.svg +++ b/dev/breeze/doc/images/output_shell.svg @@ -616,7 +616,7 @@ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Choose executor ────────────────────────────────────────────────────────────────────────────────────────────────────╮ --executor     Specify the executor to use with shell command. [default: LocalExecutor] -(LocalExecutor|KubernetesExecutor|CeleryExecutor|CeleryKubernetesExecutor|EdgeExecutor) +(localexecutor|kubernetesexecutor|celeryexecutor|celerykubernetesexecutor|edgeexecutor) --celery-brokerSpecify the celery message broker [default: redis](rabbitmq|redis) --celery-flowerStart celery flower ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/dev/breeze/doc/images/output_shell.txt b/dev/breeze/doc/images/output_shell.txt index 6a7b5dee23c3f..3544feee31efc 100644 --- a/dev/breeze/doc/images/output_shell.txt +++ b/dev/breeze/doc/images/output_shell.txt @@ -1 +1 @@ -2b113618326d9763c7e0bc1879f8ca37 +95bba676df9c9dccc5b0798fbc269f6e diff --git a/dev/breeze/doc/images/output_start-airflow.svg b/dev/breeze/doc/images/output_start-airflow.svg index f60a7ba6a942d..f5779f508e05d 100644 --- a/dev/breeze/doc/images/output_start-airflow.svg +++ b/dev/breeze/doc/images/output_start-airflow.svg @@ -548,7 +548,7 @@ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Choosing executor ──────────────────────────────────────────────────────────────────────────────────────────────────╮ --executor     Specify the executor to use with start-airflow (defaults to LocalExecutor or CeleryExecutor         -depending on the integration used). (LocalExecutor|CeleryExecutor|EdgeExecutor) +depending on the integration used). (localexecutor|celeryexecutor|edgeexecutor) --celery-brokerSpecify the celery message broker [default: redis](rabbitmq|redis) --celery-flowerStart celery flower ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/dev/breeze/doc/images/output_start-airflow.txt b/dev/breeze/doc/images/output_start-airflow.txt index d2a1e628064e7..81c11faa42964 100644 --- a/dev/breeze/doc/images/output_start-airflow.txt +++ b/dev/breeze/doc/images/output_start-airflow.txt @@ -1 +1 @@ -f0341f2a04d16d802889e257633b110c +a76fae2707fcab0cc46a68f1186c6a08 diff --git a/dev/breeze/doc/images/output_testing_airflow-ctl-integration-tests.txt b/dev/breeze/doc/images/output_testing_airflow-ctl-integration-tests.txt index dc01b623b2680..36147a39cccf1 100644 --- a/dev/breeze/doc/images/output_testing_airflow-ctl-integration-tests.txt +++ b/dev/breeze/doc/images/output_testing_airflow-ctl-integration-tests.txt @@ -1 +1 @@ -81a43bae5ec3c31ab2294a871e3d94b7 +e302335890458a12a28a52ed51b6337f diff --git a/dev/breeze/doc/images/output_testing_airflow-ctl-tests.txt b/dev/breeze/doc/images/output_testing_airflow-ctl-tests.txt index db7c6045fbc78..98f03c94d2357 100644 --- a/dev/breeze/doc/images/output_testing_airflow-ctl-tests.txt +++ b/dev/breeze/doc/images/output_testing_airflow-ctl-tests.txt @@ -1 +1 @@ -d67fcf2594fb5f78fedb1360ba07dab2 +caf04a20ceb4b3a426e095860f8a800f diff --git a/dev/breeze/doc/images/output_testing_airflow-e2e-tests.txt b/dev/breeze/doc/images/output_testing_airflow-e2e-tests.txt index 88da574d7adcf..b344eaf9673b6 100644 --- a/dev/breeze/doc/images/output_testing_airflow-e2e-tests.txt +++ b/dev/breeze/doc/images/output_testing_airflow-e2e-tests.txt @@ -1 +1 @@ -3b6adba2bcaf91d241d9829ed46ab909 +11e115062a47a3ee70aeaa380af9cd84 diff --git a/dev/breeze/doc/images/output_testing_core-integration-tests.txt b/dev/breeze/doc/images/output_testing_core-integration-tests.txt index 6abbd7610320a..aad3803373ceb 100644 --- a/dev/breeze/doc/images/output_testing_core-integration-tests.txt +++ b/dev/breeze/doc/images/output_testing_core-integration-tests.txt @@ -1 +1 @@ -363940bbe9113849e443464fbd0ba7ff +56f677845a9c84dbdc1131c51b9af83a diff --git a/dev/breeze/doc/images/output_testing_core-tests.txt b/dev/breeze/doc/images/output_testing_core-tests.txt index f4f45d2efbb36..214822e92c3f7 100644 --- a/dev/breeze/doc/images/output_testing_core-tests.txt +++ b/dev/breeze/doc/images/output_testing_core-tests.txt @@ -1 +1 @@ -8d0d4887e1705769f0622ff1be18b91c +172b27f30c0867e08ca9f2ef11da2c94 diff --git a/dev/breeze/doc/images/output_testing_docker-compose-tests.txt b/dev/breeze/doc/images/output_testing_docker-compose-tests.txt index ac16878f61e67..2c906c51d5de1 100644 --- a/dev/breeze/doc/images/output_testing_docker-compose-tests.txt +++ b/dev/breeze/doc/images/output_testing_docker-compose-tests.txt @@ -1 +1 @@ -5c018dae6739772e9b431f63d68b506b +e7f68555c25e802df53097e5e7558088 diff --git a/dev/breeze/doc/images/output_testing_helm-tests.txt b/dev/breeze/doc/images/output_testing_helm-tests.txt index 8eae6dd611a53..c816fbb2bb829 100644 --- a/dev/breeze/doc/images/output_testing_helm-tests.txt +++ b/dev/breeze/doc/images/output_testing_helm-tests.txt @@ -1 +1 @@ -f11e9a72de90980c119a5f8011390347 +2a8a6d65107b81afe9bc7ffbec9dfb2e diff --git a/dev/breeze/doc/images/output_testing_providers-integration-tests.txt b/dev/breeze/doc/images/output_testing_providers-integration-tests.txt index 6e22ed69c64e1..da0296790d848 100644 --- a/dev/breeze/doc/images/output_testing_providers-integration-tests.txt +++ b/dev/breeze/doc/images/output_testing_providers-integration-tests.txt @@ -1 +1 @@ -5cec830510384eb802d662c41bcefdb5 +1ab3cf1b8c5a5deb4181110bb41fb811 diff --git a/dev/breeze/doc/images/output_testing_providers-tests.txt b/dev/breeze/doc/images/output_testing_providers-tests.txt index b858d34068d7c..90b35cbdd7a6a 100644 --- a/dev/breeze/doc/images/output_testing_providers-tests.txt +++ b/dev/breeze/doc/images/output_testing_providers-tests.txt @@ -1 +1 @@ -697f5152883c345771c7f8de46bb94c9 +446f03c4e5fa14f9836f160d7f1557b7 diff --git a/dev/breeze/doc/images/output_testing_python-api-client-tests.txt b/dev/breeze/doc/images/output_testing_python-api-client-tests.txt index 651c4a7e14e86..ca9a2d70afa80 100644 --- a/dev/breeze/doc/images/output_testing_python-api-client-tests.txt +++ b/dev/breeze/doc/images/output_testing_python-api-client-tests.txt @@ -1 +1 @@ -02b90ef8bb36554b8cc13f7e10031a7c +0d407ea088f01326dfc1104f12a3017d diff --git a/dev/breeze/doc/images/output_testing_system-tests.txt b/dev/breeze/doc/images/output_testing_system-tests.txt index cd3db305028cc..f289c1cb3e932 100644 --- a/dev/breeze/doc/images/output_testing_system-tests.txt +++ b/dev/breeze/doc/images/output_testing_system-tests.txt @@ -1 +1 @@ -6c3be860444308c2fba7a59024dad481 +56ea5a7ea76ffad80f4f91cf8a5566d5 diff --git a/dev/breeze/doc/images/output_testing_task-sdk-integration-tests.txt b/dev/breeze/doc/images/output_testing_task-sdk-integration-tests.txt index c8448618c94ef..6e754162d012b 100644 --- a/dev/breeze/doc/images/output_testing_task-sdk-integration-tests.txt +++ b/dev/breeze/doc/images/output_testing_task-sdk-integration-tests.txt @@ -1 +1 @@ -fd52ebb44cb670b0a1f5d8c9952b0295 +76d2a06163a1c3f4dbc54f2e4aa13ade diff --git a/dev/breeze/doc/images/output_testing_task-sdk-tests.txt b/dev/breeze/doc/images/output_testing_task-sdk-tests.txt index f398aa839e900..475499ef8a804 100644 --- a/dev/breeze/doc/images/output_testing_task-sdk-tests.txt +++ b/dev/breeze/doc/images/output_testing_task-sdk-tests.txt @@ -1 +1 @@ -a40a1048d3c3f126e21cdd5b3967c2cb +58ecc16666e1b4f5c5572533e7ccc0a7 diff --git a/dev/breeze/doc/images/output_testing_ui-e2e-tests.txt b/dev/breeze/doc/images/output_testing_ui-e2e-tests.txt index 4f8ff450c99d0..69046ce01ebfe 100644 --- a/dev/breeze/doc/images/output_testing_ui-e2e-tests.txt +++ b/dev/breeze/doc/images/output_testing_ui-e2e-tests.txt @@ -1 +1 @@ -cf6fa256cb30252ee979da341309210a +109d8450ccc1fa74ebc2547ae2db41d5 diff --git a/dev/breeze/doc/images/output_ui_check-translation-completeness.txt b/dev/breeze/doc/images/output_ui_check-translation-completeness.txt index e04eab4c9f535..acab51d294f70 100644 --- a/dev/breeze/doc/images/output_ui_check-translation-completeness.txt +++ b/dev/breeze/doc/images/output_ui_check-translation-completeness.txt @@ -1 +1 @@ -104b4b8e413c3b87fb5d9948efbf8c8b +4d8c7e8b2fe193a4b8e8cf25a429ff7e diff --git a/dev/breeze/doc/images/output_ui_compile-assets.txt b/dev/breeze/doc/images/output_ui_compile-assets.txt index 43d44d3fe6e24..e8873d1d2a80f 100644 --- a/dev/breeze/doc/images/output_ui_compile-assets.txt +++ b/dev/breeze/doc/images/output_ui_compile-assets.txt @@ -1 +1 @@ -294871ec2706e2744c1e47969a9a02d9 +8df936b0f6068addf4d51460d5a27ccc diff --git a/dev/breeze/doc/images/output_workflow-run_publish-docs.txt b/dev/breeze/doc/images/output_workflow-run_publish-docs.txt index 48447dc38e201..3a57f0bb6d668 100644 --- a/dev/breeze/doc/images/output_workflow-run_publish-docs.txt +++ b/dev/breeze/doc/images/output_workflow-run_publish-docs.txt @@ -1 +1 @@ -814726db94d4b9bc9c226bd607a3e043 +7915334135094723635d68ce396033bf diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py b/dev/breeze/src/airflow_breeze/utils/selective_checks.py index cda375fa7cce9..3b1b1c730a4e3 100644 --- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py +++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py @@ -1581,6 +1581,12 @@ def selected_providers_list_as_string(self) -> str | None: def get_job_label(self, event_type: str, branch: str): import requests # type: ignore[import-untyped] + # The main CI is now split into ci-arm.yml and ci-amd.yml; the old + # ci-amd-arm.yml file no longer exists. This lookup is dormant for the + # main pipeline (which hardcodes runner-type per wrapper) and only + # remains here for the `is_disabled_integration` code path that still + # reads `runner_type`. The API call against a missing workflow returns + # nothing and the caller falls back to PUBLIC_AMD_RUNNERS. job_name = "Basic tests" workflow_name = "ci-amd-arm.yml" headers = {"Accept": "application/vnd.github.v3+json"} diff --git a/generated/PYPI_README.md b/generated/PYPI_README.md index a723a97815cbe..2372610eeb432 100644 --- a/generated/PYPI_README.md +++ b/generated/PYPI_README.md @@ -32,8 +32,8 @@ PROJECT BY THE `generate-pypi-readme` PREK HOOK. YOUR CHANGES HERE WILL BE AUTOM | Version | Build Status | |---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Main | [![GitHub Build main](https://github.com/apache/airflow/actions/workflows/ci-amd-arm.yml/badge.svg)](https://github.com/apache/airflow/actions) | -| 3.x | [![GitHub Build 3.1](https://github.com/apache/airflow/actions/workflows/ci-amd-arm.yml/badge.svg?branch=v3-1-test)](https://github.com/apache/airflow/actions) | +| Main | [![GitHub Build main](https://github.com/apache/airflow/actions/workflows/ci-amd.yml/badge.svg)](https://github.com/apache/airflow/actions) | +| 3.x | [![GitHub Build 3.2](https://github.com/apache/airflow/actions/workflows/ci-amd.yml/badge.svg?branch=v3-2-test)](https://github.com/apache/airflow/actions) | | 2.x | [![GitHub Build 2.11](https://github.com/apache/airflow/actions/workflows/ci.yml/badge.svg?branch=v2-11-test)](https://github.com/apache/airflow/actions) | @@ -55,14 +55,14 @@ Use Airflow to author workflows (Dags) that orchestrate tasks. The Airflow sched Apache Airflow is tested with: -| | Main version (dev) | Stable version (3.2.1) | Stable version (2.11.2) | -|------------|-----------------------------------|------------------------------|------------------------------| -| Python | 3.10, 3.11, 3.12, 3.13, 3.14 | 3.10, 3.11, 3.12, 3.13, 3.14 | 3.10, 3.11, 3.12 | -| Platform | AMD64/ARM64 | AMD64/ARM64 | AMD64/ARM64(\*) | -| Kubernetes | 1.30, 1.31, 1.32, 1.33, 1.34, 1.35 | 1.30, 1.31, 1.32, 1.33 | 1.26, 1.27, 1.28, 1.29, 1.30 | -| PostgreSQL | 14, 15, 16, 17, 18 | 13, 14, 15, 16, 17 | 12, 13, 14, 15, 16 | -| MySQL | 8.0, 8.4, Innovation | 8.0, 8.4, Innovation | 8.0, Innovation | -| SQLite | 3.15.0+ | 3.15.0+ | 3.15.0+ | +| | Main version (dev) | Stable version (3.2.0) | Stable version (2.11.2) | +|------------|------------------------------------|-------------------------------------|------------------------------| +| Python | 3.10, 3.11, 3.12, 3.13, 3.14 | 3.10, 3.11, 3.12, 3.13, 3.14 | 3.10, 3.11, 3.12 | +| Platform | AMD64/ARM64 | AMD64/ARM64 | AMD64/ARM64(\*) | +| Kubernetes | 1.30, 1.31, 1.32, 1.33, 1.34, 1.35 | 1.30, 1.31, 1.32, 1.33, 1.34, 1.35 | 1.26, 1.27, 1.28, 1.29, 1.30 | +| PostgreSQL | 14, 15, 16, 17, 18 | 14, 15, 16, 17, 18 | 12, 13, 14, 15, 16 | +| MySQL | 8.0, 8.4, Innovation | 8.0, 8.4, Innovation | 8.0, Innovation | +| SQLite | 3.15.0+ | 3.15.0+ | 3.15.0+ | \* Experimental @@ -124,15 +124,15 @@ them to the appropriate format and workflow that your tool requires. ```bash -pip install 'apache-airflow==3.2.1' \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.2.1/constraints-3.10.txt" +pip install 'apache-airflow==3.2.0' \ + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.2.0/constraints-3.10.txt" ``` 2. Installing with extras (i.e., postgres, google) ```bash -pip install 'apache-airflow[postgres,google]==3.2.1' \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.2.1/constraints-3.10.txt" +pip install 'apache-airflow[postgres,google]==3.2.0' \ + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.2.0/constraints-3.10.txt" ``` For information on installing provider distributions, check diff --git a/scripts/ci/analyze_e2e_flaky_tests.py b/scripts/ci/analyze_e2e_flaky_tests.py index c56fb7e48ebfc..a8942d7e261b2 100755 --- a/scripts/ci/analyze_e2e_flaky_tests.py +++ b/scripts/ci/analyze_e2e_flaky_tests.py @@ -34,7 +34,7 @@ Environment variables (optional): MAX_RUNS - Maximum number of workflow runs to analyze (default: 10) - WORKFLOW_NAME - Workflow file name to query (default: ci-amd-arm.yml) + WORKFLOW_NAME - Workflow file name to query (default: ci-amd.yml) BRANCH - Branch to filter runs (default: main) OUTPUT_FILE - Path for the Slack message output (default: slack-message.json) GITHUB_OUTPUT - Path to GitHub Actions output file @@ -525,7 +525,7 @@ def write_step_summary( def main() -> None: repo = os.environ.get("GITHUB_REPOSITORY", "apache/airflow") max_runs = int(os.environ.get("MAX_RUNS", "10")) - workflow = os.environ.get("WORKFLOW_NAME", "ci-amd-arm.yml") + workflow = os.environ.get("WORKFLOW_NAME", "ci-amd.yml") branch = os.environ.get("BRANCH", "main") output_file = Path(os.environ.get("OUTPUT_FILE", "slack-message.json")) diff --git a/scripts/ci/prek/check_ci_workflows_in_sync.py b/scripts/ci/prek/check_ci_workflows_in_sync.py new file mode 100755 index 0000000000000..3a219edd23279 --- /dev/null +++ b/scripts/ci/prek/check_ci_workflows_in_sync.py @@ -0,0 +1,375 @@ +#!/usr/bin/env python3 +# 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. +""" +Verify ci-arm.yml and ci-amd.yml stay in sync. + +The two workflows are physical copies of each other (GitHub Actions has no +cross-file YAML include) and may differ ONLY in the small set of intentional +divergences listed below. This check normalizes both files against that +allowlist, then asserts the rest matches byte-for-byte. + +Documented divergences: + +1. Header intro comment (different prose explaining what each file is for) +2. Workflow ``name:`` — ``Tests (ARM)`` vs ``Tests (AMD)`` +3. Triggers — ARM = schedule + workflow_dispatch only; AMD = pull_request + + push (to release branches) + workflow_dispatch +4. ``concurrency.group`` prefix — ``ci-arm-`` vs ``ci-amd-`` +5. ``build-info`` outputs ``platform`` and ``runner-type`` — hardcoded per + architecture (and the surrounding comment naming the "ARM/AMD copy") +6. ``print-platform`` job — ``name:`` and the architecture echoed to + GITHUB_STEP_SUMMARY + +Anything else differing between the two files is a drift bug. To +intentionally introduce a new divergence, update the rules in this script +in the same PR. + +Run from the repo root: + + uv run --project scripts python scripts/ci/prek/check_ci_workflows_in_sync.py + +Exits 0 if the workflows are in sync, 1 (with a diff) otherwise. + +Local UX +-------- + +When run interactively (TTY attached, ``CI`` env var unset) the script +also tries to figure out which side changed since the branch diverged +from ``main`` and prints concrete next steps — either mirror the change +to the other file, or add it to the per-line / per-block allowlist below. +""" + +from __future__ import annotations + +import difflib +import os +import re +import subprocess +import sys +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[3] +ARM = REPO_ROOT / ".github" / "workflows" / "ci-arm.yml" +AMD = REPO_ROOT / ".github" / "workflows" / "ci-amd.yml" +THIS_SCRIPT = Path(__file__).relative_to(REPO_ROOT) + +# Per-line regex normalizations applied to BOTH files. Each rule replaces +# the architecture-specific token with a placeholder so the two normalized +# files become identical. If you add a per-line difference between ARM and +# AMD, append a rule here. +LINE_RULES: list[tuple[str, str]] = [ + (r"^name: Tests \((?:ARM|AMD)\)$", "name: Tests (PLACEHOLDER)"), + (r"^ group: ci-(?:arm|amd)-", " group: ci-PLACEHOLDER-"), + (r'^ platform: "linux/(?:arm64|amd64)"$', ' platform: "linux/PLACEHOLDER"'), + (r"^ runner-type: '\[\"ubuntu-22\.04(?:-arm)?\"\]'$", " runner-type: 'PLACEHOLDER'"), + ( + r"^ # (?:ARM|AMD) copy\)\. The matching (?:AMD|ARM) copy lives in ci-(?:amd|arm)\.yml\.$", + " # PLACEHOLDER copy). The matching PLACEHOLDER copy lives in ci-PLACEHOLDER.yml.", + ), + (r'^ name: "Platform: (?:ARM|AMD)"$', ' name: "Platform: PLACEHOLDER"'), + ( + r"^ run: \"echo '## Architecture: (?:ARM|AMD)' >> \$GITHUB_STEP_SUMMARY\"$", + " run: \"echo '## Architecture: PLACEHOLDER' >> $GITHUB_STEP_SUMMARY\"", + ), +] + +# Whole sections that legitimately exist in only one file. Each entry is the +# verbatim block (including trailing newline) that must appear in the named +# file and must NOT appear in the other. The blocks are stripped before +# diffing so they don't show up as drift. +ARM_ONLY_BLOCK = """ schedule: + - cron: '28 1,3,7,9,13,15,19,21 * * *' +""" + +AMD_ONLY_BLOCK = """ push: + branches: + - v[0-9]+-[0-9]+-test + - providers-[a-z]+-?[a-z]*/v[0-9]+-[0-9]+ + pull_request: + branches: + - main + - v[0-9]+-[0-9]+-test + - v[0-9]+-[0-9]+-stable + - providers-[a-z]+-?[a-z]*/v[0-9]+-[0-9]+ + types: [opened, reopened, synchronize, ready_for_review] +""" + +# The header comment block (between the `---` document marker and the +# `name:` line) is intentionally different between files — each describes +# what its own file is for. Collapse to a placeholder before diffing. +HEADER_PATTERN = re.compile(r"(?<=\n---\n)(.*?)(?=^name: )", re.MULTILINE | re.DOTALL) +HEADER_PLACEHOLDER = "# PLACEHOLDER: per-file intro comment\n" + + +# --- ANSI color helpers ------------------------------------------------------- +# Local UX: colorize the report when stdout is a TTY and we're not in CI. + +_INTERACTIVE = os.environ.get("FORCE_INTERACTIVE") == "1" or ( + sys.stdout.isatty() and not os.environ.get("CI") and not os.environ.get("PREK_HEADLESS") +) + + +def _ansi(code: str, text: str) -> str: + if not _INTERACTIVE: + return text + return f"\033[{code}m{text}\033[0m" + + +def red(t: str) -> str: + return _ansi("1;31", t) + + +def green(t: str) -> str: + return _ansi("1;32", t) + + +def yellow(t: str) -> str: + return _ansi("1;33", t) + + +def cyan(t: str) -> str: + return _ansi("1;36", t) + + +def bold(t: str) -> str: + return _ansi("1", t) + + +# --- normalization ------------------------------------------------------------ + + +def normalize(content: str, *, side: str) -> str: + """Strip side-specific blocks and apply line rules so both files compare equal.""" + if side == "arm": + if ARM_ONLY_BLOCK not in content: + raise SystemExit(f"ci-arm.yml is missing its expected ARM-only trigger block:\n{ARM_ONLY_BLOCK}") + if AMD_ONLY_BLOCK in content: + raise SystemExit("ci-arm.yml contains the AMD-only trigger block — should not.") + content = content.replace(ARM_ONLY_BLOCK, "") + elif side == "amd": + if AMD_ONLY_BLOCK not in content: + raise SystemExit(f"ci-amd.yml is missing its expected AMD-only trigger block:\n{AMD_ONLY_BLOCK}") + if ARM_ONLY_BLOCK in content: + raise SystemExit("ci-amd.yml contains the ARM-only trigger block — should not.") + content = content.replace(AMD_ONLY_BLOCK, "") + else: + raise ValueError(f"Unknown side: {side}") + + for pattern, replacement in LINE_RULES: + content = re.sub(pattern, replacement, content, flags=re.MULTILINE) + content = HEADER_PATTERN.sub(HEADER_PLACEHOLDER, content) + return content + + +# --- main-branch comparison (local UX) ---------------------------------------- + + +def _git(args: list[str]) -> str | None: + """Run git from the repo root; return stdout text on success, None on failure.""" + try: + result = subprocess.run( + ["git", "-C", str(REPO_ROOT), *args], + capture_output=True, + text=True, + check=False, + ) + except FileNotFoundError: + return None + if result.returncode != 0: + return None + return result.stdout + + +def _resolve_baseline_ref() -> str | None: + """Pick a reasonable baseline ref to diff against — the closest of upstream/main, origin/main, or main.""" + for candidate in ("upstream/main", "origin/main", "main"): + if _git(["rev-parse", "--verify", "--quiet", candidate]) is not None: + return candidate + return None + + +def _diff_since_baseline(file_path: Path, baseline: str) -> str | None: + """Return the unified diff of ``file_path`` from baseline to the working tree. + + Uses ``git diff -- `` (NOT the three-dot form) so the + comparison covers committed AND uncommitted edits. The check needs to + catch a developer who edits one file and forgets to mirror it before + even running ``git add``. + """ + rel = file_path.relative_to(REPO_ROOT).as_posix() + output = _git(["diff", "--no-color", baseline, "--", rel]) + if output is None: + return None + return output.strip() or None + + +def _is_new_file_diff(diff: str | None) -> bool: + """True if the diff describes the file as added (no baseline content to compare).""" + return ( + bool(diff) and "new file mode" in diff.splitlines()[1] + if diff and len(diff.splitlines()) > 1 + else False + ) + + +def _trim_diff(diff: str, max_lines: int = 60) -> str: + """Cap diff to max_lines so the report stays readable; mention how many lines were dropped.""" + lines = diff.splitlines() + if len(lines) <= max_lines: + return diff + dropped = len(lines) - max_lines + return "\n".join( + lines[:max_lines] + [f"... ({dropped} more lines suppressed; run `git diff` to see full)"] + ) + + +def _suggest_actions(arm_diff: str | None, amd_diff: str | None) -> None: + """Print concrete suggestions about which file to edit, based on which side changed.""" + print() + print(bold("Suggested next steps:")) + print() + arm_new = _is_new_file_diff(arm_diff) + amd_new = _is_new_file_diff(amd_diff) + if arm_new and amd_new: + print( + f" • Both {cyan('ci-arm.yml')} and {cyan('ci-amd.yml')} were added in this branch — " + f"there is no baseline to attribute the drift to. Compare the two files directly " + f"({cyan('diff .github/workflows/ci-arm.yml .github/workflows/ci-amd.yml')}) and " + f"either pick one as the source of truth or extend the allowlist in " + f"{cyan(str(THIS_SCRIPT))}." + ) + return + if arm_diff and not amd_diff: + print( + f" • Only {cyan('ci-arm.yml')} has changed since the baseline. To bring AMD in line, " + f"mirror the change into {cyan('ci-amd.yml')}:" + ) + print() + print(_indent(_trim_diff(arm_diff))) + print() + print( + f" • If the change is intentionally ARM-only, add the new lines to " + f"{cyan('LINE_RULES')} (or {cyan('ARM_ONLY_BLOCK')}) in {cyan(str(THIS_SCRIPT))}." + ) + elif amd_diff and not arm_diff: + print( + f" • Only {cyan('ci-amd.yml')} has changed since the baseline. To bring ARM in line, " + f"mirror the change into {cyan('ci-arm.yml')}:" + ) + print() + print(_indent(_trim_diff(amd_diff))) + print() + print( + f" • If the change is intentionally AMD-only, add the new lines to " + f"{cyan('LINE_RULES')} (or {cyan('AMD_ONLY_BLOCK')}) in {cyan(str(THIS_SCRIPT))}." + ) + elif arm_diff and amd_diff: + print( + " • Both files have changes since the baseline. Compare the two diffs below " + "and decide which side is the source of truth, then mirror manually." + ) + print() + print(yellow("ci-arm.yml diff vs baseline:")) + print(_indent(_trim_diff(arm_diff))) + print() + print(yellow("ci-amd.yml diff vs baseline:")) + print(_indent(_trim_diff(amd_diff))) + print() + print(f" • If the divergence is intentional, document it in {cyan(str(THIS_SCRIPT))}.") + else: + # Neither file changed against the baseline, but the normalized diff is non-empty. + # That means the drift was already present before the branch — likely a bug in this + # script's allowlist or a pre-existing inconsistency that nobody caught. + print( + f" • Neither file changed since the baseline, yet the normalized diff is non-empty. " + f"This usually means {cyan(str(THIS_SCRIPT))}'s allowlist is missing a rule for a " + f"pre-existing divergence. Inspect the diff above and update LINE_RULES / " + f"ARM_ONLY_BLOCK / AMD_ONLY_BLOCK accordingly." + ) + + +def _indent(text: str, prefix: str = " ") -> str: + return "\n".join(prefix + line for line in text.splitlines()) + + +# --- entry point -------------------------------------------------------------- + + +def main() -> int: + if not ARM.exists() or not AMD.exists(): + print(red(f"ERROR: expected both {ARM.name} and {AMD.name} to exist under .github/workflows/.")) + return 1 + + arm_normalized = normalize(ARM.read_text(), side="arm") + amd_normalized = normalize(AMD.read_text(), side="amd") + + if arm_normalized == amd_normalized: + print(green(f"OK: {ARM.name} and {AMD.name} are in sync (apart from documented divergences).")) + return 0 + + print(red(f"ERROR: {ARM.name} and {AMD.name} have diverged outside the allowed set.")) + print() + print(bold("Normalized diff:")) + print() + diff = difflib.unified_diff( + arm_normalized.splitlines(), + amd_normalized.splitlines(), + fromfile=f"{ARM.name} (normalized)", + tofile=f"{AMD.name} (normalized)", + lineterm="", + ) + for line in diff: + if line.startswith("+") and not line.startswith("+++"): + print(green(line)) + elif line.startswith("-") and not line.startswith("---"): + print(red(line)) + elif line.startswith("@@"): + print(cyan(line)) + else: + print(line) + + if _INTERACTIVE: + baseline = _resolve_baseline_ref() + if baseline is None: + print() + print( + yellow( + "Could not resolve a baseline ref (tried upstream/main, origin/main, main). " + "Skipping the per-side change attribution; fix manually using the diff above." + ) + ) + return 1 + arm_diff = _diff_since_baseline(ARM, baseline) + amd_diff = _diff_since_baseline(AMD, baseline) + print() + print(bold(f"Comparing each file against {cyan(baseline)} to identify the changed side…")) + _suggest_actions(arm_diff, amd_diff) + else: + print() + print( + yellow( + "Run this script locally outside CI to see which side changed and get a " + "concrete suggestion (mirror the change, or add it to the allowlist in this script)." + ) + ) + + return 1 + + +if __name__ == "__main__": + sys.exit(main())