diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1c3482fea5ab8..97af43858a721 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,103 +1,101 @@ -# Contributing to Turbo +Thank you for your interest in contributing to Turborepo! -Thanks for your interest in contributing to Turbo! +- [General dependencies](#general-dependencies) +- [Optional dependencies](#optional-dependencies) +- [Structure of the repository](#structure-of-the-repository) +- [Building Turborepo](#building-turborepo) + - [TLS implementation](#tls-implementation) +- [Running tests](#running-tests) +- [Manually testing `turbo`](#manually-testing-turbo) + - [Repositories to test with](#repositories-to-test-with) +- [Debugging tips](#debugging-tips) + - [Verbose logging](#verbose-logging) + - [Crash logs](#crash-logs) + - [Terminal UI debugging](#terminal-ui-debugging) +- [Publishing `turbo` to the npm registry](#publishing-turbo-to-the-npm-registry) +- [Contributing to examples](#contributing-to-examples) + - [Contributing to an existing example](#contributing-to-an-existing-example) + - [Philosophy for new examples](#philosophy-for-new-examples) + - [Designing a new example](#designing-a-new-example) + - [Testing examples](#testing-examples) -- [Contributing to Turbo](#contributing-to-turbo) - - [General Dependencies](#general-dependencies) - - [Linux Dependencies](#linux-dependencies) - - [Contributing to Turborepo](#contributing-to-turborepo) - - [Building Turborepo](#building-turborepo) - - [TLS Implementation](#tls-implementation) - - [Running Turborepo Tests](#running-turborepo-tests) - - [Turborepo Tests](#turborepo-tests) - - [Debugging Turborepo](#debugging-turborepo) - - [Benchmarking Turborepo](#benchmarking-turborepo) - - [Updating `turbo`](#updating-turbo) - - [Manually testing `turbo`](#manually-testing-turbo) - - [Publishing `turbo` to the npm registry](#publishing-turbo-to-the-npm-registry) - - [Creating a new release blog post](#creating-a-new-release-blog-post) - - [Troubleshooting](#troubleshooting) +## General dependencies -## General Dependencies +You will need to have these dependences installed on your machine to work on this repository: -- [Rust](https://www.rust-lang.org/tools/install) -- [cargo-groups](https://github.com/nicholaslyang/cargo-groups) -- NodeJS v18 -- npm v10.5.0 (note: this is determined by the GitHub Actions CI, when in doubt, look at what the runner is using) -- capnproto -- protoc +- [Rust](https://www.rust-lang.org/tools/install) ([Repository toolchain](https://github.com/vercel/turborepo/blob/main/rust-toolchain.toml)) +- [NodeJS](https://nodejs.org/en) v20 +- [pnpm](https://pnpm.io/) v8 -### Linux Dependencies +### Optional dependencies -- LLD (LLVM Linker), as it's not installed by default on many Linux distributions (e.g. `apt install lld`). +- For running tests locally, `jq` and `zstd` are also required. + - macOS: `brew install jq zstd` + - Linux: ``sudo apt update && sudo apt install jq zstd` + - Windows: `choco install jq zstandard +- On Linux, ensure LLD (LLVM Linker) is installed, as it's not installed by default on many Linux distributions (e.g. `apt install lld`). -## Contributing to Turborepo +## Structure of the repository -### Building Turborepo +In general, there are two major areas in the repository: -Dependencies +- The `crates` directory with the Rust code for the `turbo` binary +- The `packages` directory with JavaScript packages +- the `examples` directory with examples of how to use Turborepo with other tools and frameworks +- The `docs` directory with the documentation for Turborepo -1. Install [turborepo crate](./crates/turborepo/README.md) build requirements +## Building Turborepo -1. Run `pnpm install` at root - -Building - -- Building `turbo` CLI: `cargo build --package turbo` -- Using `turbo` to build `turbo` CLI: `./turbow.js` +1. Run `pnpm install` at the root of the repository +2. Run `cargo build` ### TLS Implementation -Turborepo uses `reqwest`, a Rust HTTP client, to make requests to the Turbo API. `reqwest` supports two TLS +Turborepo uses [`reqwest`](https://docs.rs/reqwest/latest/reqwest/) to make requests to the Remote Cache. + +`reqwest` supports two TLS implementations: `rustls` and `native-tls`. `rustls` is a pure Rust implementation of TLS, while `native-tls` -is a wrapper around OpenSSL. Turborepo allows users to select which implementation they want with the `native-tls` -and `rustls-tls` features. By default, the `rustls-tls` feature is selected---this is done so that `cargo build` works -out of the box. If you wish to select `native-tls`, you may do so by passing -`--no-default-features --features native-tls` -to the build command. +is a wrapper around OpenSSL. You may select which implementation you want with the `native-tls` +and `rustls-tls` features. + +By default, the `rustls-tls` feature is selected so that `cargo build` works +out of the box. If you wish to select `native-tls`, you may do so by running `cargo build --no-default-features --features native-tls`. + +## Running tests + +> [!IMPORTANT] +> You will need to have `jq` and `zstd` installed on your system in order to run tests. See [General dDependencies](#general-dependencies) for instructions on how to install these tools. -### Running Turborepo Tests +First, install Turborepo globally with your package manager of choice. For instance, with npm, `npm install -g turbo`. This will install the `turbo` binary in your system's `PATH`, making it globally available. -Install dependencies +Now, from the root directory, you can run: -On macOS: +- Unit tests ```bash -brew install jq zstd + cargo test ``` -#### Turborepo Tests +- A module's unit tests -First: `npm install -g turbo`. - -Then from the root directory, you can run: +```bash +cargo test -p +``` -- Go unit tests - ```bash - pnpm test -- --filter=cli - ``` -- Rust unit tests ([install `nextest` first](https://nexte.st/book/pre-built-binaries.html)) - ```bash - cargo nextest run -p turborepo-lib --features rustls-tls - ``` - You can also use the built in [`cargo test`](https://doc.rust-lang.org/cargo/commands/cargo-test.html) - directly with `cargo test -p turborepo-lib`. -- CLI Integration tests +- Integration tests ```bash pnpm test -- --filter=turborepo-tests-integration ``` -- A single Integration test - e.g to run everything in `tests/run-summary`: +- A single integration test + e.g to run everything in `turborepo-tests/integration/tests/run-summary`: - ``` - # build first because the next command doesn't run through turbo + ```bash + # Build `turbo` first because the next command doesn't run through `turbo` pnpm -- turbo run build --filter=cli pnpm test -F turborepo-tests-integration -- "run-summary" ``` - Note: this is not through turbo, so you'll have to build turbo yourself first. - -- Updating Integration Tests +- Updating integration tests ``` turbo run build --filter=cli @@ -110,100 +108,115 @@ Then from the root directory, you can run: pnpm --filter turborepo-tests-integration test:interactive tests/turbo-help.t ``` -- Example tests - ```bash - pnpm test -- --filter=turborepo-tests-examples -- - ``` +## Manually testing `turbo` -## Debugging Turborepo +After [building `turbo`](#building-turborepo), you can manually test `turbo` for the behaviors you're affecting with your changes. We recommend setting an alias to the built binary so you can call it with your alias. -1. Install `go install github.com/go-delve/delve/cmd/dlv@latest` -1. In VS Code's "Run and Debug" tab, select `Build Basic` to start debugging the initial launch of `turbo` against the - `build` target of the Basic Example. This task is configured in [launch.json](./.vscode/launch.json). +```bash +alias devturbo='~/projects/turbo/target/debug/turbo' +devturbo run build --skip-infer +``` -## Benchmarking Turborepo +> [!IMPORTANT] +> The `--skip-infer` flag is required so that `turbo` doesn't try to use a locally installed binary of `turbo`. Forgetting to use this flag will cause `devturbo` to defer to the binary installed into the repository. -Follow the instructions in the [`benchmark/README.md`](./benchmark/README.md). +A non-exhaustive list of things to check on: -## Updating `turbo` +- Features related to your changes +- Test with and without daemon +- Installation scenarios + - Global only. `turbo` is installed as global binary without a local `turbo` in repository. + - Local only. `turbo` is installed as local binary without global `turbo` in PATH. turbo` is invoked via a root package + script. + - Global and local. `turbo` is installed as global binary, and local `turbo` in repository. Global `turbo` delegates to + local `turbo` -You might need to update `packages/turbo` in order to support a new platform. When you do that you will need to link the -module in order to be able to continue working. As an example, with `npm link`: +### Repositories to test with -```sh -cd ~/repos/vercel/turbo/packages/turbo -npm link +There are many open-source Turborepos out in the community that you can test with. A few are listed below: -# Run your build, e.g. `go build ./cmd/turbo` if you're on the platform you're adding. -cd ~/repos/vercel/turbo/cli -go build ./cmd/turbo +- [Next.js](https://github.com/vercel/next.js) +- [tldraw](https://github.com/tldraw/tldraw) +- [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss) +- [Vercel CLI](https://github.com/vercel/vercel) +- This repository! Keep in mind that you'll be building and running `turbo` in the same repository, which can be confusing at times. -# You can then run the basic example specifying the build asset path. -cd ~/repos/vercel/turbo/examples/basic -TURBO_BINARY_PATH=~/repos/vercel/turbo/cli/turbo.exe npm install -TURBO_BINARY_PATH=~/repos/vercel/turbo/cli/turbo.exe npm link turbo -``` +## Debugging tips -If you're using a different package manager replace npm accordingly. +### Verbose logging -## Manually testing `turbo` +Verbose logging can be enabled by using the `-v`, `-vv`, or `-vvv` flag on your `turbo` command, depending on the level of logging you're looking for. -Before releasing, it's recommended to test the `turbo` binary manually. -Here's a checklist of testing strategies to cover: +```bash +turbo build --vvv +``` -- Test `login`, `logout`, `login --sso-team`, `link`, `unlink` -- Test `prune` (Note `turbo` here is the unreleased turbo binary) - - `pnpm dlx create-turbo@latest prune-test --package-manager pnpm && cd prune-test` - - `turbo --skip-infer prune docs && cd out && pnpm install --frozen-lockfile` - - `turbo --skip-infer build` -- Test `--dry-run` and `--graph`. -- Test with and without daemon. +### Crash logs -There are also multiple installation scenarios worth testing: +In the event of a crash, Rust's crash logs will be written to your temp directory. When `turbo` crashes, the location of the crash log will be printed to the console. -- Global-only. `turbo` is installed as global binary, no local `turbo` in repository. -- Local-only. `turbo` is installed as local binary, no global `turbo` in PATH. turbo` is invoked via a root package - script. -- Global + local. `turbo` is installed as global binary, and local `turbo` in repository. Global `turbo` delegates to - local `turbo` +### Terminal UI debugging -Here are a few repositories that you can test on: +The architecture of the Terminal UI makes for a tricky debugging experience. Because the UI writes to the console through `stdout` in a specific way, using `println!()` statements won't work as expected. -- [next.js](https://github.com/vercel/next.js) -- [tldraw](https://github.com/tldraw/tldraw) -- [tailwindcss](https://github.com/tailwindlabs/tailwindcss) -- [vercel](https://github.com/vercel/vercel) +Instead, use `eprintln!()` to print to `stdout` and output `stdout` to a file: + +```bash +# devturbo is an alias to the debug binary of `turbo` in this case +devturbo run build --ui=tui --skip-infer 2&> ~/tmp/logs.txt +``` -These lists are by no means exhaustive. Feel free to add to them with other strategies. +> [!IMPORTANT] +> The `--skip-infer` flag is required so that `turbo` doesn't try to use a locally installed binary of `turbo`. Forgetting to use this flag will cause `devturbo` to defer to the binary installed into the repository rather than the one you're developing. ## Publishing `turbo` to the npm registry -See [the publishing guide](./release.md#release-turborepo). +See [the publishing guide](./release.md). -## Creating a new release blog post +## Contributing to examples -Creating a new release post can be done via a turborepo generator. Run the following command from anywhere within the -repo: +Contributing to examples helps the Turborepo community by showcasing how to use Turborepo in real-world scenarios with other tools and frameworks. They can be found in [the examples directory](https://github.com/vercel/turborepo/tree/main/examples) of this repository. -```bash -turbo generate run "blog - release post" -``` +The `basic` example is the default used by `create-turbo`. -This will walk you through creating a new blog post from start to finish. +For simplicity, each example is treated as a standalone "repository", separate from the rest of the repository, with its own dependencies, lockfile, `turbo` version, etc. You are able to run code and make code updates in an example without needing to install the dependencies of the rest of the repository. -NOTE: If you would like to update the stats (GitHub stars / npm downloads / time saved) for an existing blog post that -has yet to be published (useful if time has passed since the blog post was created, and up to date stats are required -before publishing) - run: +> [!NOTE] +> You may find that opening your code editor directly in the example's directory that you're working on can give you a better sense of how the example will feel to community members who download the example. -```bash -turbo generate run "blog - "blog - update release post stats" -``` +### Contributing to an existing example + +To contribute to an existing example, create your code updates and submit a pull request to the repository. No special steps are required to contribute to an example. + +### Philosophy for new examples -and choose the blog post you would like to update. +Turborepo works with any framework, tool, or even language. Because of this, the community often expresses interest in creating new examples to showcase Turborepo working with other tooling. -## Troubleshooting +However, we aim to have as few examples in the repository while still showcasing Turborepo's flexibility. By having fewer examples, the core team has a better chance to maintain the collection of examples, keeping them at a higher quality. The ecosystem evolves quickly, and keeping every example up-to-date for every tool requires a wealth of attention. Our goal is to balance the needs of the core team and the community together to keep the Turboverse in a healthy state. -See [Troubleshooting][]. +Due to these considerations, we ask that you first [open a Discussion](https://github.com/vercel/turborepo/discussions/categories/ideas) before working on a new example for the repository. It's best to make sure ahead of time that the example you'd like to propose will be accepted. Once you have received approval, you can work on and create a pull request for your example. + +#### Designing a new example + +Each example should have a specific focus when compared to the `basic` example. The goal is for an example to show how to use a singular, distinct technology's usage in a Turborepo. + +You're encouraged to start with the [`basic` example](https://github.com/vercel/turborepo/tree/main/examples/basic) and add your specific tool of interest to it. Each example should have as few modifications to the `basic` example as possible required to showcase the tool or framework. + +Key characteristics of a great example include: + +- One technology added to the `basic` example +- An updated README at the root of the example directory. Make sure to include any steps required to run the example +- All tasks in `turbo.json` in the example run successfully without any code changes needed +- Works with every package manager listed in our [Support Policy](https://turbo.build/repo/docs/getting-started/support-policy#package-managers) + +Once you've created your example (with prior approval, as discussed above), you can submit a pull request to the repository. + +### Testing examples + +To test out the experience of your example with `create-turbo`, run `create-turbo` with the `--example` flag pointed to a URL to your example's source code: + +``` +npx create-turbo@latest --example https://github.com/your-org/your-repo/tree/your-branch/... +``` -[workspaces]: https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html -[troubleshooting]: troubleshooting.md +This will allow you to use the example as a uesr would.