H-3684: Upgrade to Yarn 4 #12477
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Lint | |
on: | |
pull_request: | |
push: | |
branches: | |
- main | |
merge_group: | |
env: | |
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} | |
TURBO_TEAM: hashintel | |
TURBO_REMOTE_ONLY: true | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
cancel-in-progress: true | |
jobs: | |
setup: | |
runs-on: ubuntu-24.04 | |
outputs: | |
packages: ${{ steps.packages.outputs.packages }} | |
steps: | |
- name: Checkout source code | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
fetch-depth: 2 | |
- name: Enable corepack | |
uses: ./.github/actions/enable-corepack | |
- name: Install turbo | |
uses: ./.github/actions/install-turbo | |
- name: Determine changed packages | |
id: packages | |
run: | | |
FILTER=$(turbo run lint --dry-run=json --filter '...[HEAD^]' | jq -e '.packages | contains(["//"])' > /dev/null && echo '' || echo '--filter ...[HEAD^]') | |
PACKAGES=$(sh -c "turbo run lint --dry-run=json $FILTER" \ | |
| jq '.tasks[]' \ | |
| jq 'select(.task == "lint")' \ | |
| jq --compact-output --slurp '{ package: [.[].package] | unique, include: [( .[] | {package: .package, directory: .directory })] | unique }') | |
echo "packages=$PACKAGES" | tee -a $GITHUB_OUTPUT | |
package: | |
name: Package | |
needs: [setup] | |
strategy: | |
matrix: ${{ fromJSON(needs.setup.outputs.packages) }} | |
fail-fast: false | |
if: needs.setup.outputs.packages != '{"package":[],"include":[]}' | |
runs-on: ubuntu-24.04 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
fetch-depth: 2 | |
- name: Enable corepack | |
uses: ./.github/actions/enable-corepack | |
- name: Install turbo | |
uses: ./.github/actions/install-turbo | |
- name: Find lint steps to run | |
id: lints | |
run: | | |
set -x | |
ESLINT=$(turbo run lint:eslint --filter '${{ matrix.package }}' --dry-run=json \ | |
| jq '[.tasks[] | select(.task == "lint:eslint" and .command != "<NONEXISTENT>")] != []' || echo 'false') | |
echo "eslint=$ESLINT" | tee -a $GITHUB_OUTPUT | |
TSC=$(turbo run lint:tsc --filter '${{ matrix.package }}' --dry-run=json \ | |
| jq '[.tasks[] | select(.task == "lint:tsc" and .command != "<NONEXISTENT>")] != []' || echo 'false') | |
echo "tsc=$TSC" | tee -a $GITHUB_OUTPUT | |
CODEGEN=$(turbo run codegen --filter '${{ matrix.package }}' --dry-run=json \ | |
| jq '[.tasks[] | select(.task == "codegen" and .command != "<NONEXISTENT>")] != []' || echo 'false') | |
echo "codegen=$CODEGEN" | tee -a $GITHUB_OUTPUT | |
HAS_RUST=$([[ -f "${{ matrix.directory }}/Cargo.toml" || ${{ matrix.directory }} = "apps/hash-graph" ]] && echo 'true' || echo 'false') | |
echo "has-rust=$HAS_RUST" | tee -a $GITHUB_OUTPUT | |
if [[ $HAS_RUST = 'true' ]]; then | |
if [[ -f "${{ matrix.directory }}/rust-toolchain.toml" ]]; then | |
RUST_TOOLCHAIN_FILE="${{ matrix.directory }}/rust-toolchain.toml" | |
else | |
RUST_TOOLCHAIN_FILE="rust-toolchain.toml" | |
fi | |
echo "rust-toolchain=$(yq '.toolchain.channel' $RUST_TOOLCHAIN_FILE)" | tee -a $GITHUB_OUTPUT | |
echo "has-rustfmt=$(yq '.toolchain.components | contains(["rustfmt"])' $RUST_TOOLCHAIN_FILE)" | tee -a $GITHUB_OUTPUT | |
echo "has-clippy=$(yq '.toolchain.components | contains(["clippy"])' $RUST_TOOLCHAIN_FILE)" | tee -a $GITHUB_OUTPUT | |
fi | |
- name: Prune repository | |
uses: ./.github/actions/prune-repository | |
with: | |
scope: ${{ matrix.package }} | |
- name: Install Protobuf | |
if: always() && steps.lints.outputs.has-rust == 'true' | |
run: sudo apt install protobuf-compiler | |
- name: Install Rust toolchain | |
if: always() && steps.lints.outputs.has-rust == 'true' | |
uses: ./.github/actions/install-rust-toolchain | |
with: | |
toolchain: ${{ steps.lints.outputs.rust-toolchain }} | |
working-directory: ${{ matrix.directory }} | |
- name: Install Rust tools | |
if: always() && steps.lints.outputs.has-rust == 'true' | |
uses: taiki-e/install-action@6da51af62171044932d435033daa70a0eb3383ba # v2.45.6 | |
with: | |
tool: [email protected],[email protected],[email protected],[email protected] | |
- name: Warm up repository | |
uses: ./.github/actions/warm-up-repo | |
- name: Cache Rust dependencies | |
if: always() && steps.lints.outputs.has-rust == 'true' | |
uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 | |
with: | |
workspaces: ${{ matrix.directory }} | |
save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} | |
- name: Show disk usage | |
run: df -h | |
- name: Run codegen | |
if: always() && steps.lints.outputs.codegen == 'true' | |
run: | | |
set -o pipefail | |
turbo run codegen --force --filter "${{ matrix.package }}" | |
while IFS= read -r line; do | |
if [[ -n "$line" ]]; then | |
echo "Checking diff of ${{ matrix.directory }}/$line" | |
git --no-pager diff --exit-code --color -- "${{ matrix.directory }}/$line" | |
fi | |
done <<< "$(cat ${{ matrix.directory }}/turbo.json | grep -v '^ *//' | jq -r '.pipeline.codegen.outputs | if . == null then "." else .[] end')" | |
- name: Show disk usage | |
run: df -h | |
- name: Run ESLint | |
if: always() && steps.lints.outputs.eslint == 'true' | |
run: turbo run lint:eslint --filter "${{ matrix.package }}" | |
- name: Run TSC | |
if: always() && steps.lints.outputs.tsc == 'true' | |
run: turbo run lint:tsc --filter "${{ matrix.package }}" | |
- name: Run rustfmt | |
if: always() && steps.lints.outputs.has-rustfmt == 'true' | |
working-directory: ${{ matrix.directory }} | |
run: just format --check | |
- name: Run clippy | |
if: always() && steps.lints.outputs.has-clippy == 'true' | |
run: | | |
pushd ${{ matrix.directory }} | |
just clippy --message-format=json \ | |
| clippy-sarif \ | |
| jq '.runs[].results |= unique' \ | |
> clippy.sarif | |
popd | |
cat ${{ matrix.directory }}/clippy.sarif | sarif-fmt | |
jq -e '.runs[].results == []' ${{ matrix.directory }}/clippy.sarif> /dev/null | |
- name: Print clippy errors to summary | |
if: failure() && steps.lints.outputs.has-clippy == 'true' | |
run: | | |
echo '```' >> $GITHUB_STEP_SUMMARY | |
cat ${{ matrix.directory }}/clippy.sarif | sarif-fmt >> $GITHUB_STEP_SUMMARY | |
echo '```' >> $GITHUB_STEP_SUMMARY | |
- name: Upload SARIF file | |
uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 | |
if: always() && steps.lints.outputs.has-clippy == 'true' | |
with: | |
sarif_file: ${{ matrix.directory }}/clippy.sarif | |
category: ${{ matrix.package }} | |
- name: Check public documentation | |
if: always() && steps.lints.outputs.has-rust == 'true' | |
working-directory: ${{ matrix.directory }} | |
env: | |
RUSTDOCFLAGS: "--check -Z unstable-options -D warnings" | |
run: cargo doc --all-features --no-deps -Zrustdoc-scrape-examples | |
- name: Check private documentation | |
if: always() && steps.lints.outputs.has-rust == 'true' | |
working-directory: ${{ matrix.directory }} | |
env: | |
RUSTDOCFLAGS: "--check -Z unstable-options -D warnings" | |
run: cargo doc --all-features --no-deps -Zrustdoc-scrape-examples --document-private-items | |
- name: Show disk usage | |
run: df -h | |
global: | |
name: Global | |
runs-on: ubuntu-24.04 | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- name: Warm up repository | |
uses: ./.github/actions/warm-up-repo | |
- name: Validate package.json generated from Cargo.toml | |
if: ${{ success() || failure() }} | |
run: | | |
cargo -Zscript run --manifest-path ".github/scripts/rust/sync-turborepo.rs" . | xargs yarn prettier --write >/dev/null | |
git --no-pager diff --exit-code --color '**/package.json' | |
- name: Run yarn lint:dependency-version-consistency | |
if: ${{ success() || failure() }} | |
run: | | |
if ! yarn lint:dependency-version-consistency; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Try running `yarn fix:dependency-version-consistency` locally to apply autofixes.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1 | |
fi | |
- name: Run yarn lint:lockfile-lint | |
if: ${{ success() || failure() }} | |
run: | | |
if ! yarn lint:lockfile-lint; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Try resetting yarn.lock to its previous state and then run `yarn install`.' | |
echo 'If your `~/.npmrc` mentions a custom registry, you should remove this setting first.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1 | |
fi | |
- name: Run yarn lint:license-in-workspaces | |
if: ${{ success() || failure() }} | |
env: | |
FORCE_COLOR: "1" ## https://www.npmjs.com/package/chalk#supportsColor | |
run: | | |
if ! yarn lint:license-in-workspaces; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Please fix the above errors locally for the check to pass.' | |
echo 'If you don’t see them, try merging target branch into yours.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1 | |
fi | |
- name: Run yarn lint:markdownlint | |
if: ${{ success() || failure() }} | |
run: | | |
if ! yarn lint:markdownlint; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Try running `yarn fix:markdownlint` locally to apply autofixes.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1 | |
fi | |
- name: Run yarn lint:prettier | |
if: ${{ success() || failure() }} | |
run: | | |
if ! yarn lint:prettier; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Try running `yarn fix:prettier` locally to apply autofixes.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1 | |
fi | |
- name: Run yarn lint:taplo | |
if: ${{ success() || failure() }} | |
run: | | |
if ! yarn lint:taplo; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Try running `yarn fix:taplo` locally to apply autofixes.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1 | |
fi | |
## TODO: Replace with `yarn fix:yarn-dedupe` after upgrading to Yarn v3+ | |
## https://yarnpkg.com/cli/dedupe | |
## https://github.com/yarnpkg/berry/issues/2297 | |
- name: Run yarn lint:yarn-deduplicate | |
if: ${{ success() || failure() }} | |
run: | | |
if ! yarn lint:yarn-deduplicate; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Some dependencies can be deduplicated, which will make node_modules' | |
echo 'lighter and potentially save us from unexplainable bugs.' | |
echo 'Please run `yarn fix:yarn-deduplicate` locally and commit yarn.lock.' | |
echo 'You may need to run the command 2-3 times in some rare cases.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1 | |
fi | |
## yarn --frozen-lockfile does not work for monorepos, so using a workaround: | |
## https://github.com/yarnpkg/yarn/issues/5840#issuecomment-467516207 | |
## TODO: Use `yarn install --immutable` after upgrading to Yarn v3+ | |
- name: Check yarn.lock stability | |
if: ${{ success() || failure() }} | |
run: | | |
git diff yarn.lock | |
if ! git diff --exit-code yarn.lock; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Changes were detected in yarn.lock file after running `yarn install`.' | |
echo 'This makes runtime less stable, so should be avoided.' | |
echo 'Please run `yarn install` locally and commit yarn.lock.' | |
echo 'You may also want to run `yarn fix:yarn-deduplicate` just in case.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1; | |
fi | |
- name: Validate renovate config | |
if: ${{ success() || failure() }} | |
run: | | |
# Adding renovate in `package.json` causes incompatibility between our dependencies and their dependencies. | |
npm install --global renovate | |
if ! renovate-config-validator; then | |
echo '' | |
echo '' | |
echo 'ℹ️ ℹ️ ℹ️' | |
echo 'Please fix the above errors locally for the check to pass.' | |
echo 'If you don’t see them, try merging target branch into yours.' | |
echo 'ℹ️ ℹ️ ℹ️' | |
exit 1 | |
fi | |
passed: | |
name: Linting passed | |
needs: [setup, package, global] | |
if: always() | |
runs-on: ubuntu-latest | |
steps: | |
- name: Check setup script | |
run: | | |
[[ ${{ needs.setup.result }} = success ]] | |
- name: Check package results | |
run: | | |
[[ ${{ needs.package.result }} =~ success|skipped ]] | |
- name: Check global results | |
run: | | |
[[ ${{ needs.global.result }} =~ success|skipped ]] | |
- name: Notify Slack on failure | |
uses: rtCamp/action-slack-notify@c33737706dea87cd7784c687dadc9adf1be59990 | |
if: ${{ failure() && github.event_name == 'merge_group' }} | |
env: | |
SLACK_LINK_NAMES: true | |
SLACK_MESSAGE: "At least one linting job failed for a Pull Request in the Merge Queue failed <@U0143NL4GMP> <@U02NLJY0FGX>" # Notifies C & T | |
SLACK_TITLE: Linting failed | |
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} | |
SLACK_USERNAME: GitHub | |
VAULT_ADDR: "" | |
VAULT_TOKEN: "" |