Skip to content

docs: Add Bun equivalent for updating dependencies (#12580) #10160

docs: Add Bun equivalent for updating dependencies (#12580)

docs: Add Bun equivalent for updating dependencies (#12580) #10160

name: Test
on:
pull_request:
push:
branches: [main]
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: write
jobs:
find-changes:
name: Find path changes
runs-on: ubuntu-latest
timeout-minutes: 30
outputs:
is-release-pr: ${{ steps.check-release.outputs.is-release-pr }}
docs: ${{ steps.filter.outputs.docs }}
rest: ${{ steps.filter.outputs.rest }}
rust: ${{ steps.filter.outputs.rust }}
native-lib: ${{ steps.filter.outputs.native-lib }}
steps:
# Detect automated release PRs which only contain version bumps.
# These PRs are created by the release workflow after code has already
# been tested on main. Skipping tests on version-only changes saves CI time.
- name: Checkout
uses: actions/checkout@v4
- name: Check if automated release PR
id: check-release
uses: ./.github/actions/check-release-pr
- name: Check path changes
if: steps.check-release.outputs.is-release-pr != 'true'
id: filter
run: |
# Determine the base and head commits to compare
if [ "${{ github.event_name }}" == "pull_request" ]; then
# For pull requests, compare the base branch to the current HEAD
git fetch origin ${{ github.base_ref }}
BASE_COMMIT="origin/${{ github.base_ref }}"
HEAD_COMMIT="HEAD"
else
# For pushes, use the before and after SHAs
BASE_COMMIT="${{ github.event.before }}"
HEAD_COMMIT="${{ github.event.after }}"
fi
echo "Comparing changes between $BASE_COMMIT and $HEAD_COMMIT"
# Function to check if files in given paths have changed
check_path_changes() {
local name=$1
shift
local paths=("$@")
# Create a command that checks all paths
local cmd="git diff --name-only $BASE_COMMIT $HEAD_COMMIT -- "
for path in "${paths[@]}"; do
cmd+="\"$path\" "
done
# Run the command and check if there are any results
if eval "$cmd" | grep -q .; then
echo "$name=true" >> $GITHUB_OUTPUT
echo "Changes detected in $name paths"
else
echo "$name=false" >> $GITHUB_OUTPUT
echo "No changes in $name paths"
fi
}
# Function to make path checking more readable
check_paths() {
local name=$1
local path_string=$2
# Convert the comma-separated string to an array
IFS=',' read -ra path_array <<< "$path_string"
# Call the check_path_changes function with the name and paths
check_path_changes "$name" "${path_array[@]}"
}
# Check each path pattern with a more readable syntax
echo "Checking path patterns..."
check_paths "docs" "docs/"
check_paths "native-lib" "packages/turbo-repository/,crates/"
# Handle the "rest" pattern - files that are NOT in examples/ or docs/
CHANGED_FILES=$(git diff --name-only $BASE_COMMIT $HEAD_COMMIT)
# Filter to only include files that do NOT start with examples/ or docs/
FILES_NOT_IN_EXAMPLES_OR_DOCS=$(echo "$CHANGED_FILES" | grep -v -E "^(examples/|docs/)" || true)
if [ -n "$FILES_NOT_IN_EXAMPLES_OR_DOCS" ]; then
echo "rest=true" >> $GITHUB_OUTPUT
echo "Changes detected outside examples/ and docs/ directories"
else
echo "rest=false" >> $GITHUB_OUTPUT
echo "No changes outside examples/ and docs/ directories"
fi
# Detect if Rust/core code changed (requires Rust tests + integration tests)
# This excludes JS-only changes like packages/*, lockfile, etc.
RUST_PATTERNS="^(crates/|cli/|Cargo\.|rust-toolchain|\.cargo/|\.config/|\.github/|turborepo-tests/)"
RUST_CHANGES=$(echo "$CHANGED_FILES" | grep -E "$RUST_PATTERNS" || true)
if [ -n "$RUST_CHANGES" ]; then
echo "rust=true" >> $GITHUB_OUTPUT
echo "Rust/core changes detected:"
echo "$RUST_CHANGES"
else
echo "rust=false" >> $GITHUB_OUTPUT
echo "No Rust/core changes detected (JS-only change)"
fi
turbo_types_check:
name: "@turbo/types codegen check"
needs:
- find-changes
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && needs.find-changes.outputs.rust == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Generate schemas from Rust
run: |
cargo run -p turborepo-schema-gen -- schema -o packages/turbo-types/schemas/schema.json
cargo run -p turborepo-schema-gen -- typescript -o packages/turbo-types/src/types/config-v2.ts
pnpm exec oxfmt packages/turbo-types/schemas/schema.json packages/turbo-types/src/types/config-v2.ts
- name: Check for uncommitted changes
run: |
if ! git diff --exit-code; then
echo "::error::Generated schema files are out of sync with Rust types"
echo "::error::Please run 'pnpm generate-schema' in packages/turbo-types and commit the changes"
git diff
exit 1
fi
build_rust_test_windows:
runs-on: windows-latest-8-core-oss
timeout-minutes: 45
needs:
- find-changes
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && needs.find-changes.outputs.rust == 'true' }}
name: Build test artifacts (windows)
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
SCCACHE_BUCKET: turborepo-sccache
SCCACHE_REGION: us-east-2
RUSTC_WRAPPER: ${{ !github.event.pull_request.head.repo.fork && 'sccache' || '' }}
CARGO_INCREMENTAL: 0
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
SCCACHE_IDLE_TIMEOUT: 0
SCCACHE_REQUEST_TIMEOUT: 30
SCCACHE_ERROR_LOG: error
steps:
- name: Install git (Windows larger runners)
shell: cmd
run: |
curl -L -o "%TEMP%\mingit.zip" "https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.2/MinGit-2.47.1.2-64-bit.zip"
mkdir "%ProgramFiles%\Git"
tar -xf "%TEMP%\mingit.zip" -C "%ProgramFiles%\Git"
del "%ProgramFiles%\Git\etc\gitconfig"
echo %ProgramFiles%\Git\cmd>> "%GITHUB_PATH%"
- name: Set git to use LF line endings
# Ensures the turborepo source code is checked out with LF endings
# so the Rust build and test fixtures work correctly. Turbo's CRLF
# normalization is driven by .gitattributes (not core.autocrlf).
# Tests create CRLF content directly and configure repos per-test —
# see turborepo-scm's crlf.rs and package_deps.rs CRLF tests.
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
node-version: "18.20.2"
package-install: "false"
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.6
- name: Install cargo-nextest
shell: cmd
run: |
curl -L -o "%TEMP%\nextest.zip" "https://get.nexte.st/latest/windows"
tar -xf "%TEMP%\nextest.zip" -C "%USERPROFILE%\.cargo\bin"
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Build and archive test binaries
run: |
if [ -z "${RUSTC_WRAPPER}" ]; then
unset RUSTC_WRAPPER
fi
turbo run build:test-archive --filter=@turbo/cli
shell: bash
build_rust_test_macos:
runs-on: macos-latest-xlarge
timeout-minutes: 45
needs:
- find-changes
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && needs.find-changes.outputs.rust == 'true' }}
name: Build test artifacts (macos)
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
SCCACHE_BUCKET: turborepo-sccache
SCCACHE_REGION: us-east-2
RUSTC_WRAPPER: ${{ !github.event.pull_request.head.repo.fork && 'sccache' || '' }}
CARGO_INCREMENTAL: 0
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
SCCACHE_IDLE_TIMEOUT: 0
SCCACHE_REQUEST_TIMEOUT: 30
SCCACHE_ERROR_LOG: error
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
node-version: "18.20.2"
package-install: "false"
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.6
- name: Install cargo-nextest
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532
with:
tool: nextest
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Build and archive test binaries
run: |
if [ -z "${RUSTC_WRAPPER}" ]; then
unset RUSTC_WRAPPER
fi
turbo run build:test-archive --filter=@turbo/cli
shell: bash
rust_test_macos:
runs-on: macos-latest-xlarge
timeout-minutes: 45
needs:
- find-changes
- build_rust_test_macos
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && needs.find-changes.outputs.rust == 'true' }}
strategy:
fail-fast: false
matrix:
partition: [1, 2]
name: Rust testing on macos (partition ${{ matrix.partition }}/2)
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
node-version: "18.20.2"
package-install: "false"
- name: Install Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1
- name: Install cargo-nextest
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532
with:
tool: nextest
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Restore test archive from cache
run: turbo run build:test-archive --filter=@turbo/cli
shell: bash
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
- name: Run tests
timeout-minutes: 45
run: |
cargo nextest run --archive-file cli/nextest-archive.tar.zst --no-fail-fast --partition hash:${{ matrix.partition }}/2
shell: bash
rust_test_windows:
strategy:
fail-fast: false
matrix:
partition: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
runs-on: windows-latest
timeout-minutes: 45
needs:
- find-changes
- build_rust_test_windows
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && needs.find-changes.outputs.rust == 'true' }}
name: Rust testing on windows (partition ${{ matrix.partition }}/10)
steps:
- name: Set git to use LF line endings
# Ensures the turborepo source code is checked out with LF endings
# so the Rust build and test fixtures work correctly. Turbo's CRLF
# normalization is driven by .gitattributes (not core.autocrlf).
# Tests create CRLF content directly and configure repos per-test —
# see turborepo-scm's crlf.rs and package_deps.rs CRLF tests.
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
node-version: "18.20.2"
capnproto: ${{ github.event.pull_request.head.repo.fork && 'true' || 'false' }}
rust: ${{ github.event.pull_request.head.repo.fork && 'true' || 'false' }}
package-install: "false"
rust-cache: "false"
- name: Install Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1
- name: Install cargo-nextest
shell: cmd
run: |
curl -L -o "%TEMP%\nextest.zip" "https://get.nexte.st/latest/windows"
tar -xf "%TEMP%\nextest.zip" -C "%USERPROFILE%\.cargo\bin"
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Restore test archive from cache
run: turbo run build:test-archive --filter=@turbo/cli
shell: bash
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
- name: Run tests
timeout-minutes: 45
run: |
cargo nextest run --archive-file cli/nextest-archive.tar.zst --no-fail-fast --partition hash:${{ matrix.partition }}/10 --workspace-remap "$GITHUB_WORKSPACE"
shell: bash
env:
INSTA_WORKSPACE_ROOT: ${{ github.workspace }}
build_rust_test_ubuntu:
runs-on: ubuntu-latest
timeout-minutes: 45
needs:
- find-changes
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && needs.find-changes.outputs.rust == 'true' }}
name: Build test artifacts (ubuntu)
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
SCCACHE_BUCKET: turborepo-sccache
SCCACHE_REGION: us-east-2
RUSTC_WRAPPER: ${{ !github.event.pull_request.head.repo.fork && 'sccache' || '' }}
CARGO_INCREMENTAL: 0
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
SCCACHE_IDLE_TIMEOUT: 0
SCCACHE_REQUEST_TIMEOUT: 30
SCCACHE_ERROR_LOG: error
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
node-version: "18.20.2"
package-install: "false"
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.6
- name: Install cargo-nextest
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532
with:
tool: nextest
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Build and archive test binaries
run: |
if [ -z "${RUSTC_WRAPPER}" ]; then
unset RUSTC_WRAPPER
fi
turbo run build:test-archive --filter=@turbo/cli
shell: bash
rust_test_ubuntu:
runs-on: ubuntu-latest
timeout-minutes: 45
needs:
- find-changes
- build_rust_test_ubuntu
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && needs.find-changes.outputs.rust == 'true' }}
strategy:
fail-fast: false
matrix:
partition: [1, 2]
name: Rust testing on ubuntu (partition ${{ matrix.partition }}/2)
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
node-version: "18.20.2"
package-install: "false"
- name: Install Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1
- name: Install cargo-nextest
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532
with:
tool: nextest
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Restore test archive from cache
run: turbo run build:test-archive --filter=@turbo/cli
shell: bash
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
- name: Run tests
timeout-minutes: 45
run: |
cargo nextest run --archive-file cli/nextest-archive.tar.zst --no-fail-fast --partition hash:${{ matrix.partition }}/2
shell: bash
check-examples:
name: Check examples
timeout-minutes: 40
needs:
- find-changes
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Install dependencies
run: pnpm install
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Setup Vercel credentials
run: |
cd examples
npx vercel link --yes --token=${{ secrets.VERCEL_TOKEN }} --project turborepo-examples-app
npx vercel env pull --yes --token=${{ secrets.VERCEL_TOKEN }}
- name: Run examples check
run: turbo run check-examples --filter=turborepo-examples --env-mode=strict
check-lockfiles:
name: Integration - Lockfile parsers
timeout-minutes: 15
needs:
- find-changes
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' }}
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
SCCACHE_BUCKET: turborepo-sccache
SCCACHE_REGION: us-east-2
RUSTC_WRAPPER: ${{ !github.event.pull_request.head.repo.fork && 'sccache' || '' }}
CARGO_INCREMENTAL: 0
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.6
- name: Build turbo binary
run: cargo build
- name: Run lockfile tests
run: pnpm check-lockfiles
working-directory: lockfile-tests
js_native_packages:
name: "@turbo/repository (${{matrix.os.name}}, Node ${{matrix.node-version}})"
needs:
- find-changes
if: ${{ needs.find-changes.outputs.is-release-pr != 'true' && needs.find-changes.outputs.native-lib == 'true' }}
timeout-minutes: 30
runs-on: ${{ matrix.os.runner }}
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
runner: ubuntu-latest
- name: macos
runner: macos-latest
node-version:
- 18
- 20
- 22
- 24
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_CACHE: remote:rw
steps:
- name: Determine fetch depth
id: fetch-depth
run: |
echo "depth=$(( ${{ github.event.pull_request.commits || 1 }} + 1 ))" >> $GITHUB_OUTPUT
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
fetch-depth: ${{ steps.fetch-depth.outputs.depth }}
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
node-version: ${{ matrix.node-version }}
- name: Install Global Turbo
uses: ./.github/actions/install-global-turbo
- name: Run tests
run: |
TURBO_API= turbo run test --filter "turborepo-repository" --color --env-mode=strict
env:
NODE_VERSION: ${{ matrix.node-version }}
summary:
name: Test Summary
runs-on: ubuntu-latest
timeout-minutes: 30
if: always()
needs:
- find-changes
- turbo_types_check
- build_rust_test_macos
- build_rust_test_windows
- build_rust_test_ubuntu
- rust_test_macos
- rust_test_windows
- rust_test_ubuntu
- check-examples
- check-lockfiles
- js_native_packages
steps:
- name: Skip for release PR
if: needs.find-changes.outputs.is-release-pr == 'true'
run: |
echo "Release PR detected - skipping tests (code already tested on main)"
- name: Compute info
id: info
if: needs.find-changes.outputs.is-release-pr != 'true'
run: |
cancelled=false
failure=false
subjob () {
local result=$1
if [ "$result" = "cancelled" ]; then
cancelled=true
elif [ "$result" != "success" ] && [ "$result" != "skipped" ]; then
failure=true
fi
}
subjob ${{needs.turbo_types_check.result}}
subjob ${{needs.build_rust_test_macos.result}}
subjob ${{needs.build_rust_test_windows.result}}
subjob ${{needs.build_rust_test_ubuntu.result}}
subjob ${{needs.rust_test_macos.result}}
subjob ${{needs.rust_test_windows.result}}
subjob ${{needs.rust_test_ubuntu.result}}
subjob ${{needs.check-examples.result}}
subjob ${{needs.check-lockfiles.result}}
subjob ${{needs.js_native_packages.result}}
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: Failed
if: needs.find-changes.outputs.is-release-pr != 'true' && steps.info.outputs.failure == 'true'
run: exit 1
- name: Succeeded
if: needs.find-changes.outputs.is-release-pr != 'true' && steps.info.outputs.success == 'true'
run: echo Ok
cleanup:
name: Cleanup
needs: summary
if: always()
uses: ./.github/workflows/pr-clean-caches.yml
secrets: inherit