Skip to content

feat(turborepo): FS Cache #11107

feat(turborepo): FS Cache

feat(turborepo): FS Cache #11107

Workflow file for this run

name: Test
on:
push:
branches: [main]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
actions: write
contents: read
pull-requests: read
jobs:
determine_jobs:
name: Determine jobs to run
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Find PR Comment
id: comment
if: github.event_name == 'pull_request'
uses: peter-evans/find-comment@v2
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: "github-actions[bot]"
body-includes: "<!-- CI COMMENT -->"
- name: Create or update PR comment
if: github.event_name == 'pull_request' && steps.comment.outputs.comment-id != ''
uses: peter-evans/create-or-update-comment@v2
continue-on-error: true
with:
comment-id: ${{ steps.comment.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: |
## :hourglass_flowing_sand: CI is running again... :hourglass_flowing_sand:
[Wait for it...](https://github.com/vercel/turbo/actions/runs/${{ github.run_id }})
<!-- CI COMMENT -->
edit-mode: replace
- name: Checkout
uses: actions/checkout@v3
- name: CI related changes
id: ci
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
.github/actions/**
.github/workflows/test.yml
.github/workflows/setup-nextjs-build.yml
.github/workflows/nextjs-integration-test-results.yml
.github/workflows/upload-nextjs-integration-test-results.yml
- name: Root cargo related changes
id: cargo
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
Cargo.*
rust-toolchain
- name: Rust related changes
id: rust
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
pnpm-lock.yaml
package.json
Cargo.**
crates/**
shim/**
xtask/**
.cargo/**
rust-toolchain
!**.md
!**.mdx
- name: Turbopack related changes
id: turbopack
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
pnpm-lock.yaml
package.json
crates/**
xtask/**
.cargo/**
rust-toolchain
!crates/turborepo*/**
!**.md
!**.mdx
- name: Turbopack Benchmark related changes
id: turbopack_bench
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
crates/turbopack-bench/**
!*.md
- name: Turbopack TypeScript related changes
id: turbopack_typescript
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
crates/turbopack*/js/**
- name: Turborepo Rust related changes
id: turborepo_rust
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
pnpm-lock.yaml
package.json
crates/turborepo*/**
.cargo/**
rust-toolchain
!**.md
!**.mdx
- name: Turborepo Go related changes
id: turborepo_go
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
cli/**
- name: Turborepo integration tests changes
id: turborepo_integration
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
turborepo-tests/integration/**
turborepo-tests/helpers/**
- name: Turborepo e2e tests changes
id: turborepo_e2e
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
turborepo-tests/e2e/**
turborepo-tests/helpers/**
- name: Examples related changes
id: examples
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
examples/**
examples-tests/**
!**.md
!**.mdx
- name: Turborepo JS Package related changes
id: turborepo_js
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
packages/**
- name: Formatting related changes
id: format
uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/*.{yml,yaml,md,mdx,js,jsx,ts,tsx,json,toml,css}
outputs:
rust: ${{ steps.ci.outputs.diff != '' || steps.rust.outputs.diff != '' }}
cargo_only: ${{ steps.ci.outputs.diff != '' || (steps.cargo.outputs.diff != '' && steps.turbopack.outputs.diff == '' && steps.turborepo_rust.outputs.diff == '') }}
# We only test workspace dependency changes on main, not on PRs to speed up CI
cargo_on_main: ${{ steps.ci.outputs.diff != '' || (steps.cargo.outputs.diff != '' && github.event_name == 'push' && github.ref == 'refs/heads/main') }}
turbopack: ${{ steps.ci.outputs.diff != '' || steps.turbopack.outputs.diff != '' }}
turbopack_typescript: ${{ steps.ci.outputs.diff != '' || steps.turbopack_typescript.outputs.diff != '' }}
turborepo_rust: ${{ steps.ci.outputs.diff != '' || steps.turborepo_rust.outputs.diff != '' }}
turbopack_bench: ${{ steps.ci.outputs.diff != '' || steps.turbopack_bench.outputs.diff != '' }}
go: ${{ steps.ci.outputs.diff != '' || steps.turborepo_go.outputs.diff != '' || steps.turborepo_rust.outputs.diff != '' }}
turborepo_e2e: ${{ steps.ci.outputs.diff != '' || steps.turborepo_go.outputs.diff != '' || steps.turborepo_rust.outputs.diff != '' || steps.turborepo_e2e.outputs.diff != '' }}
go_integration: ${{ steps.ci.outputs.diff != '' || steps.turborepo_go.outputs.diff != '' || steps.turborepo_rust.outputs.diff != '' || steps.turborepo_integration.outputs.diff != '' }}
examples: ${{ steps.ci.outputs.diff != '' || steps.turborepo_go.outputs.diff != '' || steps.turborepo_rust.outputs.diff != '' || steps.examples.outputs.diff != '' }}
turborepo_js: ${{ steps.ci.outputs.diff != '' || steps.turborepo_js.outputs.diff != '' }}
format: ${{ steps.ci.outputs.diff != '' || steps.format.outputs.diff != '' }}
push: ${{ steps.ci.outputs.diff != '' || github.event_name == 'push' }}
tag: ${{ steps.ci.outputs.diff != '' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/node-file-trace')) }}
main_push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
tag_push: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/node-file-trace') }}
go_lint:
name: Go linting
runs-on: ubuntu-latest
needs: determine_jobs
if: needs.determine_jobs.outputs.go == 'true'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Setup Protos
run: cd cli && make compile-protos
- name: Build turborepo-ffi
run: cd cli && make turborepo-ffi-install
- name: golangci Linting
uses: golangci/golangci-lint-action@v3
with:
# More config options documented here: https://github.com/golangci/golangci-lint-action
version: latest
working-directory: cli
args: --new-from-rev=${{ github.event.pull_request.base.sha || 'HEAD~1' }}
go_unit:
name: Go Unit Tests
needs: determine_jobs
if: needs.determine_jobs.outputs.go == 'true'
timeout-minutes: 45
runs-on: ${{ matrix.os.runner }}
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
runner: ubuntu-latest
- name: macos
runner: macos-latest
- name: windows
runner: windows-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup-turborepo-environment
with:
target: ${{ matrix.os.name }}
github-token: "${{ secrets.GITHUB_TOKEN }}"
- run: turbo run test --filter=cli --color
go_integration:
name: Go Integration Tests
needs: determine_jobs
if: needs.determine_jobs.outputs.go_integration == 'true'
timeout-minutes: 30
runs-on: ${{ matrix.os.runner }}
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
runner: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup-turborepo-environment
with:
target: ${{ matrix.os.name }}
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Cache Prysk
id: cache-prysk
uses: actions/cache@v3
with:
path: cli/.cram_env
key: prysk-venv-${{ matrix.os.name }}
- name: Integration Tests
run: turbo run test --filter=turborepo-tests-integration --color --env-mode=strict
turborepo_e2e:
name: Turborepo E2E Tests
needs: determine_jobs
if: needs.determine_jobs.outputs.turborepo_e2e == 'true'
timeout-minutes: 60
runs-on: ${{ matrix.os.runner }}
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
runner: ubuntu-latest
- name: macos
runner: macos-latest
- name: windows
runner: windows-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup-turborepo-environment
with:
target: ${{ matrix.os.name }}
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: E2E Tests
run: turbo run test --filter=turborepo-tests-e2e --remote-only --token=${{ secrets.TURBO_TOKEN }} --team=${{ vars.TURBO_TEAM }} --color --env-mode=strict
turborepo_examples:
name: Turborepo Examples
needs: determine_jobs
if: needs.determine_jobs.outputs.examples == 'true'
timeout-minutes: 40
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
runner: ubuntu-latest
- name: macos
runner: macos-latest
runs-on: ${{ matrix.os.runner }}
steps:
- name: Checkout
uses: actions/checkout@v3
# Note: the setup-node action inside this is somehow required for
# the node setup below this step. Not sure why.
- uses: ./.github/actions/setup-turborepo-environment
with:
target: ${{ matrix.os.name }}
github-token: "${{ secrets.GITHUB_TOKEN }}"
# TODO: .github/actions/setup-node is pretty similar to the following
# steps (Setup Pnpm, pnpm cache, corepack, setup node), but it didn't
# work out of box. We should take another stab at it later.
- name: Setup Pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.2.1
- name: Make sure pnpm always has a cache
shell: bash
run: |
mkdir -p `pnpm store path`
# Disable corepack, actions/setup-node invokes other package managers and
# that causes corepack to throw an error, so we disable it first.
- name: Disable corepack
shell: bash
run: corepack disable
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
cache: ${{ matrix.manager }}
cache-dependency-path: package.json
- name: Check examples
shell: bash
# Note: using CLI flags instead of env vars because
# envs var would apply to the actual tests that exercise turbo also,
# making test output non-deterministic.
run: turbo run example-test --color --remote-only --token=${{ secrets.TURBO_TOKEN }} --team=${{ vars.TURBO_TEAM }} --env-mode=strict
# Re-enable corepack, actions/setup-node invokes other package managers and
# that causes corepack to throw an error, so we disable it here. The "Post" step
# for actions/setup-node will run at the end of this job, so we need to prep for it.
- name: Disable corepack again
shell: bash
run: corepack disable
js_packages:
name: JS Package Tests
timeout-minutes: 30
if: needs.determine_jobs.outputs.turborepo_js == 'true'
needs: determine_jobs
runs-on: ${{ matrix.os.runner }}
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
runner: ubuntu-latest
- name: macos
runner: macos-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_REMOTE_ONLY: true
steps:
# on main -> current + prev commit
# pr -> pr commits + base commit
- name: Determine fetch depth
id: fetch-depth
run: |
echo "depth=$(( ${{ github.event.pull_request.commits || 1 }} + 1 ))" >> $GITHUB_OUTPUT
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.ref }}
fetch-depth: ${{ steps.fetch-depth.outputs.depth }}
- name: Build turborepo CLI from source
uses: ./.github/actions/setup-turborepo-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
target: ${{ matrix.os.name }}
- name: Run tests
run: |
turbo run check-types test --filter={./packages/*}...[${{ github.event.pull_request.base.sha || 'HEAD^1' }}] --color
turbopack_typescript:
name: Turbopack TypeScript files
runs-on: ubuntu-latest
needs: determine_jobs
if: needs.determine_jobs.outputs.turbopack_typescript == 'true'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Install dependencies
run: pnpm install -r --side-effects-cache false
- name: Check turbopack-node types
working-directory: crates/turbopack-node/js
run: pnpm run check
- name: Check turbopack-cli types
working-directory: crates/turbopack-cli/js
run: pnpm run check
- name: Check turbopack-ecmascript-runtime types
working-directory: crates/turbopack-ecmascript-runtime/js
run: pnpm run check
rust_lint:
needs: [determine_jobs]
if: needs.determine_jobs.outputs.rust == 'true'
name: Rust lints
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
components: rustfmt
- name: Run cargo fmt check
run: |
cargo fmt --check
- name: Check Cargo.toml formatting (taplo)
run: npx @taplo/cli format --check
- name: Check licenses
uses: EmbarkStudios/cargo-deny-action@v1
with:
command: check licenses
turborepo_rust_check:
needs: [determine_jobs]
# We test dependency changes only on main
if: |
(needs.determine_jobs.outputs.rust == 'true' && needs.determine_jobs.outputs.turborepo_rust == 'true') ||
needs.determine_jobs.outputs.cargo_on_main == 'true' ||
needs.determine_jobs.outputs.cargo_only == 'true'
name: Turborepo rust check
runs-on: ubuntu-latest-16-core-oss
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
components: clippy
targets: wasm32-unknown-unknown
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Run cargo check
run: |
cargo groups check turborepo-libraries --features rustls-tls
turborepo_rust_clippy:
needs: [turborepo_rust_check]
name: Turborepo rust clippy
runs-on: ubuntu-latest-16-core-oss
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
components: clippy
targets: wasm32-unknown-unknown
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Run cargo clippy
run: |
cargo groups clippy turborepo-libraries --features rustls-tls
turbopack_rust_check:
needs: [determine_jobs]
# We test dependency changes only on main
if: |
(needs.determine_jobs.outputs.rust == 'true' && needs.determine_jobs.outputs.turbopack == 'true') ||
needs.determine_jobs.outputs.cargo_on_main == 'true' ||
needs.determine_jobs.outputs.cargo_only == 'true'
name: Turbopack rust check
runs-on: ubuntu-latest-16-core-oss
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
components: clippy
targets: wasm32-unknown-unknown
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Run cargo check release
run: |
RUSTFLAGS="-D warnings -A deprecated" cargo groups check turbopack --features rustls-tls --release
turbopack_rust_clippy:
needs: [turbopack_rust_check]
name: Turbopack rust clippy
runs-on: ubuntu-latest-16-core-oss
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
components: clippy
targets: wasm32-unknown-unknown
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Run cargo clippy
run: |
RUSTFLAGS="-D warnings -A deprecated" cargo groups clippy turbopack --features rustls-tls
next_dev_check:
needs: [determine_jobs]
if: needs.determine_jobs.outputs.turbopack == 'true' || needs.determine_jobs.outputs.cargo_on_main == 'true'
name: Check next-swc
runs-on: ubuntu-latest-8-core-oss
permissions:
pull-requests: write
steps:
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
- name: Checkout Next.js
uses: actions/checkout@v3
with:
repository: vercel/next.js
- name: Setup Rust
uses: ./.github/actions/setup-rust
- name: Build next-swc
run: |
export TURBOPACK_REMOTE="https://github.com/vercel/turbo"
# patch the turbo git dependency with the commit of the current PR.
export BINDING=$(printf 'patch."%s".%s.git="%s?rev=%s"' "$TURBOPACK_REMOTE" "turbopack-binding" "$TURBOPACK_REMOTE" "$GITHUB_SHA")
export TASKS=$(printf 'patch."%s".%s.git="%s?rev=%s"' "$TURBOPACK_REMOTE" "turbo-tasks" "$TURBOPACK_REMOTE" "$GITHUB_SHA")
export TASKS_FS=$(printf 'patch."%s".%s.git="%s?rev=%s"' "$TURBOPACK_REMOTE" "turbo-tasks-fs" "$TURBOPACK_REMOTE" "$GITHUB_SHA")
# set pipefail so the exit code of `cargo check` gets preserved
(set -o pipefail && \
cargo check \
--config $BINDING --config $TASKS --config $TASKS_FS \
--all -p next-swc-api -p next-dev \
--no-default-features --features cli,custom_allocator,rustls-tls \
--message-format short --quiet \
2>&1 | tee cargo_output.log)
- name: Success Log
run: |
printf ":white_check_mark: This change can build \`next-swc\`" > out.log
- name: Post logs if there are errors
if: failure()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
job_url=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}/jobs --paginate --jq '.jobs.[] | select(.name == "Check next-swc").html_url')
# strip ansi colors with `sed`
echo "\
:warning: This change may fail to build \`next-swc\`.
<details><summary>Logs</summary>
<p>
\`\`\`
$(cat cargo_output.log | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g")
\`\`\`
</p>
</details>
See [job summary]($job_url) for details
" > out.log
- name: PR comment with file
uses: thollander/actions-comment-pull-request@v2
if: always() && github.repository == 'vercel/turbo'
# We'll not block CI on this step
continue-on-error: true
with:
filePath: ./out.log
comment_tag: check_next_swc_turbopack
turborepo_rust_test:
needs: [turborepo_rust_check]
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
runner: ubuntu-latest-16-core-oss
nextest: linux
- name: macos
runner: macos-latest
nextest: mac
- name: windows
runner: windows-latest
nextest: windows-tar
runs-on: ${{ matrix.os.runner }}
name: Turborepo Rust testing on ${{ matrix.os.name }}
steps:
- name: Set git to use LF line endings
run: |
git config --global core.autocrlf false
git config --global core.eol lf
if: matrix.os.name == 'windows'
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
save-cache: true
- name: Setup Protoc
uses: arduino/setup-protoc@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run tests
timeout-minutes: 120
run: |
cargo groups test turborepo-libraries
turbopack_rust_test1:
needs: [turbopack_rust_check]
runs-on: ubuntu-latest-16-core-oss
name: Turbopack Rust testing on ubuntu
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
save-cache: true
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
# TODO: update to Node 18. Currently fails because the node-canvas dependency doesn't compile for node 18
# Did not spend too much time investigating so it could be an easy fix.
node-version: 16
- name: Install tests dependencies
working-directory: crates/turbopack/tests/node-file-trace
run: pnpm install -r --side-effects-cache false
- name: Install tests dependencies in examples/with-yarn
working-directory: examples/with-yarn
run: npm install
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Build nextest
timeout-minutes: 120
run: |
cargo tp-pre-test
- name: Run nextest
timeout-minutes: 120
run: |
cargo tp-test --profile tp-test-linux
- name: Upload results
if: always()
uses: actions/upload-artifact@v3
with:
name: test_reports
path: target/nextest/**/*.xml
turbopack_rust_test2:
needs: [turbopack_rust_check]
strategy:
fail-fast: false
matrix:
os:
- name: macos
runner: macos-latest
- name: windows
runner: windows-latest
runs-on: ${{ matrix.os.runner }}
name: Turbopack Rust testing on ${{ matrix.os.name }}
steps:
- name: Set git to use LF line endings
run: |
git config --global core.autocrlf false
git config --global core.eol lf
if: matrix.os.name == 'windows'
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
save-cache: true
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
# TODO: update to Node 18. Currently fails because the node-canvas dependency doesn't compile for node 18
# Did not spend too much time investigating so it could be an easy fix.
node-version: 16
- name: Setup Protoc
uses: arduino/setup-protoc@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare toolchain on Windows
run: |
pnpx node-gyp install
echo 'node-linker = "hoisted"' > crates/turbopack/tests/node-file-trace/.npmrc
if: matrix.os.name == 'windows'
- name: Install tests dependencies
working-directory: crates/turbopack/tests/node-file-trace
run: pnpm install -r --side-effects-cache false
- name: Install tests dependencies in examples/with-yarn
working-directory: examples/with-yarn
run: npm install
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Build nextest
timeout-minutes: 120
run: |
cargo tp-pre-test
- name: Run nextest (Mac)
timeout-minutes: 120
if: matrix.os.name == 'macos'
run: |
cargo tp-test --profile tp-test-mac
- name: Run nextest (Windows)
timeout-minutes: 120
if: matrix.os.name == 'windows'
run: |
cargo tp-test --profile tp-test-win
- name: Upload results
if: always()
uses: actions/upload-artifact@v3
with:
name: test_reports
path: target/nextest/**/*.xml
turbopack_rust_test_bench1:
needs: [turbopack_rust_check]
runs-on: ubuntu-latest-16-core-oss
name: Turbopack Rust testing benchmarks on ubuntu
env:
TURBOPACK_BENCH_COUNTS: "100"
TURBOPACK_BENCH_PROGRESS: "1"
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
save-cache: true
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
# TODO: update to Node 18. Currently fails because the node-canvas dependency doesn't compile for node 18
# Did not spend too much time investigating so it could be an easy fix.
node-version: 16
- name: Build benchmarks for tests
timeout-minutes: 120
run: |
cargo tp-bench-test --no-run
- name: Run cargo test on benchmarks
timeout-minutes: 120
run: |
cargo tp-bench-test
- name: Build benchmarks for tests for other bundlers
if: needs.determine_jobs.outputs.turbopack_bench == 'true'
timeout-minutes: 120
run: |
cargo test --benches --release -p turbopack-bench --no-run
- name: Run cargo test on benchmarks for other bundlers
if: needs.determine_jobs.outputs.turbopack_bench == 'true'
timeout-minutes: 120
run: |
cargo test --benches --release -p turbopack-bench
turbopack_rust_test_bench2:
needs: [turbopack_rust_check]
strategy:
fail-fast: false
matrix:
os:
- name: macos
runner: macos-latest
# Temporarily disable windows bench due to consistent timeouts
# - name: windows
# runner: windows-2019
runs-on: ${{ matrix.os.runner }}
name: Turbopack Rust testing benchmarks on ${{ matrix.os.name }}
env:
TURBOPACK_BENCH_COUNTS: "100"
TURBOPACK_BENCH_PROGRESS: "1"
steps:
- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
if: matrix.os.name == 'windows'
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
save-cache: true
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
# TODO: update to Node 18. Currently fails because the node-canvas dependency doesn't compile for node 18
# Did not spend too much time investigating so it could be an easy fix.
node-version: 16
- name: Build benchmarks for tests
timeout-minutes: 120
run: |
cargo test --benches --release --workspace --exclude turbopack-bench --no-run
- name: Run cargo test on benchmarks
timeout-minutes: 120
run: |
cargo test --benches --release --workspace --exclude turbopack-bench
- name: Build benchmarks for tests for other bundlers
if: needs.determine_jobs.outputs.turbopack_bench == 'true'
timeout-minutes: 120
run: |
cargo test --benches --release -p turbopack-bench --no-run
- name: Run cargo test on benchmarks for other bundlers
if: needs.determine_jobs.outputs.turbopack_bench == 'true'
timeout-minutes: 120
run: |
cargo test --benches --release -p turbopack-bench
turbopack_rust_bench:
needs: [determine_jobs, turbopack_rust_check]
if: needs.determine_jobs.outputs.push == 'true' || needs.determine_jobs.outputs.turbopack_bench == 'true'
strategy:
fail-fast: false
matrix:
bench:
# One of Turbopack with 1000 modules is benchmarked in every run
# to create a baseline result for normalization (should the runners performance vary between jobs)
# This runs all the non next-dev benchmarks
- name: generic
cache_key: all
args: --workspace --exclude turbopack-bench
# This measures Turbopack with small app
- name: turbopack
cache_key: turbopack-cli
args: -p turbopack-cli
TURBOPACK_BENCH_COUNTS: 100,500,1000
# This measures Turbopack with normal apps
- name: turbopack-large
cache_key: turbopack-cli
args: -p turbopack-cli
TURBOPACK_BENCH_COUNTS: 1000,2000,3000
# This measures Turbopack with larger apps
- name: turbopack-xlarge
cache_key: turbopack-cli
args: -p turbopack-cli
TURBOPACK_BENCH_COUNTS: 1000,5000
# This measures Turbopack with huge apps
- name: turbopack-xxlarge
cache_key: turbopack-cli
args: -p turbopack-cli
TURBOPACK_BENCH_COUNTS: 1000,10000
runs-on: ubuntu-latest-8-core-oss
name: Benchmark on ${{ matrix.bench.name }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
shared-cache-key: benchmark-${{ matrix.bench.cache_key }}
save-cache: true
- name: Clear benchmarks
run: rm -rf target/criterion
- name: Compile cargo benches
run: cargo bench --no-run ${{ matrix.bench.args }}
- name: Run cargo bench
timeout-minutes: 180
run: cargo bench ${{ matrix.bench.args }}
env:
TURBOPACK_BENCH_COUNTS: ${{ matrix.bench.TURBOPACK_BENCH_COUNTS }}
- name: Install critcmp
if: always()
uses: baptiste0928/cargo-install@v1
with:
crate: critcmp
- name: Compare results
if: always()
run: critcmp --group "([^/]+/)[^/]+(?:/)(.+)" base
- name: Export results
if: always()
run: critcmp --export base > raw.json
- name: Upload results to datadog
if: always()
continue-on-error: true
env:
DATADOG_API_KEY: ${{ secrets.DD_KEY_TURBOPACK }}
run: |
npm install -g @datadog/datadog-ci
# Query raw benchmark output, create key:value pairs for each benchmark entries.
# The generated key name is compact format the path of the benchmark entry, i.e
# `base.hmr_to_commit.CSR.1000.mean`
# [TODO]: datadog-ci sometimes return 400 without detail, need to investigate further. For now accept the flaky uploads.
for item in $(cat raw.json | jq -r ".benchmarks[] | { name: .fullname, mean: .criterion_estimates_v1.mean.point_estimate, std: .criterion_estimates_v1.std_dev.point_estimate } | @base64"); do
_jq() {
echo ${item} | base64 --decode | jq -r ${1}
}
export METRICS_MEAN+=" --metrics $(echo ${{ matrix.bench.name }} | sed -e 's/turbopack-//g').$(_jq ".name" | sed -e 's/\/bench_/\//g' | sed -e 's/\/Turbopack /\//g' | sed -e 's/ modules//g'| sed -e 's/ /./g' | sed -e 's/\//./g').mean:$(printf "%0.2f" $(_jq ".mean"))"
export METRICS_STD+=" --metrics $(echo ${{ matrix.bench.name }} | sed -e 's/turbopack-//g').$(_jq ".name" | sed -e 's/\/bench_/\//g' | sed -e 's/\/Turbopack /\//g' | sed -e 's/ modules//g'| sed -e 's/ /./g' | sed -e 's/\//./g').std:$(printf "%0.2f" $(_jq ".std"))"
done
echo "Sending metrics $METRICS_MEAN"
datadog-ci metric --level pipeline --no-fail $METRICS_MEAN
echo "Sending metrics $METRICS_STD"
datadog-ci metric --level pipeline --no-fail $METRICS_STD
- name: Upload results
if: always()
uses: actions/upload-artifact@v3
with:
name: bench_${{ matrix.bench.name }}
path: raw.json
# This avoids putting this data into the rust-cache
- name: Clear benchmarks
run: rm -rf target/criterion
turbopack_rust_bench_commit:
needs: [determine_jobs, turbopack_rust_bench]
if: always() && needs.determine_jobs.outputs.push == 'true'
name: Store benchmark result
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Get current date
id: date
run: |
echo "year=$(date +'%Y')" >> $GITHUB_OUTPUT
echo "month=$(date +'%m')" >> $GITHUB_OUTPUT
echo "date=$(date +'%s')" >> $GITHUB_OUTPUT
echo "pretty=$(date +'%Y-%m-%d %H:%M')" >> $GITHUB_OUTPUT
- name: Checkout benchmark-data
uses: actions/checkout@v3
with:
ref: benchmark-data
- name: Download benchmark data
uses: actions/download-artifact@v3
with:
path: artifacts
- name: Copy benchmark results
run: |
find artifacts -size 0 -delete
mkdir -p data/${{ steps.date.outputs.year }}/${{ steps.date.outputs.month }}/ubuntu-latest-8-core/${{ steps.date.outputs.date }}-${{ github.sha }}/
mv artifacts/bench_* data/${{ steps.date.outputs.year }}/${{ steps.date.outputs.month }}/ubuntu-latest-8-core/${{ steps.date.outputs.date }}-${{ github.sha }}/
- name: Git pull
run: git pull --depth=1 --no-tags origin benchmark-data
- name: Push data to branch
if: needs.determine_jobs.outputs.main_push == 'true'
uses: stefanzweifel/git-auto-commit-action@v4
with:
file_pattern: data/**
commit_message: Benchmark result for ${{ steps.date.outputs.pretty }} (${{ github.sha }})
turbopack_build_release:
needs: [determine_jobs, turbopack_rust_check]
if: needs.determine_jobs.outputs.push == 'true'
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu-latest-16-core-oss
target: x86_64-unknown-linux-musl
- name: macos-latest
target: x86_64-apple-darwin
- name: macos-latest
target: aarch64-apple-darwin
- name: ubuntu-latest-16-core-oss
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os.name }}
name: Rust building release for ${{ matrix.os.target }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
components: ${{ matrix.os.target == 'x86_64-pc-windows-msvc' && 'llvm-tools-preview' || '' }}
targets: ${{ matrix.os.target }}
cache-key: ${{ matrix.os.target }}
save-cache: true
- name: Install musl tools
run: |
wget https://github.com/napi-rs/napi-rs/releases/download/linux-musl-cross%4011.2.1/x86_64-linux-musl-native.tgz -O musl.tgz
tar -xvzf musl.tgz
sudo mv x86_64-linux-musl-native /usr/x86_64-linux-musl
sudo ln -sf /usr/x86_64-linux-musl/bin/x86_64-linux-musl-cc /usr/bin/musl-gcc
sudo ln -sf /usr/x86_64-linux-musl/bin/x86_64-linux-musl-g++ /usr/bin/musl-g++
if: matrix.os.target == 'x86_64-unknown-linux-musl'
- name: Install Cargo xwin toolchain
if: matrix.os.target == 'x86_64-pc-windows-msvc'
uses: baptiste0928/cargo-install@v1
with:
crate: cargo-xwin
- name: Build node-file-trace
if: matrix.os.target != 'x86_64-pc-windows-msvc'
run: |
cargo build --release -p node-file-trace --target ${{ matrix.os.target }}
- name: Build node-file-trace
if: matrix.os.target == 'x86_64-pc-windows-msvc'
run: |
cargo xwin build --release -p node-file-trace --target ${{ matrix.os.target }}
- name: Build turbopack-cli (native-tls)
if: matrix.os.target != 'x86_64-pc-windows-msvc' && matrix.os.target != 'x86_64-unknown-linux-musl'
run: |
cargo build --release -p turbopack-cli --target ${{ matrix.os.target }}
- name: Build turbopack-cli (rustls-tls)
if: matrix.os.target == 'x86_64-unknown-linux-musl'
run: |
cargo build --release -p turbopack-cli --target ${{ matrix.os.target }} --no-default-features --features custom_allocator,rustls-tls
- uses: actions/upload-artifact@v3
with:
name: release-${{ matrix.os.target }}
path: |
target/${{ matrix.os.target }}/release/turbopack-cli
target/${{ matrix.os.target }}/release/turbopack-cli.exe
turbopack_bench_pr:
needs: [turbopack_rust_check]
if: github.event_name == 'pull_request'
name: Benchmark and compare Turbopack performance on ${{ matrix.os.title }}
strategy:
fail-fast: false
matrix:
os:
- name: linux
title: Linux
quiet: false
runner: ubuntu-latest-16-core-oss
- name: macos
title: MacOS
quiet: true
runner: macos-latest
- name: windows
title: Windows
quiet: true
runner: windows-latest
runs-on: ${{ matrix.os.runner }}
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Fetch the base branch
run: git -c protocol.version=2 fetch --no-tags --progress --no-recurse-submodules --depth=1 origin +${{ github.base_ref }}:base
- name: Setup Go
uses: ./.github/actions/setup-go
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
shared-cache-key: benchmark-${{ matrix.os.name }}
- name: Benchmark and compare with base branch
uses: sokra/criterion-compare-action@main
timeout-minutes: 180
with:
branchName: base
title: ${{ matrix.os.title }} Benchmark
quiet: ${{ matrix.os.quiet }}
cwd: crates/turbopack-cli
format_lint:
name: Formatting
runs-on: ubuntu-latest
needs: determine_jobs
if: needs.determine_jobs.outputs.format == 'true'
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_REMOTE_ONLY: true
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: ./.github/actions/setup-turborepo-environment
with:
target: ubuntu
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Format check
# This is the syntax for running the `//#lint` task specifically in turbo.json
# It runs the taplo check on taplo.toml, and lint:prettier per workspace.
# Skip `cli` workspace for now. It has the lint task, but in GitHub CI
# we need to set up golangci-lint to make it work. Go linting is run in the "Go linting"
# job in this workflow. We can move that in here in the next step.
run: turbo run lint --filter=!cli
final:
name: Ok
needs:
- determine_jobs
- go_lint
- go_unit
- turborepo_examples
- turborepo_e2e
- go_integration
- js_packages
- rust_lint
- turborepo_rust_check
- turborepo_rust_clippy
- turbopack_rust_check
- turbopack_rust_clippy
- turbopack_rust_test1
- turbopack_typescript
- turborepo_rust_test
- turbopack_rust_test_bench1
- turbopack_build_release
- format_lint
if: always()
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Compute info
id: info
if: always()
run: |
cancelled=false
failure=false
subjob () {
local result=$1
local name=$2
if [ "$result" = "cancelled" ]; then
cancelled=true
elif [ "$result" != "success" ] && [ "$result" != "skipped" ]; then
echo "- $name" >> failures.md
failure=true
fi
}
subjob ${{needs.determine_jobs.result}} "Determining jobs"
subjob ${{needs.go_lint.result}} "Go lints"
subjob ${{needs.go_unit.result}} "Go unit tests"
subjob ${{needs.turborepo_examples.result}} "Turborepo examples"
subjob ${{needs.turborepo_e2e.result}} "Go e2e tests"
subjob ${{needs.go_integration.result}} "Go integration tests"
subjob ${{needs.js_packages.result}} "JS Package tests"
subjob ${{needs.rust_lint.result}} "Rust lints"
subjob ${{needs.turborepo_rust_check.result}} "Turborepo Rust checks"
subjob ${{needs.turborepo_rust_clippy.result}} "Turborepo Rust clippy"
subjob ${{needs.turbopack_rust_check.result}} "Turbopack Rust checks"
subjob ${{needs.turbopack_rust_clippy.result}} "Turbopack Rust clippy"
subjob ${{needs.turbopack_rust_test1.result}} "Turbopack Rust tests (linux)"
subjob ${{needs.turbopack_typescript.result}} "Turbopack Typescript checks"
subjob ${{needs.turborepo_rust_test.result}} "Turborepo Rust tests"
subjob ${{needs.turbopack_rust_test_bench1.result}} "Turbopack Rust benchmark tests (linux)"
subjob ${{needs.turbopack_build_release.result}} "Turbopack Release Build"
subjob ${{needs.format_lint.result}} "Formatting"
if [ "$cancelled" = "true" ]; then
echo "cancelled=true" >> $GITHUB_OUTPUT
elif [ "$failure" = "true" ]; then
echo "failure=true" >> $GITHUB_OUTPUT
else
echo "success=true" >> $GITHUB_OUTPUT
fi
- name: Add failure prose text
if: steps.info.outputs.failure == 'true'
run: |
echo "## :warning: CI failed :warning:" > comment.md
echo >> comment.md
echo "The following steps have failed in CI:" >> comment.md
echo >> comment.md
cat failures.md >> comment.md
echo >> comment.md
echo "See [workflow summary](https://github.com/vercel/turbo/actions/runs/${{ github.run_id }}) for details">> comment.md
echo >> comment.md
echo "<!-- CI COMMENT -->" >> comment.md
- name: Add success prose text
if: steps.info.outputs.success == 'true'
run: |
echo "## :green_circle: CI likely successful :green_circle:" > comment.md
echo >> comment.md
echo "A few longer running steps are still running, but they should not be considered as blocking." >> comment.md
echo >> comment.md
echo "See [workflow summary](https://github.com/vercel/turbo/actions/runs/${{ github.run_id }}) for details">> comment.md
echo >> comment.md
echo "<!-- CI COMMENT -->" >> comment.md
- name: Find PR Comment
id: comment
if: always() && github.event_name == 'pull_request' && steps.info.outputs.cancelled != 'true'
uses: peter-evans/find-comment@v2
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: "github-actions[bot]"
body-includes: "<!-- CI COMMENT -->"
- name: Create or update PR comment
if: always() && github.event_name == 'pull_request' && steps.info.outputs.cancelled != 'true'
uses: peter-evans/create-or-update-comment@v2
continue-on-error: true
with:
comment-id: ${{ steps.comment.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body-file: "comment.md"
edit-mode: replace
- name: It's not fine
if: steps.info.outputs.failure == 'true'
run: exit 1
- name: It's fine
if: steps.info.outputs.success == 'true'
run: echo Ok
# Upload Turbopack's test results into datadog.
upload_test_results:
name: Upload Test results
needs: [determine_jobs, turbopack_rust_test1, turbopack_rust_test2]
# We have to set condition to always, since we want to upload test results for the failed tests as well.
if: ${{ always() }}
runs-on: ubuntu-latest
# Do not block CI if upload fails for some reason
continue-on-error: true
steps:
# Uploading test results does not require turbopack's src codes, but this
# allows datadog uploader to sync with git information.
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3.6.0
with:
node-version: 18
- name: Install datadog
run: npm install -g @datadog/datadog-ci
- name: Download test results
uses: actions/download-artifact@v3
with:
path: artifacts
- name: Upload
continue-on-error: true
env:
DATADOG_API_KEY: ${{ secrets.DD_KEY_TURBOPACK }}
run: |
DD_ENV=ci datadog-ci junit upload --service Turbopack ./artifacts/test_reports/**/*.xml
done:
name: Done
needs:
- final
- determine_jobs
- go_lint
- go_unit
- turborepo_examples
- turborepo_e2e
- go_integration
- rust_lint
- turborepo_rust_check
- turborepo_rust_clippy
- turbopack_rust_check
- turbopack_rust_clippy
- turbopack_rust_test1
- turbopack_rust_test2
- turbopack_typescript
- turborepo_rust_test
- turbopack_rust_test_bench1
- turbopack_rust_test_bench2
- turbopack_build_release
- turbopack_rust_bench
- format_lint
if: always()
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Compute info
id: info
if: always()
run: |
cancelled=false
failure=false
subjob () {
local result=$1
local name=$2
echo "$name: $result"
if [ "$result" = "cancelled" ]; then
cancelled=true
elif [ "$result" != "success" ] && [ "$result" != "skipped" ]; then
echo "- $name" >> failures.md
failure=true
fi
}
subjob ${{needs.determine_jobs.result}} "Determining jobs"
subjob ${{needs.go_lint.result}} "Go lints"
subjob ${{needs.go_unit.result}} "Go unit tests"
subjob ${{needs.turborepo_examples.result}} "Turborepo examples"
subjob ${{needs.turborepo_e2e.result}} "Turborepo e2e tests"
subjob ${{needs.go_integration.result}} "Go integration tests"
subjob ${{needs.rust_lint.result}} "Rust lints"
subjob ${{needs.turborepo_rust_check.result}} "Turborepo Rust checks"
subjob ${{needs.turborepo_rust_clippy.result}} "Turborepo Rust clippy"
subjob ${{needs.turbopack_rust_check.result}} "Turbopack Rust checks"
subjob ${{needs.turbopack_rust_clippy.result}} "Turbopack Rust clippy"
subjob ${{needs.turbopack_rust_test1.result}} "Turbopack Rust tests (linux)"
subjob ${{needs.turbopack_rust_test2.result}} "Turbopack Rust tests (mac/win, non-blocking)"
subjob ${{needs.turbopack_typescript.result}} "Turbopack Typescript checks"
subjob ${{needs.turborepo_rust_test.result}} "TurboRepo Rust tests"
subjob ${{needs.turbopack_rust_test_bench1.result}} "Turbopack Rust benchmark tests (linux)"
subjob ${{needs.turbopack_rust_test_bench2.result}} "Turbopack Rust benchmark tests (mac/win, non-blocking)"
subjob ${{needs.format_lint.result}} "Formatting"
subjob ${{needs.turbopack_rust_bench.result}} "Turbopack Rust benchmarks (non-blocking)"
subjob ${{needs.turbopack_build_release.result}} "Turbopack Release Build"
if [ "$cancelled" = "true" ]; then
echo "cancelled=true" >> $GITHUB_OUTPUT
elif [ "$failure" = "true" ]; then
echo "failure=true" >> $GITHUB_OUTPUT
else
echo "success=true" >> $GITHUB_OUTPUT
fi
- name: Add failure prose text
if: steps.info.outputs.failure == 'true'
run: |
echo "## :warning: CI failed :warning:" > comment.md
echo >> comment.md
echo "The following steps have failed in CI:" >> comment.md
echo >> comment.md
cat failures.md >> comment.md
echo >> comment.md
echo "See [workflow summary](https://github.com/vercel/turbo/actions/runs/${{ github.run_id }}) for details">> comment.md
echo >> comment.md
echo "<!-- CI COMMENT -->" >> comment.md
- name: Add success prose text
if: steps.info.outputs.success == 'true'
run: |
echo "## :green_circle: CI successful :green_circle:" > comment.md
echo >> comment.md
echo "Thanks" >> comment.md
echo >> comment.md
echo "<!-- CI COMMENT -->" >> comment.md
- name: Find PR Comment
id: comment
if: always() && github.event_name == 'pull_request' && steps.info.outputs.cancelled != 'true'
uses: peter-evans/find-comment@v2
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: "github-actions[bot]"
body-includes: "<!-- CI COMMENT -->"
- name: Create or update PR comment
if: always() && github.event_name == 'pull_request' && steps.info.outputs.cancelled != 'true'
uses: peter-evans/create-or-update-comment@v2
continue-on-error: true
with:
comment-id: ${{ steps.comment.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body-file: "comment.md"
edit-mode: replace
- name: It's not fine
if: steps.info.outputs.failure == 'true'
run: exit 1
- name: It's fine
if: steps.info.outputs.success == 'true'
run: echo Ok
cleanup:
name: Cleanup
needs: [done]
if: always()
uses: ./.github/workflows/pr-clean-caches.yml
secrets: inherit