---
title: GitHub Actions
description: Learn how to use GitHub Actions with Turborepo.
---

import { PackageManagerTabs, Tab } from '#components/tabs';
import { Steps, Step } from '#components/steps';
import { Callout } from '#components/callout';

The following example shows how to use Turborepo with [GitHub Actions](https://github.com/features/actions).

For a given root `package.json`:

```json title="./package.json"
{
  "name": "my-turborepo",
  "scripts": {
    "build": "turbo run build",
    "test": "turbo run test"
  },
  "devDependencies": {
    "turbo": "latest"
  }
}
```

And a `turbo.json`:

```json title="./turbo.json"
{
  "$schema": "https://turborepo.com/schema.json",
  "tasks": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**", "other-output-dirs/**"],
      "dependsOn": ["^build"]
    },
    "test": {
      "dependsOn": ["^build"]
    }
  }
}
```

Create a file called `.github/workflows/ci.yml` in your repository with the following contents:

<PackageManagerTabs>
  <Tab value="pnpm">
    ```yaml title=".github/workflows/ci.yml"
    name: CI

    on:
      push:
        branches: ["main"]
      pull_request:
        types: [opened, synchronize]

    jobs:
      build:
        name: Build and Test
        timeout-minutes: 15
        runs-on: ubuntu-latest
        # To use Remote Caching, uncomment the next lines and follow the steps below.
        # env:
        #  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
        #  TURBO_TEAM: ${{ vars.TURBO_TEAM }}

        steps:
          - name: Check out code
            uses: actions/checkout@v4
            with:
              fetch-depth: 2

          - uses: pnpm/action-setup@v3
            with:
              version: 8

          - name: Setup Node.js environment
            uses: actions/setup-node@v4
            with:
              node-version: 20
              cache: 'pnpm'

          - name: Install dependencies
            run: pnpm install

          - name: Build
            run: pnpm build

          - name: Test
            run: pnpm test
    ```

  </Tab>

  <Tab value="yarn">

    ```yaml title=".github/workflows/ci.yml"
    name: CI

    on:
      push:
        branches: ["main"]
      pull_request:
        types: [opened, synchronize]

    jobs:
      build:
        name: Build and Test
        timeout-minutes: 15
        runs-on: ubuntu-latest
        # To use Remote Caching, uncomment the next lines and follow the steps below.
        # env:
        #  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
        #  TURBO_TEAM: ${{ vars.TURBO_TEAM }}

        steps:
          - name: Check out code
            uses: actions/checkout@v4
            with:
              fetch-depth: 2

          - name: Setup Node.js environment
            uses: actions/setup-node@v4
            with:
              node-version: 20
              cache: 'yarn'

          - name: Install dependencies
            run: yarn

          - name: Build
            run: yarn build

          - name: Test
            run: yarn test
    ```

  </Tab>
  <Tab value="npm">

    ```yaml title=".github/workflows/ci.yml"
    name: CI

    on:
      push:
        branches: ["main"]
      pull_request:
        types: [opened, synchronize]

    jobs:
      build:
        name: Build and Test
        timeout-minutes: 15
        runs-on: ubuntu-latest
        # To use Remote Caching, uncomment the next lines and follow the steps below.
        # env:
        #  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
        #  TURBO_TEAM: ${{ vars.TURBO_TEAM }}
        #  TURBO_REMOTE_ONLY: true

        steps:
          - name: Check out code
            uses: actions/checkout@v4
            with:
              fetch-depth: 2

          - name: Setup Node.js environment
            uses: actions/setup-node@v4
            with:
              node-version: 20
              cache: 'npm'

          - name: Install dependencies
            run: npm install

          - name: Build
            run: npm run build

          - name: Test
            run: npm run test
    ```

  </Tab>

  <Tab value="bun (Beta)">
    ```yaml title=".github/workflows/ci.yml"
    name: CI

    on:
      push:
        branches: ["main"]
      pull_request:
        types: [opened, synchronize]

    jobs:
      build:
        name: Build and Test
        timeout-minutes: 15
        runs-on: ubuntu-latest
        # To use Remote Caching, uncomment the next lines and follow the steps below.
        # env:
        #  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
        #  TURBO_TEAM: ${{ vars.TURBO_TEAM }}

        steps:
          - name: Check out code
            uses: actions/checkout@v4
            with:
              fetch-depth: 2

          - uses: oven-sh/setup-bun@v2

          - name: Setup Node.js environment
            uses: actions/setup-node@v4
            with:
              node-version: 20

          - name: Install dependencies
            run: bun install

          - name: Build
            run: bun run build

          - name: Test
            run: bun run test
    ```

  </Tab>

</PackageManagerTabs>

## Remote Caching with Vercel Remote Cache

To use Remote Caching with GitHub Actions, add the following environment variables to your GitHub Actions workflow
to make them available to your `turbo` commands.

- `TURBO_TOKEN` - The Bearer token to access the Remote Cache
- `TURBO_TEAM` - The slug of the Vercel team to share the artifacts with

To use Remote Caching, retrieve the team and token for the Remote Cache for your provider. In this example, we'll use [Vercel Remote Cache](https://vercel.com/docs/monorepos/remote-caching).

<Steps>
<Step>
Create a Scoped Access Token to your account in the [Vercel Dashboard](https://vercel.com/account/tokens)

![Vercel Access Tokens](/images/docs/vercel-create-token.png)

Copy the value to a safe place. You'll need it in a moment.

</Step>
<Step>
Go to your GitHub repository settings and click on the **Secrets** and then **Actions** tab. Create a new secret called `TURBO_TOKEN` and enter the value of your Scoped Access Token.

![GitHub Secrets](/images/docs/github-actions-secrets.png)
![GitHub Secrets Create](/images/docs/github-actions-create-secret.png)

</Step>

<Step>
Create a new repository variable (click the **Variables** tab) called `TURBO_TEAM` and set it to your team slug - the part after `vercel.com/` in [your Team URL](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fsettings&title=Find+Team+URL). For example, the slug for `vercel.com/acme` is `acme`.

<Callout type="good-to-know">
  Using a repository variable rather than a secret will keep GitHub Actions from
  censoring your team name in log output.
</Callout>

![GitHub Repository Variables](/images/docs/vercel-team-repo-var.png)

</Step>
<Step>
At the top of your GitHub Actions workflow, provide the following environment variables to jobs that use `turbo`:

```yaml title=".github/workflows/ci.yml"
# ...

jobs:
  build:
    name: Build and Test
    timeout-minutes: 15
    runs-on: ubuntu-latest
    # To use Turborepo Remote Caching, set the following environment variables for the job.
    env: # [!code highlight]
      TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} # [!code highlight]
      TURBO_TEAM: ${{ vars.TURBO_TEAM }} # [!code highlight]

    steps:
      - name: Check out code
        uses: actions/checkout@v4
        with:
          fetch-depth: 2
    # ...
```

</Step>
</Steps>

## Using Remote Caching with Reusable Workflows

For information on passing secrets to reusable workflows, see [GitHub's documentation on passing secrets to nested workflows](https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows#passing-secrets-to-nested-workflows).

## Remote Caching with GitHub actions/cache

The following steps show how you could use [actions/cache](https://github.com/actions/cache) to cache your monorepo artifacts on GitHub.

<Steps>
<Step>
Supply a package.json script that will run tasks using Turborepo.

Example `package.json` with a `build` script:

```json title="./package.json"
{
  "name": "my-turborepo",
  "scripts": {
    "build": "turbo run build"
  },
  "devDependencies": {
    "turbo": "1.2.5"
  }
}
```

</Step>
<Step>
Configure your GitHub pipeline with a step which uses the `actions/cache@v4` action before the build steps of your CI file.

- Make sure that the `path` attribute set within the `actions/cache` action matches the output location above. In the example below, `path` was set to `.turbo`.
- State the cache key for the current run under the `key` attribute. In the example below, we used a combination of the runner os and GitHub sha as the cache key.
- State the desired cache prefix pattern under the `restore-keys` attribute. Make sure this pattern will remain valid for future ci runs. In the example below, we used the `${{ runner.os }}-turbo-` as the cache key prefix pattern to search against. This allows us to hit the cache on any subsequent ci runs despite `github.sha` changing.

Example `ci` yaml with `.turbo` as chosen cache folder:

```yaml title=".github/workflows/ci.yml"
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Cache turbo build setup # [!code highlight]
        uses: actions/cache@v4 # [!code highlight]
        with: # [!code highlight]
          path: .turbo # [!code highlight]
          key: ${{ runner.os }}-turbo-${{ github.sha }} # [!code highlight]
          restore-keys: | # [!code highlight]
            ${{ runner.os }}-turbo-

      - name: Setup Node.js environment
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npm run build
```

</Step>
</Steps>
