File Inputs
By default, a workspace is considered to have been updated when any of the files in that workspace have changed. However, not every file change inside of the entire repo should result in rerunning a task. Turborepo gives you the tools to make sure that you can define every file that matters.
Global Files
Almost every repository has some configuration that appears at the root of the repository. These files have the potential to impact the behavior of child workspaces.
package.json
and turbo.json
By default, Turborepo includes the root package.json
and the root turbo.json
file into the global hash. You do not need to specify them separately.
Specifying Additional Inputs
If there are additional files that should be considered for every single workspace, such as a root tsconfig.json
you should specify that in globalDependencies
:
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["tsconfig.json"],
"pipeline": {
"type-check": {}
}
}
This customization is additive to Turborepo's default behavior for package.json
and turbo.json
.
In this example every single task in the turborepo would be rerun when the root tsconfig.json
file changes.
Workspace Files
In addition to global files, which appear outside of any workspace, you may also specify which files to include on a per-workspace basis.
package.json
and turbo.json
The contents of each workspaces's package.json
and turbo.json
(if it exists) are automatically considered for workspace hashes. This behavior is not configurable.
Turborepo's Default Behavior
The default behavior of Turborepo is to inspect the repository and identify which files should be included in the hash calculation. Turborepo typically uses Git to identify which files to consider:
- All of the files which appear in the Git index which are children of the workspace directory.
- All of the untracked files which are children of the workspace directory and are not
.gitignore
d.
If Git is not available, or a repository has not been setup, we attempt to approximate the contents which would appear in the Git index using the following strategy:
- Include all of the files which are children of a workspace directory.
- Exclude all of the files which appear in the root
.gitignore
and the workspace directory's.gitignore
.
These two approaches do not always produce identical results! The scenarios where this does not produce identical results:
.gitignore
files at other places in the directory hierarchy.- Files added to the Git index which are also specified inside of a
.gitignore
.
You should aim to have both Git and the Git index of your repository available for maximum correctness.
Customizing the Behavior
Customizing the inputs
immediately opts out of the default behavior. You must manually specify via pipeline.<task>.inputs
all of the files that should be considered.
For some tasks it is worthwhile to reduce the number of file inputs into the task hash consideration. Very few tasks depend on the contents of README.md
. Specifying just the files that matter can increase the frequency of cache hits.
For example, in many build
tasks the only files that may matter might appear in the src
directory. Alternatively, a test
task may depend only on files in the src
and test
directory. You can specify this using glob patterns passed to pipeline.<task>.inputs
:
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"inputs": ["src/**"]
},
"test": {
"inputs": ["src/**", "test/**"]
}
}
}
These glob patterns are relative to the workspace's path, so, for build
inside of the website
app, it would treat /apps/website/src/**
as file inputs, and, for build
inside of the utils
workspace it would consider /packages/utils/src/**
as file inputs.
If a task depends on another task which specifies file dependencies they do not need to be listed again. Dependency relationships between tasks can be used to ensure that all file dependencies are met:
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"inputs": ["src/**"]
},
"test": {
// This task dependsOn build...
"dependsOn": ["build"],
// ...which means that it does not need to specify "src/**" here:
"inputs": ["test/**"]
}
}
}
This pattern can be used to save yourself from needing to repetitively enumerate a list of file globs for every single task.