ci: Define default shell for all workflows (#47883)

Finn Evers created

GitHub allows defining a default shell for all jobs on the workflow
level, which we did not use before, yet practically did when it comes
down to our usage of `named::bash`. Since this makes stuff quite
verbose, I decided on using the defaults instead so the workflows become
somewhat easier to audit when reading the generated files.

Powershell steps continue to use Powershell, only the default for bash
scripts was modified.


Release Notes:

- N/A

Change summary

.github/workflows/after_release.yml                     |  7 
.github/workflows/autofix_pr.yml                        | 18 --
.github/workflows/bump_patch_version.yml                |  4 
.github/workflows/cherry_pick.yml                       |  4 
.github/workflows/compare_perf.yml                      | 13 -
.github/workflows/danger.yml                            |  5 
.github/workflows/extension_bump.yml                    |  6 
.github/workflows/extension_release.yml                 |  4 
.github/workflows/extension_tests.yml                   | 11 -
.github/workflows/extension_workflow_rollout.yml        | 10 -
.github/workflows/release.yml                           | 48 --------
.github/workflows/release_nightly.yml                   | 28 ----
.github/workflows/run_agent_evals.yml                   | 10 -
.github/workflows/run_bundling.yml                      | 15 --
.github/workflows/run_cron_unit_evals.yml               | 10 -
.github/workflows/run_tests.yml                         | 57 ----------
.github/workflows/run_unit_evals.yml                    | 10 -
extensions/workflows/run_tests.yml                      |  3 
extensions/workflows/shared/bump_version.yml            |  4 
extensions/workflows/shared/release_version.yml         |  3 
tooling/xtask/src/tasks/workflows/bump_patch_version.rs |  1 
tooling/xtask/src/tasks/workflows/run_tests.rs          |  9 -
tooling/xtask/src/tasks/workflows/steps.rs              | 39 +++---
23 files changed, 81 insertions(+), 238 deletions(-)

Detailed changes

.github/workflows/after_release.yml 🔗

@@ -26,14 +26,12 @@ jobs:
     steps:
     - name: after_release::rebuild_releases_page::refresh_cloud_releases
       run: curl -fX POST https://cloud.zed.dev/releases/refresh?expect_tag=${{ github.event.release.tag_name || inputs.tag_name }}
-      shell: bash -euxo pipefail {0}
     - name: steps::checkout_repo
       uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
       with:
         clean: false
     - name: after_release::rebuild_releases_page::redeploy_zed_dev
       run: ./script/redeploy-vercel
-      shell: bash -euxo pipefail {0}
       env:
         VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
   post_to_discord:
@@ -52,7 +50,6 @@ jobs:
         fi
 
         echo "URL=$URL" >> "$GITHUB_OUTPUT"
-      shell: bash -euxo pipefail {0}
     - id: get-content
       name: after_release::post_to_discord::get_content
       uses: 2428392/gh-truncate-string-action@b3ff790d21cf42af3ca7579146eedb93c8fb0757
@@ -137,6 +134,8 @@ jobs:
       run: |
         curl -X POST -H 'Content-type: application/json'\
          --data '{"text":"❌ ${{ github.workflow }} failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}' "$SLACK_WEBHOOK"
-      shell: bash -euxo pipefail {0}
       env:
         SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_WORKFLOW_FAILURES }}
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/autofix_pr.yml 🔗

@@ -23,14 +23,12 @@ jobs:
         clean: false
     - name: autofix_pr::run_autofix::checkout_pr
       run: gh pr checkout ${{ inputs.pr_number }}
-      shell: bash -euxo pipefail {0}
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     - name: steps::setup_cargo_config
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -38,13 +36,10 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_pnpm
       uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2
       with:
@@ -58,21 +53,16 @@ jobs:
     - name: autofix_pr::run_autofix::run_cargo_fix
       if: ${{ inputs.run_clippy }}
       run: cargo fix --workspace --release --all-targets --all-features --allow-dirty --allow-staged
-      shell: bash -euxo pipefail {0}
     - name: autofix_pr::run_autofix::run_cargo_machete_fix
       if: ${{ inputs.run_clippy }}
       run: cargo machete --fix
-      shell: bash -euxo pipefail {0}
     - name: autofix_pr::run_autofix::run_clippy_fix
       if: ${{ inputs.run_clippy }}
       run: cargo clippy --workspace --release --all-targets --all-features --fix --allow-dirty --allow-staged
-      shell: bash -euxo pipefail {0}
     - name: autofix_pr::run_autofix::run_prettier_fix
       run: ./script/prettier --write
-      shell: bash -euxo pipefail {0}
     - name: autofix_pr::run_autofix::run_cargo_fmt
       run: cargo fmt --all
-      shell: bash -euxo pipefail {0}
     - id: create-patch
       name: autofix_pr::run_autofix::create_patch
       run: |
@@ -83,7 +73,6 @@ jobs:
             git diff > autofix.patch
             echo "has_changes=true" >> "$GITHUB_OUTPUT"
         fi
-      shell: bash -euxo pipefail {0}
     - name: upload artifact autofix-patch
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -95,7 +84,6 @@ jobs:
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     outputs:
       has_changes: ${{ steps.create-patch.outputs.has_changes }}
   commit_changes:
@@ -117,7 +105,6 @@ jobs:
         token: ${{ steps.get-app-token.outputs.token }}
     - name: autofix_pr::commit_changes::checkout_pr
       run: gh pr checkout ${{ inputs.pr_number }}
-      shell: bash -euxo pipefail {0}
       env:
         GITHUB_TOKEN: ${{ steps.get-app-token.outputs.token }}
     - name: autofix_pr::download_patch_artifact
@@ -126,12 +113,10 @@ jobs:
         name: autofix-patch
     - name: autofix_pr::commit_changes::apply_patch
       run: git apply autofix.patch
-      shell: bash -euxo pipefail {0}
     - name: autofix_pr::commit_changes::commit_and_push
       run: |
         git commit -am "Autofix"
         git push
-      shell: bash -euxo pipefail {0}
       env:
         GIT_COMMITTER_NAME: Zed Zippy
         GIT_COMMITTER_EMAIL: 234243425+zed-zippy[bot]@users.noreply.github.com
@@ -141,3 +126,6 @@ jobs:
 concurrency:
   group: ${{ github.workflow }}-${{ inputs.pr_number }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/bump_patch_version.yml 🔗

@@ -46,7 +46,6 @@ jobs:
         git commit -am "Bump to $output for @$GITHUB_ACTOR"
         git tag "v${output}${tag_suffix}"
         git push origin HEAD "v${output}${tag_suffix}"
-      shell: bash -euxo pipefail {0}
       env:
         GIT_COMMITTER_NAME: Zed Zippy
         GIT_COMMITTER_EMAIL: 234243425+zed-zippy[bot]@users.noreply.github.com
@@ -56,3 +55,6 @@ jobs:
 concurrency:
   group: ${{ github.workflow }}-${{ inputs.branch }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/cherry_pick.yml 🔗

@@ -37,8 +37,10 @@ jobs:
         private-key: ${{ secrets.ZED_ZIPPY_APP_PRIVATE_KEY }}
     - name: cherry_pick::run_cherry_pick::cherry_pick
       run: ./script/cherry-pick ${{ inputs.branch }} ${{ inputs.commit }} ${{ inputs.channel }}
-      shell: bash -euxo pipefail {0}
       env:
         GIT_COMMITTER_NAME: Zed Zippy
         GIT_COMMITTER_EMAIL: hi@zed.dev
         GITHUB_TOKEN: ${{ steps.get-app-token.outputs.token }}
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/compare_perf.yml 🔗

@@ -28,21 +28,16 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: compare_perf::run_perf::install_hyperfine
       uses: taiki-e/install-action@hyperfine
     - name: steps::git_checkout
       run: git fetch origin ${{ inputs.base }} && git checkout ${{ inputs.base }}
-      shell: bash -euxo pipefail {0}
     - name: compare_perf::run_perf::cargo_perf_test
       run: |2-
 
@@ -51,10 +46,8 @@ jobs:
                     else
                         cargo perf-test -p vim -- --json=${{ inputs.base }};
                     fi
-      shell: bash -euxo pipefail {0}
     - name: steps::git_checkout
       run: git fetch origin ${{ inputs.head }} && git checkout ${{ inputs.head }}
-      shell: bash -euxo pipefail {0}
     - name: compare_perf::run_perf::cargo_perf_test
       run: |2-
 
@@ -63,10 +56,8 @@ jobs:
                     else
                         cargo perf-test -p vim -- --json=${{ inputs.head }};
                     fi
-      shell: bash -euxo pipefail {0}
     - name: compare_perf::run_perf::compare_runs
       run: cargo perf-compare --save=results.md ${{ inputs.base }} ${{ inputs.head }}
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact results.md'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -77,4 +68,6 @@ jobs:
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/danger.yml 🔗

@@ -31,10 +31,11 @@ jobs:
         cache-dependency-path: script/danger/pnpm-lock.yaml
     - name: danger::danger_job::install_deps
       run: pnpm install --dir script/danger
-      shell: bash -euxo pipefail {0}
     - name: danger::danger_job::run
       run: pnpm run --dir script/danger danger ci
-      shell: bash -euxo pipefail {0}
       env:
         GITHUB_TOKEN: not_a_real_token
         DANGER_GITHUB_API_BASE_URL: https://danger-proxy.zed.dev/github
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/extension_bump.yml 🔗

@@ -55,7 +55,6 @@ jobs:
           echo "needs_bump=false" >> "$GITHUB_OUTPUT"
 
         echo "current_version=${CURRENT_VERSION}" >> "$GITHUB_OUTPUT"
-      shell: bash -euxo pipefail {0}
     outputs:
       needs_bump: ${{ steps.compare-versions-check.outputs.needs_bump }}
       current_version: ${{ steps.compare-versions-check.outputs.current_version }}
@@ -80,7 +79,6 @@ jobs:
         clean: false
     - name: extension_bump::install_bump_2_version
       run: pip install bump2version --break-system-packages
-      shell: bash -euxo pipefail {0}
     - id: bump-version
       name: extension_bump::bump_version
       run: |
@@ -104,7 +102,6 @@ jobs:
         NEW_VERSION="$(sed -n 's/version = \"\(.*\)\"/\1/p' < extension.toml)"
 
         echo "new_version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
-      shell: bash -euxo pipefail {0}
     - name: extension_bump::create_pull_request
       uses: peter-evans/create-pull-request@v7
       with:
@@ -150,3 +147,6 @@ jobs:
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/extension_release.yml 🔗

@@ -33,7 +33,6 @@ jobs:
         EXTENSION_ID="$(sed -n 's/id = \"\(.*\)\"/\1/p' < extension.toml)"
 
         echo "extension_id=${EXTENSION_ID}" >> "$GITHUB_OUTPUT"
-      shell: bash -euxo pipefail {0}
     - name: extension_release::release_action
       uses: huacnlee/zed-extension-action@v2
       with:
@@ -41,3 +40,6 @@ jobs:
         push-to: zed-industries/extensions
       env:
         COMMITTER_TOKEN: ${{ steps.generate-token.outputs.token }}
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/extension_tests.yml 🔗

@@ -45,7 +45,6 @@ jobs:
 
         check_pattern "check_rust" '^(Cargo.lock|Cargo.toml|.*\.rs)$' -qP
         check_pattern "check_extension" '^.*\.scm$' -qP
-      shell: bash -euxo pipefail {0}
     outputs:
       check_rust: ${{ steps.filter.outputs.check_rust }}
       check_extension: ${{ steps.filter.outputs.check_extension }}
@@ -66,18 +65,14 @@ jobs:
         path: ~/.rustup
     - name: extension_tests::install_rust_target
       run: rustup target add wasm32-wasip2
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_fmt
       run: cargo fmt --all -- --check
-      shell: bash -euxo pipefail {0}
     - name: extension_tests::run_clippy
       run: cargo clippy --release --all-targets --all-features -- --deny warnings
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_install_nextest
       uses: taiki-e/install-action@nextest
     - name: steps::cargo_nextest
       run: 'cargo nextest run --workspace --no-fail-fast --target "$(rustc -vV | sed -n ''s|host: ||p'')"'
-      shell: bash -euxo pipefail {0}
       env:
         NEXTEST_NO_TESTS: warn
     timeout-minutes: 6
@@ -102,13 +97,11 @@ jobs:
       run: |
         wget --quiet "https://zed-extension-cli.nyc3.digitaloceanspaces.com/$ZED_EXTENSION_CLI_SHA/x86_64-unknown-linux-gnu/zed-extension"
         chmod +x zed-extension
-      shell: bash -euxo pipefail {0}
     - name: extension_tests::check
       run: |
         mkdir -p /tmp/ext-scratch
         mkdir -p /tmp/ext-output
         ./zed-extension --source-dir . --scratch-dir /tmp/ext-scratch --output-dir /tmp/ext-output
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 4
   tests_pass:
     needs:
@@ -133,7 +126,9 @@ jobs:
         check_result "check_extension" "${{ needs.check_extension.result }}"
 
         exit $EXIT_CODE
-      shell: bash -euxo pipefail {0}
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/extension_workflow_rollout.yml 🔗

@@ -75,7 +75,6 @@ jobs:
         fi
         echo "Found previous rollout at commit: $PREV_COMMIT"
         echo "prev_commit=$PREV_COMMIT" >> "$GITHUB_OUTPUT"
-      shell: bash -euxo pipefail {0}
       working-directory: zed
     - id: calc-changes
       name: extension_workflow_rollout::rollout_workflows_to_extension::get_removed_files
@@ -101,7 +100,6 @@ jobs:
 
         echo "Files to remove: $REMOVED_FILES"
         echo "removed_files=$REMOVED_FILES" >> "$GITHUB_OUTPUT"
-      shell: bash -euxo pipefail {0}
       working-directory: zed
     - name: extension_workflow_rollout::rollout_workflows_to_extension::sync_workflow_files
       run: |
@@ -125,12 +123,10 @@ jobs:
         else
             cp zed/extensions/workflows/shared/*.yml extension/.github/workflows/
         fi
-      shell: bash -euxo pipefail {0}
     - id: short-sha
       name: extension_workflow_rollout::rollout_workflows_to_extension::get_short_sha
       run: |
         echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
-      shell: bash -euxo pipefail {0}
       working-directory: zed
     - id: create-pr
       name: extension_workflow_rollout::rollout_workflows_to_extension::create_pull_request
@@ -156,7 +152,6 @@ jobs:
             cd extension
             gh pr merge "$PR_NUMBER" --auto --squash
         fi
-      shell: bash -euxo pipefail {0}
       env:
         GH_TOKEN: ${{ steps.generate-token.outputs.token }}
     timeout-minutes: 10
@@ -182,7 +177,6 @@ jobs:
       run: |
         git config user.name "zed-zippy[bot]"
         git config user.email "234243425+zed-zippy[bot]@users.noreply.github.com"
-      shell: bash -euxo pipefail {0}
     - name: extension_workflow_rollout::create_rollout_tag::update_rollout_tag
       run: |
         if git rev-parse "extension-workflows" >/dev/null 2>&1; then
@@ -193,5 +187,7 @@ jobs:
         echo "Creating new tag 'extension-workflows' at $(git rev-parse --short HEAD)"
         git tag "extension-workflows"
         git push origin "extension-workflows"
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 1
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/release.yml 🔗

@@ -21,7 +21,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -35,15 +34,12 @@ jobs:
       uses: taiki-e/install-action@nextest
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 300
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_nextest
       run: cargo nextest run --workspace --no-fail-fast
-      shell: bash -euxo pipefail {0}
     - name: steps::cleanup_cargo_config
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   run_tests_linux:
     if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
@@ -57,7 +53,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -65,13 +60,10 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_node
       uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
       with:
@@ -80,15 +72,12 @@ jobs:
       uses: taiki-e/install-action@nextest
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 250
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_nextest
       run: cargo nextest run --workspace --no-fail-fast
-      shell: bash -euxo pipefail {0}
     - name: steps::cleanup_cargo_config
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
     services:
       postgres:
@@ -139,7 +128,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -147,7 +135,6 @@ jobs:
         path: ~/.rustup
     - name: steps::clippy
       run: ./script/clippy
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   clippy_linux:
     if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
@@ -161,7 +148,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -169,16 +155,12 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::clippy
       run: ./script/clippy
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   clippy_windows:
     if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
@@ -207,15 +189,12 @@ jobs:
         clean: false
     - name: run_tests::check_scripts::run_shellcheck
       run: ./script/shellcheck-scripts error
-      shell: bash -euxo pipefail {0}
     - id: get_actionlint
       name: run_tests::check_scripts::download_actionlint
       run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_scripts::run_actionlint
       run: |
         ${{ steps.get_actionlint.outputs.executable }} -color
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_scripts::check_xtask_workflows
       run: |
         cargo xtask workflows
@@ -224,7 +203,6 @@ jobs:
           echo "Please run 'cargo xtask workflows' locally and commit the changes"
           exit 1
         fi
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   create_draft_release:
     if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
@@ -238,16 +216,12 @@ jobs:
         ref: ${{ github.ref }}
     - name: script/determine-release-channel
       run: script/determine-release-channel
-      shell: bash -euxo pipefail {0}
     - name: mkdir -p target/
       run: mkdir -p target/
-      shell: bash -euxo pipefail {0}
     - name: release::create_draft_release::generate_release_notes
       run: node --redirect-warnings=/dev/null ./script/draft-release-notes "$RELEASE_VERSION" "$RELEASE_CHANNEL" > target/release-notes.md
-      shell: bash -euxo pipefail {0}
     - name: release::create_draft_release::create_release
       run: script/create-draft-release target/release-notes.md
-      shell: bash -euxo pipefail {0}
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     timeout-minutes: 60
@@ -272,16 +246,12 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: ./script/bundle-linux
       run: ./script/bundle-linux
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact zed-linux-aarch64.tar.gz'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -316,16 +286,12 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: ./script/bundle-linux
       run: ./script/bundle-linux
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact zed-linux-x86_64.tar.gz'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -369,10 +335,8 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 300
-      shell: bash -euxo pipefail {0}
     - name: run_bundling::bundle_mac::bundle_mac
       run: ./script/bundle-mac aarch64-apple-darwin
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact Zed-aarch64.dmg'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -416,10 +380,8 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 300
-      shell: bash -euxo pipefail {0}
     - name: run_bundling::bundle_mac::bundle_mac
       run: ./script/bundle-mac x86_64-apple-darwin
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact Zed-x86_64.dmg'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -540,7 +502,6 @@ jobs:
         path: ./artifacts/
     - name: ls -lR ./artifacts
       run: ls -lR ./artifacts
-      shell: bash -euxo pipefail {0}
     - name: release::prep_release_artifacts
       run: |-
         mkdir -p release-artifacts/
@@ -557,10 +518,8 @@ jobs:
         mv ./artifacts/zed-remote-server-linux-x86_64.gz/zed-remote-server-linux-x86_64.gz release-artifacts/zed-remote-server-linux-x86_64.gz
         mv ./artifacts/zed-remote-server-windows-aarch64.zip/zed-remote-server-windows-aarch64.zip release-artifacts/zed-remote-server-windows-aarch64.zip
         mv ./artifacts/zed-remote-server-windows-x86_64.zip/zed-remote-server-windows-x86_64.zip release-artifacts/zed-remote-server-windows-x86_64.zip
-      shell: bash -euxo pipefail {0}
     - name: gh release upload "$GITHUB_REF_NAME" --repo=zed-industries/zed release-artifacts/*
       run: gh release upload "$GITHUB_REF_NAME" --repo=zed-industries/zed release-artifacts/*
-      shell: bash -euxo pipefail {0}
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
   validate_release_assets:
@@ -584,7 +543,6 @@ jobs:
         fi
 
         echo "All expected assets are present in the release."
-      shell: bash -euxo pipefail {0}
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
   auto_release_preview:
@@ -601,7 +559,6 @@ jobs:
         private-key: ${{ secrets.ZED_ZIPPY_APP_PRIVATE_KEY }}
     - name: gh release edit "$GITHUB_REF_NAME" --repo=zed-industries/zed --draft=false
       run: gh release edit "$GITHUB_REF_NAME" --repo=zed-industries/zed --draft=false
-      shell: bash -euxo pipefail {0}
       env:
         GITHUB_TOKEN: ${{ steps.get-app-token.outputs.token }}
   push_release_update_notification:
@@ -641,16 +598,17 @@ jobs:
         fi
         )
         echo "message=$MESSAGE" >> "$GITHUB_OUTPUT"
-      shell: bash -euxo pipefail {0}
       env:
         GH_TOKEN: ${{ github.token }}
     - name: release::send_slack_message
       run: |
         curl -X POST -H 'Content-type: application/json'\
          --data '{"text":"${{ steps.generate-webhook-message.outputs.message }}"}' "$SLACK_WEBHOOK"
-      shell: bash -euxo pipefail {0}
       env:
         SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_WORKFLOW_FAILURES }}
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/release_nightly.yml 🔗

@@ -22,10 +22,8 @@ jobs:
         fetch-depth: 0
     - name: steps::cargo_fmt
       run: cargo fmt --all -- --check
-      shell: bash -euxo pipefail {0}
     - name: ./script/clippy
       run: ./script/clippy
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   run_tests_windows:
     if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
@@ -94,23 +92,18 @@ jobs:
         version=$(git rev-parse --short HEAD)
         echo "Publishing version: ${version} on release channel nightly"
         echo "nightly" > crates/zed/RELEASE_CHANNEL
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_sentry
       uses: matbour/setup-sentry-cli@3e938c54b3018bdd019973689ef984e033b0454b
       with:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: ./script/bundle-linux
       run: ./script/bundle-linux
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact zed-linux-aarch64.tar.gz'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -145,23 +138,18 @@ jobs:
         version=$(git rev-parse --short HEAD)
         echo "Publishing version: ${version} on release channel nightly"
         echo "nightly" > crates/zed/RELEASE_CHANNEL
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_sentry
       uses: matbour/setup-sentry-cli@3e938c54b3018bdd019973689ef984e033b0454b
       with:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: ./script/bundle-linux
       run: ./script/bundle-linux
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact zed-linux-x86_64.tar.gz'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -201,7 +189,6 @@ jobs:
         version=$(git rev-parse --short HEAD)
         echo "Publishing version: ${version} on release channel nightly"
         echo "nightly" > crates/zed/RELEASE_CHANNEL
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_node
       uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
       with:
@@ -212,10 +199,8 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 300
-      shell: bash -euxo pipefail {0}
     - name: run_bundling::bundle_mac::bundle_mac
       run: ./script/bundle-mac aarch64-apple-darwin
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact Zed-aarch64.dmg'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -255,7 +240,6 @@ jobs:
         version=$(git rev-parse --short HEAD)
         echo "Publishing version: ${version} on release channel nightly"
         echo "nightly" > crates/zed/RELEASE_CHANNEL
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_node
       uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
       with:
@@ -266,10 +250,8 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 300
-      shell: bash -euxo pipefail {0}
     - name: run_bundling::bundle_mac::bundle_mac
       run: ./script/bundle-mac x86_64-apple-darwin
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact Zed-x86_64.dmg'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -417,7 +399,6 @@ jobs:
         cachixArgs: -v
     - name: nix_build::build_nix::build
       run: nix build .#default -L --accept-flake-config
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
     continue-on-error: true
   build_nix_mac_aarch64:
@@ -448,7 +429,6 @@ jobs:
         cachixArgs: -v
     - name: nix_build::build_nix::build
       run: nix build .#default -L --accept-flake-config
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
     continue-on-error: true
   update_nightly_tag:
@@ -473,7 +453,6 @@ jobs:
         path: ./artifacts/
     - name: ls -lR ./artifacts
       run: ls -lR ./artifacts
-      shell: bash -euxo pipefail {0}
     - name: release::prep_release_artifacts
       run: |-
         mkdir -p release-artifacts/
@@ -490,10 +469,8 @@ jobs:
         mv ./artifacts/zed-remote-server-linux-x86_64.gz/zed-remote-server-linux-x86_64.gz release-artifacts/zed-remote-server-linux-x86_64.gz
         mv ./artifacts/zed-remote-server-windows-aarch64.zip/zed-remote-server-windows-aarch64.zip release-artifacts/zed-remote-server-windows-aarch64.zip
         mv ./artifacts/zed-remote-server-windows-x86_64.zip/zed-remote-server-windows-x86_64.zip release-artifacts/zed-remote-server-windows-x86_64.zip
-      shell: bash -euxo pipefail {0}
     - name: ./script/upload-nightly
       run: ./script/upload-nightly
-      shell: bash -euxo pipefail {0}
       env:
         DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
         DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
@@ -507,7 +484,6 @@ jobs:
         git config user.email github-actions@github.com
         git tag -f nightly
         git push origin nightly --force
-      shell: bash -euxo pipefail {0}
     - name: release::create_sentry_release
       uses: getsentry/action-release@526942b68292201ac6bbb99b9a0747d4abee354c
       with:
@@ -532,6 +508,8 @@ jobs:
       run: |
         curl -X POST -H 'Content-type: application/json'\
          --data '{"text":"❌ ${{ github.workflow }} failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}' "$SLACK_WEBHOOK"
-      shell: bash -euxo pipefail {0}
       env:
         SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_WORKFLOW_FAILURES }}
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/run_agent_evals.yml 🔗

@@ -34,24 +34,18 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_cargo_config
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: cargo build --package=eval
       run: cargo build --package=eval
-      shell: bash -euxo pipefail {0}
     - name: run_agent_evals::agent_evals::run_eval
       run: cargo run --package=eval -- --repetitions=8 --concurrency=1 --model "${MODEL_NAME}"
-      shell: bash -euxo pipefail {0}
       env:
         ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
         OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
@@ -61,8 +55,10 @@ jobs:
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 600
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/run_bundling.yml 🔗

@@ -30,16 +30,12 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: ./script/bundle-linux
       run: ./script/bundle-linux
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact zed-linux-aarch64.tar.gz'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -73,16 +69,12 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: ./script/bundle-linux
       run: ./script/bundle-linux
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact zed-linux-x86_64.tar.gz'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -125,10 +117,8 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 300
-      shell: bash -euxo pipefail {0}
     - name: run_bundling::bundle_mac::bundle_mac
       run: ./script/bundle-mac aarch64-apple-darwin
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact Zed-aarch64.dmg'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -171,10 +161,8 @@ jobs:
         token: ${{ secrets.SENTRY_AUTH_TOKEN }}
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 300
-      shell: bash -euxo pipefail {0}
     - name: run_bundling::bundle_mac::bundle_mac
       run: ./script/bundle-mac x86_64-apple-darwin
-      shell: bash -euxo pipefail {0}
     - name: '@actions/upload-artifact Zed-x86_64.dmg'
       uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
@@ -279,3 +267,6 @@ jobs:
 concurrency:
   group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/run_cron_unit_evals.yml 🔗

@@ -28,7 +28,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -36,21 +35,16 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_install_nextest
       uses: taiki-e/install-action@nextest
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 250
-      shell: bash -euxo pipefail {0}
     - name: ./script/run-unit-evals
       run: ./script/run-unit-evals
-      shell: bash -euxo pipefail {0}
       env:
         ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
         OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
@@ -61,7 +55,6 @@ jobs:
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     - name: run_agent_evals::cron_unit_evals::send_failure_to_slack
       if: ${{ failure() }}
       uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52
@@ -74,3 +67,6 @@ jobs:
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/run_tests.yml 🔗

@@ -51,7 +51,6 @@ jobs:
         check_pattern "run_licenses" '^(Cargo.lock|script/.*licenses)' -qP
         check_pattern "run_nix" '^(nix/|flake\.|Cargo\.|rust-toolchain.toml|\.cargo/config.toml)' -qP
         check_pattern "run_tests" '^(docs/|script/update_top_ranking_issues/|\.github/(ISSUE_TEMPLATE|workflows/(?!run_tests)))' -qvP
-      shell: bash -euxo pipefail {0}
     outputs:
       run_action_checks: ${{ steps.filter.outputs.run_action_checks }}
       run_docs: ${{ steps.filter.outputs.run_docs }}
@@ -77,16 +76,12 @@ jobs:
         version: '9'
     - name: steps::prettier
       run: ./script/prettier
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_fmt
       run: cargo fmt --all -- --check
-      shell: bash -euxo pipefail {0}
     - name: ./script/check-todos
       run: ./script/check-todos
-      shell: bash -euxo pipefail {0}
     - name: ./script/check-keymaps
       run: ./script/check-keymaps
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_style::check_for_typos
       uses: crate-ci/typos@2d0ce569feab1f8752f1dde43cc2f2aa53236e06
       with:
@@ -125,7 +120,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -133,16 +127,12 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::clippy
       run: ./script/clippy
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   clippy_mac:
     needs:
@@ -158,7 +148,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -166,7 +155,6 @@ jobs:
         path: ~/.rustup
     - name: steps::clippy
       run: ./script/clippy
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   run_tests_windows:
     needs:
@@ -213,7 +201,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -221,13 +208,10 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_node
       uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
       with:
@@ -236,15 +220,12 @@ jobs:
       uses: taiki-e/install-action@nextest
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 250
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_nextest
       run: cargo nextest run --workspace --no-fail-fast
-      shell: bash -euxo pipefail {0}
     - name: steps::cleanup_cargo_config
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
     services:
       postgres:
@@ -268,7 +249,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -282,15 +262,12 @@ jobs:
       uses: taiki-e/install-action@nextest
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 300
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_nextest
       run: cargo nextest run --workspace --no-fail-fast
-      shell: bash -euxo pipefail {0}
     - name: steps::cleanup_cargo_config
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   doctests:
     needs:
@@ -309,28 +286,22 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::setup_cargo_config
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - id: run_doctests
       name: run_tests::doctests::run_doctests
       run: |
         cargo test --workspace --doc --no-fail-fast
-      shell: bash -euxo pipefail {0}
     - name: steps::cleanup_cargo_config
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   check_workspace_binaries:
     needs:
@@ -346,7 +317,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -354,24 +324,18 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: cargo build -p collab
       run: cargo build -p collab
-      shell: bash -euxo pipefail {0}
     - name: cargo build --workspace --bins --examples
       run: cargo build --workspace --bins --examples
-      shell: bash -euxo pipefail {0}
     - name: steps::cleanup_cargo_config
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   check_dependencies:
     needs:
@@ -399,7 +363,6 @@ jobs:
         command: machete
     - name: run_tests::check_dependencies::check_cargo_lock
       run: cargo update --locked --workspace
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_dependencies::check_vulnerable_dependencies
       if: github.event_name == 'pull_request'
       uses: actions/dependency-review-action@67d4f4bd7a9b17a0db54d2a7519187c65e339de8
@@ -420,7 +383,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -434,16 +396,12 @@ jobs:
         jobSummary: false
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: ./script/generate-action-metadata
       run: ./script/generate-action-metadata
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_docs::install_mdbook
       uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08
       with:
@@ -452,7 +410,6 @@ jobs:
       run: |
         mkdir -p target/deploy
         mdbook build ./docs --dest-dir=../target/deploy/docs/
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_docs::lychee_link_check
       uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332
       with:
@@ -477,10 +434,8 @@ jobs:
         path: ~/.rustup
     - name: ./script/check-licenses
       run: ./script/check-licenses
-      shell: bash -euxo pipefail {0}
     - name: ./script/generate-licenses
       run: ./script/generate-licenses
-      shell: bash -euxo pipefail {0}
   check_scripts:
     needs:
     - orchestrate
@@ -493,15 +448,12 @@ jobs:
         clean: false
     - name: run_tests::check_scripts::run_shellcheck
       run: ./script/shellcheck-scripts error
-      shell: bash -euxo pipefail {0}
     - id: get_actionlint
       name: run_tests::check_scripts::download_actionlint
       run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_scripts::run_actionlint
       run: |
         ${{ steps.get_actionlint.outputs.executable }} -color
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_scripts::check_xtask_workflows
       run: |
         cargo xtask workflows
@@ -510,7 +462,6 @@ jobs:
           echo "Please run 'cargo xtask workflows' locally and commit the changes"
           exit 1
         fi
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
   build_nix_linux_x86_64:
     needs:
@@ -540,7 +491,6 @@ jobs:
         pushFilter: -zed-editor-[0-9.]*-nightly
     - name: nix_build::build_nix::build
       run: nix build .#debug -L --accept-flake-config
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
     continue-on-error: true
   build_nix_mac_aarch64:
@@ -571,7 +521,6 @@ jobs:
         pushFilter: -zed-editor-[0-9.]*-nightly
     - name: nix_build::build_nix::build
       run: nix build .#debug -L --accept-flake-config
-      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
     continue-on-error: true
   check_postgres_and_protobuf_migrations:
@@ -591,7 +540,6 @@ jobs:
         fetch-depth: 0
     - name: run_tests::check_postgres_and_protobuf_migrations::remove_untracked_files
       run: git clean -df
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_postgres_and_protobuf_migrations::ensure_fresh_merge
       run: |
         if [ -z "$GITHUB_BASE_REF" ];
@@ -602,7 +550,6 @@ jobs:
           git merge -q "origin/$GITHUB_BASE_REF" -m "merge main into temp"
           echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> "$GITHUB_ENV"
         fi
-      shell: bash -euxo pipefail {0}
     - name: run_tests::check_postgres_and_protobuf_migrations::bufbuild_setup_action
       uses: bufbuild/buf-setup-action@v1
       with:
@@ -663,7 +610,9 @@ jobs:
         check_result "build_nix_mac_aarch64" "${{ needs.build_nix_mac_aarch64.result }}"
 
         exit $EXIT_CODE
-      shell: bash -euxo pipefail {0}
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/run_unit_evals.yml 🔗

@@ -31,7 +31,6 @@ jobs:
       run: |
         mkdir -p ./../.cargo
         cp ./.cargo/ci-config.toml ./../.cargo/config.toml
-      shell: bash -euxo pipefail {0}
     - name: steps::cache_rust_dependencies_namespace
       uses: namespacelabs/nscloud-cache-action@v1
       with:
@@ -39,21 +38,16 @@ jobs:
         path: ~/.rustup
     - name: steps::setup_linux
       run: ./script/linux
-      shell: bash -euxo pipefail {0}
     - name: steps::install_mold
       run: ./script/install-mold
-      shell: bash -euxo pipefail {0}
     - name: steps::download_wasi_sdk
       run: ./script/download-wasi-sdk
-      shell: bash -euxo pipefail {0}
     - name: steps::cargo_install_nextest
       uses: taiki-e/install-action@nextest
     - name: steps::clear_target_dir_if_large
       run: ./script/clear-target-dir-if-larger-than 250
-      shell: bash -euxo pipefail {0}
     - name: ./script/run-unit-evals
       run: ./script/run-unit-evals
-      shell: bash -euxo pipefail {0}
       env:
         ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
         OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
@@ -64,7 +58,9 @@ jobs:
       if: always()
       run: |
         rm -rf ./../.cargo
-      shell: bash -euxo pipefail {0}
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.run_id }}
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

extensions/workflows/run_tests.yml 🔗

@@ -16,3 +16,6 @@ jobs:
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}pr
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

extensions/workflows/shared/bump_version.yml 🔗

@@ -28,7 +28,6 @@ jobs:
             bump_type="patch"
         fi
         echo "bump_type=$bump_type" >> $GITHUB_OUTPUT
-      shell: bash -euxo pipefail {0}
       env:
         HAS_MAJOR_LABEL: |-
           ${{ (github.event.action == 'labeled' && github.event.label.name == 'major') ||
@@ -57,3 +56,6 @@ jobs:
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}labels
   cancel-in-progress: true
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

tooling/xtask/src/tasks/workflows/bump_patch_version.rs 🔗

@@ -48,7 +48,6 @@ fn run_bump_patch_version(branch: &WorkflowInput) -> steps::NamedJob {
             git tag "v${output}${tag_suffix}"
             git push origin HEAD "v${output}${tag_suffix}"
         "#})
-        .shell(steps::BASH_SHELL)
         .add_env(("GIT_COMMITTER_NAME", "Zed Zippy"))
         .add_env((
             "GIT_COMMITTER_EMAIL",

tooling/xtask/src/tasks/workflows/run_tests.rs 🔗

@@ -7,7 +7,7 @@ use indexmap::IndexMap;
 use crate::tasks::workflows::{
     nix_build::build_nix,
     runners::Arch,
-    steps::{BASH_SHELL, CommonJobConditions, repository_owner_guard_expression},
+    steps::{CommonJobConditions, repository_owner_guard_expression},
     vars::{self, PathCondition},
 };
 
@@ -175,12 +175,7 @@ pub fn orchestrate(rules: &[&PathCondition]) -> NamedJob {
             "fetch-depth",
             "${{ github.ref == 'refs/heads/main' && 2 || 350 }}",
         )))
-        .add_step(
-            Step::new(step_name.clone())
-                .run(script)
-                .id(step_name)
-                .shell(BASH_SHELL),
-        );
+        .add_step(Step::new(step_name.clone()).run(script).id(step_name));
 
     NamedJob { name, job }
 }

tooling/xtask/src/tasks/workflows/steps.rs 🔗

@@ -2,7 +2,7 @@ use gh_workflow::*;
 
 use crate::tasks::workflows::{runners::Platform, vars, vars::StepOutput};
 
-pub const BASH_SHELL: &str = "bash -euxo pipefail {0}";
+const BASH_SHELL: &str = "bash -euxo pipefail {0}";
 // https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstepsshell
 pub const PWSH_SHELL: &str = "pwsh";
 
@@ -160,7 +160,7 @@ pub fn script(name: &str) -> Step<Run> {
     if name.ends_with(".ps1") {
         Step::new(name).run(name).shell(PWSH_SHELL)
     } else {
-        Step::new(name).run(name).shell(BASH_SHELL)
+        Step::new(name).run(name)
     }
 }
 
@@ -290,9 +290,7 @@ pub mod named {
     /// (You shouldn't inline this function into the workflow definition, you must
     /// wrap it in a new function.)
     pub fn bash(script: impl AsRef<str>) -> Step<Run> {
-        Step::new(function_name(1))
-            .run(script.as_ref())
-            .shell(BASH_SHELL)
+        Step::new(function_name(1)).run(script.as_ref())
     }
 
     /// Returns a pwsh-script step with the same name as the enclosing function.
@@ -308,25 +306,26 @@ pub mod named {
     pub fn run(platform: Platform, script: &str) -> Step<Run> {
         match platform {
             Platform::Windows => Step::new(function_name(1)).run(script).shell(PWSH_SHELL),
-            Platform::Linux | Platform::Mac => {
-                Step::new(function_name(1)).run(script).shell(BASH_SHELL)
-            }
+            Platform::Linux | Platform::Mac => Step::new(function_name(1)).run(script),
         }
     }
 
-    /// Returns a Workflow with the same name as the enclosing module.
+    /// Returns a Workflow with the same name as the enclosing module with default
+    /// set for the running shell.
     pub fn workflow() -> Workflow {
-        Workflow::default().name(
-            named::function_name(1)
-                .split("::")
-                .collect::<Vec<_>>()
-                .into_iter()
-                .rev()
-                .skip(1)
-                .rev()
-                .collect::<Vec<_>>()
-                .join("::"),
-        )
+        Workflow::default()
+            .name(
+                named::function_name(1)
+                    .split("::")
+                    .collect::<Vec<_>>()
+                    .into_iter()
+                    .rev()
+                    .skip(1)
+                    .rev()
+                    .collect::<Vec<_>>()
+                    .join("::"),
+            )
+            .defaults(Defaults::default().run(RunDefaults::default().shell(BASH_SHELL)))
     }
 
     /// Returns a Job with the same name as the enclosing function.