From 80ae61deb1d24a4acc7e58462904fe704b9324a3 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 20 Feb 2026 10:45:29 -0600 Subject: [PATCH 1/8] [CI] Split build dependencies into own step on Windows --- .github/workflows/windows.yml | 61 +++++++++++++++++++++++++++++++++++ ci-matrix.py | 34 ++++++++++++++++++- cpython-windows/build.py | 9 ++++++ 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index cae9a192..354e5bed 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -56,6 +56,7 @@ jobs: outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }} + dep-build-matrix: ${{ steps.set-matrix.outputs.dep-build-matrix }} any_builds: ${{ steps.set-matrix.outputs.any_builds }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -97,6 +98,7 @@ jobs: # Extract python-build matrix echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT + echo "dep-build-matrix=$(jq -c '."dep-build"' matrix.json)" >> $GITHUB_OUTPUT # Display the matrix for debugging too cat matrix.json | jq @@ -116,6 +118,7 @@ jobs: needs: - generate-matrix - crate-build + - build-deps # Permissions used for actions/attest-build-provenance permissions: id-token: write @@ -152,6 +155,11 @@ jobs: run: | uv run build.py --help + - name: Download build dependencies + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + with: + name: build-deps-${{ matrix.target_triple }}-${{ matrix.build_options}} + - name: Build if: ${{ ! matrix.dry-run }} shell: cmd @@ -185,3 +193,56 @@ jobs: run: | $Dists = Resolve-Path -Path "dist/*.tar.zst" -Relative .\pythonbuild.exe validate-distribution --run $Dists + + build-deps: + timeout-minutes: 90 + needs: + - generate-matrix + # Permissions used for actions/attest-build-provenance + runs-on: ${{ matrix.runner }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.dep-build-matrix) }} + fail-fast: false + name: ${{ matrix.target_triple }} / ${{ matrix.build_options }} + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Install Cygwin Environment + uses: cygwin/cygwin-install-action@f2009323764960f80959895c7bc3bb30210afe4d # v6 + with: + packages: autoconf automake libtool + + - name: Set up uv + uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4 + with: + enable-cache: false + + # We need to do this before we activate the VC++ environment or else binary packages + # don't get compiled properly. + - name: Bootstrap Python environment + run: | + uv run build.py --help + + - name: Build + if: ${{ ! matrix.dry-run }} + shell: cmd + run: | + IF "%MATRIX_VS_VERSION%"=="2026" ( + call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\%MATRIX_VCVARS%" + ) ELSE ( + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\%MATRIX_VCVARS%" + ) + uv run build.py --only-deps --sh c:\cygwin\bin\sh.exe --options %MATRIX_BUILD_OPTIONS% --vs %MATRIX_VS_VERSION% + env: + MATRIX_VCVARS: ${{ matrix.vcvars }} + MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }} + MATRIX_VS_VERSION: ${{ matrix.vs_version }} + + - name: Upload Build Dependencies + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: build-deps-${{ matrix.target_triple }}-${{ matrix.build_options }} + path: build/*.tar \ No newline at end of file diff --git a/ci-matrix.py b/ci-matrix.py index c88f09b2..abbc8476 100644 --- a/ci-matrix.py +++ b/ci-matrix.py @@ -127,6 +127,30 @@ def generate_docker_matrix_entries( return matrix_entries +def generate_deps_build_matrix_entries( + python_entries: list[dict[str, str]], + platform_filter: str | None = None, +) -> list[dict[str, str]]: + """Generate matrix entries for deps builds based on python build matrix.""" + include_keys = { + "arch", + "target_triple", + "platform", + "runner", + "build_options", + "vcvars", + "vs_version", + } + dep_build_pairs = set() + for entry in python_entries: + platform = entry["platform"] + if platform_filter and platform != platform_filter: + continue + pairs = tuple((k, v) for k, v in entry.items() if k in include_keys) + dep_build_pairs.add(pairs) + return [dict(pairs) for pairs in dep_build_pairs] + + def generate_crate_build_matrix_entries( python_entries: list[dict[str, str]], runners: dict[str, Any], @@ -355,7 +379,7 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--matrix-type", - choices=["python-build", "docker-build", "crate-build", "all"], + choices=["python-build", "docker-build", "crate-build", "deps-build", "all"], default="all", help="Which matrix types to generate (default: all)", ) @@ -443,6 +467,14 @@ def main() -> None: ) result["crate-build"] = {"include": crate_entries} + # Generate deps-build matrix if requested + if args.matrix_type in ["deps-build", "all"]: + deps_entries = generate_deps_build_matrix_entries( + python_entries, + args.platform, + ) + result["deps-build"] = {"include": deps_entries} + print(json.dumps(result)) diff --git a/cpython-windows/build.py b/cpython-windows/build.py index 3b27e679..8e58882e 100644 --- a/cpython-windows/build.py +++ b/cpython-windows/build.py @@ -1910,6 +1910,11 @@ def main() -> None: default="10.0.26100.0", help="Windows SDK version to build with", ) + parser.add_argument( + "--only-deps", + action='store_true', + help="Build only dependencies, not CPython", + ) args = parser.parse_args() build_options = args.options @@ -1964,6 +1969,10 @@ def main() -> None: libffi_archive, ) + # Stop if only building dependencies + if args.only_deps: + return + LOG_PREFIX[0] = "cpython" tar_path = build_cpython( args.python, From 4ec666a8043a25f49020457abafb584b2e5c5f36 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 20 Feb 2026 10:49:17 -0600 Subject: [PATCH 2/8] fix typo --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 354e5bed..0d3d76ea 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -98,7 +98,7 @@ jobs: # Extract python-build matrix echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT - echo "dep-build-matrix=$(jq -c '."dep-build"' matrix.json)" >> $GITHUB_OUTPUT + echo "dep-build-matrix=$(jq -c '."deps-build"' matrix.json)" >> $GITHUB_OUTPUT # Display the matrix for debugging too cat matrix.json | jq From 938fc62e1345dcdcd0f407032bb79b07534792f6 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 20 Feb 2026 11:11:36 -0600 Subject: [PATCH 3/8] debug, download path, better name --- .github/workflows/windows.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 0d3d76ea..9edef393 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -159,11 +159,13 @@ jobs: uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: name: build-deps-${{ matrix.target_triple }}-${{ matrix.build_options}} + path: build - name: Build if: ${{ ! matrix.dry-run }} shell: cmd run: | + DIR IF "%MATRIX_VS_VERSION%"=="2026" ( call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\%MATRIX_VCVARS%" ) ELSE ( @@ -203,7 +205,7 @@ jobs: strategy: matrix: ${{ fromJson(needs.generate-matrix.outputs.dep-build-matrix) }} fail-fast: false - name: ${{ matrix.target_triple }} / ${{ matrix.build_options }} + name: build-deps / ${{ matrix.target_triple }} / ${{ matrix.build_options }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: From a37d04e33324aec5e05293e61d30b01b8bc23a8b Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 27 Feb 2026 13:30:58 -0600 Subject: [PATCH 4/8] fixup based on review comments --- .github/workflows/windows.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 9edef393..b28a1c7a 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -118,7 +118,7 @@ jobs: needs: - generate-matrix - crate-build - - build-deps + - build-dependencies # Permissions used for actions/attest-build-provenance permissions: id-token: write @@ -196,11 +196,10 @@ jobs: $Dists = Resolve-Path -Path "dist/*.tar.zst" -Relative .\pythonbuild.exe validate-distribution --run $Dists - build-deps: - timeout-minutes: 90 + build-dependencies: + timeout-minutes: 20 needs: - generate-matrix - # Permissions used for actions/attest-build-provenance runs-on: ${{ matrix.runner }} strategy: matrix: ${{ fromJson(needs.generate-matrix.outputs.dep-build-matrix) }} From 6c4a7b45fd50468f3454572cb453247f82b3e934 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 27 Feb 2026 13:33:21 -0600 Subject: [PATCH 5/8] format with ruff --- cpython-windows/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpython-windows/build.py b/cpython-windows/build.py index 8e58882e..87c04539 100644 --- a/cpython-windows/build.py +++ b/cpython-windows/build.py @@ -1912,7 +1912,7 @@ def main() -> None: ) parser.add_argument( "--only-deps", - action='store_true', + action="store_true", help="Build only dependencies, not CPython", ) From d82aaf4c0005d572a0013bc2fdca25a81059d62d Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 27 Feb 2026 14:36:07 -0600 Subject: [PATCH 6/8] add --facet-by-triple option to ci-matrix.py --- ci-matrix.py | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/ci-matrix.py b/ci-matrix.py index abbc8476..cdd6e646 100644 --- a/ci-matrix.py +++ b/ci-matrix.py @@ -9,6 +9,7 @@ import argparse import json import sys +from collections import defaultdict from typing import Any import yaml @@ -127,11 +128,11 @@ def generate_docker_matrix_entries( return matrix_entries -def generate_deps_build_matrix_entries( +def generate_dependencies_build_matrix_entries( python_entries: list[dict[str, str]], platform_filter: str | None = None, ) -> list[dict[str, str]]: - """Generate matrix entries for deps builds based on python build matrix.""" + """Generate matrix entries for dependencies builds based on python build matrix.""" include_keys = { "arch", "target_triple", @@ -236,6 +237,17 @@ def generate_python_build_matrix_entries( return matrix_entries +def facet_by_triple(entries: list[dict[str, str]]) -> dict[str, dict[str, list]]: + """Split entries into sections based upon the target_triple key.""" + by_triple = defaultdict(list) + for entry in entries: + by_triple[entry["target_triple"]].append(entry) + entries_by_triple = { + triple: {"include": entries} for triple, entries in by_triple.items() + } + return entries_by_triple + + def find_runner(runners: dict[str, Any], platform: str, arch: str, free: bool) -> str: # Find a matching platform first match_platform = [ @@ -357,12 +369,18 @@ def parse_args() -> argparse.Namespace: choices=["darwin", "linux", "windows"], help="Filter matrix entries by platform", ) - parser.add_argument( + group = parser.add_mutually_exclusive_group() + group.add_argument( "--max-shards", type=int, default=0, help="The maximum number of shards allowed; set to zero to disable ", ) + group.add_argument( + "--facet-by-triple", + action="store_true", + help="Facet the python-build and dependencies-build entries by target_triple", + ) parser.add_argument( "--labels", help="Comma-separated list of labels to filter by (e.g., 'platform:darwin,python:3.13,build:debug'), all must match.", @@ -379,7 +397,13 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--matrix-type", - choices=["python-build", "docker-build", "crate-build", "deps-build", "all"], + choices=[ + "python-build", + "docker-build", + "crate-build", + "dependencies-build", + "all", + ], default="all", help="Which matrix types to generate (default: all)", ) @@ -467,13 +491,21 @@ def main() -> None: ) result["crate-build"] = {"include": crate_entries} - # Generate deps-build matrix if requested - if args.matrix_type in ["deps-build", "all"]: - deps_entries = generate_deps_build_matrix_entries( + # Generate dependencies-build matrix if requested + if args.matrix_type in ["dependencies-build", "all"]: + deps_entries = generate_dependencies_build_matrix_entries( python_entries, args.platform, ) - result["deps-build"] = {"include": deps_entries} + result["dependencies-build"] = {"include": deps_entries} + + # facet + if args.facet_by_triple: + result["python-build"] = facet_by_triple(result["python-build"]["include"]) + if "dependencies-build" in result: + result["dependencies-build"] = facet_by_triple( + result["dependencies-build"]["include"] + ) print(json.dumps(result)) From 4cb60fbbbcd86717b29e6a83e2963377b116336e Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 27 Feb 2026 14:54:52 -0600 Subject: [PATCH 7/8] facet windows action by architecture Have separate jobs for build-{python,dependencies} for x86_64, i686 and aarch64 to allow the build-python jobs to start when the corresponding build-dependencies job finishes. --- .github/workflows/windows.yml | 97 +++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b28a1c7a..01b03840 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -54,9 +54,13 @@ jobs: name: Generate build matrix runs-on: ubuntu-latest outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} + matrix-x86_64: ${{ steps.set-matrix.outputs.matrix-x86_64 }} + matrix-i686: ${{ steps.set-matrix.outputs.matrix-i686 }} + matrix-aarch64: ${{ steps.set-matrix.outputs.matrix-aarch64 }} crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }} - dep-build-matrix: ${{ steps.set-matrix.outputs.dep-build-matrix }} + dependencies-build-matrix-x86_64: ${{ steps.set-matrix.outputs.dependencies-build-matrix-x86_64 }} + dependencies-build-matrix-i686: ${{ steps.set-matrix.outputs.dependencies-build-matrix-x86_64 }} + dependencies-build-matrix-aarch64: ${{ steps.set-matrix.outputs.dependencies-build-matrix-aarch64 }} any_builds: ${{ steps.set-matrix.outputs.any_builds }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -93,17 +97,23 @@ jobs: - name: Generate build matrix id: set-matrix run: | - uv run ci-matrix.py --platform windows --labels "${STEPS_GET_LABELS_OUTPUTS_LABELS}" ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json + uv run ci-matrix.py --platform windows --facet-by-triple --labels "${STEPS_GET_LABELS_OUTPUTS_LABELS}" ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json # Extract python-build matrix - echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT + echo "matrix-x86_64=$(jq -c '."python-build"?["x86_64-pc-windows-msvc"]? // {"include": []}' matrix.json)" >> $GITHUB_OUTPUT + echo "matrix-i686=$(jq -c '."python-build"?["i686-pc-windows-msvc"]? // {"include": []}' matrix.json)" >> $GITHUB_OUTPUT + echo "matrix-aarch64=$(jq -c '."python-build"?["aarch64-pc-windows-msvc"]? // {"include": []}' matrix.json)" >> $GITHUB_OUTPUT + echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT - echo "dep-build-matrix=$(jq -c '."deps-build"' matrix.json)" >> $GITHUB_OUTPUT + + echo "dependencies-build-matrix-x86_64=$(jq -c '."dependencies-build"?["x86_64-pc-windows-msvc"]? // {"include": []}' matrix.json)" >> $GITHUB_OUTPUT + echo "dependencies-build-matrix-i686=$(jq -c '."dependencies-build"?["i686-pc-windows-msvc"]? // {"include": []}' matrix.json)" >> $GITHUB_OUTPUT + echo "dependencies-build-matrix-aarch64=$(jq -c '."dependencies-build"?["aarch64-pc-windows-msvc"]? // {"include": []}' matrix.json)" >> $GITHUB_OUTPUT # Display the matrix for debugging too cat matrix.json | jq - if jq -e '."python-build".include | length > 0' matrix.json > /dev/null; then + if jq -e '."python-build" | length > 0' matrix.json > /dev/null; then # Build matrix has entries echo "any_builds=true" >> $GITHUB_OUTPUT else @@ -113,22 +123,23 @@ jobs: env: STEPS_GET_LABELS_OUTPUTS_LABELS: ${{ steps.get-labels.outputs.labels }} - build: + + build-python-x86_64: timeout-minutes: 90 needs: - generate-matrix - crate-build - - build-dependencies + - build-dependencies-x86_64 # Permissions used for actions/attest-build-provenance permissions: id-token: write attestations: write runs-on: ${{ matrix.runner }} strategy: - matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} + matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-x86_64) }} fail-fast: false name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }} - steps: + steps: &build-python-steps - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 @@ -196,16 +207,50 @@ jobs: $Dists = Resolve-Path -Path "dist/*.tar.zst" -Relative .\pythonbuild.exe validate-distribution --run $Dists - build-dependencies: + build-python-i686: + timeout-minutes: 90 + needs: + - generate-matrix + - crate-build + - build-dependencies-i686 + # Permissions used for actions/attest-build-provenance + permissions: + id-token: write + attestations: write + runs-on: ${{ matrix.runner }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-i686) }} + fail-fast: false + name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }} + steps: *build-python-steps + + build-python-aarch64: + timeout-minutes: 90 + needs: + - generate-matrix + - crate-build + - build-dependencies-aarch64 + # Permissions used for actions/attest-build-provenance + permissions: + id-token: write + attestations: write + runs-on: ${{ matrix.runner }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-aarch64) }} + fail-fast: false + name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }} + steps: *build-python-steps + + build-dependencies-x86_64: timeout-minutes: 20 needs: - generate-matrix runs-on: ${{ matrix.runner }} strategy: - matrix: ${{ fromJson(needs.generate-matrix.outputs.dep-build-matrix) }} + matrix: ${{ fromJson(needs.generate-matrix.outputs.dependencies-build-matrix-x86_64) }} fail-fast: false - name: build-deps / ${{ matrix.target_triple }} / ${{ matrix.build_options }} - steps: + name: build-dependencies / ${{ matrix.target_triple }} / ${{ matrix.build_options }} + steps: &build-dependencies-steps - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 @@ -246,4 +291,26 @@ jobs: uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: build-deps-${{ matrix.target_triple }}-${{ matrix.build_options }} - path: build/*.tar \ No newline at end of file + path: build/*.tar + + build-dependencies-i686: + timeout-minutes: 20 + needs: + - generate-matrix + runs-on: ${{ matrix.runner }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.dependencies-build-matrix-i686) }} + fail-fast: false + name: build-dependencies / ${{ matrix.target_triple }} / ${{ matrix.build_options }} + steps: *build-dependencies-steps + + build-dependencies-aarch64: + timeout-minutes: 20 + needs: + - generate-matrix + runs-on: ${{ matrix.runner }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.dependencies-build-matrix-aarch64) }} + fail-fast: false + name: build-dependencies / ${{ matrix.target_triple }} / ${{ matrix.build_options }} + steps: *build-dependencies-steps From 6c1bfbde5ec0d3e1ffbb66616c4cc565f5de9f10 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 27 Feb 2026 15:32:02 -0600 Subject: [PATCH 8/8] fix typo --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 01b03840..0a035e9c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -59,7 +59,7 @@ jobs: matrix-aarch64: ${{ steps.set-matrix.outputs.matrix-aarch64 }} crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }} dependencies-build-matrix-x86_64: ${{ steps.set-matrix.outputs.dependencies-build-matrix-x86_64 }} - dependencies-build-matrix-i686: ${{ steps.set-matrix.outputs.dependencies-build-matrix-x86_64 }} + dependencies-build-matrix-i686: ${{ steps.set-matrix.outputs.dependencies-build-matrix-i686 }} dependencies-build-matrix-aarch64: ${{ steps.set-matrix.outputs.dependencies-build-matrix-aarch64 }} any_builds: ${{ steps.set-matrix.outputs.any_builds }} steps: