From 70bde54a2c861310eeb005e177019c96947dff09 Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Fri, 18 Jul 2025 15:15:07 -0400 Subject: [PATCH] ci: Lint GitHub Actions workflows with actionlint (#34729) Added [rhysd/actionlint](https://github.com/rhysd/actionlint/) a static checker for GitHub Actions workflow files. Install locally with `brew install actionlint` the run with `actionlint`. Inspired by: https://github.com/zed-industries/zed/pull/34704 which yielded this observation: > In github actions: > 1. strings are truthy > 2. `${{ }}` will become a string if it doesn't wrap the whole value. > > So `if: false && true` becomes `false` > and `if: ${{ false && true }}` becomes `false` > but `if: false && ${{ true }}` becomes `"false && true"` which evaluates true > The reason you sometimes need `${{ }}` is because YAML doesn't like `!` > so `if: !false` is invalid yaml > and `if: ${{ !false }}` works just fine. Changes: - Add `actionlint` job - Refactor `job_spec` job to be more readable - Fix all `actionlint` and `shellcheck` errors in Actions workflows (62 in all) - Add `self-mini-macos` and `self-32vcpu-windows-2022` labels to self-hosted runners. Not strictly related, but useful if you need to take a runner out of the rotation (since `macOS`, `self-hosted`, and `ARM64` are auto-set and cannot be added/removed). - Change ci.yml macos_relase to target `self-mini-macos` instead of `bundle` which was previously deprecated. This would've caught the error fixed in https://github.com/zed-industries/zed/pull/34704. Here's what that [job failure](https://github.com/zed-industries/zed/actions/runs/16376993944/job/46279281842?pr=34729) would've looked like. Release Notes: - N/A --- .github/actionlint.yml | 30 ++++++ .github/workflows/bump_patch_version.yml | 8 +- .github/workflows/ci.yml | 100 +++++++++++------- .../workflows/community_release_actions.yml | 6 +- .github/workflows/deploy_collab.yml | 9 +- .github/workflows/eval.yml | 2 +- .github/workflows/nix.yml | 10 +- .github/workflows/release_nightly.yml | 5 +- .github/workflows/unit_evals.yml | 2 +- 9 files changed, 111 insertions(+), 61 deletions(-) create mode 100644 .github/actionlint.yml diff --git a/.github/actionlint.yml b/.github/actionlint.yml new file mode 100644 index 0000000000..d93ec5b15e --- /dev/null +++ b/.github/actionlint.yml @@ -0,0 +1,30 @@ +# Configuration related to self-hosted runner. +self-hosted-runner: + # Labels of self-hosted runner in array of strings. + labels: + # GitHub-hosted Runners + - github-8vcpu-ubuntu-2404 + - github-16vcpu-ubuntu-2404 + - windows-2025-16 + - windows-2025-32 + - windows-2025-64 + # Buildjet Ubuntu 20.04 - AMD x86_64 + - buildjet-2vcpu-ubuntu-2004 + - buildjet-4vcpu-ubuntu-2004 + - buildjet-8vcpu-ubuntu-2004 + - buildjet-16vcpu-ubuntu-2004 + - buildjet-32vcpu-ubuntu-2004 + # Buildjet Ubuntu 22.04 - AMD x86_64 + - buildjet-2vcpu-ubuntu-2204 + - buildjet-4vcpu-ubuntu-2204 + - buildjet-8vcpu-ubuntu-2204 + - buildjet-16vcpu-ubuntu-2204 + - buildjet-32vcpu-ubuntu-2204 + # Buildjet Ubuntu 22.04 - Graviton aarch64 + - buildjet-8vcpu-ubuntu-2204-arm + - buildjet-16vcpu-ubuntu-2204-arm + - buildjet-32vcpu-ubuntu-2204-arm + - buildjet-64vcpu-ubuntu-2204-arm + # Self Hosted Runners + - self-mini-macos + - self-32vcpu-windows-2022 diff --git a/.github/workflows/bump_patch_version.yml b/.github/workflows/bump_patch_version.yml index 02857a9151..8a48ff96f1 100644 --- a/.github/workflows/bump_patch_version.yml +++ b/.github/workflows/bump_patch_version.yml @@ -28,7 +28,7 @@ jobs: run: | set -eux - channel=$(cat crates/zed/RELEASE_CHANNEL) + channel="$(cat crates/zed/RELEASE_CHANNEL)" tag_suffix="" case $channel in @@ -43,9 +43,9 @@ jobs: ;; esac which cargo-set-version > /dev/null || cargo install cargo-edit - output=$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //') + output="$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')" export GIT_COMMITTER_NAME="Zed Bot" export GIT_COMMITTER_EMAIL="hi@zed.dev" git commit -am "Bump to $output for @$GITHUB_ACTOR" --author "Zed Bot " - git tag v${output}${tag_suffix} - git push origin HEAD v${output}${tag_suffix} + git tag "v${output}${tag_suffix}" + git push origin HEAD "v${output}${tag_suffix}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6987022f7a..a4da5e99ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,7 @@ jobs: run_license: ${{ steps.filter.outputs.run_license }} run_docs: ${{ steps.filter.outputs.run_docs }} run_nix: ${{ steps.filter.outputs.run_nix }} + run_actionlint: ${{ steps.filter.outputs.run_actionlint }} runs-on: - ubuntu-latest steps: @@ -47,39 +48,40 @@ jobs: run: | if [ -z "$GITHUB_BASE_REF" ]; then echo "Not in a PR context (i.e., push to main/stable/preview)" - COMPARE_REV=$(git rev-parse HEAD~1) + COMPARE_REV="$(git rev-parse HEAD~1)" else echo "In a PR context comparing to pull_request.base.ref" git fetch origin "$GITHUB_BASE_REF" --depth=350 - COMPARE_REV=$(git merge-base "origin/${GITHUB_BASE_REF}" HEAD) + COMPARE_REV="$(git merge-base "origin/${GITHUB_BASE_REF}" HEAD)" fi - # Specify anything which should skip full CI in this regex: + CHANGED_FILES="$(git diff --name-only "$COMPARE_REV" ${{ github.sha }})" + + # Specify anything which should potentially skip full test suite in this regex: # - docs/ # - script/update_top_ranking_issues/ # - .github/ISSUE_TEMPLATE/ # - .github/workflows/ (except .github/workflows/ci.yml) SKIP_REGEX='^(docs/|script/update_top_ranking_issues/|\.github/(ISSUE_TEMPLATE|workflows/(?!ci)))' - if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep -vP "$SKIP_REGEX") ]]; then - echo "run_tests=true" >> $GITHUB_OUTPUT - else - echo "run_tests=false" >> $GITHUB_OUTPUT - fi - if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep '^docs/') ]]; then - echo "run_docs=true" >> $GITHUB_OUTPUT - else - echo "run_docs=false" >> $GITHUB_OUTPUT - fi - if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep -P '^(Cargo.lock|script/.*licenses)') ]]; then - echo "run_license=true" >> $GITHUB_OUTPUT - else - echo "run_license=false" >> $GITHUB_OUTPUT - fi - NIX_REGEX='^(nix/|flake\.|Cargo\.|rust-toolchain.toml|\.cargo/config.toml)' - if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep -P "$NIX_REGEX") ]]; then - echo "run_nix=true" >> $GITHUB_OUTPUT - else - echo "run_nix=false" >> $GITHUB_OUTPUT - fi + + echo "$CHANGED_FILES" | grep -qvP "$SKIP_REGEX" && \ + echo "run_tests=true" >> "$GITHUB_OUTPUT" || \ + echo "run_tests=false" >> "$GITHUB_OUTPUT" + + echo "$CHANGED_FILES" | grep -qP '^docs/' && \ + echo "run_docs=true" >> "$GITHUB_OUTPUT" || \ + echo "run_docs=false" >> "$GITHUB_OUTPUT" + + echo "$CHANGED_FILES" | grep -qP '^\.github/(workflows/|actions/|actionlint.yml)' && \ + echo "run_actionlint=true" >> "$GITHUB_OUTPUT" || \ + echo "run_actionlint=false" >> "$GITHUB_OUTPUT" + + echo "$CHANGED_FILES" | grep -qP '^(Cargo.lock|script/.*licenses)' && \ + echo "run_license=true" >> "$GITHUB_OUTPUT" || \ + echo "run_license=false" >> "$GITHUB_OUTPUT" + + echo "$CHANGED_FILES" | grep -qP '^(nix/|flake\.|Cargo\.|rust-toolchain.toml|\.cargo/config.toml)' && \ + echo "run_nix=true" >> "$GITHUB_OUTPUT" || \ + echo "run_nix=false" >> "$GITHUB_OUTPUT" migration_checks: name: Check Postgres and Protobuf migrations, mergability @@ -89,8 +91,7 @@ jobs: needs.job_spec.outputs.run_tests == 'true' timeout-minutes: 60 runs-on: - - self-hosted - - macOS + - self-mini-macos steps: - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -112,11 +113,11 @@ jobs: run: | if [ -z "$GITHUB_BASE_REF" ]; then - echo "BUF_BASE_BRANCH=$(git merge-base origin/main HEAD)" >> $GITHUB_ENV + echo "BUF_BASE_BRANCH=$(git merge-base origin/main HEAD)" >> "$GITHUB_ENV" else git checkout -B temp - git merge -q origin/$GITHUB_BASE_REF -m "merge main into temp" - echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV + git merge -q "origin/$GITHUB_BASE_REF" -m "merge main into temp" + echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> "$GITHUB_ENV" fi - uses: bufbuild/buf-setup-action@v1 @@ -140,7 +141,7 @@ jobs: - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Add Rust to the PATH - run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH + run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Install cargo-hakari uses: clechasseur/rs-cargo@8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386 # v2 with: @@ -178,7 +179,7 @@ jobs: - name: Prettier Check on /docs working-directory: ./docs run: | - pnpm dlx prettier@${PRETTIER_VERSION} . --check || { + pnpm dlx "prettier@${PRETTIER_VERSION}" . --check || { echo "To fix, run from the root of the Zed repo:" echo " cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .." false @@ -188,7 +189,7 @@ jobs: - name: Prettier Check on default.json run: | - pnpm dlx prettier@${PRETTIER_VERSION} assets/settings/default.json --check || { + pnpm dlx "prettier@${PRETTIER_VERSION}" assets/settings/default.json --check || { echo "To fix, run from the root of the Zed repo:" echo " pnpm dlx prettier@${PRETTIER_VERSION} assets/settings/default.json --write" false @@ -234,6 +235,20 @@ jobs: - name: Build docs uses: ./.github/actions/build_docs + actionlint: + runs-on: ubuntu-latest + if: github.repository_owner == 'zed-industries' && needs.job_spec.outputs.run_actionlint == 'true' + needs: [job_spec] + steps: + - uses: actions/checkout@v4 + - name: Download actionlint + id: get_actionlint + run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) + shell: bash + - name: Check workflow files + run: ${{ steps.get_actionlint.outputs.executable }} -color + shell: bash + macos_tests: timeout-minutes: 60 name: (macOS) Run Clippy and tests @@ -242,8 +257,7 @@ jobs: github.repository_owner == 'zed-industries' && needs.job_spec.outputs.run_tests == 'true' runs-on: - - self-hosted - - macOS + - self-mini-macos steps: - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -312,7 +326,7 @@ jobs: - buildjet-16vcpu-ubuntu-2204 steps: - name: Add Rust to the PATH - run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH + run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -364,7 +378,7 @@ jobs: - buildjet-8vcpu-ubuntu-2204 steps: - name: Add Rust to the PATH - run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH + run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -444,6 +458,7 @@ jobs: - job_spec - style - check_docs + - actionlint - migration_checks # run_tests: If adding required tests, add them here and to script below. - workspace_hack @@ -465,6 +480,11 @@ jobs: if [[ "${{ needs.job_spec.outputs.run_docs }}" == "true" ]]; then [[ "${{ needs.check_docs.result }}" != 'success' ]] && { RET_CODE=1; echo "docs checks failed"; } fi + + if [[ "${{ needs.job_spec.outputs.run_actionlint }}" == "true" ]]; then + [[ "${{ needs.actionlint.result }}" != 'success' ]] && { RET_CODE=1; echo "actionlint checks failed"; } + fi + # Only check test jobs if they were supposed to run if [[ "${{ needs.job_spec.outputs.run_tests }}" == "true" ]]; then [[ "${{ needs.workspace_hack.result }}" != 'success' ]] && { RET_CODE=1; echo "Workspace Hack failed"; } @@ -484,8 +504,7 @@ jobs: timeout-minutes: 120 name: Create a macOS bundle runs-on: - - self-hosted - - bundle + - self-mini-macos if: | startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') @@ -802,10 +821,9 @@ jobs: && endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre') needs: [bundle-mac, bundle-linux-x86_x64, bundle-linux-aarch64, bundle-windows-x64] runs-on: - - self-hosted - - bundle + - self-mini-macos steps: - name: gh release - run: gh release edit $GITHUB_REF_NAME --draft=false + run: gh release edit "$GITHUB_REF_NAME" --draft=false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/community_release_actions.yml b/.github/workflows/community_release_actions.yml index 3e253978b7..31dda1fa6d 100644 --- a/.github/workflows/community_release_actions.yml +++ b/.github/workflows/community_release_actions.yml @@ -18,7 +18,7 @@ jobs: URL="https://zed.dev/releases/stable/latest" fi - echo "URL=$URL" >> $GITHUB_OUTPUT + echo "URL=$URL" >> "$GITHUB_OUTPUT" - name: Get content uses: 2428392/gh-truncate-string-action@b3ff790d21cf42af3ca7579146eedb93c8fb0757 # v1.4.1 id: get-content @@ -50,9 +50,9 @@ jobs: PREVIEW_TAG="${VERSION}-pre" if git rev-parse "$PREVIEW_TAG" > /dev/null 2>&1; then - echo "was_promoted_from_preview=true" >> $GITHUB_OUTPUT + echo "was_promoted_from_preview=true" >> "$GITHUB_OUTPUT" else - echo "was_promoted_from_preview=false" >> $GITHUB_OUTPUT + echo "was_promoted_from_preview=false" >> "$GITHUB_OUTPUT" fi - name: Send release notes email diff --git a/.github/workflows/deploy_collab.yml b/.github/workflows/deploy_collab.yml index cfd455f920..f7348a1069 100644 --- a/.github/workflows/deploy_collab.yml +++ b/.github/workflows/deploy_collab.yml @@ -79,12 +79,12 @@ jobs: - name: Build docker image run: | docker build -f Dockerfile-collab \ - --build-arg GITHUB_SHA=$GITHUB_SHA \ - --tag registry.digitalocean.com/zed/collab:$GITHUB_SHA \ + --build-arg "GITHUB_SHA=$GITHUB_SHA" \ + --tag "registry.digitalocean.com/zed/collab:$GITHUB_SHA" \ . - name: Publish docker image - run: docker push registry.digitalocean.com/zed/collab:${GITHUB_SHA} + run: docker push "registry.digitalocean.com/zed/collab:${GITHUB_SHA}" - name: Prune Docker system run: docker system prune --filter 'until=72h' -f @@ -131,7 +131,8 @@ jobs: source script/lib/deploy-helpers.sh export_vars_for_environment $ZED_KUBE_NAMESPACE - export ZED_DO_CERTIFICATE_ID=$(doctl compute certificate list --format ID --no-header) + ZED_DO_CERTIFICATE_ID="$(doctl compute certificate list --format ID --no-header)" + export ZED_DO_CERTIFICATE_ID export ZED_IMAGE_ID="registry.digitalocean.com/zed/collab:${GITHUB_SHA}" export ZED_SERVICE_NAME=collab diff --git a/.github/workflows/eval.yml b/.github/workflows/eval.yml index 6eefdfea95..2ad302a602 100644 --- a/.github/workflows/eval.yml +++ b/.github/workflows/eval.yml @@ -35,7 +35,7 @@ jobs: - buildjet-16vcpu-ubuntu-2204 steps: - name: Add Rust to the PATH - run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH + run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 155fc484f5..beacd27774 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -43,8 +43,8 @@ jobs: - name: Set path if: ${{ ! matrix.system.install_nix }} run: | - echo "/nix/var/nix/profiles/default/bin" >> $GITHUB_PATH - echo "/Users/administrator/.nix-profile/bin" >> $GITHUB_PATH + echo "/nix/var/nix/profiles/default/bin" >> "$GITHUB_PATH" + echo "/Users/administrator/.nix-profile/bin" >> "$GITHUB_PATH" - uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31 if: ${{ matrix.system.install_nix }} @@ -56,11 +56,13 @@ jobs: name: zed authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" pushFilter: "${{ inputs.cachix-filter }}" - cachixArgs: '-v' + cachixArgs: "-v" - run: nix build .#${{ inputs.flake-output }} -L --accept-flake-config - name: Limit /nix/store to 50GB on macs if: ${{ ! matrix.system.install_nix }} run: | - [ $(du -sm /nix/store | cut -f1) -gt 50000 ] && nix-collect-garbage -d || : + if [ "$(du -sm /nix/store | cut -f1)" -gt 50000 ]; then + nix-collect-garbage -d || true + fi diff --git a/.github/workflows/release_nightly.yml b/.github/workflows/release_nightly.yml index 4be20525f9..f799133ea7 100644 --- a/.github/workflows/release_nightly.yml +++ b/.github/workflows/release_nightly.yml @@ -85,8 +85,7 @@ jobs: name: Create a macOS bundle if: github.repository_owner == 'zed-industries' runs-on: - - self-hosted - - bundle + - self-mini-macos needs: tests env: MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }} @@ -132,7 +131,7 @@ jobs: clean: false - name: Add Rust to the PATH - run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH + run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Install Linux dependencies run: ./script/linux && ./script/install-mold 2.34.0 diff --git a/.github/workflows/unit_evals.yml b/.github/workflows/unit_evals.yml index 705caff37a..cb4e39d151 100644 --- a/.github/workflows/unit_evals.yml +++ b/.github/workflows/unit_evals.yml @@ -26,7 +26,7 @@ jobs: - buildjet-16vcpu-ubuntu-2204 steps: - name: Add Rust to the PATH - run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH + run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4