Просмотр исходного кода

Add automated nightly builds, uploaded as pre-releases. (#4055)

There is still a lot more we should try to do here, but this gets us
a decent start and should be enough for some of the developers working
on Carbon to use for simple cases, or tools like Compiler Explorer.

This first factors most of the complex setup for our CI workflow into
local actions that we can reuse in other workflows. It's actually
a fairly nice cleanup I think even without the specific use case of
a nightly release process. These use "composite" actions which is the
cleanest model for factoring out a subsequence of steps from a workflow.
I've tried to keep the inputs fairly minimal and easy to spot.

Next, it adds a cron-scheduled action that builds and creates a nightly
release. It also supports explicitly running the workflow, which can be
useful if the nightly release is broken in some way: a fix can be landed
and then a force run used.

Tested the `tests` workflow using our `action-test` branch:
https://github.com/carbon-language/carbon-lang/actions/runs/9545546278

Also tested the nightly release action by hacking in a `push` trigger
and using *draft* release. If you have admin rights, you can see an
example draft nightly build here:

https://github.com/carbon-language/carbon-lang/releases/tag/untagged-6a85cdce7b3a784a2e6b

Note that the GitHub releases are easily deleted, and even the tags
created in the repository can be cleaned up as needed so it should be
fairly harmless to fix this forward if needed.
Chandler Carruth 1 год назад
Родитель
Сommit
5332b71eec

+ 107 - 0
.github/actions/build-setup-common/action.yml

@@ -0,0 +1,107 @@
+# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+name: Setup build environment (macOS)
+inputs:
+  matrix_runner:
+    required: true
+  remote_cache_upload:
+    required: true
+runs:
+  using: composite
+  steps:
+    # Setup Python and related tools.
+    - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
+      with:
+        # Match the min version listed in docs/project/contribution_tools.md
+        # or the oldest version available on the OS.
+        python-version:
+          ${{ inputs.matrix_runner == 'macos-14' && '3.11' || '3.9' }}
+
+    - uses: ./.github/actions/build-setup-macos
+      if: startsWith(inputs.matrix_runner, 'macos')
+      with:
+        matrix_runner: ${{ inputs.matrix_runner }}
+
+    - uses: ./.github/actions/build-setup-ubuntu
+      if: startsWith(inputs.matrix_runner, 'ubuntu')
+
+    # Print the various tool paths and versions to help in debugging.
+    - name: Print tool debugging info
+      shell: bash
+      run: |
+        echo '*** PATH'
+        echo $PATH
+        echo '*** bazelisk'
+        which bazelisk
+        bazelisk --version
+        echo '*** run_bazel.py'
+        ./scripts/run_bazel.py --version
+        echo '*** python'
+        which python
+        python --version
+        echo '*** clang'
+        which clang
+        clang --version
+        echo '*** clang++'
+        which clang++
+        clang++ --version
+
+    # Add our bazel configuration and print basic info to ease debugging.
+    - name: Configure Bazel and print info
+      env:
+        # Add a cache version for changes that bazel won't otherwise detect,
+        # like llvm version changes.
+        CACHE_VERSION: 1
+      shell: bash
+      run: |
+        cat >user.bazelrc <<EOF
+        # Enable remote cache for our CI but minimize downloads.
+        build --remote_cache=https://storage.googleapis.com/carbon-builds-github-v${CACHE_VERSION}
+        build --remote_download_minimal
+
+        # We import a special key into every action in order to key the Bazel
+        # remote cache in a way that avoids collisions between different
+        # runners. Anything that might change the system external to Bazel but
+        # not be fully captured by the sand-boxing of the build should be used
+        # as part of the key. We don't need to use the CPU target for example,
+        # as that is captured by Bazel's configuration of each action. And the
+        # Clang version is incorporated by our Clang toolchain setup. But we
+        # do need to capture any differences between GitHub runner OSes that
+        # don't impact the Bazel configuration to avoid collisions between
+        # those.
+        build --action_env=BAZEL_REMOTE_CACHE_KEY=github-action-${{ inputs.matrix_runner }}
+
+        build ${{ inputs.remote_cache_upload }}
+
+        # Set an artificially high jobs count. This flag controls the number
+        # of concurrency Bazel itself uses, which is essential for actions
+        # that are internally blocked on for example downloading results form
+        # the cache above. Without setting this high, Bazel will pick a small
+        # number based on the available host CPUs and the reality will be a
+        # long chain of largely serialized download events with little or no
+        # usage of the host machine. Fortunately, local actions are
+        # *separately* gated on '--local_*_resources' that will avoid a large
+        # jobs value overwhelming the host. There is a bug to make downloads
+        # behave completely asynchronously and remove the need for this filed
+        # back in 2018 but work seemed to not finish:
+        # https://github.com/bazelbuild/bazel/issues/6394
+        #
+        # There is a new effort (yay!) but until then it seems worth using the
+        # workaround of a high jobs value. The biggest downside (increased
+        # heap usage) seems like it isn't currently a big loss for our builds.
+        #
+        # Higher values like 50 have led to CI failures with network errors
+        # and IOExceptions, see
+        # https://discord.com/channels/655572317891461132/707150492370862090/1151605725576056934
+        build --jobs=32
+
+        # Avoid any cache impact from build stamping in CI.
+        build --nostamp
+
+        # General build options.
+        build --verbose_failures
+        test --test_output=errors
+        EOF
+        ./scripts/run_bazel.py info

+ 74 - 0
.github/actions/build-setup-macos/action.yml

@@ -0,0 +1,74 @@
+# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+name: Setup build environment (macOS)
+inputs:
+  matrix_runner:
+    required: true
+runs:
+  using: composite
+  steps:
+    # Install and cache LLVM 16 from Homebrew.
+    # TODO: We can potentially remove this and simplify things when the
+    # Homebrew version of LLVM updates to 16 here:
+    # https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md
+    - name: Cache Homebrew
+      id: cache-homebrew-macos
+      uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+      env:
+        cache-name: cache-homebrew
+      with:
+        # Cover all the critical parts of Homebrew here. Homebrew on Arm macOS
+        # uses its own prefix making this easy to cover, but we need a few
+        # different paths for Intel.
+        path: |
+          ${{
+            runner.arch == 'ARM64' && '/opt/homebrew' ||
+            '
+              /usr/local/Homebrew
+              /usr/local/Cellar
+              /usr/local/Frameworks
+              /usr/local/bin
+              /usr/local/opt
+            '
+          }}
+        # Note the key needs to include all the packages we're adding.
+        key: Homebrew-Cache-${{ inputs.matrix_runner }}-${{ runner.arch }}
+
+    - name: Install LLVM and Clang with Homebrew
+      if: steps.cache-homebrew-macos.outputs.cache-hit != 'true'
+      shell: bash
+      run: |
+        echo '*** Prune brew leaves'
+        # We prune all the leaf packages to have a minimal environment. This
+        # both minimizes the install space and avoids accidental dependencies
+        # on installed packages.
+        brew leaves
+        LEAVES=$(brew leaves | egrep -v '^(bazelisk|gh|git|git-lfs|gnu-tar|go@.*|jq|pipx|node@.*|openssl@.*|wget|yq|zlib)$')
+        brew uninstall -f --ignore-dependencies $LEAVES
+        echo '*** Installing LLVM deps'
+        brew install --force-bottle --only-dependencies llvm@16
+        echo '*** Installing LLVM itself'
+        brew install --force-bottle --force --verbose llvm@16
+        echo '*** brew info llvm@16'
+        brew info llvm@16
+        echo '*** brew autoremove'
+        brew autoremove
+        echo '*** brew info'
+        brew info
+        echo '*** brew leaves'
+        brew leaves
+        echo '*** brew config'
+        brew config
+
+    - name: Setup LLVM and Clang
+      shell: bash
+      run: |
+        LLVM_PATH="$(brew --prefix llvm@16)"
+        echo "Using ${LLVM_PATH}"
+        echo "${LLVM_PATH}/bin" >> $GITHUB_PATH
+        echo '*** ls "${LLVM_PATH}"'
+        ls "${LLVM_PATH}"
+        echo '*** ls "${LLVM_PATH}/bin"'
+        ls "${LLVM_PATH}/bin"

+ 66 - 0
.github/actions/build-setup-ubuntu/action.yml

@@ -0,0 +1,66 @@
+# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+name: Setup build environment (Ubuntu)
+runs:
+  using: composite
+  steps:
+    # Ubuntu images start with 23GB available, and this adds 14GB more. For
+    # comparison, MacOS images have >100GB free.
+    #
+    # Although we could delete more, if we run into a limit, not deleting
+    # everything provides a little flexibility to get space while trying
+    # to shrink the build.
+    - name: Free up disk space
+      uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
+      with:
+        android: true
+        dotnet: true
+        haskell: true
+
+    # Cache and install a recent version of LLVM. This uses the GitHub action
+    # cache to avoid directly downloading on each iteration and improve
+    # reliability.
+    - name: Cache LLVM and Clang installation
+      id: cache-llvm-ubuntu
+      uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+      env:
+        cache-name: cache-llvm
+      with:
+        path: ~/llvm
+        key: LLVM-16-Cache-ubuntu-${{ runner.arch }}
+
+    - name: Download LLVM and Clang installation
+      if: steps.cache-llvm-ubuntu.outputs.cache-hit != 'true'
+      shell: bash
+      run: |
+        cd ~
+        LLVM_RELEASE=clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04
+        echo "*** Downloading $LLVM_RELEASE"
+        wget --show-progress=off "https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/$LLVM_RELEASE.tar.xz"
+        echo "*** Extracting $LLVM_RELEASE"
+        tar -xJf "$LLVM_RELEASE.tar.xz"
+        echo "*** Moving to 'llvm'"
+        mv "$LLVM_RELEASE" llvm
+        echo "*** Testing `clang++ --version`"
+        ~/llvm/bin/clang++ --version
+
+        # The installation contains *huge* parts of LLVM we don't need for the
+        # toolchain. Prune them here to keep our cache small.
+        echo "*** Cleaning the 'llvm' directory"
+        rm llvm/lib/{*.a,*.so,*.so.*,*.bc}
+        rm llvm/bin/{flang-*,mlir-*,clang-{scan-deps,check,repl},*-test,llvm-{lto*,reduce,bolt*,exegesis,jitlink},bugpoint,opt,llc}
+        echo "*** Size of the 'llvm' directory"
+        du -hs llvm
+
+    - name: Setup LLVM and Clang paths
+      shell: bash
+      run: |
+        LLVM_PATH=~/llvm
+        echo "Using ${LLVM_PATH}"
+        echo "${LLVM_PATH}/bin" >> $GITHUB_PATH
+        echo '*** ls "${LLVM_PATH}"'
+        ls "${LLVM_PATH}"
+        echo '*** ls "${LLVM_PATH}/bin"'
+        ls "${LLVM_PATH}/bin"

+ 93 - 0
.github/workflows/nightly-release.yaml

@@ -0,0 +1,93 @@
+# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+# This workflow creates a GitHub "release" of a nightly build of the project.
+#
+# Note: This is just an initial rough attempt, there is a lot of future work
+# needed here. A brief summary of TODOs:
+#
+# - Configure a nice release notes template and switch to generating the title
+#   and notes instead of hard coding them.
+#
+# - Do some amount of testing prior to building and uploading the release.
+#   - Tempting to try to examine existing testing workflow, but maybe better to
+#     allow re-using any complex parts and do our own testing. That would, for
+#     example, allow us to narrow or expand the set of tests uses for
+#     pre-release testing to potentially be different from continuous testing.
+#   - Some questions around what to do in the event of a failure... error? Where
+#     does the error go? Create a draft, unpublished release instead?
+#
+# - Build artifacts for all the different OSes we have GitHub runners for rather
+#   than just x86 Linux.
+
+name: Nightly Release
+
+on:
+  schedule:
+    - cron: '0 2 * * *'
+  # Enable manual runs for testing or manually (re-)creating a nightly release.
+  workflow_dispatch:
+
+permissions:
+  contents: write # For creating and uploading to releases.
+
+jobs:
+  release:
+    runs-on: ubuntu-22.04
+    steps:
+      - name: Harden Runner
+        uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
+        with:
+          egress-policy: audit
+
+      - name: Checkout branch
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+
+      - name: Set up remote cache access
+        env:
+          REMOTE_CACHE_KEY: ${{ secrets.CARBON_BUILDS_GITHUB }}
+        run: |
+          echo "$REMOTE_CACHE_KEY" | base64 -d > $HOME/remote_cache_key.json
+          echo "remote_cache_upload=--google_credentials=$HOME/remote_cache_key.json" \
+              >> $GITHUB_ENV
+
+      - uses: ./.github/actions/build-setup-common
+        with:
+          matrix_runner: ubuntu-22.04
+          remote_cache_upload: ${{ env.remote_cache_upload }}
+
+      - name: Get nightly date
+        run: |
+          echo "nightly_date=$(date '+%Y.%m.%d')" >> $GITHUB_ENV
+
+      - name: Build release
+        run: |
+          ./scripts/run_bazel.py \
+            --attempts=5 --jobs-on-last-attempt=4 \
+            build -c opt --remote_download_toplevel \
+            --pre_release=nightly --nightly_date=${{ env.nightly_date }} \
+            //toolchain/install:prefix_root/bin/carbon \
+            //toolchain/install:carbon_toolchain_tar_rule
+
+      - name: Extract the release version
+        run: |
+          # Make sure we can run the toolchain to get the version.
+          ./bazel-bin/toolchain/install/prefix_root/bin/carbon version
+
+          # Now stash it in a variable and export it.
+          VERSION=$( \
+            ./bazel-bin/toolchain/install/prefix_root/bin/carbon version \
+            | cut -d' ' -f5 | cut -d'+' -f1)
+          echo "release_version=$VERSION" >> $GITHUB_ENV
+
+      - name: Create the release
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          gh release create \
+            --title "Nightly build ${{ env.nightly_date }}" \
+            --notes 'A nightly development build of Carbon.' \
+            --prerelease \
+            v${{ env.release_version }} \
+            "bazel-bin/toolchain/install/carbon_toolchain-${{ env.release_version }}.tar.bz2"

+ 4 - 216
.github/workflows/tests.yaml

@@ -37,29 +37,12 @@ jobs:
             build_mode: clang-tidy
             build_mode: clang-tidy
     runs-on: ${{ matrix.runner }}
     runs-on: ${{ matrix.runner }}
 
 
-    env:
-      os: ${{ startsWith(matrix.runner, 'ubuntu') && 'ubuntu' || 'macos' }}
-
     steps:
     steps:
       - name: Harden Runner
       - name: Harden Runner
         uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
         uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
         with:
         with:
           egress-policy: audit
           egress-policy: audit
 
 
-      # Ubuntu images start with 23GB available, and this adds 14GB more. For
-      # comparison, MacOS images have >100GB free.
-      #
-      # Although we could delete more, if we run into a limit, not deleting
-      # everything provides a little flexibility to get space while trying
-      # to shrink the build.
-      - name: Free up disk space (Ubuntu)
-        if: env.os == 'ubuntu'
-        uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
-        with:
-          android: true
-          dotnet: true
-          haskell: true
-
       # Checkout the pull request head or the branch.
       # Checkout the pull request head or the branch.
       - name: Checkout pull request
       - name: Checkout pull request
         if: github.event_name == 'pull_request'
         if: github.event_name == 'pull_request'
@@ -81,149 +64,6 @@ jobs:
             has_code:
             has_code:
               - '!{**/*.md,LICENSE,CODEOWNERS,.git*}'
               - '!{**/*.md,LICENSE,CODEOWNERS,.git*}'
 
 
-      # Setup Python and related tools.
-      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
-        if: steps.filter.outputs.has_code == 'true'
-        with:
-          # Match the min version listed in docs/project/contribution_tools.md
-          # or the oldest version available on the OS.
-          python-version: ${{ matrix.runner == 'macos-14' && '3.11' || '3.9' }}
-
-      # Install and cache LLVM 16 from Homebrew.
-      # TODO: We can potentially remove this and simplify things when the
-      # Homebrew version of LLVM updates to 16 here:
-      # https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md
-      - name: Cache Homebrew (macOS)
-        if: steps.filter.outputs.has_code == 'true' && env.os == 'macos'
-        id: cache-homebrew-macos
-        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
-        env:
-          cache-name: cache-homebrew
-        with:
-          # Cover all the critical parts of Homebrew here. Homebrew on Arm macOS
-          # uses its own prefix making this easy to cover, but we need a few
-          # different paths for Intel.
-          path: |
-            ${{
-              runner.arch == 'ARM64' && '/opt/homebrew' ||
-              '
-                /usr/local/Homebrew
-                /usr/local/Cellar
-                /usr/local/Frameworks
-                /usr/local/bin
-                /usr/local/opt
-              '
-            }}
-          # Note the key needs to include all the packages we're adding.
-          key: Homebrew-Cache-${{ matrix.runner }}-${{ runner.arch }}
-
-      - name: Install LLVM and Clang with Homebrew (macOS)
-        if:
-          steps.filter.outputs.has_code == 'true' && env.os == 'macos' &&
-          steps.cache-homebrew-macos.outputs.cache-hit != 'true'
-        run: |
-          echo '*** Prune brew leaves'
-          # We prune all the leaf packages to have a minimal environment. This
-          # both minimizes the install space and avoids accidental dependencies
-          # on installed packages.
-          brew leaves
-          LEAVES=$(brew leaves | egrep -v '^(bazelisk|gh|git|git-lfs|gnu-tar|go@.*|jq|pipx|node@.*|openssl@.*|wget|yq|zlib)$')
-          brew uninstall -f --ignore-dependencies $LEAVES
-          echo '*** Installing LLVM deps'
-          brew install --force-bottle --only-dependencies llvm@16
-          echo '*** Installing LLVM itself'
-          brew install --force-bottle --force --verbose llvm@16
-          echo '*** brew info llvm@16'
-          brew info llvm@16
-          echo '*** brew autoremove'
-          brew autoremove
-          echo '*** brew info'
-          brew info
-          echo '*** brew leaves'
-          brew leaves
-          echo '*** brew config'
-          brew config
-
-      - name: Setup LLVM and Clang (macOS)
-        if: steps.filter.outputs.has_code == 'true' && env.os == 'macos'
-        run: |
-          LLVM_PATH="$(brew --prefix llvm@16)"
-          echo "Using ${LLVM_PATH}"
-          echo "${LLVM_PATH}/bin" >> $GITHUB_PATH
-          echo '*** ls "${LLVM_PATH}"'
-          ls "${LLVM_PATH}"
-          echo '*** ls "${LLVM_PATH}/bin"'
-          ls "${LLVM_PATH}/bin"
-
-      # Cache and install a recent version of LLVM. This uses the GitHub action
-      # cache to avoid directly downloading on each iteration and improve
-      # reliability.
-      - name: Cache LLVM and Clang installation (Ubuntu)
-        if: steps.filter.outputs.has_code == 'true' && env.os == 'ubuntu'
-        id: cache-llvm-ubuntu
-        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
-        env:
-          cache-name: cache-llvm
-        with:
-          path: ~/llvm
-          key: LLVM-16-Cache-${{ env.os }}-${{ runner.arch }}
-
-      - name: Download LLVM and Clang installation (Ubuntu)
-        if:
-          steps.filter.outputs.has_code == 'true' && env.os == 'ubuntu' &&
-          steps.cache-llvm-ubuntu.outputs.cache-hit != 'true'
-        run: |
-          cd ~
-          LLVM_RELEASE=clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04
-          echo "*** Downloading $LLVM_RELEASE"
-          wget --show-progress=off "https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/$LLVM_RELEASE.tar.xz"
-          echo "*** Extracting $LLVM_RELEASE"
-          tar -xJf "$LLVM_RELEASE.tar.xz"
-          echo "*** Moving to 'llvm'"
-          mv "$LLVM_RELEASE" llvm
-          echo "*** Testing `clang++ --version`"
-          ~/llvm/bin/clang++ --version
-
-          # The installation contains *huge* parts of LLVM we don't need for the
-          # toolchain. Prune them here to keep our cache small.
-          echo "*** Cleaning the 'llvm' directory"
-          rm llvm/lib/{*.a,*.so,*.so.*,*.bc}
-          rm llvm/bin/{flang-*,mlir-*,clang-{scan-deps,check,repl},*-test,llvm-{lto*,reduce,bolt*,exegesis,jitlink},bugpoint,opt,llc}
-          echo "*** Size of the 'llvm' directory"
-          du -hs llvm
-
-      - name: Setup LLVM and Clang paths (Ubuntu)
-        if: steps.filter.outputs.has_code == 'true' && env.os == 'ubuntu'
-        run: |
-          LLVM_PATH=~/llvm
-          echo "Using ${LLVM_PATH}"
-          echo "${LLVM_PATH}/bin" >> $GITHUB_PATH
-          echo '*** ls "${LLVM_PATH}"'
-          ls "${LLVM_PATH}"
-          echo '*** ls "${LLVM_PATH}/bin"'
-          ls "${LLVM_PATH}/bin"
-
-      # Print the various tool paths and versions to help in debugging.
-      - name: Print tool debugging info
-        if: steps.filter.outputs.has_code == 'true'
-        run: |
-          echo '*** PATH'
-          echo $PATH
-          echo '*** bazelisk'
-          which bazelisk
-          bazelisk --version
-          echo '*** run_bazel.py'
-          ./scripts/run_bazel.py --version
-          echo '*** python'
-          which python
-          python --version
-          echo '*** clang'
-          which clang
-          clang --version
-          echo '*** clang++'
-          which clang++
-          clang++ --version
-
       # Disable uploads when the remote cache is read-only.
       # Disable uploads when the remote cache is read-only.
       - name: Set up remote cache access (read-only)
       - name: Set up remote cache access (read-only)
         if:
         if:
@@ -245,63 +85,11 @@ jobs:
           echo "remote_cache_upload=--google_credentials=$HOME/remote_cache_key.json" \
           echo "remote_cache_upload=--google_credentials=$HOME/remote_cache_key.json" \
               >> $GITHUB_ENV
               >> $GITHUB_ENV
 
 
-      # Add our bazel configuration and print basic info to ease debugging.
-      - name: Configure Bazel and print info
+      - uses: ./.github/actions/build-setup-common
         if: steps.filter.outputs.has_code == 'true'
         if: steps.filter.outputs.has_code == 'true'
-        env:
-          # Add a cache version for changes that bazel won't otherwise detect,
-          # like llvm version changes.
-          CACHE_VERSION: 1
-        run: |
-          cat >user.bazelrc <<EOF
-          # Enable remote cache for our CI but minimize downloads.
-          build --remote_cache=https://storage.googleapis.com/carbon-builds-github-v${CACHE_VERSION}
-          build --remote_download_minimal
-
-          # We import a special key into every action in order to key the Bazel
-          # remote cache in a way that avoids collisions between different
-          # runners. Anything that might change the system external to Bazel but
-          # not be fully captured by the sand-boxing of the build should be used
-          # as part of the key. We don't need to use the CPU target for example,
-          # as that is captured by Bazel's configuration of each action. And the
-          # Clang version is incorporated by our Clang toolchain setup. But we
-          # do need to capture any differences between GitHub runner OSes that
-          # don't impact the Bazel configuration to avoid collisions between
-          # those.
-          build --action_env=BAZEL_REMOTE_CACHE_KEY=github-action-${{ matrix.runner }}
-
-          build ${{ env.remote_cache_upload }}
-
-          # Set an artificially high jobs count. This flag controls the number
-          # of concurrency Bazel itself uses, which is essential for actions
-          # that are internally blocked on for example downloading results form
-          # the cache above. Without setting this high, Bazel will pick a small
-          # number based on the available host CPUs and the reality will be a
-          # long chain of largely serialized download events with little or no
-          # usage of the host machine. Fortunately, local actions are
-          # *separately* gated on '--local_*_resources' that will avoid a large
-          # jobs value overwhelming the host. There is a bug to make downloads
-          # behave completely asynchronously and remove the need for this filed
-          # back in 2018 but work seemed to not finish:
-          # https://github.com/bazelbuild/bazel/issues/6394
-          #
-          # There is a new effort (yay!) but until then it seems worth using the
-          # workaround of a high jobs value. The biggest downside (increased
-          # heap usage) seems like it isn't currently a big loss for our builds.
-          #
-          # Higher values like 50 have led to CI failures with network errors
-          # and IOExceptions, see
-          # https://discord.com/channels/655572317891461132/707150492370862090/1151605725576056934
-          build --jobs=32
-
-          # Avoid any cache impact from build stamping in CI.
-          build --nostamp
-
-          # General build options.
-          build --verbose_failures
-          test --test_output=errors
-          EOF
-          ./scripts/run_bazel.py info
+        with:
+          matrix_runner: ${{ matrix.runner }}
+          remote_cache_upload: ${{ env.remote_cache_upload }}
 
 
       # Just for visibility, print space before and after the build.
       # Just for visibility, print space before and after the build.
       - name: Disk space before build
       - name: Disk space before build