# Local linting Source: https://docs.trunk.io/code-quality/overview/deal-with-existing-issues After initializing Trunk, you can begin scanning for issues in your repo, and decide whether to fix them up front, fix them incrementally as you code, or ignore irrelevant suggestions. This page walks through the process of linting locally and fixing existing issues. ### Running for the first time After initializing Trunk Code Quality, you can run **all tools** on **all files** to look for existing issues. You can run Trunk on **all files** in your repo with this command. This will output all issues detected by every linter enabled in your project. **Hold-the-line** You don't need to fix all issues upfront. Trunk lets you fix linter errors incrementally with hold-the-line. Learn more about [hold-the-line](./deal-with-existing-issues#hold-the-line). #### Issues in pull requests You can reproduce issues discovered in CI by running `trunk check` and addressing issues. If `trunk check` continues to identify new Code Quality issues on your PR, first try merging the latest changes from your base branch. Trunk will rebase your changes on top of the current `HEAD` in main to ensure it catches all issues before merging. If this continues to fail, then run `git checkout refs/pull//merge && trunk check`. This is a reference to the merge commit GitHub creates. ### Hold-the-line After initializing Trunk, you can begin scanning for issues in your repo, and decide whether to fix them up front, fix them incrementally as you code, or ignore irrelevant suggestions. This page walks through the process of linting locally and fixing existing issues. If you **only want to prevent new issues** from new code changes, skip to [prevent-new-issues](./prevent-new-issues/). ### Running for the first time After initializing Trunk Code Quality, you can run **all tools** on **all files** to look for existing issues. You can run Trunk on **all files** in your repo with this command. This will output all issues detected by every linter enabled in your project. ```bash theme={null} trunk check --all ``` **Trunk is Git aware** When you run `trunk check` without specifying `--all`, it will **only run on files you've modified according to git**. Remember to [specify a base branch](./initialize-trunk#initializing-trunk) if you're using something other than `main` or `master`. ### Fixing existing issues There are different approaches to dealing with existing issues, such as running `format` and applying automatic fixes, ignoring irrelevant issues, and sampling linters/files. This section walks you through the process to make fixing issues easier. **Hold-the-line** You don't need to fix all issues upfront. Trunk lets you fix linter errors incrementally with hold-the-line. Learn more about [hold-the-line](./deal-with-existing-issues#hold-the-line). #### Running formatters and applying fixes Some issues can be fixed automatically. You can apply fixes by running the following command. ```bash theme={null} trunk check --all --fix ``` #### Overwhelmed by existing issues? You can also focus on the issues revealed by 1 linter at a time. ```bash theme={null} trunk check --all --filter= ``` If that still produces too many issues, you can sample your files, such as 1/5 files. ```bash theme={null} trunk check --all --filter= --sample=5 ``` You can drill down further and run only one single file. ```bash theme={null} trunk check --all --filter= --sample=5 ``` If you're still overwhelmed by the results, you can fix them incrementally as you change files. See the [hold-the-line](./deal-with-existing-issues#hold-the-line) section. #### Disabling linters Some recommended linters could be unnecessary for your project. You can disable and enable linters with these commands: ```bash theme={null} trunk check enable trunk check disable ``` #### Ignore issues If there are warnings that don't apply to your project, you can ignore them by line, by file, or by class of warnings in each linter's config file. You can tell Trunk Code Quality to ignore a line in your source code with a special comment like this: ```cpp theme={null} struct FooBar { // trunk-ignore(clang-tidy) void *ptr = NULL; }; ``` The comment should contain the name of the linter you want to ignore the following line, in this case `clang-tidy` For more complex ignore commands, see [Ignoring Issues](./linters/ignoring-issues-and-files). Sometimes you may want to ignore entire files or groups of files, such as generated code. To ignore them, use the `ignore` key to your `.trunk/trunk.yaml` file: ```yaml theme={null} lint: ignore: - linters: [ALL] paths: # Ignore generated files - src/generated/** ``` You can also ignore an entire class of warnings using the config file of your linter, either at the project root or in `.trunk/configs` For example, these are the ignores for Markdownlint in `.trunk/configs/.markdownlint.yaml`: ```yaml theme={null} # Prettier friendly markdownlint config (all formatting rules disabled) extends: markdownlint/style/prettier MD024: false MD033: false MD034: false ``` #### Issues in pull requests You can reproduce issues discovered in CI by running `trunk check` and addressing issues. If `trunk check` continues to identify new Code Quality issues on your PR, first try merging the latest changes from your base branch. Trunk will rebase your changes on top of the current `HEAD` in main to ensure it catches all issues before merging. If this continues to fail, then run `git checkout refs/pull//merge && trunk check`. This is a reference to the merge commit GitHub creates. ### Hold-the-line You don't need to fix all the issues. Trunk Code Quality has the ability to ***Hold The Line***, which means it only lints your git diffs; only what you changed on your branch gets linted. The pre-existing issues can be managed later. This allows you to clean up as you go, preventing new issues and letting your team leave each file with better code quality than before. When you've fixed the existing issues you want to fix, you can skip to [prevent-new-issues](./prevent-new-issues/) directly. # Debugging Source: https://docs.trunk.io/code-quality/overview/debugging ## Why aren't issues showing up anymore? If you aren’t seeing any issues the likely cause is that your local repo is clean. By default Trunk Code Quality only processes new changes to your codebase (read about [hold-the-line](/code-quality/overview#hold-the-line)). You can use `trunk check` to scan for older, pre-existing lint issues. For example, to look at a sampling of each linter's issues for 5 random files: ```sh theme={null} trunk check --samples=5 ``` You can also scan all files using `--all`: ```sh theme={null} trunk check --all ``` [Read our docs for more information on CLI options](./deal-with-existing-issues#fixing-existing-issues). ## My linters are failing or not running as expected When your linters aren’t working the way you expect, first check their configuration. Trunk’s [list of supported linters](./linters/supported/) provides some specific tips for certain linters. You can see the full default configuration of every linter in [Trunk’s public plugin repo](https://github.com/trunk-io/plugins/tree/main). You can also try running `trunk check --verbose` to see what’s going on under the hood. If that still doesn’t work then please contact us at [support@trunk.io](mailto:support@trunk.io) with the output of `trunk check --verbose`. ## Why does Trunk take up so much disk space? Trunk Code Quality uses hermetically versioned tools, which means it downloads a separate copy of the tools and runtime for each tool version. Over time, as tools are upgraded, this can leave a lot of unnecessary files in the cache directory. Trunk is working on a way to automatically remove unneeded files from the cache. In the meantime, you can safely clear your cache with ``` trunk cache clean --all ``` then run `trunk install` again in your repos. ## How do I make a linter work with a different file type? Every linter defines a set of file types that it wants to work with in a section of the YAML called `files`. To change this you need to override the files section of that linter’s definition. [More linter application file types](./getting-started/configuration/lint/files-and-caching#applicable-filetypes). Suppose you are using the **foo-linter** which normally runs on `foo` files. The config might look like this: ```yaml theme={null} lint: files: - name: foo extensions: [foo] definitions: - name: foo-linter files: [foo] commands: - name: lint output: pass_fail run: echo “foo” success_codes: [0, 1] ``` To add support for `bar` files add this to your `trunk.yaml` file. The first part defines the `bar` file type, and the second says that `foo-linter` uses both `foo` and `bar` files. ```yaml theme={null} lint: files: - name: bar extensions: [bar] ... definitions: - name: foo-linter files: - foo - bar ``` ## How can I disable trunk on a commit for just me, but keep it on for the rest of my team? If you prefer to never run Trunk on commit and push you can disable it just for you. Edit or create the `.trunk/user.yaml` file and change the `actions.disabled` section to look like this: ```yaml theme={null} version: 0.1 actions: disabled: - trunk-check-pre-push - trunk-fmt-pre-commit ``` This will disable the checks for just the current user. The `.trunk/user.yaml` file is specifically gitignored but will be loaded locally if present. ## What should I do if a linter process seems to take longer than expected during a Trunk check? There are two main strategies to address this issue: **configuring timeouts** and **ignoring certain files**. **Timeout Configuration** Each linter integrated with Trunk Code Quality has a default timeout of 10 minutes to prevent processes from running indefinitely. If a linter exceeds this time frame, Trunk Code Quality will automatically terminate the process and notify you of the timeout. To adjust the timeout duration for a specific linter, you can modify its `run_timeout` setting in your configuration. For example: ```yaml theme={null} lint: definitions: - name: clang-tidy run_timeout: 5m ``` Timeouts can be specified using `s` for seconds, `m` for minutes, or `h` for hours, allowing you to tailor the behavior to your project's needs. More on [linter timeouts](./linters/configure-linters#timeout). **Ignoring Files** Certain files, particularly those that are auto-generated, may not require linting and can significantly extend the duration of checks. To exclude these from being checked, use the `ignore` key in your configuration: ```yaml theme={null} lint: ignore: - linters: [ALL] paths: # Ignore generated files - src/generated/** # Except for files ending in .foo - !src/generated/**/*.foo # Test data - test/test_data ``` This approach lets you specify which linters to ignore for particular paths, optimizing the check process and focusing on relevant files. [More details on ignoring files](./linters/). ## `trunk init` says "Trunk can only init if it's run at the root of a git repo" Trunk requires that you run `trunk init` from the root of a git repository. Trunk is git-aware, and relies on git to understand which files are modified, gitignored, and more. If you see this message, it means that you are not in the root directory of a git repository. If you are in a git worktree, Trunk *does* support worktrees. Your worktree may be in a broken state, try running `git worktree repair` and then `trunk init` again. # Git Hooks Source: https://docs.trunk.io/code-quality/overview/getting-started/actions/git-hooks Trunk supports triggering actions on all githooks ### Features * Seamlessly bring `git-hooks` under version control. `git-hooks` can be a major headache for organizations - they require manual installation and are not easily versioned along with the rest of your code. * Take advantage of Trunk's powerful sandboxing and environment management to write and execute hooks using the programming language and runtime of your choice, as opposed to dealing with complicated bash scripts. ### Manual installation ```bash theme={null} trunk git-hooks sync ``` ### Automatic Installation Trunk will automatically install and begin managing your `githooks` if you have any actions enabled in `trunk.yaml` which trigger from git events. ### Triggering an action from a githook As an example let's examine how we implement the `git-lfs` action in the [plugins repo](https://github.com/trunk-io/plugins). #### Definition ```yaml theme={null} - id: git-lfs display_name: Git LFS description: Git LFS hooks run: git lfs "${hook}" "${@}" triggers: - git_hooks: [post-checkout, post-commit, post-merge, pre-push] ``` #### Template resolution As documented by [git](https://git-scm.com/docs/githooks), each githook generates a variable number of parameters that can be referenced in the `run` entry for the action. The following special variables are made available for template resolution when reacting to a git event: | Variable | Description | | ----------------------------- | --------------------------------------------------------------- | | `${hook}` | Hook that triggered this action (e.g. `pre-commit`, `pre-push`) | | `${1}`,`${2}`, `${3}`, etc... | Positional parameters passed by `git` to the hook | | `${@}` | All parameters passed to the hook | #### Interactivity ```yaml theme={null} interactive: true ``` Setting `interactive` to true will allow your githook action to be run from an interactive terminal. This enables you to write more complicated hooks to react to user input. #### Testing a `githook` action The following command will simulate a githook event and execute all of the enabled actions for the provided hook in the order you defined them. ```bash theme={null} trunk git-hooks callback -- ``` Alternatively, once an action is enabled you can call `git` and debug with the actual `git` provided data. This is sometimes easier since some git parameters point to txt files and fabricating those formats through manual testing can be tricky. #### Debugging a `githook` action You can observe the actions that are triggered by a `git` event by calling: ```bash theme={null} trunk actions history ``` Which will print out the last 10 executions including timestamps of the specified action \\ ### Uninstalling Remove all actions that are triggered by githooks from `trunk.yaml` and run ```bash theme={null} git config --unset core.hooksPath ``` # Actions Source: https://docs.trunk.io/code-quality/overview/getting-started/actions/index The most common Trunk Actions are provided out of the box with trunk, and are triggered to invisibly autoformat (`trunk fmt`) your commits every time you `git commit`, and run `trunk check` when you `git push`. ### Triggers There are several different types of Trunk Actions, based on when they are triggered: | Trigger | Description | | ----------------------- | -------------------------------------------------------------------- | | time-based | run on a schedule (once per hour, once per day, once per week) | | file modification | run whenever a file or directory in your repo changes. | | [githooks](./git-hooks) | run whenever a listed githook event fires (e.g. pre-commit, on-push) | | manual | `trunk run ` | ### **Command line** | trunk actions \ | Description | | ------------------------ | -------------------------------------------------------------------------- | | `list` | list all available actions in the repository | | `history ` | print the history for execution of the provided action | | `enable ` | enable the provided action | | `disable ` | disable the provided action | | `run ` | manually trigger the provided action
alias: `trunk run ` | ### Discovering actions The trunk [plugins](https://github.com/trunk-io/plugins) repo ships with a collection of actions that can help supercharge your repository and provide examples of how to write your own actions. To see a list of actions that you can enable in your repo run: ```bash theme={null} trunk actions list ``` ### Enable/Disable actions Trunk only runs actions listed in the `enabled` section of your `trunk.yaml`. Some built-in actions are enabled by default and can be disabled explicitly by adding them to the disabled list. You can always run `trunk actions list` to check the enabled status of an action. ```yaml theme={null} actions: enabled: - trunk-announce - git-lfs - trunk-check-pre-push - trunk-fmt-pre-commit - trunk-cache-prune - trunk-upgrade-available ``` # Announce Source: https://docs.trunk.io/code-quality/overview/getting-started/announce ### Trunk Announce Does your Git commit carry some important information to share with the rest of your organization? Now you can easily share it with the rest of the org by including `/trunk announce` at the beginning of one of the lines of your commit message. If your org squashes commit messages, you should put it in your PR description Any additional text on that line will form an optional title, and the remaining text of the commit message will form the commit body (both are optional, but either a title or body is required). These will then be displayed to other users when they pull or rebase. ### Enable Trunk Announce Trunk Announce is a githook-triggered Trunk Action. You can enable this Trunk Action by running this command: ``` trunk actions enable trunk-announce ``` ### Viewing Announcements When you pull new changes, new announcements are automatically shown. If you would like to see changes since some commit, use `trunk show-announcements since `. For example: ``` trunk show-announcements since HEAD~1 ``` # Caching Source: https://docs.trunk.io/code-quality/overview/getting-started/caching Trunk hermetically manages all the tools that it runs. To do this, it will download and install them into its cache folder only when needed. On Linux and macOS you may find the cache folder at `$HOME/.cache/trunk`. ### Viewing your repo's cache If you need to debug your repo's cache, you can find its location by running the cache command. ``` trunk cache ``` ### Cleaning cache Trunk will automatically clean up downloads that have not been used in a while, such as old versions of tools and linters. If you want to manually prune files in your cache directory that are no longer needed, you can run this command: ``` trunk cache prune ``` If you need to clean your entire cache manually, you can use the command: ```sh theme={null} trunk cache clean --all ``` Remember to rerun the install command to reinstall the necessary tools and linters. ``` trunk install ``` # Code Quality Source: https://docs.trunk.io/code-quality/overview/getting-started/code-quality CLI Metalinter and VSCode extension for over 100 code checking tools. Available as a CLI tool and VSCode extension, Code Quality is a separate from the Trunk Platform for CI Stability, which includes [Merge Queue](/merge-queue/merge-queue) and [Flaky Tests](/flaky-tests/overview). Code Quality runs entirely locally and does not require access to the Trunk web app or platform services. Trunk Code Quality is a **metalinter** that lets you lint every language and every file in your project with a single tool using 100+ supported idiomatic code-checking tools, such as ESLint, Prettier, Ruff, and more for every language and project. Trunk Code Quality is trusted by popular open-source projects like [**ESLint**](https://eslint.org/) to improve their developer experience. [Learn more about how ESLint leverages Code Quality in their repos](https://trunk.io/blog/improving-linting-experience-in-eslint-s-open-source-repo-with-trunk-code-quality). ### What is Code Quality? A tour of Code Quality, what it does, its key features, and its components. How Code Quality works under the hood to level up your linting experience. What makes Trunk Code Quality different from other metalinters. Browse the 100+ supported static analysis tools to lint, format, and secure your projects. ### How do I get started? # Actions Source: https://docs.trunk.io/code-quality/overview/getting-started/commands-reference/actions ### Trunk Actions `trunk actions`: Workflow automation for your repo. #### **Usage** **example** ``` trunk actions [options] [subcommand] ``` #### Options * `--version`: The version * `--monitor`: Enable the trunk daemon to monitor file changes in your repo * `--ci`: Run in continuous integration mode * `--no-progress`: Don't show progress updates * `--ci-progress`: Rate limit progress updates to every 30s (implied by `--ci`) * `--action_timeout`: Timeout for downloads, lint runs, etc * `-v`, `--verbose`: Output details about what's happening under the hood * `--color`: Enable/disable color output ### Trunk Actions run `trunk actions run`: Run a specified trunk action. **Usage** **bash** ``` trunk actions run [options] ``` #### **Options** * `--nolog`: Don't create a log file for the action run * `--version`: The version * `--monitor`: Enable the trunk daemon to monitor file changes in your repo * `--ci`: Run in continuous integration mode * `--no-progress`: Don't show progress updates * `--ci-progress`: Rate limit progress updates to every 30s (implied by `--ci`) * `--action_timeout`: Timeout for downloads, lint runs, etc. * `-v`, `--verbose`: Output details about what's happening under the hood * `--color`: Enable/disable color output * `--name `: Specify the name of the Trunk action to be executed * `--branch `: Run the action on a specific branch * `--retry `: Number of times to retry the action on failure ### Trunk Actions history `trunk actions history`: View the history of Trunk actions. #### **Usage** example ``` trunk actions history [options] ``` #### **Options** * `--count`: Number of logs to show * `--version`: The version * `--monitor`: Enable the trunk daemon to monitor file changes in your repo * `--ci`: Run in continuous integration mode * `--no-progress`: Don't show progress updates * `--ci-progress`: Rate limit progress updates to every 30s (implied by `--ci`) * `--action_timeout`: Timeout for downloads, lint runs, etc. * `-v`, `--verbose`: Output details about what's happening under the hood * `--color`: Enable/disable color output ### Trunk Actions list `trunk actions list`: List all Trunk actions. #### **Usage** example ``` trunk actions list [options] ``` #### **Options** * `--version`: The version * `--monitor`: Enable the trunk daemon to monitor file changes in your repo * `--ci`: Run in continuous integration mode * `--no-progress`: Don't show progress updates * `--ci-progress`: Rate limit progress updates to every 30s (implied by `--ci`) * `--action_timeout`: Timeout for downloads, lint runs, etc. * `-v`, `--verbose`: Output details about what's happening under the hood * `--color`: Enable/disable color output ### Trunk Actions enable `trunk actions enable`: Enable a specified Trunk action. #### **Usage** example ``` trunk actions enable [options] ``` #### **Options** * `--version`: The version * `--monitor`: Enable the trunk daemon to monitor file changes in your repo * `--ci`: Run in continuous integration mode * `--no-progress`: Don't show progress updates * `--ci-progress`: Rate limit progress updates to every 30s (implied by `--ci`) * `--action_timeout`: Timeout for downloads, lint runs, etc. * `-v`, `--verbose`: Output details about what's happening under the hood * `--color`: Enable/disable color output ### Trunk Actions disable `trunk actions disable`: Disable a specified Trunk action. #### **Usage** example ``` trunk actions disable [options] ``` #### **Options** * `--version`: The version * `--monitor`: Enable the trunk daemon to monitor file changes in your repo * `--ci`: Run in continuous integration mode * `--no-progress`: Don't show progress updates * `--ci-progress`: Rate limit progress updates to every 30s (implied by `--ci`) * `--action_timeout`: Timeout for downloads, lint runs, etc. * `-v`, `--verbose`: Output details about what's happening under the hood * `--color`: Enable/disable color output ### Trunk Shellhooks `trunk shellhooks`: Let Trunk manage your shell hooks similar to `direnvs` trunk shellhooks install \ #### **Usage** example ``` trunk shellhooks install [options] ``` ### Trunk Git Hooks `trunk git-hooks sync`: Sync githooks with what's defined in `trunk.yaml` #### **Usage** example ``` trunk git-hook sync [options] ``` ### Trunk show announcements since a commit **`trunk show-announcements since`**: Show announcements since a specified commit #### **Usage** example: ```sh theme={null} trunk show-announcements since --commit abc123 ``` #### **Options**: * `--color`: Enable/disable color output * `-v`, `--verbose`: Output details about what's happening under the hood * `--action_timeout`: Timeout for downloads, lint runs, etc. * `--ci-progress`: Rate limit progress updates to every 30s (implied by `--ci`) * `--no-progress`: Don't show progress updates * `--ci`: Run in continuous integration mode * `--monitor`: Enable the trunk daemon to monitor file changes in your repo * `--version`: The version ### **Trunk show announcements post-merge** **`trunk show-announcements post-merge`**: Run on git pull/merge, usually run by a git-hook and not directly. **Usage Example**: ```sh theme={null} trunk show-announcements post-merge --verbose ``` ### **Trunk show announcements pre-rebase** **`trunk show-announcements pre-rebase`**: Run on git pre-rebase, usually run by a git-hook and not directly. #### **Usage** example: ```sh theme={null} trunk show-announcements pre-rebase [options] [branch-refs...] ``` ### **Trunk show announcements post-checkout** **`trunk show-announcements post-checkout`**: Run on git checkout/switch, usually run by a git-hook and not directly. #### **Usage** example:: ```sh theme={null} trunk show-announcements post-checkout [options] [branch-refs...] ``` # Code Quality Source: https://docs.trunk.io/code-quality/overview/getting-started/commands-reference/code-quality ### trunk check `trunk check`: Universal code checker. #### **Usage** **example** ``` trunk check [options] ``` #### Filtering options * `-a, --all`: Check all files instead of only changed files * `--sample`: Run each linter on N files * `--filter`: Comma-separated list of linters and/or issue codes to include or exclude * `--exclude`: Shorthand for an inverse --filter * `--scope`: Scope of checks to run \{all | security} * `--ignore`: Glob pattern to exclude files from linting * `--force`: Run on all files, even if ignored * `--include-existing-autofixes`: Include existing issues that can be autofixed #### **CI** options * `--ci`: Run in non-interactive mode designed for CI environments * `-j`, `--jobs`: Number of concurrent jobs #### Git Hooks options * `--index`: Run linter on git-indexed files * `--index-file`: Run linter on git-indexed files based on specified index * `--commit-ref`: Commit ref to lint (instead of current working tree) * `--commit-ref-from-pre-push`: Commit ref to lint from the stdin of a pre-push git hook (instead of the current working tree) #### Output options * `--show-existing`: Show existing issues otherwise hidden by * `--print-failures`: Print any failures that occur * `--diff`: Diff printing mode \{none | compact | full} * `-v, --verbose`: Show verbose output for debugging purposes * `--debug`: Show debug output #### Behavior options * `-y, --fix`: Automatically apply all fixes without prompting * `-n, --no-fix`: Don't automatically apply fixes * `--cache`: Disable to skip cache for all check actions * `--ignore-git-state`: Run linters even if a merge, rebase, or revert is in progress * `--upstream`: Upstream branch used to compute changed files ### Trunk Check Enable Linter `trunk check enable`: Enable linters for trunk check. #### **Usage** **example** ``` trunk check enable [options] ``` ### Trunk Check Disable Linter `trunk check disable`: Disable linters for trunk check. #### **Usage** **example** ``` trunk check disable [options] ``` ### Trunk Check List Linters `trunk check list`: List linters for trunk check. #### **Usage** **example** ``` trunk check list [options] ``` ### Trunk Check Run Format `trunk fmt`: List linters for trunk check. #### **Usage** **example** ``` trunk fmt [options] ``` #### **Options** #### Filtering options * `-a, --all`: Check all files instead of only changed files * `--filter`: Comma-separated list of linters and/or issue codes to include or exclude * `--exclude`: Shorthand for an inverse --filter * `--scope`: Scope of checks to run \{all | security} * `--ignore`: Glob pattern to exclude files from linting * `--force`: Run on all files, even if ignored * `--show-existing`: Show existing issues otherwise hidden by [hold-the-line](/code-quality/overview#hold-the-line) * `--ignore-git-state`: Run linters even if a merge, rebase, or revert is in progress #### Git Hooks options * `--index`: Run linter on git-indexed files * `--index-file`: Run linter on git-indexed files based on specified index * `--commit-ref`: Commit ref to lint (instead of current working tree) * `--commit-ref-from-pre-push`: Commit ref to lint from the stdin of a pre-push git hook (instead of the current working tree) #### Output options * `--show-existing`: Show existing issues otherwise hidden by * `--print-failures`: Print any failures that occur * `--diff`: Diff printing mode \{none | compact | full} * `-v, --verbose`: Show verbose output for debugging purposes * `--debug`: Show debug output #### Behavior options * `-y, --fix`: Automatically apply all fixes without prompting * `-n, --no-fix`: Don't automatically apply fixes * `--cache`: Disable to skip cache for all check actions * `--ignore-git-state`: Run linters even if a merge, rebase, or revert is in progress * `--upstream`: Upstream branch used to compute changed files * `-j`, `--jobs`: Number of concurrent jobs ## Advanced Trunk Check features | Options & Flags | Explanation | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `--root` | Explicitly set the root of the repository to run against | | `--upstream` | Specify the upstream branch used to calculate new vs existing issued. | | `--trigger` | Supports running trunk check from inside a git hook. Options are manual (default), git-push, git-commit. Controls whether the check returns early and its interactivity. | | `--output=format` | Output results in specified format: `text` (default) or `json` | | `--output-file=FILE` | Write json results to specified file | #### --filter `--filter` argument allows you to restrict `trunk check` to a subset of the linters enabled in your repository. For example, to run `eslint` and `isort` on the entire repo: ```bash theme={null} trunk check --all --filter=eslint,isort ``` Alternatively, to run every linter *except* `clang-tidy` and `shellcheck`: ```bash theme={null} trunk check --all --filter=-clang-tidy,-shellcheck ``` #### --sample `--sample=N` will attempt to run every enabled linter against the requested number of files. The goal of the `sample` flag is to test the setup of the linters in your repository as well as any specific configuration they might honor. The sample command will attempt to run each linter N times, but may run fewer if not enough applicable files exist in your set of files to lint. `--sample=N` can be combined with any other set of options for `trunk check`. For example, to run `prettier` against 10 different prettier supported files: ```bash theme={null} trunk check --sample=10 --filter=prettier ``` Alternatively, to run every linter at most 5 times against its supported files: ```bash theme={null} trunk check --sample=5 ``` # Commands reference Source: https://docs.trunk.io/code-quality/overview/getting-started/commands-reference/index ### trunk init `trunk init`: Set up trunk in this repo. #### **Usage** Example ``` trunk init ``` ### trunk version `trunk version`: Output the version. #### **Usage** example ``` trunk version ``` ### trunk upgrade `trunk upgrade`: Upgrade Trunk and its linters to the latest releases. #### **Usage** **example** ``` trunk upgrade [options] ``` #### **Options** * `-y, --yes-to-all`: Answer yes to all upgrade prompts * `-n, --no-to-all`: Answer no to all upgrade prompts * `--apply-to`: Apply upgrades to a specified file * `--filter`: Filter the upgraded linters * `--dry-run`: Detect available upgrades, but do not apply changes ### trunk login `trunk login`: Login to trunk.io. #### **Usage** example ``` trunk login ``` ### trunk logout `trunk logout`: Logout from trunk.io. #### **Usage** example ``` trunk logout ``` ### trunk plugins add `trunk plugins add`: Add a plugin by URI. #### **Usage** example ``` trunk plugins [uri] [ref] [options] ``` ### trunk tools `trunk tools`: Universal tool manager. #### **Usage** example ``` trunk tools [options] ``` ### trunk daemon status Report the status of the daemon. #### **Usage** example ``` trunk daemon status ``` ### trunk daemon start Start the trunk daemon in the background if it’s not already running. #### **Usage** example ``` trunk daemon start ``` ### **trunk daemon shutdown** `trunk daemon shutdown`: Shutdown the trunk daemon if it is running. #### **Usage** example ``` trunk daemon shutdown ``` ### **trunk daemon launch** `trunk daemon launch`: Start the trunk daemon in the foreground if it’s not already running. #### **Usage** example ``` trunk daemon launch ``` ### trunk whoami `trunk whoami`: print who you're logged in as #### **Usage** example ``` trunk whoami ``` ### trunk deinit `trunk deinit`: Deinitialize Trunk in your repo #### **Usage** example ``` trunk deinit [options] ``` #### **Options** * `-y`, `--yes`: Proceed unconditionally * `-v`, `--verbose`: Output details about what's happening under the hood * `--color`: Enable/disable color output ### trunk config share `trunk config share`: Remove Trunk config files from your local git ignores. #### **Usage** example ``` trunk config share ``` ### trunk config hide `trunk config hide`: Add Trunk config files to your local git ignores. #### **Usage** example ``` trunk config hide ``` ### trunk config print `trunk config print`: Print the resolved trunk config. #### **Usage** example ``` trunk config print ``` ### trunk cache clean `trunk cache clean`: Clean cached files used by Trunk. #### **Usage** Example ``` trunk cache clean ``` ### trunk cache prune `trunk cache prune`: Prune unused cached files. #### **Usage** example ``` trunk cache clean ``` ### trunk install `trunk install`: Download & install enabled runtimes/linters. #### **Usage** example ``` trunk install [options] ``` #### **Options** * `--version`: The version * `--monitor`: Enable the trunk daemon to monitor file changes in your repo * `--ci`: Run in continuous integration mode * `--no-progress`: Don't show progress updates * `--ci-progress`: Rate limit progress updates to every 30s (implied by `--ci`) * `--action_timeout`: Timeout for downloads, lint runs, etc. * `-v`, `--verbose`: Output details about what's happening under the hood * `--color`: Enable/disable color output # Compatibility Source: https://docs.trunk.io/code-quality/overview/getting-started/compatibility ### Linux Trunk will run on most Linux flavors, including Ubuntu, Arch, and others. We do require glibc version 2.19 or later. Alpine Linux is not supported. ### macOS Trunk will run on macOS version 10.15 or later. ### Windows Trunk only supports Windows with the following versions and above: | Tool | Where to Modify | Minimum Required Version | | ------- | --------------------------------------------------- | ------------------------ | | CLI | `cli` `version` in `.trunk/trunk.yaml` | `1.13.0` | | Plugins | `ref` for the `trunk` plugin in `.trunk/trunk.yaml` | `v1.0.0` | | VSCode | Reload VSCode to update | `3.4.4` | You will also need to install [C and C++ runtime libraries](https://aka.ms/vs/17/release/vc_redist.x64.exe) to run some linters. #### Getting in touch Thank you for being a beta tester of Trunk Check on Windows! We are actively working to improve the experience. If you have any feedback or questions, please contact us at [support@trunk.io](mailto:support@trunk.io). If you want to override a repo-wide setting just for your Windows machine, you can modify your [`.trunk/user.yaml`](./configuration/per-user-overrides). #### Supported features We intend to bring full feature support to Windows for Trunk. Currently, the following features are supported: * [Trunk Code Quality](./code-quality) * Non-interactive [Trunk Actions](./actions/) and [git-hooks](./actions/git-hooks) * [VSCode](../ide-integration/vscode) ### Plugin compatibility This section was last updated for Plugins v1.2.0 Trunk runs most linters on all platforms. However, some linters are not yet supported on Windows. For a full list of all linters, see our [Plugins repo](https://github.com/trunk-io/plugins). | Linter | Plans for Support | | -------------------- | --------------------------------------- | | ansible-lint | Only supported on WSL | | clang-format | Long-term plans for LLVM linter support | | clang-tidy | Long-term plans for LLVM linter support | | detekt-gradle | Long-term plans for support | | include-what-you-use | Long-term plans for LLVM linter support | | nixpkgs-fmt | Long-term plans for support | | perlcritic | No immediate plans for support | | perltidy | No immediate plans for support | | scalafmt | No download available for Windows | | semgrep | No download available for Windows | | shellcheck | No download available for Windows | | stringslint | Only supported on MacOS | | swiftformat | Only supported on MacOS | | swiftlint | Only supported on MacOS | | taplo | No download available for Windows | ### Backward compatibility We generally strive to maintain backward compatibility between the [Trunk Launcher](./install#the-trunk-launcher) and the Trunk binary, but you may need to occasionally upgrade the launcher to support the newest version of Trunk. # Actions Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/actions/index Actions are defined and enabled in the `actions` section of `trunk.yaml`. Here is an example of the actions section of `trunk.yaml`. If you are curious what your resolved configuration for actions looks like, run `trunk config print`. ```yaml theme={null} actions: enabled: - trunk-announce - trunk-upgrade-available - npm-install - seed-database - custom-git-hook - login definitions: - id: npm-install triggers: - files: [package.json] run: npm install - id: seed-database triggers: - schedule: 24h run: python3 seed_database.py runtime: python run_from: utils packages_file: requirements.txt - id: custom-git-hook triggers: - git_hooks: [pre-push, pre-commit] run: my_script.sh - id: login run: my_complicated_login_script.sh interactive: true ``` ### Action Definitions Now we'll walk through the process of creating your own action. Actions are required to have a `id` and `run` command. The command will implicitly run relative to your workspace, but you can also specify a `run_from` if you'd prefer to execute from a sub-directory. #### Runtime management We sandbox action executions and allow you to control the runtime. You can do this by specifying a `runtime` and `packages_file`. You can specify one of our built-in runtimes (`node`, `python`, ...) or a system runtime that you define. See the [runtimes documentation](../runtimes) for more information. For the `python` and `node` runtimes, we additionally provide the ability to install a requirements file like `requirements.txt` or `package.json`. ### Triggers You can run actions manually, or you can also provide a set of triggers so that actions run in response to some event. They are documented below. #### Manual runs You may run an action manually by running `trunk run ` or `trunk actions run `. For manually triggered runs, we support the `${@}` and `${pwd}` variables for template resolution in the `run` declaration. `${@}` will be replaced with the arguments passed to the action, and `${pwd}` will be replaced with the directory the action is triggered from. ```yaml theme={null} id: my-action run: echo "The action was run from ${pwd} with arguments ${@}" ``` #### Time-based triggers We provide the ability to run actions in the background on a schedule. Under `triggers`, you can add one or more `schedule` entries. For example: ```yaml theme={null} id: my-action triggers: - schedule: 1d ``` The `schedule` entry should be in the Duration format specified [here](https://pkg.go.dev/time#ParseDuration). The action will be run once per `duration`. This is a short-hand for specifying schedule as an object. You can also write: ```yaml theme={null} id: my-action triggers: - schedule: interval: 1d ``` The action may occasionally run more often than the specified duration depending on the Trunk daemon's lifetime. If you wish to stagger the execution of an action from others on a similar schedule, you may use the `delay` field: ```yaml theme={null} id: my-action triggers: - schedule: interval: 1d delay: 1h ``` You may also use cron syntax: ```yaml theme={null} nid: my-action triggers: # run every 2 hours - schedule: "0 0 */2 * * ?" ``` or equivalently: ```yaml theme={null} id: my-action triggers: # run every 2 hours - schedule: cron: "0 0 */2 * * ?" ``` #### File-based triggers We provide the ability to run actions automatically based on a file edit. You may provide exact filenames, or globs. ```yaml theme={null} id: my-action triggers: - files: [foo.txt, bar/**] ``` In this case `my-action` will execute if either `foo.txt` is edited (or created), or if a file inside `bar` is edited or created. In case you need to know which file triggered the action, you can use the `${target}` variable in the `run` command. ```yaml theme={null} id: my-action triggers: - files: [foo.txt, bar/**] run: echo "The file ${target} was edited" ``` If you do a bulk file modification, the `${target}` template may resolve to a space-separated list of files that were simultaneously edited. > Note: We only provide file triggers for files inside of your workspace. #### Git hooks You can also configure Trunk to manage your git hooks. More detail is provided on this in our [git hooks reference](../../actions/git-hooks). ### Interactivity Actions can read from `stdin` if they are marked as interactive (define `interactive: true` on the action). Note: this feature is only available for git hooks and manually run actions - since file-triggered and scheduled actions run in the background, you cannot interact with their execution. # Logging and Troubleshooting Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/actions/logging-and-troubleshooting Diagnosing problems with actions We provide a number of tools for inspecting the results of actions that run in the background and wouldn't otherwise surface their errors. Every action execution is logged. We consider an action execution to have failed if it has a non-zero exit code. `trunk actions history ` gives a history of the recent runs of an action and whether it succeeded. You can control how many recent runs to show with the `--count` flag (for example, `trunk actions history trunk-upgrade-available --count=10`). When available, a full stacktrace is written to a file and made available. Failed action executions will also produce a notification so that background failures are periodically surfaced to the user. You can also inspect action logs at `.trunk/out/actions//`. We recommend running actions manually when you develop them to verify that they work correctly. ### Output Level To see a more verbose output when running trunk actions, particularly from git-hooks, you can add the following to your `trunk.yaml`: ```yaml theme={null} actions: output_level: ``` # Notifications Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/actions/notifications Trunk Actions can also produce notifications to display in your terminal or in the VSCode extension! ### Defining actions that produce notifications Typically, whatever actions write to stdout are stored in the log file and perhaps shown to the user. However, actions can also produce structured output if `output_type` is set on the Action Definition to be `notification_v1`. In this case, the action should print yaml to output with the following structure: ```yaml theme={null} notifications: - id: action-id # Display-related fields title: My action message: some text about the notification rendered: A rendered message string for color terminals icon: https://uri/to/icon commands: - title: A button title run: a run command run_from: directory to run from priority: high # Can be one of low, high (default low) ``` Some notes: 1. The ID can be whatever you want it to be, but generally should be made to match the action ID. 2. You may emit multiple notifications per action. 3. `icon` and `commands` are used to control notifications display in VSCode. 4. High-priority notifications are immediately shown to the user in terminal. Low-priority notifications are only shown every 24 hours (These are configurable). ### Deleting notifications Actions can also clear their own notifications. in this case, make the output looks like this: ```yaml theme={null} notifications_to_delete: [action-id] ``` If actions produce a notification that is reflective of a current state or something actionable for the user to do, they may clear the notification once that state changes/when the user takes the requested action. ### An example We illustrate the cycle of actions managing their own notifications with the following example. Consider the built-in action for `trunk upgrade` - a command that upgrades trunk and a repo's enabled linters to their most recent versions. We'd like to notify the user of new upgrades once a day. Thus our `trunk-upgrade-available` action definition looks like this: ```yaml theme={null} id: trunk-upgrade-available output_type: notification_v1 run: trunk upgrade --notify triggers: - schedule: 1h - files: [.trunk/trunk.yaml] ``` `trunk upgrade --notify` produces a notification that looks like this: ```yaml theme={null} notifications: - commands: - run: trunk upgrade title: Upgrade Trunk id: trunk-upgrade message: "Upgrades available\n\n Trunk version 0.17.0-beta\n 10 linter updates\n\nRun trunk upgrade to upgrade all\n or trunk upgrade trunk to just upgrade trunk" priority: low rendered: "\x1b[1m\x1b[90m\nUpgrades available\x1b[0m\n\x1b[90m\n\x1b[0m• \x1b[90mTrunk version\x1b[0m \x1b[92m0.17.0-beta\x1b[0m\x1b[90m\n\x1b[0m• \x1b[92m11 linter\x1b[0m \x1b[90mupdates\n\x1b[0m\n\x1b[90mRun\x1b[0m\x1b[96m trunk upgrade\x1b[0m\x1b[90m to upgrade all\x1b[0m\x1b[90m\n or\x1b[0m\x1b[96m trunk upgrade trunk\x1b[0m\x1b[90m to just upgrade trunk\x1b[0m\x1b[90m\n\x1b[0m" ``` If there are no upgrades available, `trunk upgrade --notify` will produce: ```yaml theme={null} notifications_to_delete: [trunk-upgrade-available] ``` So in this scenario, the `trunk-upgrade-available` action runs in the background periodically and produces a notification. The user takes action by running `trunk upgrade`. Since `trunk upgrade` modifies `.trunk/trunk.yaml`, this will again trigger the `trunk-upgrade-available` action (due to the file trigger). Since there is nothing else to upgrade, `trunk upgrade --notify` will produce output telling Trunk to delete its notification. Now, the user is no longer shown a notification about available upgrades! # Configuration Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/index The Trunk CLI has its top-level config defined in `.trunk/trunk.yaml`. ``` /your_repo ├── .trunk │ └── trunk.yaml └── src ├── bar └── foo ``` This is initially generated by `trunk init` and is the central source of truth for how Trunk operates inside your repository. As we build new services and features, we'll extend `trunk.yaml` to include configuration sections for them. We believe strongly in "configuration as code" and being able to guarantee that `trunk` can be run reproducibly. ### Config format The Trunk configuration file is written in YAML and is meant to be self-descriptive. Below is a sample config file to help you understand how the pieces come together. Alternatively, you can also refer to [the `trunk.yaml` in our GitHub Action](https://github.com/trunk-io/trunk-action/blob/main/.trunk/trunk.yaml) as an example or [`trunk-yaml-schema.json`](https://static.trunk.io/pub/trunk-yaml-schema.json). ```yaml theme={null} version: 0.1 # the version of this config file. cli: version: 0.15.1 # the version of trunk you will run in your repository runtimes: enabled: - ruby@>=2.7.1 - python@3.9.1 repo: # main is the branch that everyone's work is merged into # (this is usually inferred and not required to be set) trunk_branch: main lint: definitions: - name: my_custom_linter files: [ALL] commands: output: sarif run: ${workspace}/bin/foo --file ${target} read_output_from: stdout run_linter_from: workspace success_codes: [0, 1] enabled: - ansible-lint@5.3.2 - bandit@1.7.0 - black@21.6b0 - buf-lint@1.0.0-rc3 - buildifier@5.1.0 - cfnlint@0.51.0 - eslint@7.30.0 - gitleaks@7.6.1 - gofmt@1.16.7 - golangci-lint@1.41.1 - hadolint@2.6.0 - isort@5.8.0 - markdownlint@0.28.1 - mypy@0.910 - prettier@2.3.2 - pylint@2.8.1 - rustfmt@1.55.0 - semgrep@0.104.0 - shellcheck@0.7.2 - shfmt@3.3.1 disabled: - rufo - tflint ignore: - linters: [ALL] paths: # Generated files - a/proto/code_pb* # Test data - b/test_data/** - linters: [eslint] paths: - c/run.ts triggers: - linters: - ansible-lint paths: - ansible # A directory targets: - ansible # A directory ``` ### `version` The `version field` is the schema version of `trunk.yaml.` ### `cli` ```yaml theme={null} cli: version: 0.15.1 # the version of trunk you will run in your repository options: - commands: [ALL] # apply to all `trunk` commands args: --monitor=true - commands: [check, fmt] # apply only to `trunk check` and `trunk fmt` commands args: -y ``` In addition to specifying `version`, `cli` allows you to specify default command line arguments using the `options` field. Specified `args` will be appended to strictly matched `commands` during `trunk` invocations. Specifying `ALL` as a `commands` element applies its options to all `trunk` subcommands. Any command line options will take precedence over these `args`. Some examples using the configuration above: * `trunk check` resolves to `trunk check -y --monitor=true` * `trunk check -n` resolves to `trunk check -n --monitor=true` * `trunk fmt` resolves to `trunk fmt -y --monitor=true` ### `repo` ```yaml theme={null} repo: # main is the branch that everyone's work is merged into # (this is usually inferred and not required to be set) trunk_branch: main ``` Some Trunk features require Trunk to be aware of the canonical repository your organization uses, such as the repository that everyone pulls from and makes pull requests into. The Trunk CLI can infer this from your `origin` remote, but if you don't want your `origin` to be used for this purpose, you can explicitly specify your canonical repository. Other features - namely `trunk check` - need to be aware of the primary upstream branch that everyone branches from. If you use `main` or `master`, `trunk` can infer this; however, if you use some other primary branch, then you may want to consider setting this. The above configuration is how you would specify that [https://github.com/github/gitignore](https://github.com/github/gitignore) is your canonical repository and that `main` is the branch which `trunk` should always think of as your upstream branch. ### `api` ```yaml theme={null} api: # name of your trunk organization on app.trunk.io org: { your-org-name } ``` Some Trunk features, like the CI Debugger, require knowledge of the Trunk organization your repository is using. This information can be provided on the command line or hard-coded in the `trunk.yaml` file. ### `trunk_remote_hint` ```yaml theme={null} repo: trunk_remote_hint: github.com/organization/my_repo ``` If this hint is set, Trunk will search all local remotes looking for the one that best matches `//` instead of defaulting to `origin`. It will then use this remote as the default upstream for computing changed files. ### Stacked PR support ```yaml theme={null} repo: use_branch_upstream: true ``` By default, `trunk` will auto-detect all changed files relative to your main branch. If you would instead like it to compare against the upstream of your current git branch, you can enable this feature by setting `use_branch_upstream` to `true`. ### Disable upgrade notifications Trunk will periodically tell you to upgrade to a newer version if one is available. If you prefer not to see these notifications, edit (or add) the section of your `.trunk/trunk.yaml` to include the following lines: ```yaml theme={null} actions: disabled: - trunk-upgrade-available ``` ### Overriding defaults Trunk ships with a default configuration which `trunk.yaml` is merged into to produce the actual configuration that Trunk runs with. You can view this merged configuration using `trunk print-config`. You may find while using Trunk that you want to modify one of these defaults: perhaps you want `clang-tidy` to not run on the upstream, or maybe you want the `node` runtime to include another environment variable. In these cases, you can specify the field in your `trunk.yaml` to override the default value. Let's take `clang-tidy` as an example, which ships with the following default configuration: ```yaml theme={null} definitions: ... - name: clang-tidy files: [c/c++-source] type: llvm commands: - output: llvm run: clang-tidy --export-fixes=- ${target} success_codes: [0] download: clang-tidy direct_configs: [.clang-tidy] disable_upstream: true include_scanner_type: compile_command environment: - name: PATH list: ["${linter}/bin"] ... ``` If you wanted to flip the value of `disable_upstream` to `false`, you could, in your own `trunk.yaml`, specify: ```yaml theme={null} definitions: ... - name: clang-tidy disable_upstream: false ... ``` Some linters have multiple commands, such as [trivy](https://github.com/trunk-io/plugins/blob/main/linters/trivy/plugin.yaml), which can run in different ways. Similarly, some linters are configured to run differently on different platforms or at different versions. When overriding a command definition, overrides are applied on the tuple `[name, version, platforms]`. For example, if you wanted to disable batching when running [ktlint](https://github.com/trunk-io/plugins/blob/main/linters/ktlint/plugin.yaml) on Windows, you could consider its default configuration: ```yaml theme={null} definitions: ... - name: ktlint ... commands: - name: format platforms: [windows] run: java -jar ${linter}/ktlint.exe -F "${target}" output: rewrite cache_results: true formatter: true in_place: true batch: true success_codes: [0, 1] - name: format run: ktlint -F "${target}" output: rewrite cache_results: true formatter: true in_place: true batch: true success_codes: [0, 1] ... ``` and override it as such: ```yaml theme={null} definitions: ... - name: ktlint ... commands: - name: format platforms: [windows] batch: false ... ``` When executing linters, Trunk will execute the first matching command based on its compatible platforms and linter version. Note when overriding that new commands that don't match an existing tuple are prepended to the resulting commands list. Alternatively, consider the default `node` runtime: ```yaml theme={null} runtimes: definitions: - type: node download: node runtime_environment: - name: HOME value: ${home} - name: PATH list: ["${runtime}/bin"] linter_environment: - name: PATH list: ["${linter}/node_modules/.bin"] version: 16.14.2 version_commands: - run: "node --version" parse_regex: ${semver} ``` If you wanted to add `${home}/my/special/node/path` to `PATH`, you could specify the following: ```yaml theme={null} runtimes: - type: node runtime_environment: - name: HOME value: ${home} - name: PATH list: ["${home}/my/special/node/path", "${runtime}/bin"] ``` ### Validation Custom linter, download, and runtime configs must be defined in full and will be validated. Overrides of existing linter, download, and runtime configs can be partial overrides. They do not have to be full definitions. Merged configurations are subject to the same validation that custom linters are - they must all have a name, type, command, and either `success_codes` or `error_codes` set. ### Known limitations 1. Scalar values are overridden in a straightforward manner - the value specified in the override\ takes the place of the default, and otherwise, default values are retained. 2. To override a sequence value in the default (ex. `environment` in the `node` runtime), it is\ necessary to fully specify the new sequence. This is why the `environment` override above also defines `HOME`. If you just wanted to add a new value, you would have to copy in the existing\ sequence to your overriding config, and add your new value to the end of the list. 3. It is not possible to set sequences of non-zero length to zero length. For example, if the\ default config has `success_codes: [0]`, you may override this to `success_codes: [0, 1]`, but you cannot clear its value. # Auto-Enable Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/lint/auto-enable Simply defining a linter does not enable it. Trunk needs to know when to auto-enable the linter for certain projects (ex: all python projects) or if certain files are already present (ex: `.eslintrc`). ## Auto Enabling The `direct_configs` property contains a list of config files that the underlying linter uses. The `suggest_if` property determines when `trunk check` should suggest this linter. If `suggest_if` is set to `config_present`, then trunk will search for the listed config files. If found, the linter will be enabled automatically when the user does `trunk init` or `trunk update`. For example: in the following yaml, the **flake8** linter sets `suggest_if` to `config_preset` and sets `direct_configs` to `[.flake8]`. If any `*.flake8` files are found, then trunk check will automatically enable flake8. **Flake8** linter definition. [full source](https://github.com/trunk-io/plugins/blob/main/linters/flake8/plugin.yaml) ```yaml theme={null} version: 0.1 tools: definitions: - name: flake8 runtime: python package: flake8 shims: [flake8] known_good_version: 4.0.1 lint: definitions: - name: flake8 files: [python] tools: [flake8] direct_configs: [.flake8] suggest_if: config_present affects_cache: - setup.cfg - tox.ini # In case the user installs https://pypi.org/project/Flake8-pyproject/ - pyproject.toml issue_url_format: https://flake8.pycqa.org/en/latest/user/error-codes.html known_good_version: 4.0.1 version_command: parse_regex: ${semver} run: flake8 --version ``` The **suggest\_if** field can be one of the following: * `config_present` will auto-enable a linter if Trunk sees any `direct_config` for it . * `files_present` will auto-enable a linter if Trunk sees any file type that it operates on. * `never` will never auto-enable this linter. Trunk curates the values of `suggest_if` for all linters in the [plugins](https://github.com/trunk-io/plugins) repo. ## Manually enabling and disabling Setting the `lint.definitions[*].enabled` property to true will force the linter to be enabled. Setting the `lint.definitions[*].disabled` property to true will force the linter to never be enabled, even if the `enabled` property is true, and will never suggest this linter, even if `suggest_if` says it should. For additional information on the properties of Linters, see the [Linter Definition Reference](./definitions). # Commands Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/lint/commands A command is the fundamental unit of linters. It defines specifically *what binary and arguments* are used to run the linter. A linter can have multiple commands in case it has multiple behaviors (ex: lint and format), but it must have at least one. ## How Code Quality Runs Linters The `run` property is the command to actually run a linter. This command can use [variables](./commands#template-variables) provided by the runtime such as `${plugin}` and `${target}`. For example: this is the `run` field for **black**, one of our Python linters. The `run` field is set to `black -q ${target}`. ```yaml theme={null} version: 0.1 tools: definitions: - name: black runtime: python package: black[python2,jupyter] shims: [black] known_good_version: 22.3.0 lint: definitions: - name: black files: [python, jupyter, python-interface] commands: - name: format output: rewrite run: black -q ${target} success_codes: [0] batch: true in_place: true allow_empty_files: false cache_results: true formatter: true tools: [black] suggest_if: files_present affects_cache: [pyproject.toml] known_good_version: 22.3.0 version_command: parse_regex: black, version (.*) run: black --version ``` This command template contains all the information Trunk needs to execute `black` in a way where Trunk will be able to understand `blacks`'s output. ## Input Target The `target` field specifies what paths this linter will run on given an input file. It may be a string literal such as `.`, which will run the linter on the whole repository. It also supports various substitutions: | Variable | Description | | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | `${file}` | The input file. | | `${parent}` | The folder containing the file. | | `${parent_with()}` | Walks up toward the repository root looking for the first folder containing ``. If `` is not found, do not run any linter. | | `${root_or_parent_with()}` | Walks up toward the repository root looking for the first folder containing ``. If `` is not found, evaluate to the repository root. | | `${root_or_parent_with_regex()}` | Walks up toward the repository root looking for the first folder containing a name matching ``. If not found, evaluate to the repository root. | If `target` is not specified it will default to `${file}`. This target may be referenced in the `run` field as `${target}`, as in the example above for **black**, or this simple example. ```yaml theme={null} lint: definitions: - name: noop files: [ALL] commands: - name: format output: rewrite formatter: true run: cat ${target} ``` or via `stdin`, by specifying `stdin: true`: ```yaml theme={null} lint: definitions: - name: noop files: [ALL] commands: - name: format output: rewrite formatter: true run: cat - stdin: true ``` > Note: Linters that take their input via `stdin` may still want to know the file's path so that they can, say, generate diagnostics with the file's path. In these cases you can still use `${target}` in `run`. ## Exit codes Linters often use different exit codes to categorize the outcome. For instance, [`markdownlint`](https://github.com/igorshubovych/markdownlint-cli#exit-codes) uses `0` to indicate that no issues were found, `1` to indicate that the tool ran successfully but issues were found, and `2`, `3`, and `4` for tool execution failures. Trunk supports specifying either `success_codes` or `error_codes` for a linter: * if `success_codes` are specified, Trunk expects a successful linter invocation (which may or may not find issues) to return one of the specified `success_codes`; * if `error_codes` are specified, Trunk expects a successful linter invocation to return any exit\ code which is *not* one of the specified `error_codes`. `markdownlint`, for example, has `success_codes: [0, 1]` in its configuration. **Note:** A linter command should set either success codes or error codes, but not both\*\*.\*\* ## Working directory `run_from` determines what directory a linter command is run from. | run\_from | Description | | --------------------------------------- | ------------------------------------------------------------------------------------------ | | `` (`.` by default) | Explicit path to run from | | `${parent}` | Parent of the target file; e.g. would be `foo/bar` for `foo/bar/hello.txt` | | `${root_or_parent_with()}` | Nearest parent directory containing the specified file | | `${root_or_parent_with_dir()}` | Nearest parent directory containing the specified directory | | `${root_or_parent_with_regex()}` | Nearest parent directory containing a file or directory matching specified regex | | `${root_or_parent_with_direct_config}` | Nearest parent directory containing a file from `direct_configs` | | `${root_or_parent_with_any_config}` | Nearest parent directory containing a file from `affects_cache` or `direct_configs` | | `${target_directory}` | Run the linter from the same directory as the target file, and change the target to be `.` | | `${compile_command}` | Run from the directory where `compile_commands.json` is located | ## Template Variables Note that some of the fields in this command template contain `${}` tokens: these tokens are why `command` is a template and are replaced at execution time with the value of that variable within the context of the lint action being executed. | Variable | Description | | ----------------- | ----------------------------------------------------------------------------- | | `${workspace}` | Path to the root of the repository | | `${target}` | Path to the file to check, relative to `${workspace}` | | `${linter}` | Path to the directory the linter was downloaded to | | `${runtime}` | Path to the directory the runtime (e.g. `node`) was downloaded to | | `${upstream-ref}` | Upstream git commit that is being used to calculate new/existing/fixed issues | | `${plugin}` | Path to the root of the plugin's repository | ## Limiting concurrency If you would like to limit the number of times trunk will invoke a linter concurrently, then you can use the `maximum_concurrency` option. For example, setting `maximum_concurrency: 1` will limit Trunk from running more than one instance of the linter simultaneously. ## Environment variables Trunk by default runs linters *without* environment variables from the parent shell; however, most linters need at least some such variables to be set, so Trunk allows specifying them using `environment`; for example, the `environment` for `ktlint` looks like this: ```yaml theme={null} lint: definitions: name: ktlint # ... environment: - name: PATH list: ["${linter}"] - name: LANG value: en_US.UTF-8 ``` Most `environment` entries are maps with `name` and `value` keys; these become `name=value` environment variables. For `PATH`, we allow specifying `list`, in which case we concatenate the entries with `:`. We use the same template syntax for `environment` as we do for [`command`](./commands#commands). ## Output Types and Parsing The output of a command should be in one of the supported output types like [SARIF](./output#sarif) or something that can be parsed with a [regex](./output#regex). See [See Output Types](./commands#output-types-and-parsing) for more details. If the standard output types do not meet your needs, you can also create a [custom parser](./output-parsing). ## Full Reference The linter command definitions are defined in `lint.definitions.commands`. A single linter can have multiple commands if it is used in different ways. *Note:*. If you define the executable to run here (the command definition), then you should *not* define it also in the linter definition. Defining it here as a command is preferred. ## `allow_empty_files` `allow_empty_files`: *optional boolean*. Skip linting empty files for this linter. Trunk will assume there are no linters if the file is empty. ## `batch` `batch`: *optional boolean*. Combine multiple files into the same execution. If true, the `${target}` template substitution in the `run` field may expand into multiple files. ## `cache_ttl` `cache_ttl`, *duration string*. If this linter is not [idempotent](./commands#idempotent), this is how long cached results are kept before they expire. Defaults to 24hrs. See [Output Caching](../../caching) for more details. ## `cache_results` `cache_results`: *optional boolean*. Indicates if this linter wants to cache results. See [Caching](./files-and-caching) for more details. ## `disable_upstream` `disable_upstream`: *optional boolean*, Whether this linter supports comparing against the upstream version of this file. ## `error_codes` `error_codes`: List of exit codes this linter will return when it hit an internal failure and couldn't generate results. **A linter should set either success codes or error codes, but not both.** See also [`success_codes`](./commands#success_codes). ## `enabled` `enabled`: *optional boolean*. Whether the command is enabled to run when the linter is run. Allows some commands of a linter to be run by default without others. ## `files` `files` is a list of file types listed in the `lint.files` section that this linter applies to. Example: **prettier** [full source](https://github.com/trunk-io/plugins/blob/main/linters/prettier/plugin.yaml) ```yaml theme={null} lint: definitions: - name: prettier files: - typescript - yaml - css - sass - html - markdown - json - javascript - graphql - prettier_supported_configs ``` ## `fix_prompt` `fix_prompt`, *optional string.* e.g. 'Incorrect formatting' or 'Unoptimized image'. This string is used when prompting the user to use the linter interactively. ## `fix_verb` `fix_verb`: *optional string*. This string is used when prompting the user to use the linter interactively. Example: `optimize`, `autoformat`, or `compress`. ## `formatter` `formatter`: *optional boolean*. Whether this command is a formatter and should be included in `trunk fmt`. ## `in_place` `in_place`: *optional boolean*. Indicates that this formatter will rewrite the file in place. **Only applies to formatters**. ## `idempotent` `idempotent`: *optional boolean*. Indicates whether a linter is idempotent with config and source code inputs. For example, `semgrep` fetches rules from the Internet, so it is not idempotent . If set, will only cache results a duration of `cache_ttl`. See [Output Caching](./files-and-caching) for more details. ## `is_security` `is_security`: *optional boolean*. Whether findings from this command should be considered "security" or not. Allows this linter to be run with `--scope==security`. [See Command Line Options](/merge-queue/using-the-queue/reference) ## `maximum_file_size` `maximum_file_size`: *optional number*. The maximum file size in bytes for input files to the linter. If not specified, the [lint.default\_max\_file\_size](./#default_max_file_size) will be used. ## `max_concurrency` `max_concurrency`: *optional integer*, The maximum number of processes that Trunk Code Quality will run concurrently for this linter. [See Limiting Concurrency](./commands#limiting-concurrency) ## `name` `name`: *string*. A unique name for this command (some tools expose multiple commands, format, lint, analyze, etc.). ## `no_issues_codes` `no_issues_codes`: List of exit codes that Trunk will use to assume there were no issues without parsing the output. ## `output` `output`: *string*. which type of output this linter produces. [See Output Types](./commands#output-types-and-parsing). ## `parser` `parser`: The definition of a parser that will transform the output of the linter into SARIF. Not needed if linter is already output SARIF. [See Output Types](./commands#output-types-and-parsing) ## `parse_regex` `parse_regex`: *string*. A regular expression used to support regex parsing. [See Regex output type](./output#regex) ## `platforms` `platforms`: A list of platforms this linter supports. (ex: `windows`, `macos`, `linux`). Linters using managed runtimes (node, python, etc.) can generally run cross-platform and do not need the `platforms` property set. For tools which *are* platform specific or which have different configuration for each platform, this property can be used to distinguish between them. When multiple command definitions have the same name, Trunk Check will pick the first one that matches the `platforms` setting. For example, the `detekt` plugin has different exit codes for Windows than MacOS or Linux, and has two command definitions with different `success_codes` fields. [Full Source](https://github.com/trunk-io/plugins/blob/main/linters/detekt/plugin.yaml). ```yaml theme={null} lint: definitions: - name: detekt files: [kotlin] download: detekt commands: - name: lint platforms: [windows] output: sarif run: detekt-cli --build-upon-default-config --config .detekt.yaml --input ${target,} --report sarif:${tmpfile} success_codes: [0, 1, 2] read_output_from: tmp_file batch: true cache_results: true - name: lint output: sarif run: detekt-cli --build-upon-default-config --config .detekt.yaml --input ${target,} --report sarif:${tmpfile} success_codes: [0, 2] read_output_from: tmp_file batch: true cache_results: true ``` ## `prepare_run` `prepare_run`: An extra command to run before running a linter. ## `read_output_from` `read_output_from`: Tell parser where to expect output from for reading. Should be one of `stdout`, `stderr`, and `tmp_file`. [See Output Sources](./output#output-sources) ## `run` `run`: The command to run a linter. This command can use variables provided at runtime such as `$plugin}` and `$target}`. [Full list of variables](./commands#template-variables). See [Run](./commands#how-code-qualit-runs-linters) for more details. `dart` `format` command: [full source](https://github.com/trunk-io/plugins/blob/main/linters/dart/plugin.yaml) ```yaml theme={null} lint: files: - name: dart extensions: [dart] definitions: - name: dart main_tool: dart commands: - name: format output: rewrite run: dart format ${target} ``` ## `run_from` `run_from`: What current working directory to run the linter from. See [Working Directory](./commands#working-directory) for more details. ## `run_when` `run_when`: When this command should be run. One of `cli`, `lsp`, `monitor`, or `ci`. ## `std_in` `std_in`: *optional boolean*. Should the command be fed the file on standard input? ## `success_codes` `success_codes:` List of exit codes that indicates linter ran successfully. **This is unrelated to whether or not there were issues reported by the linter**. **Note:** a linter should set either success codes or error codes, but not both. See also [`error_codes`](./commands#error_codes). ## `target` `target`, *optional string*, What target does this run on. By default, the target is the modified source code file, `${file}`. Some linters operate on a whole repo or directory. See [Input Target](./commands#input-target) for more details. Examples: **nancy** uses `.` as the target. [full source](https://github.com/trunk-io/plugins/blob/main/linters/nancy/plugin.yaml) ```yaml theme={null} # nancy uses . definitions: - name: nancy files: [go-lockfile] download: nancy runtime: go commands: - output: sarif run: sh ${plugin}/linters/nancy/run.sh success_codes: [0, 1, 2] target: . read_output_from: stdout is_security: true ``` **tflint** uses `${parent}` as the target. [full source](https://github.com/trunk-io/plugins/blob/main/linters/tflint/plugin.yaml) ```yaml theme={null} lint: definitions: - name: tflint files: [terraform] commands: - name: lint output: sarif prepare_run: tflint --init run: tflint --format=sarif --force success_codes: [0, 1, 2] read_output_from: stdout # tflint can only run on the current directory unless --recursive is passed target: ${parent} run_from: ${target_directory} version: ">=0.47.0" ``` **Clippy** uses `${parent_with(Cargo.toml)}` as the target. [full source](https://github.com/trunk-io/plugins/blob/main/linters/clippy/plugin.yaml) ```yaml theme={null} version: 0.1 lint: definitions: # clippy has 3 lint severities: deny, warn, and allow. Unfortunately deny causes rustc to # fail eagerly due to its implementation (https://github.com/rust-lang/rust/pull/87337), # We use --cap-lints to downgrade "deny" severity lints to warn. So rustc will find all # issues instead of hard stopping. There are currently only 70 of them, so we could hardcode # the list to fix their severity levels correctly. - name: clippy files: [rust] download: rust commands: - name: lint # Custom parser type defined in the trunk cli to handle clippy's JSON output. output: clippy target: ${parent_with(Cargo.toml)} run: cargo clippy --message-format json --locked -- --cap-lints=warn --no-deps success_codes: [0, 101, 383] run_from: ${target_directory} disable_upstream: true ``` ## `version` `version`: *optional string*, Version constraint. When a linter has multiple commands with the same name, Trunk Code Quality will select the first command that matches the version constraint. This is useful for when multiple incompatible versions of a tool need to be supported. Example: the `ruff` linter changed a command line argument from `--format` to `--output-format` in version `v0.1.0`. To handle both versions, the linter defines two commands with different version attributes. The first is for version `>=0.1.0`. If the first is not matched (because the install version of run is less that 0.1.0) then Trunk Code Quality will move on to the next command until it finds a match. [Full source](https://github.com/trunk-io/plugins/blob/main/linters/ruff/plugin.yaml). ```yaml theme={null} lint: definitions: - name: ruff files: [python] commands: - name: lint # As of ruff v0.1.0, --format is replaced with --output-format version: ">=0.1.0" run: ruff check --cache-dir ${cachedir} --output-format json ${target} output: sarif parser: runtime: python run: python3 ${cwd}/ruff_to_sarif.py 0 batch: true success_codes: [0, 1] - name: lint run: ruff check --cache-dir ${cachedir} --format json ${target} output: sarif parser: runtime: python run: python3 ${cwd}/ruff_to_sarif.py 1 batch: true success_codes: [0, 1] ``` # Definitions Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/lint/definitions The definition of a particular linter is put under `lint.definitions`. The following properties define the settings of a *particular linter*, not for all linters. For global linter settings, see [Lint Config](./). ## `affects_cache` `affects_cache`: The list of files that affect the cache results of this linter. [See Caching](../../caching). ## `allow_empty_files` `allow_empty_files`: *optional boolean*. Indicates to skip linting empty files for this linter. ## `batch` `batch`: *optional boolean*. Combine multiple files into the same execution. ## `commands` `commands`: The list of commands exposed by this linter. See [Linter Command Definition](./commands). ## `deprecated` `deprecated`: *string*. Indicates the linter is deprecated and should not be used. ## `direct_configs` `direct_configs`: *string list*. Indicates config files used to auto-enable the linter. See [Auto Enabling](./auto-enable). ## `disabled` `disabled`: *optional boolean*: Whether linter is actively disabled (and will not be recommended) and will not run (overrides enabled). ## `download` `download`: *string*. The download URL. You must provide either runtime + packages or download, not both. Using runtimes is preferred. See [Runtimes](../runtimes). ## `enabled` `enabled`: *optional boolean*. Whether this linter is enabled. ## `environment` `environment`: a list of runtime variables used when running the linter. See [Command Environment Variables](./commands#environment-variables). ## `extra_packages` `extra_packages`: list of strings, Extra packages to install, versions are optional. See [Linter Dependencies](./dependencies). ## `formatter` `formatter`: *boolean*. Indicates whether this is a formatter and should be included in `trunk fmt`. ## `good_without_config` `good_without_config`: *optional boolean*. Indicates whether this linter is recommended without the user tuning its configuration. Prefer [`suggest_if`](./definitions#suggest_if). ## `hold_the_line` `hold_the_line`: *optional boolean*. Whether [hold-the-line will](/code-quality/overview#hold-the-line) be done for this linter or not. ## `include_lfs` `include_lfs`: *boolean*. Allow this linter to operate on files tracked using [git LFS](https://git-lfs.com/). ## `include_scanner_type` `include_scanner_type`: which include scanner to use, if any. ## `issue_url_format` `issue_url_format`: *string*, a format string that accepts issue codes for links to issues docs. ## `known_good_version` `known_good_version`: *string*. A version to be used when Trunk cannot query the latest version. Currently, Trunk can query the latest version for all package managers and downloads hosted on GitHub. ## `known_bad_versions` `known_bad_versions`: *string list*. Versions of a linter that are known to be broken and should not be run with Trunk. We will fall back to a `known_good_version` if init or upgrade chooses something in this set. ## `main_tool` `main_tool`, *string*. If your linter depends on more than a single tool, and none of the tools has the same name as the linter, then you will need to specify which is the main tool here. It will be used to version the tool from the linter's enabled version. ## `name` `name` *required string.* The name of the linter. This property will be used to refer to the linter in other parts of the config, for example, in the list of enabled linters. ## `package` `package`: string, What primary package to install, if using a package manager runtime. The enabled version of the runtime for this linter will apply to this package. See [Linter Dependencies](./dependencies). ## `path_format` `path_format`, Whether to use the platform-specific paths or generic "/". Default native. ## `plugin_url` `plugin_url`: *string*, a plugin url for reporting issues. ## `prepare_command` `prepare_command`. A command that is run once per session before linting any number of files using this linter. ex. `[tflint, --init]`. ## `query_compile_commands` `query_compile_commands`, *optional boolean*. ## `runtime` `runtime`: RuntimeType, Which package manager runtime, if any, to require to be setup for this linter. Ex: `node`, `ruby`, `python`. See [Linter Dependencies](./dependencies). ## `run_timeout` `run_timeout`: *duration string*. Describes how long a linter can run before timing out. [See timeouts](../../../linters/configure-linters#timeout). ## `suggest_if` How to determine if this linter should be auto-enabled/recommended. Possible values are `never`, `config_present`, and `files_present`. [See auto-enabling](./auto-enable) for more details. ## `supported_platforms` Platform constraint. If incompatible, renders a notice. See also [Command `platforms`](./commands#platforms). ## `tools` `tools`, *string list*. The list of tools used by this linter. See [Linter Dependencies](./dependencies). ## `version_command` `version_command`: Version check commands. ## `verbatim_message` `verbatim_message`: Do not try to truncate or reflow the output of this linter. # Dependencies Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/lint/dependencies Linters use the `tools` section of the `.trunk/trunk.yaml` to specify Trunk configured binaries that the linter uses to run. The `linter.definitions.tools` key specifies a list of tool names. There are two ways for a linter to depend on a tool: [Eponymous Tools](./dependencies#eponymous-tool-dependencies) and [Additional Tools](./dependencies#additional-tool-dependencies) ## Eponymous Tool Dependencies When the name of the tool matches the name of a linter, it is called an *eponymous tool dependency*. In the example below the `pylint` linter depends on the `pylint` tool, which is defined as the package `pylint` running with the `python` runtime. Eponymous tools need to be defined *separately* from the linter but implicitly enabled with the linter's version. You may explicitly enable the eponymous tool if you wish, but note that its version needs to be synced to that of the linter. See the [Tools Configuration](../tools) page for more details on how to set up Tools. ```yaml theme={null} tools: definitions: - name: pylint runtime: python package: pylint shims: [pylint] known_good_version: 2.11.1 lint: definitions: - name: pylint files: [python] commands: - name: lint # Custom parser type defined in the trunk cli to # handle pylint's JSON output. output: pylint run: pylint --exit-zero --output ${tmpfile} --output-format json ${target} success_codes: [0] read_output_from: tmp_file batch: true cache_results: true tools: [pylint] suggest_if: config_present direct_configs: - pylintrc - .pylintrc affects_cache: - pyproject.toml - setup.cfg issue_url_format: http://pylint-messages.wikidot.com/messages:{} known_good_version: 2.11.1 version_command: parse_regex: pylint ${semver} run: pylint --version ``` ## Additional Tool Dependencies You can also have a scenario where a linter depends on a tool that is not identically named - an *additional tool dependency*. We give an example below: ```yaml theme={null} tools: definitions: - name: terragrunt known_good_version: 0.45.8 download: terragrunt shims: - name: terragrunt target: terragrunt lint: definitions: - name: terragrunt tools: [terragrunt, terraform] known_good_version: 0.45.8 files: [hcl] suggest_if: never environment: - name: PATH list: ["${linter}"] commands: - name: format output: rewrite run: terragrunt hclfmt ${target} success_codes: [0] sandbox_type: copy_targets in_place: true formatter: true batch: true version_command: parse_regex: terragrunt v${semver} run: terragrunt -version ``` In this scenario, `terraform` is an additional tool dependency - `terragrunt` requires it to be in `$PATH`. If the tool is an additional dependency, it must be enabled explicitly and versioned independently of the linter - that is, it must be listed in the `tools.enabled` section. ## Download via package manager If your linter can be downloaded via `gem install`, `go get`, `npm install`, or `pip install`, you can specify a `runtime` and the `package` key: ```yaml theme={null} lint: definitions: - name: fizz-buzz files: [javascript] # npm install fizz-buzz runtime: node package: fizz-buzz ``` This will now create a hermetic directory in `~/.cache/trunk/linters/fizz-buzz` and `npm install fizz-buzz` there. You can refer to different versions of your package in `trunk.yaml` as normal, via `fizz-buzz@1.2.3`. > Note: Such downloads will use the *hermetic* version of the specified runtime that `trunk` installs, not the one you've installed on your machine. See [Package-based Tools](../tools#package-based-tools) for more information. # Files and Caching Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/lint/files-and-caching ## Applicable filetypes To determine which linters to run on which files (i.e. compute the set of lint actions), Trunk requires that every linter define the set of filetypes it applies to in `lint.files`, then reference those files from `lint.definitions[*].files`. We have a number of pre-defined filetypes (e.g. `c++-header`, `gemspec`, `rust`; see our [plugins repo](https://github.com/trunk-io/plugins/blob/main/linters/plugin.yaml) for an up-to-date list), but you can also define your own filetypes. Here's how we define the `python` filetype: ```yaml theme={null} lint: files: - name: python extensions: - py - py2 - py3 shebangs: - python - python3 ``` This tells Trunk that files matching either of the following criteria should be considered `python` files: * the extension is any of `.py`, `.py2`, or `.py3` (e.g. `lib.py`) * the shebang is any of `python` or `python3` (e.g. `#!/usr/bin/env python3`) The **flake8** linter definition uses python files, so it references the filetype above in its definition. ```yaml theme={null} lint: definitions: - name: flake8 files: [python] commands: ... affects_cache: - setup.cfg - tox.ini # In case the user uses https://pypi.org/project/Flake8-pyproject/ - pyproject.toml ``` ## Caching Trunk Code Quality automatically caches results from previous runs of linters to speed up development. To do this Trunk needs to know which files could potentially affect the cache, besides the source code files themselves. ### Enabling caching If a linter wishes Trunk to cache the results it should set `cache_results` to true. ## Files which affect caching The `lint.definitions[*].affects_cache` property is a list of files which could affect the cache. General these are files which would change the configuration of the linter, and therefore invalidate the current cached results. For example, the **flake8** tool tells trunk to invalidate the cache whenever the `setup.cfg`, `tox.ini`, or `pyproject.toml` files are changed. ```yaml theme={null} lint: definitions: - name: flake8 files: [python] commands: ... affects_cache: - setup.cfg - tox.ini # In case the user uses https://pypi.org/project/Flake8-pyproject/ - pyproject.toml ``` ### Idempotency Trunk Code Quality also needs to know if the linter command itself is idempotent, meaning the command will return the exact same results given the exact same inputs. Most linters are, however semgrep, for example, fetches rules from the internet so the output could be different each time. Setting the `linter.definitions[*].commands.idempotent` property to true will tell trunk to only cache the result for a duration of `cache_ttl`, which is set to 24hrs by default. # Lint Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/lint/index ### Lint Config The `lint` section of `.trunk/trunk.yaml` represents the configuration of all linters. This is where you can: * Define the linters (`lint.definitions`), * List linters to enable and disable (`lint.enabled` and `lint.disabled`) * Define file categories (`lint.files`) * List required `runtimes` and `downloads`. * And additional cross-linter settings. ### `bazel` `bazel`: bazel configuration * `paths` locations to look for Bazel binary. [Example](../../../linters/supported/clang-tidy#using-bazel). ### `comment_formats` `comment_formats`: Definitions of comment formats. Reused in linter definitions. Trunk Quality already defines many common comment format such as `hash` (`# comment`), `slashes-block` (`/* comment */`), and `slashes-inline` (`// comment`). For the full list [see the linters plugin.yaml](https://github.com/trunk-io/plugins/blob/main/linters/plugin.yaml). To create a new comment format provide the name and delimiters like this: ```yaml theme={null} lint: comment_formats: - name: dashes-block leading_delimiter: --[[ trailing_delimiter: --] ``` ### `compile_commands` `compile_commands`: compile commands for clang-tidy. Must be one of `json` or `bazel`. ### `compile_commands_roots` `compile_commands_roots`: Directories to search for `compile_commands.json`. The default is `build/`. ### `default_max_file_size` `default_max_file_size`: Default maximum filesize in bytes. Trunk Code Quality will not run linters on any files larger than this. Default value is 4 megabytes. ### `definitions` `definitions`: Where you define or override linter settings. See [Linter Definition Config](./definitions). ### `disabled` `disabled`: The list of linters to disable. Adding a linter here will prevent trunk from suggesting it as a new linter each time you upgrade. Linter names can be in the form of `` or `@`, the same format as the [enabled](./#enabled) property. ### `downloads` `downloads`: Locations to download binary artifacts from. Using [tool definitions](../tools) instead is preferred. ### `enabled` `enabled`: The list of linters to enable. Linter names can be in the form of `` or `@`. Examples: ```yaml theme={null} lint: enabled: # Mutually exclusive, choose one: - eslint # Use the system version of markdownlint - eslint@9.0.0 # Use a hermetically managed version of eslint - eslint@node # Use eslint from node_modules/.bin ``` ### `exported_configs` `exported_configs`: Linter configs to export when another project is [importing this plugin](../../../linters/shared-configs) ### `extra_compilation_flags` `extra_compilation_flags`: When running clang-tidy, this list will be appended to the compile command. ### `files` `files`: Definitions of filetypes Every linter must define the set of filetypes it applies to in the `lint.files` section. New filetypes are defined with the name and extensions properties. They may also include the comments properties to describe what style of comments are used in these files. This is how the C++ source filetype is defined. See also [Files and Caching](./files-and-caching). ```yaml theme={null} lint: files: - name: c++-source extensions: - C - cc - cpp - cxx comments: - slashes-block - slashes-inline ``` ### `ignore` `ignore`: files to be ignored by linters. ### `reuse_upstream` `reuse_upstream`: If enabled, Trunk will cache upstream sandboxes instead of creating a new one each time. Options are `true`, or `false`. ### `runtimes` `runtimes`: Node, python, cargo, etc. Used to define or override a runtime environment for package management. [See Runtimes](../runtimes). ### `skip_missing_compile_command` `skip_missing_compile_command`: For linters that depend on compile commands, setting this will cause Trunk to skip files without a compile command rather than report an error. ### `threshold` `threshold`: where you specify the blocking behavior of linters. The [threshold](../../../linters/configure-linters#blocking-thresholds) for whether an error from a linter should block commits or not. ### `upstream_mode` `upstream_mode`: How to generate the upstream sandbox used for generating lint results for revisions not currently checked out. Options are`symlink` (default), `hardlink`, or `copy`. If using `copy`, it can be slow without also enabling `reuse_upstream: true`. # Output Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/lint/output ## Output Sources The output format that Trunk expects from a linter is determined by its [`output`](./output#output-types) type. **`stdout`, `stderr` or `tmp_file`** `trunk` generally expects a linter to output its findings to `stdout`, but does support other output mechanisms: | `read_output_from` | Description | | ------------------ | --------------------------------------------------------------------------------- | | `stdout` | Standard output. | | `stderr` | Standard error. | | `tmp_file` | If `${tmpfile}` was specified in `command`, the path of the created `${tmpfile}`. | ## Output Types Trunk supports several different generic output types. Most linters will use one of these output types, but if your linter doesn't conform well to any of these specifications, you can also write a [custom parser](./output-parsing). In general, SARIF should be preferred over other formats because it is the most flexible and battle tested. Trunk currently supports the following linter output types. | Linter Type | Autofix support | Description | | --------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | [`sarif`](#sarif) | ✓ | Produces diagnostics as [Static Analysis Results Interchange Format](https://docs.oasis-open.org/sarif/sarif/v2.0/sarif-v2.0.html) JSON. | | [`lsp_json`](#lsp-json) | | Produces diagnostics as [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) JSON. | | [`pass_fail`](#pass-fail-linters) | | Writes a single file-level diagnostic to `stdout`. | | [`regex`](#regex) | | Produces diagnostics using a custom regex format. | | [`arcanist`](#arcanist) | ✓ | Produces diagnostics as Arcanist JSON. | | [`rewrite`](#formatters) | ✓ | Writes the formatted version of a file to `stdout`. | If your linter produces a different output type, you can also write a [parser](./output-parsing) to transform the linter's output into something Trunk can understand. ### SARIF `output: sarif` linters produce diagnostics in the [Static Analysis Results Interchange Format](https://docs.oasis-open.org/sarif/sarif/v2.0/sarif-v2.0.html): ```json theme={null} { "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", "version": "2.1.0", "runs": [ { "results": [ { "level": "warning", "locations": [ { "physicalLocation": { "artifactLocation": { "uri": "/dev/shm/sandbox/detekt_test_repo/example.kt" }, "region": { "startColumn": 12, "startLine": 18 } } } ], "message": { "text": "A class should always override hashCode when overriding equals and the other way around." }, "ruleId": "detekt.potential-bugs.EqualsWithHashCodeExist" } ], "tool": { "driver": { "downloadUri": "https://github.com/detekt/detekt/releases/download/v1.19.0/detekt", "fullName": "detekt", "guid": "022ca8c2-f6a2-4c95-b107-bb72c43263f3", "informationUri": "https://detekt.github.io/detekt", "language": "en", "name": "detekt", "organization": "detekt", "semanticVersion": "1.19.0", "version": "1.19.0" } } } ] } ``` ### LSP JSON `output: lsp_json` linters output issues as [Language Server Protocol](https://microsoft.github.io/language-server-protocol/specification#diagnostic) JSON. ```json theme={null} [ { "message": "Not formatted correctly. Missing owner", "code": "missing-owner", "severity": "Error", "range": { "start": { "line": 12, "character": 8 }, "end": { "line": 12, "character": 12 } } }, { "message": "TODO is assigned to someone not listed in this project", "code": "unknown-user", "severity": "Warning", "range": { "start": { "line": 37, "character": 0 }, "end": { "line": 37, "character": 14 } } } ] ``` ### Pass/Fail Linters `output: pass_fail` linters find either: * no issues in a file, indicated by exiting with `exit_code=0`, or * a single file-level issue in a file, whose message is the linter's `stdout`, indicated by exiting\ with `exit_code=1`. > Note: Exiting with `exit_code=1` but writing nothing to `stdout` is considered to be a linter tool failure. > > Note: `pass_fail` linters are required to have `success_codes: [0, 1]` ### Regex `output: regex` linters produce output that can be parsed with custom regular expressions and named capture groups. The regular expression is specified in the `parse_regex` field. `regex` supports capturing strings from a linter output for the following named capture groups: * `path`: file path (required) * `line`: line number * `col`: column number * `severity`: one of `note`, `notice`, `allow`, `deny`, `disabled`, `error`, `info`, `warning` * `code`: linter diagnostic code * `message`: description For example, the output ``` .trunk/trunk.yaml:7:81: [error] line too long (82 > 80 characters) (line-length) ``` can be parsed with the regular expression ``` ((?P.*):(?P\d+):(?P\d+): \[(?P.*)\] (?P.*) \((?P.*)\)) ``` and would result in a `trunk` diagnostic that looks like this: ``` 7:81 high line too long (82 > 80 characters) regex-linter/line-length ``` In the event that multiple capture groups of the same name are specified, the nonempty capture will be preferred. If there are multiple non-empty captures, a linter error will be thrown. Adjust your regular expression accordingly to match the specifics of your output. > Note: For additional information on building custom regular expressions, see [re2](https://github.com/google/re2/wiki/Syntax). More complicated regex may require additional escape characters in yaml configuration. ### Arcanist You can also output JSON using the Arcanist format. ```json theme={null} [ { "Char": 1, "Code": "missing_copyright", "Description": "Message about things\nMaybe contain multiple lines and web\nlinks\nhttps://website.com/notice-about-stuff\n", "Line": 1, "Name": "Incorrect (or missing) copyright notice", "OriginalText": "", "Path": "somefile.py" } ] ``` ### Formatters `output: rewrite` linters write the formatted version of a file to `stdout`; this becomes an autofix which `trunk` can prompt you to apply (which is what `trunk check` does by default) or automatically apply for you (if you `trunk check --fix` or `trunk fmt`). For example, if you wanted a linter to normalize your line endings, you could do this: ```yaml theme={null} lint: definitions: - name: no-carriage-returns files: [ALL] commands: - output: rewrite formatter: true command: sed s/\r// ${target} success_codes: [0] ``` Setting `formatter: true` will cause `trunk fmt` to run this linter. # Output Parsing Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/lint/output-parsing If you have a command or utility that you want to run pretty much as-is, but Trunk doesn't natively understand how to parse it, you can inject your own custom parser to translate its output into a format that Trunk does understand! For example, let's say that we want to use `grep` as a linter, but we want to add more context to the matches. We could define a custom linter like so: ```yaml theme={null} lint: definitions: - name: todo-finder files: [ALL] commands: - output: regex # matches the parser run output parse_regex: "((?P.*):(?P\\d+):(?P\\d+): \\[(?P.*)\\] (?P.*) \\((?P.*)\\))" run: grep --with-filename --line-number --ignore-case todo ${target} success_codes: [0, 1] read_output_from: stdout parser: run: "sed -E 's/(.*):([0-9]+):(.*)/\\1:\\2:0: [error] Found todo in \"\\3\" (found-todo)/'" ``` The execution model that `trunk` follows for a parser is that it will: * execute the linter's `run` field, asserting that either: * the linter's exit code is in `success_codes`, or * the linter's exit code is not in `error_codes`; * execute `parser.run`, * with the `read_output_from` of the linter execution fed to `parser.run` as `stdin`, * assert that the exit code of the parser is 0, and then * use `output` to determine how it should parse the parser's `stdout`. Note that you can also set `parser.runtime` to [`node`](./output-parsing#node) or [`python`](./output-parsing#python) so that you can write your parser in Javascript or Python instead, if you so prefer! You can find plenty of examples of python parsers in our [plugins repo](https://github.com/trunk-io/plugins). **Node** ```yaml theme={null} lint: definitions: - name: todo-finder-node files: [ALL] commands: - output: parsable # parse_regex matches the parser run output parse_regex: "((?P.*):(?P\\d+):(?P\\d+): \\[(?P.*)\\] (?P.*) \\((?P.*)\\))" run: grep --with-filename --line-number --ignore-case todo ${target} success_codes: [0, 1] read_output_from: stdout parser: runtime: node run: ${workspace}/todo-finder-parser.js ``` ```javascript theme={null} #!/usr/bin/env node 'use strict'; let readline = require('readline'); let rl = readline.createInterface({ input: process.stdin }); rl.on('line', function(line){ let match = line.match(/(.*):([0-9]+):(.*)/); if (match) { let [_, path, line_number, line_contents] = match; console.log(`${path}:${line_number}:0: [error]` +` Found todo in "${line_contents}" (found-todo)`); } ``` Remember to run `chmod u+x todo-finder-parser.js` so that `trunk` can run it! **Python** ```yaml theme={null} lint: definitions: - name: todo-finder-python files: [ALL] commands: - output: parsable # parse_regex matches the parser run output parse_regex: "((?P.*):(?P\\d+):(?P\\d+): \\[(?P.*)\\] (?P.*) \\((?P.*)\\))" run: grep --with-filename --line-number --ignore-case todo ${target} success_codes: [0, 1] read_output_from: stdout parser: runtime: python run: ${workspace}/todo-finder-parser.js ``` ```python theme={null} #!/usr/bin/env python import re, sys for line in sys.stdin.readlines(): match = re.match("(.*):([0-9]+):(.*)", line) if match: path, line_number, line_contents = match.groups() print(f"{path}:{line_number}:0: [error] " "Found todo in \"{line_contents}\" (found-todo)") ``` Remember to run `chmod u+x todo-finder-parser.py` so that `trunk` can run it! # Merge Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/merge Custom `required_statuses` defined in the `.trunk/trunk.yaml` file take precedence over the GitHub required status checks from branch protection. Use custom `required_statuses` when your checks don't match what you configure on GitHub one-to-one. ```yaml theme={null} version: 0.1 ``` ```yaml theme={null} cli: version: 1.16.0 merge: required_statuses: - Trunk Check - Unit tests & test coverage # Add more required statuses here ``` # Per User Overrides Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/per-user-overrides ## Per-User Customization Trunk can also be managed by the `.trunk/user.yaml` file in your repository. This file is optional, but it allows individual developers to customize how they want `trunk` to run on their machines. Simply configure `.trunk/user.yaml` as you would for `.trunk/trunk.yaml`. Now you can add additional linters, enable [actions](../actions/), or specify [default command options](./#cli), without impacting the way other developers run `trunk`. Be mindful that `.trunk/user.yaml` takes precedence over `.trunk/trunk.yaml`, so substantial modifications could violate hermeticity. ## Identity Config Trunk also saves a user config in `$HOME/.cache/trunk/user.yaml`. This is auto-generated in order to manage [anonymous usage data](./telemetry) and persist login sessions. # Exporting linter configs Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/plugins/exported-configs Reusing linter configs across projects. Plugin repositories can also export their own linter config files to keep configuration synced across an organization. Simply add an `exported_configs` section to a `plugin.yaml`, with paths to all of the config files you want to export, relative to the repository root. For example: ```yaml theme={null} lint: exported_configs: - configs: - .eslintrc.yaml - .trunk/configs/.shellcheckrc ``` These config files will be available for linters that enumerate them in `affects_cache`or `direct_configs` to reference. These files are automatically symlinked into the repository root during linter execution. The set of applicable config files can be viewed in the details yaml file listed when running `trunk check --verbose`. Plugin-exported configs are sourced in lockstep with the plugin itself, so you will need to update\ the `ref` field to use the latest configs. Note that if you're using an IDE Extension like clangd with an LSP that relies on those configs being in the root, you will need to manually create a symlink to the plugin's config. You can do this by running `ln -s .trunk/plugins// `. For an example of a plugin repo with config files, see our own [configs](https://github.com/trunk-io/configs) repo. ### Importing configs This process can also be reversed to import config files from a plugins repository which\ does not explicitly export them. Given a plugin sourced with id `trunk`, the sourcing repository can\ achieve the same effect by including the following in its `.trunk/trunk.yaml`. ```yaml theme={null} lint: exported_configs: - plugin_id: trunk configs: - .eslintrc.yaml - .trunk/configs/.shellcheckrc ``` # Share config between codebases Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/plugins/external-repositories Sharing configuration between codebases using public config repos To standardize Trunk configuration across an organization, you can create and publish a public plugins repository. This repo can define new linter definitions, specify enabled linters and actions, and even [export linter configs](./exported-configs). Once you've created your plugin repository, you can source it in other repositories to adopt shared configuration across your organization. For an example of how we do this in our own org, check out our [configs repo](https://github.com/trunk-io/configs). Note that in order to keep linters and tools up to date in your plugin configs repo, you'll need to run `trunk upgrade --apply-to=plugin.yaml` to apply [upgrades](../../../linters/upgrades). After making a public GitHub release with your plugin changes, other dependent repos will pick up these changes automatically when running `trunk upgrade`. ### Get started Let's walk through how to create a simple linter that warns about TODOs in your codebase. We'll start by creating a new Git repository: ```bash theme={null} PLUGIN_PATH=~/my-first-trunk-plugin mkdir "${PLUGIN_PATH}" && cd "${PLUGIN_PATH}" git init ``` And then create a linter that can find TODOs in your codebase using `grep` and `sed`: ```bash theme={null} cat >plugin.yaml < trunk check enable todo-finder ``` And now, to demonstrate how this works, let's `trunk check` some files where we know we have TODOs: ```bash theme={null} trunk check $(git grep -li todo | head -n 10) ``` which will show you something like this: ``` .eslintrc.yaml:19:0 19:0 high Found todo in " # TODO(chris): Figure out why this causes a massive slowdown ... .trunk/dev-out/O1F.txt local.todo-finder/found-todo 101:0 high Found todo in " node/no-unpublished-import: off # TODO: do we want this?" local.todo-finder/found-todo ``` ### Organizing your code In the example we gave above, we put the linter's source code in `plugin.yaml`, which is fine for an example, but not really great for anything more than that. We can take the `sed` command from the plugin we created earlier and push that into the shell script: ```bash theme={null} #!/bin/bash sed -E 's/(.*):([0-9]+):(.*)/\1:\2:0: [error] Found todo in \"\3\" (found-todo)/'" ``` > Tip: Remember to run `chmod u+x todo-finder-parser.sh` so that `trunk` can run it! and also point the definition of `todo-finder` at it: ```bash theme={null} version: 0.1 lint: definitions: - name: todo-finder files: [ALL] commands: - output: parsable run: grep --with-filename --line-number --ignore-case todo ${target} success_codes: [0, 1] read_output_from: stdout parser: run: ${plugin}/todo-finder-parser.sh ``` We can also go another step and push the entire linter definition into a shell script: ```bash theme={null} #!/bin/bash grep --with-filename --line-number --ignore-case todo "${1}" | \ sed -E 's/(.*):([0-9]+):(.*)/\1:\2:0: [error] Found todo in \"\3\" (found-todo)/'" ``` ```yaml theme={null} version: 0.1 lint: definitions: - name: todo-finder files: [ALL] commands: - output: parsable run: ${plugin}/todo-finder.sh success_codes: [0] ``` See our documentation on [custom linters](../../../linters/custom-linters) and [custom parsers](../lint/output-parsing) for more on what you can do, such as writing your parser in Javascript or Python! ### Publishing your plugin To share your plugin with the world, all you have to do is tag a release and push it to GitHub, GitLab, or some other repository hosting service: ```bash theme={null} git add . git commit "Create a TODO finder" git tag -a v0.0.0 --message "Initial TODO finder release" git remote add origin git push origin main v0.0.0 ``` Now that it's available on the Internet, everyone else can just use your plugin by running: ```bash theme={null} trunk plugins add --id=their-first-plugin v0.0.0 ``` # Plugins Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/plugins/index ### Plugin config merging Trunk uses a plugin system where a root configuration is defined in the [trunk-io/plugin repository](https://github.com/trunk-io/plugins). You can import many plugin config sources, and fields defined at each level override the level above. When plugin configs are merged, only fields defined in a config file are merged into the level above. You can define just the fields you wish to override in `.trunk/trunk.yaml and .trunk/user.yaml.` When using trunk, you can merge several sets of configuration files with a `trunk.yaml` schema. Config merging proceeds as follows: 1. Remote plugins sourced in `.trunk/trunk.yaml` (and `.trunk/user.yaml`). Plugins are sourced in the order they're defined, with later plugins overriding those defined before it. The [`trunk`](https://github.com/trunk-io/plugins) plugin is implicitly sourced first. 2. Your repo level `.trunk/trunk.yaml` file, complete with a CLI version and any definitions or enables. Configurations defined here override what's defined in the remote plugins. 3. Optionally, `.trunk/user.yaml`, a local **git-ignored** file where users can provide their own overrides. Additionally, any files enumerated in the lint `exported_configs` section are symlinked from their relevant plugin into the root of the workspace when an applicable linter is run with `trunk check`. ### Importing a plugin repository By default, trunk imports the trunk-io/plugins repository. To import a repo add it to the `plugins.sources` list. Each repo requires a URI and ref. ```yaml theme={null} plugins: sources: - id: trunk uri: https://github.com/trunk-io/plugins ref: v1.2.6 ``` | Field | Description | | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | unique identifier for this repository | | `uri` | address used to clone the target repository | | `ref` | commit id or tag to checkout. **Do not use branch names, as these can be unstable** | | `local` | path to local (on-disk) repository. Takes precedence over uri/ref if defined | | `import_to_global` (default: `true`) | import content into the global namespace. If set to false actions and linters defined in the plugin must be referenced by `.` | ### Plugin capabilities Any configuration used in `trunk.yaml` can also be used in a plugin repository, with [some exceptions](./#excluded-fields). A plugin repository must have one root level `plugin.yaml` and can have any number of other `plugin.yaml` files in other subdirectories. These configuration files are then merged into one composite plugin configuration. The most common use for a plugin repository is to define custom linters, actions, or tools. But they can also be used to define a common set of shared tools across an organization. For more info, see [organization configs](./external-repositories). The root `plugin.yaml` file may also have a `required_trunk_version` field which governs compatibility when [upgrading](../../../linters/upgrades) between CLI versions. #### Add a plugin to your `trunk.yaml` file To add a plugin from GitHub: ``` trunk plugins add https://github.com/trunk-io/plugins --id=trunk ``` To add a plugin from GitHub at a specific version: ``` trunk plugins add https://github.com/trunk-io/plugins v1.2.6 --id=trunk ``` To add a plugin from a local repository: ``` trunk plugins add /home/user/self/hello-world --id=hello-world ``` Note that when specifying a remote plugin, the `ref` field must be a tag or SHA. ### Plugins scope Plugins are merged serially, in the order that they are sourced, and can override almost any Trunk\ configuration. This allows organizations to provide a set of overrides and definitions in one\ central place. For instance, you can create your own `my-plugins` repository with `plugin.yaml`: ```yaml theme={null} version: 0.1 lint: definitions: - name: trufflehog commands: - name: lint # override trufflehog to use '--only-verified' run: trufflehog filesystem --json --fail --only-verified ${target} enabled: - ruff@0.0.256 ``` sourced in a `.trunk/trunk.yaml` file from another repository as follows: ```yaml theme={null} version: 0.1 plugins: sources: - id: trunk uri: https://github.com/trunk-io/plugins ref: v1.2.6 - id: my-plugins local: ../my-plugins ``` When a user runs `trunk` in the sourcing repository, they will already have `ruff` enabled, along with the `trufflehog` override from the `my-plugins` repository. Note that private GitHub plugin repositories are not currently supported. ### Excluded fields Plugin `sources`, as well as the `cli` `version`, are not merged from plugin repositories to ensure\ that config merging occurs in a predictable, stable fashion. # Runtimes Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/runtimes Trunk manages the hermetic installation of all required runtimes. You can also specifically pin a version of a runtime you'd like Trunk to use, or tell Trunk to reuse an already-installed runtime on the system. Trunk makes it easy for you to run tools (such as linters and actions) because, under the hood, Trunk actually downloads everything a given tool depends on, and then executes said tool in the context of its dependencies. In other words, you can run tools like `golangci-lint` and `rubocop` without wasting hours figuring out how to install the right Go and Ruby versions on your machine, because Trunk will install a `go` and `ruby` runtime for those tools to depend on. Importantly, just like how Trunk by design requires you to version your tools, i.e. specify which version of `golangci-lint` and `rubocop` is enabled in your repository at a given commit, Trunk also versions your runtimes. This means that you can stop asking questions like "Wait, which version of Go are you using?" and "How do I choose a Ruby version to install on this new Jenkins runner?"; instead, all you have to do is look at the `runtimes` section in your `.trunk/trunk.yaml`, and you know which version of which runtime Trunk will use for a tool at any given moment: ``` runtimes: enabled: - go@1.18.3 - node@16.14.2 - python@3.10.3 - ruby@3.1.0 ``` ## How does this work? Runtimes are defined by a combination of configuration and native code inside Trunk itself. Let's walk through an example, `prettier`: ```yaml theme={null} lint: definitions: - name: prettier runtime: node package: prettier commands: - run: prettier -w ${target} ... ``` Since Prettier uses the `node` runtime, let's also look at that definition; specifically, the `runtime_environment` and `linter_environment`: ```yaml theme={null} runtimes: definitions: - type: node linter_environment: - name: PATH list: - ${linter}/node_modules/.bin runtime_environment: - name: HOME value: ${home} - name: PATH list: - ${runtime}/bin ``` Now we have all the config fields we need to understand what Trunk does in this example. ### Installing `prettier` Before Trunk can run `prettier`, it needs to install `prettier`; this is done using the package manager associated with a given runtime, the mechanism for which is defined natively inside Trunk (i.e. Trunk has custom code for every runtime to manage how packages for said runtime are installed). For most runtimes, this is as simple as executing the runtime's package manager in the context of the `runtime_environment`; in this example, that means doing `npm install ${package}` with environment variables `HOME=${home}` and `PATH=${runtime}/bin`. ### Running `prettier` Once `prettier` is installed, we combine its runtime's `linter_environment` with any other environment variables that might be defined in a given `lint.definitions` entry (in this case there are none), and then use that as the environment when we execute the command for a given linter. ## Specifying a runtime version If you would like to use the system-installed runtime instead of the Trunk managed version you can always use the `runtimes.definitions.system_version` property in your `trunk.yaml` file. ```yaml theme={null} runtimes: enabled: - go@x.y.z # or runtimes: enabled: - go@>=x.y.z definitions: - type: go system_version: allowed ``` If you choose to use a system-managed version, you will also need to specify a runtime version constraint in your enabled section, e.g. `python@>=3.0.0`. # Telemetry Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/telemetry Trunk sends basic usage metrics from our local tools ([CLI](/code-quality/overview/cli/getting-started) & [VS Code Extension](../../ide-integration/vscode)) to our analytics system to help us understand our usage and improve our tools over time. We do not send your code or codebase to our backend. ## Why we collect usage data Our product team constantly works on feature enhancement and new areas to invest in. Usage data allows us best to understand the ergonomics and performance of our tools. For example, if we add a new subcommand to the command line interface - how often is it used? Additionally, usage data is gathered to track usage and compliance against our free and paid product offerings. To give concrete examples: we track our users' client version and operating system to understand backward compatibility requirements, and the time it takes our user base to upgrade to our latest releases. ## Example usage data ```json theme={null} { "anonymous_id": , "command": "check --all", "launcher_version": "1.2.3", "os": "macOS", "release": 1.4.1, "source": "client", "time": , "exit_code": 0, "duration_ms": 232, "repository": } ``` ## Can I disable usage data? Yes. You can disable usage telemetry by setting the following environment variable: ```bash theme={null} TRUNK_TELEMETRY=off ``` # Tools Source: https://docs.trunk.io/code-quality/overview/getting-started/configuration/tools Tool definitions Each tool definition shares a set of attributes: | Field | | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | The name of the tool. Must be unique. | | `known_good_version` | The default version to initialize the tool at (required). | | `shims` | A list of binaries exposed by the tool. Each of these will correspond to one identically named executable installed in `.trunk/tools.`In the most common case, there is exactly one shim matching the name of the tool. We'll discuss other cases below. | | `environment` | You can specify an environment for the tool. We provide the `${tool}` template argument that resolves to the installation directory of the tool. By default, we prepend this to `$PATH` within the shim script, so this is used to locate the binary. For legacy reasons, `${linter}` also resolves to this directory. | > Note: If the tool has a `runtime` attribute, the runtime's environment is merged in to its environment (discussed in the examples below). Broadly speaking, there are 3 kinds of tools - download, package, and runtime-based tools. We'll look at each one in turn: #### Download-based tools Download-based tools are straightforward: They reference a named download configuration in the global `downloads` section. Here is an example: ```yaml theme={null} downloads: - name: gh downloads: - os: linux: linux cpu: x86_64: amd64 arm_64: arm64 url: https://github.com/cli/cli/releases/download/v${version}/gh_${version}_${os}_${cpu}.tar.gz strip_components: 1 - os: windows: windows cpu: x86_64: amd64 arm_64: arm64 url: https://github.com/cli/cli/releases/download/v${version}/gh_${version}_${os}_${cpu}.zip strip_components: 1 # macOS releases since 2.28.0 started using .zip instead of .tar.gz - os: macos: macOS cpu: x86_64: amd64 arm_64: arm64 url: https://github.com/cli/cli/releases/download/v${version}/gh_${version}_${os}_${cpu}.zip strip_components: 1 version: ">=2.28.0" - os: macos: macOS cpu: x86_64: amd64 arm_64: arm64 url: https://github.com/cli/cli/releases/download/v${version}/gh_${version}_${os}_${cpu}.tar.gz strip_components: 1 tools: definitions: - name: gh download: gh known_good_version: 2.27.0 environment: - name: PATH list: ["${tool}/bin"] shims: [gh] ``` Note that for the downloaded archive, the binary named `gh` is inside the `bin` directory, so we use the environment to point the `$PATH` there. #### Download fields `strip_components`: This number of leading directory components to remove from all files in an archive when extracting. `rename_single_file`: If an archive contains a single file, this will cause that file to be renamed to the name of the tool. This is most useful for downloads of gzip'd binaries with the platform name in the binary. #### Package-based tools Package-based tools depend on specified `package` and `runtime` attributes. Here is an example of configuring `mypy` as a tool: ```yaml theme={null} tools: definitions: - name: mypy runtime: python package: mypy shims: [mypy] known_good_version: 0.931 extra_packages: - types-six@1.16.21 - types-request ``` `extra_packages` behaves equivalently to a package file like `requirements.txt` for Python or `package.json` for Node. They can be optionally pinned at versions. The version of the primary package (in this case, `mypy`) is specified in the `tools.enabled`. So to enable the `mypy` tool at `1.4.0`, list it as `- mypy@1.4.0`. If you don't want to include additional packages in the tool definition, you can instead make them explicit in the enabled section of your `.trunk/trunk.yaml` as you would for [linters](../../linters/), for example: ```yaml theme={null} tools: enabled: - mypy@1.4.0: packages: - types-six@1.16.21 ``` #### Runtime-based tools Runtime-based tools are a special case that are not explicitly defined. Rather, each runtime object exposes a set of `shims` (just like `tool` definitions). If the runtime is enabled and listed in `tools.runtimes`, then shims exposed by that runtime are automatically installed in the `.trunk/tools` directory alongside those of other tools (`trunk tools enable ` does that for you). Thus you can run `python`, `pip`, etc as `trunk`-managed tools. Example: ```yaml theme={null} tools: runtimes: - python ``` If this is disruptive to your workflow, simply remove the runtime's name `(go, node, python,...)` from `tools.runtimes` section or run `trunk tools disable ` which will handle it for you. Runtimes cannot be enabled or versioned via the `tools.enabled` section, however, and runtimes must be enabled in the `runtimes` section to be available to have their shims installed. # Code Quality CLI Source: https://docs.trunk.io/code-quality/overview/getting-started/index Trunk provides command-line tools for different products. Choose your product below: * [Trunk Launcher Install](./install): Trunk uses a launcher to automatically install the appropriate CLI for your platform * [Trunk Code Quality CLI](./commands-reference/): commands reference * [Trunk Code Quality CLI Configuration](./configuration/): the Trunk CLI has its top-level config defined in `.trunk/trunk.yaml` * [Trunk Tools CLI](./tools): manage tools used by your repo * [Trunk Actions](./actions/): local workflow automation and githooks manager ## Initializing Trunk in a git repo is as simple as running: ```bash theme={null} trunk init ``` This will scan your repository and create a `.trunk/trunk.yaml` file which enables all the linters, formatters, and security analyzers that [Trunk C](./code-quality)[ode Quality ](./code-quality)recommends. Security-conscious users may want to also record the signature of the CLI, which the [Trunk Launcher](./install#the-trunk-launcher) will use to verify the CLI's provenance: ``` trunk init --lock ``` ### Tweak the configuration Trunk is completely controlled through the `trunk.yaml` file. If for example you are not using the `check` tool you can safely remove the `lint` section from the file. [Learn more about CLI configuration](./configuration/) ### Single-player mode If you want to run `trunk` inside your repository but are not ready to roll it out team-wide, you can run `trunk` in what we call single-player mode. When in single-player mode, the `.trunk` directory will be listed in `.git/info/exclude`, which will cause git to ignore its contents. When trunk is automatically initialized by the VSCode extension, you will be started in this mode. You can also initialize this way explicitly with the `trunk init --single-player-mode` command. If at any time you wish to toggle single-player mode on or off, it can be done with the following two commands: ```bash theme={null} # Turn single-player mode on. trunk config hide ``` ```bash theme={null} # Turn single-player mode off. trunk config share ``` ### Only enabling detected tools `trunk init` supports the flags `--only-detected-formatters` and `--only-detected-linters`. Each of these flags limits `trunk init` to only enable tools that we detect you are already using. We provide support for running `trunk` in GitHub Codespaces. [GitHub Codespaces](https://github.com/features/codespaces) are fully configured virtual containers for developing your GitHub repositories. # Install Source: https://docs.trunk.io/code-quality/overview/getting-started/install ### The Trunk launcher Trunk uses a launcher to automatically install the appropriate CLI for your platform. The launcher is a bash script that downloads the appropriate Trunk CLI version and runs it. The launcher invisibly runs the Trunk CLI version specified in a project's `.trunk/trunk.yaml` file. The actual Trunk CLI is a single binary that is cached locally in `~/.cache/trunk` and is updated automatically. ### Install the launcher The Trunk CLI can be installed in many different ways, depending on your use case. #### Using NPM If your project uses a `package.json`, you can specify the Trunk Launcher as a dependency so your developers can start using Trunk after installing Node dependencies. ```sh npm theme={null} npm install -D @trunkio/launcher ``` ```sh pnpm theme={null} pnpm add -D @trunkio/launcher ``` ```sh yarn theme={null} yarn add -D @trunkio/launcher ``` ```sh bun theme={null} bun install -D @trunkio/launcher ``` Then add Trunk Launcher in your `package.json` as a script: ```json theme={null} { "scripts": { "trunk": "trunk", "lint": "trunk check", "fmt": "trunk fmt" } } ``` #### Using cURL You can install the Trunk Launcher script directly by downloading it through cURL. The launcher script supports both macOS and Linux environments. To allow your teammates to use `trunk` without installing anything, the launcher can be committed directly into your repo: ``` curl -LO https://trunk.io/releases/trunk chmod +x trunk git commit ./trunk -m "Commit Trunk to our repo" ``` When the launcher is called for the first time by your teammates, the Trunk Launcher will download, manage, and run the appropriate binary for the environment. #### Using Homebrew You can run the following command if you prefer to install this tool via homebrew. Keep in mind that other developers on your team will also have to install manually. ```bash theme={null} brew install trunk-io ``` #### Using Windows From **`git-bash` or `msys2`**, download the Bash launcher and add it to your `PATH`: ```bash theme={null} curl https://get.trunk.io -fsSL | bash ``` From **`powershell`**, download the powershell launcher: ``` Invoke-RestMethod -Uri https://trunk.io/releases/trunk.ps1 -OutFile trunk.ps1 ``` Ensure you can execute powershell scripts: ``` Set-ExecutionPolicy Bypass -Scope CurrentUser ``` You can then execute trunk as `.\trunk.ps1`. #### Compatibility Trunk only supports Windows with the following versions and above: | Tool | Where to Modify | Minimum Required Version | | ------- | --------------------------------------------------- | ------------------------ | | CLI | `cli` `version` in `.trunk/trunk.yaml` | `1.13.0` | | Plugins | `ref` for the `trunk` plugin in `.trunk/trunk.yaml` | `v1.0.0` | | VSCode | Reload VSCode to update | `3.4.4` | You will also need to install [C and C++ runtime libraries](https://aka.ms/vs/17/release/vc_redist.x64.exe) in order to run some linters. ### Uninstall instructions #### From your system Trunk has a very minimal installation, and therefore, there's not much to uninstall. The two system paths we use are: * `/usr/local/bin/trunk`: the [Trunk Launcher](./install#the-trunk-launcher) * `~/.cache/trunk`: cached versions of the trunk cli, linters, formatters, etc. You can delete those two paths to uninstall. #### From a repo To cleanly remove Trunk from a particular repo, run: ```bash theme={null} trunk deinit ``` #### VS Code extension To uninstall the Trunk VS Code extension, do so as you would any extension ([docs](https://code.visualstudio.com/docs/editor/extension-marketplace)). Then reload VS Code. ### Binary download (not recommended) You can directly download the `trunk` binary. *We don't recommend this mode of operation because your ability to version the tool through* `trunk.yaml` *will not function when launching* `trunk` *directly from a downloaded binary.* Regardless you can bypass the launcher support by downloading the prebuilt binaries here: | variable | options | | -------- | --------------------------------------------- | | version | the semver of the binary you want to download | | platform | 'darwin\`, 'linux' | ```bash theme={null} # for example https://trunk.io/releases/1.0.0/trunk-1.0.0-linux-x86_64.tar.gz https://trunk.io/releases/${version}/trunk-${version}-${platform}-x86_64.tar.gz ``` ### Pre-installing tools Trunk hermetically manages all the tools that it runs. To do this, it will download and install them into its cache folder only when they are needed. If you would like to ensure that all tools are installed ahead of time, then you can use the `trunk install` command. This may be useful if you want to prepare to work offline or if you would like to include the tools in a docker image. On Linux and macOS you may find the cache folder at `$HOME/.cache/trunk`. # Tools Source: https://docs.trunk.io/code-quality/overview/getting-started/tools You can use the Trunk CLI to manage tools used by your repo. Trunk CLI can install the tools needed for a project according to what's configured in the `trunk.yaml` config file and let your teammates easily install the same versions of the tools. Trunk will also help you expose those installed tools by dynamically adding them to your `PATH` when you enter the project directory, but will not pollute your `PATH` outside of the project. ### Command line | trunk tools \ | Description | | -------------------------------- | ------------------------------------------------------------------------------ | | `list` | list all available tools in the repository and whether they are enabled or not | | `install` | install your enabled tools into `.trunk/tools` | | `enable` `[@version]` | enable the provided tool, optionally at a specified version | | `disable` `` | disable the provided tool | ### Discovering tools The Trunk [plugins repo](https://github.com/trunk-io/plugins) ships with a collection of tools that can help supercharge your repository and provide examples for how to write your own. To see a list of tools that you can enable in your own repo run: ```shell theme={null} trunk tools list ``` ### Configuring shell hooks Before running any tools managed by Trunk, enable shell hooks. With shell hooks, Trunk can manage your path variable dynamically, which lets you install tools used only in specific repos without polluting your shell by installing global tools. This is especially useful if you work on two repos using the same tool, but locked to different versions. You can enable shell hooks by running `trunk shellhooks install`, which will install the Trunk hooks to the config file of your \$SHELL. You can also run `trunk shellhooks install ` to install a specific shell hook. Supported shells: * bash * zsh * tcsh * fish * elvish For organizations that want to require the use of the hooks, they can add to the config file: ```yaml theme={null} # .trunk/trunk.yaml: version: 0.1 cli: shell_hooks: enforce: true ``` On the next Trunk command (like check or fmt), it will update your shell RC file to load our hooks. After reloading your shell, whenever you're inside your repo at the command line, you can just run shims installed by `trunk tools` directly by name. N.B. There is a known incompatibility with direnv when using PATH\_ADD. To use our hooks, remove PATH\_ADD from your .envrc and add them to your Trunk config as such: ```yaml theme={null} version: 0.1 cli: shell_hooks: path_add: - "${workspace}/tools" ``` Paths can either be absolute, or relative to the workspace using the special `${workspace}` variable. ### Running tools With shell hooks enabled, you can just run your tools by their name. For example, if you have run `trunk tools install grpcui` to install the GRPC UI tool, you can run it with: ``` grpcui ``` #### Running tools without shell hooks Trunk installs your enabled tools into the `.trunk/tools` directory. Each tool exposes a list of **shims** (these may or may not be identically named to the tool - most typically a tool has one shim matching the name of the tool). Each shim is installed into the `.trunk/tools` directory. You can run your tools by referring to the path `/.trunk/tools/` but this is unwieldy. We highly recommend using our shell hooks to manage your PATH. ### Troubleshooting linters Tools enable you to run your linter binaries on the command line independent of `trunk check` and test and troubleshoot your integrations more easily. Tools are configured in the `tools` section of `trunk.yaml`. As with other settings, you can override these values in your [User YAML](./configuration/per-user-overrides). ```yaml theme={null} tools: auto_sync: false # whether shims should be hot-reloaded off config changes. enabled: - bazel@6.0.0 - mypy@1.4.1 - ibazel@0.22.0 - helm@3.9.4 - eksctl@0.74.0 - asciinema@2.1.0 disabled: - gt definitions: - name: gh download: gh known_good_version: 2.27.0 environment: - name: PATH list: ["${tool}/bin"] shims: [gh] ``` Like with actions and linters, we have a (versioned) `enabled` section and a `disabled` section, which can be manipulated using `trunk tools enable/disable`. There is also a list of `definitions`, which are merged across your `trunk.yaml`, `user.yaml`, as well as any plugins that you use. `auto_sync` controls whether or not Trunk automatically installs your tools for you when your config changes. This defaults to `true`. Note that the daemon must be running with the monitor in order for this to function properly. # GitHub Codespaces Source: https://docs.trunk.io/code-quality/overview/ide-integration/github-codespaces We provide support for running `trunk` in GitHub Codespaces. [GitHub Codespaces](https://github.com/features/codespaces) are fully configured virtual containers for developing your GitHub repositories. ## Installing the Trunk feature You can install the Trunk Launcher in your codespace by including the following line in your `devcontainer.json` file under `features`: ```json theme={null} "features": { "ghcr.io/trunk-io/devcontainer-feature/trunk": "latest", }, ``` The feature is defined [here](https://www.github.com/trunk-io/devcontainer-feature). To have the launcher binary install the CLI tool and associated linters, you can add `trunk install` to `updateContentCommand` in `devcontainer.json`: ```json theme={null} "updateContentCommand": "trunk install", ``` Read the [GitHub docs](https://docs.github.com/en/codespaces/prebuilding-your-codespaces/configuring-prebuilds#configuring-time-consuming-tasks-to-be-included-in-the-prebuild) to learn more about `updateContentCommand` . Note: You should only add `trunk install` if you have a Trunk-configured repository. You can then [configure pre-builds](https://docs.github.com/en/codespaces/prebuilding-your-codespaces/configuring-prebuilds) to run from GitHub workflows, ensuring the `trunk` CLI and needed linters are available and ready to go when you need to boot up your codespace. ## Installing the Trunk extension If you are using the Trunk feature, we will automatically install the Trunk extension on your behalf. Note: We highly recommend turning off auto-save in your VSCode settings in your codespace (or set autosave to a longer timeout). Saving files triggers the extension to re-lint, which can quickly overload the extension for anything but the fastest linters. The auto-save setting is detailed [here](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save). Otherwise, You can add `trunk` to your list of extensions in `devcontainer.json` - ```json theme={null} "customizations": { "vscode": { "extensions": [..., "trunk.io"] } }, ``` Then you're all set to run `trunk` in your Codespace! # IDE integrations Source: https://docs.trunk.io/code-quality/overview/ide-integration/index Code Quality helps you shorten the feedback loop by integrating with your favorite IDEs and code editors. ### How it works Code Quality runs a daemon that looks for files that change in real time and lints the changes using the same tools and configuration as running `trunk check`. With LSP support, you will get instant feedback on your code changes as you write. ### Supported IDEs # Neovim Source: https://docs.trunk.io/code-quality/overview/ide-integration/neovim The Trunk Code Quality Neovim Plugin is available for beta! Try it out by following the instructions below. ### Prerequisites The Neovim Plugin needs the following prerequisites: | Tool | Minimum Required Version | | ------ | ------------------------ | | CLI | 1.17.0 | | Neovim | v0.9.2 | ### Get started Using the [lazy.nvim](https://github.com/folke/lazy.nvim#readme) plugin manager: ```lua theme={null} require("lazy").setup({ { "trunk-io/neovim-trunk", lazy = false, -- optionally pin a version tag = "v0.1.3", -- these are optional config arguments (defaults shown) config = { -- trunkPath = "trunk", -- lspArgs = {}, -- formatOnSave = true, -- formatOnSaveTimeout = 10, -- seconds -- logLevel = "info" }, main = "trunk", dependencies = {"nvim-telescope/telescope.nvim", "nvim-lua/plenary.nvim"} } }) ``` For other plugin managers and installation methods, see our [Neovim Plugin repo](https://github.com/trunk-io/neovim-trunk#installation). ### Features The Neovim Plugin is designed to mirror the [VSCode extension](./vscode). Supported features include: * Provide inline diagnostics and auto-fixes * Format files on save * Run [Trunk Actions](../getting-started/actions/) notifications * Display the linters that Trunk runs on a file ### Limitations The Trunk Code Quality Neovim Plugin is in beta with limited support. If you encounter any issues, feel free to reach out at [support@trunk.io](mailto:support@trunk.io). For other notes and configuration, see the [Neovim Plugins repo](https://github.com/trunk-io/neovim-trunk#trunk-check-neovim-plugin). # OpenAI Codex Support Source: https://docs.trunk.io/code-quality/overview/ide-integration/openai-codex-support Trunk Code Quality for OpenAI Codex This document provides guidance for integrating Trunk Code Quality into OpenAI Codex environments. ### Requirements Ensure you’re running the following minimum versions in your `.trunk/trunk.yaml` file: * Trunk CLI: v1.24.0 or later * Trunk Plugins: v1.7.0 or later ### Installation In your Codex environment setup script, include: ``` # Install Trunk CLI and dependent tools curl https://get.trunk.io -fsSL | bash trunk install ``` It's important to pre-install all trunk dependencies during the setup because codex environments are network-isolated post-setup. #### Debugging installation If the environment setup is slow, run the following to diagnose: ``` trunk install --debug ``` This command will detail installation timings and potential bottlenecks. ### Handling network isolation Codex environments are network-isolated post-setup. Linters requiring network access must be excluded from running explicitly: Example: ``` trunk check --filter=-trufflehog,-semgrep ``` ### Teaching Codex how to use Trunk Codex can automatically run trunk commands for you, by informing it to do so in your AGENTS.md file: ``` ## AGENTS Instructions ### Formatting and Linting - Run `trunk check -y --filter=-trufflehog,-semgrep` after modifying code to format and fix linting issues. - Review and verify changes before committing. - If only formatting is required, run `trunk fmt`. - Exclude linters requiring network access by adding them to the negative filter list as shown above. ``` # VSCode Source: https://docs.trunk.io/code-quality/overview/ide-integration/vscode Trunk Code Quality is available as a [VSCode extension](https://marketplace.visualstudio.com/items?itemName=trunk.io) that you can use to streamline your linting and formatting experience. ### Get started By default, Trunk will try to automatically initialize itself in single-player mode. This means that it'll create a Trunk configuration that is hidden from git, which allows you to try it out [without Trunk's versioning powers](./vscode#single-player-mode). If Trunk has not initialized itself in single-player mode, then you will need to initialize it manually, either by pressing the 'Initialize Trunk' button in the Trunk side panel: ![initialize trunk](https://static.trunk.io/assets/vscode_init_trunk.png) ### Features #### Discovery Trunk will suggest tools that will supercharge your development, from `actionlint`, for your GitHub Actions, to`sql-formatter` and `sqlfluff` for your SQL, to`yamllint`, for your YAML files. We believe that everything in your repository not only can be, but should be, automatically formatted and linted. We recognize that part of this is making it easy for developers to discover tools that apply to their codebases. When Trunk is initialized, we turn on as many additional tools as we can, and periodically follow up with additional suggestions. #### Seamless user experience On the sidebar to the left, you'll see the Trunk icon which you can use to open the side panel to view issues. By default, issues are populated for every file you open as well as any modified files. ![side panel](https://static.trunk.io/assets/vscode_side_panel.png) Trunk also shows Trunk Code Quality Issues in a panel in the File Explorer, but you can hide it if you wish: ![hide explorer panel](https://static.trunk.io/assets/vscode_hide_explorer_panel.jpg) #### Single-player mode In single-player mode, Trunk creates a [configuration file](../linters/configure-linters) and hides it from Git, so that you can test out Trunk on your own and get familiar with how it works, without committing this file. Users normally check this file into your repository so that you can run Trunk reproducibly. It pins the version of trunk, as well as that of every runtime and linter that you've enabled, allowing your team to guarantee that everyone and your CI runners are always running the same checks on your code. To check it into your repository, all you have to do is run ```bash theme={null} trunk config share ``` or click on the notification to "Share trunk config", which will commit `.trunk/trunk.yaml`, the Trunk configuration file. ### Trunk as default formatter You can use Trunk as your default formatter in VSCode if you have Trunk configured for the project. You can set `trunk.io` as the default formatter for just one language as in the example, or as a default for all languages. In your `settings.json` like this: ```json theme={null} "[markdown]": { "editor.defaultFormatter": "trunk.io" } ``` For manual formatting, open the command palette and use `Format Document With...` and select `Trunk` there. ### Learn more Check out how to [install the CLI](../setup-and-installation/), [set it up in CI](../initialize-trunk), [ignore issues](../linters/ignoring-issues-and-files), and set up [Custom Linters](../linters/custom-linters). ![linter code docs](https://static.trunk.io/assets/vscode_doc_links.png) ![trunk-ignore](https://static.trunk.io/assets/vscode_ignore_issue.gif) ### Configuration * `trunk.inlineDecorators` – allows you to disable inline decorators for diagnostics. * `trunk.inlineDecoratorsForAllExtensions` – allows you to only render inline decorators for diagnostics that were generated by Trunk. ### Debugging If you look at the "Window" output for the extension, you may find useful error logs. ### Feature requests and bug reports Looking for another feature? Hit a bug? [Let us know!](mailto:support@trunk.io) # Overview Source: https://docs.trunk.io/code-quality/overview/index Trunk Code Quality is a metalinter and static analysis manager designed to unify linting, formatting, and security scanning across polyglot repositories. It consolidates tool management, runtime isolation, and execution logic into a single CLI and daemon. ### Architecture Trunk consists of a C++ CLI that orchestrates the download, installation, and execution of third-party static analysis tools. #### Hermetic Tool Management Trunk manages tools and their runtimes hermetically. Instead of relying on the host system’s environment (e.g., `/usr/bin/python` or global `npm` packages), Trunk downloads and caches specific versions of runtimes required by the linters. * Isolation: A project requiring Python 3.10 for a specific linter will not conflict with a system installed Python 3.7. * Consistency: All engineers and CI runners execute the exact same version of the linter and its runtime dependencies. * Scope: Covers primary languages, Infrastructure as Code (IaC), build scripts, CI configurations (YAML), and documentation. #### The Trunk Daemon The CLI (`trunk check`) launches a background daemon. This process: 1. Monitors file system events. 2. Triggers jobs to precompute linting results in the background. 3. Caches results to speed up subsequent checks. 4. Serves real-time annotations to IDE extensions (VSCode, Neovim). Users can override background execution behavior by modifying the `run_when` configuration for specific tools if they are too compute-intensive. ### Execution Model #### Git-Aware Scanning Trunk optimizes execution by checking only modified files or lines. It relies on git diffs to determine the scope of analysis, preventing full-repo scans during standard development workflows. ### Hold-the-line **Hold The Line** (HTL) is the principle that Trunk Code Quality will *only run on new changes* in your codebase rather than every file in the whole repo. This allows you to use Check to improve your codebase **incrementally** rather than having to address all of the issues at once. HTL also runs checks much faster than scanning the entire codebase would. *Hold The Line* **works at the line level** of your source code. For example, if a single line has multiple pre-existing issues and a new linter is added, which reports the new issue, then Trunk Code Quality will report just the new issue and not the previous ones. By default, Trunk runs in hold-the-line mode: ``` trunk check foo.file ``` You can still run on all files. ``` trunk check --all ``` ***Hold the Line*** is built into Trunk Code Quality itself. This means existing linters that do not support line-by-line functionality will still work with *Hold the Line*. Even [custom linters](./linters/custom-linters) you write yourself. ### Daemon The Trunk CLI, specifically `trunk check`, runs a daemon that monitors relevant file changes and triggers jobs to precompute in the background while you work. The daemon is used both to support real-time background checking in supported extensions such as [VSCode](./ide-integration/vscode) and [Neovim](./ide-integration/neovim), and to precompute check results for faster commits/pushes. Some native linters are more compute/memory intensive and `check` allows you to disable background linting for those tools. By default, linters run whenever a file is modified in the background. You can override this behavior by editing the [`run_when`](./getting-started/configuration/lint/commands#run_when) configuration for a tool. ### Hermetic tools and runtime management Trunk hermetically installs the static analysis tools you run and their required runtimes. This means these tools are installed and managed by the Trunk CLI, and are unaffected by your systems environment. If a tool requires `python 3.10` but the projects you're working on require `python 3.7`, Trunk will manage that tool and its `python 3.10` runtime automatically and not affect the `python 3.7` environment. This means Trunk will not modify or pollute your machine. Trunk manages the hermetic installation of all required runtimes. You can also specifically pin a version of a runtime you'd like Trunk to use, or tell Trunk to reuse an already-installed runtime on the system. ### Plugin system Trunk is fully extensible and configurable through the [Trunk Plugins Repo](https://github.com/trunk-io/plugins/). When installing a plugin through Trunk, the definition of a plugin's behavior, including install, run, and report instructions, is defined in the Plugins Repo. This can be overridden by defining your own plugin repo to import, overriding individual linter definitions locally, and even writing your own custom linters. [Learn more about the plugin system.](./getting-started/configuration/plugins/) ### Run on every pull request Trunk works in CI. Trunk Code Quality provides [GitHub integration](./setup-and-installation/github-integration) and can run in any other CI environment. This lets you check Code Quality in every PR with consistent config and consistent results. [Learn more about Code Quality in CI.](./prevent-new-issues/) ### Setup and installation Trunk Code Quality is easy to adopt for new and legacy projects alike. You can run Trunk Code Quality using your existing linter configurations, incrementally address existing problems, and prevent new issues from being committed to your repo. Initialize Trunk in your repo to generate Trunk config files and get linter recommendations based on your project's files. Check for existing issues in your project. You can address problems up front, use hold-the-line to fix them incrementally, and configure ignores for irrelevant issues. Set up automated runs on commits, before pushes, and on PRs to prevent new issues from appearing in your repo. # Initialize Trunk Source: https://docs.trunk.io/code-quality/overview/initialize-trunk Before you can start using Trunk Code Quality, you need to install and initialize Trunk in your repo. This page covers the initialization process. ### Install the CLI The Trunk CLI can be installed in many different ways depending on your use case. We recommend installing the CLI via **NPM** if you’re already using NPM, or using **cURL** and **committing the launcher to Git** for all other projects. Both methods allow your teammates to use Trunk without needing an additional install step. #### The Trunk Launcher The easiest way to give everyone access to Trunk is to use the Trunk launcher. The Trunk launcher is a small script that will automatically install and run Trunk when invoked for the first time, similar to other command line tools like the [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html). You can install the [Trunk Launcher](./getting-started/install#the-trunk-launcher) script directly by downloading it through cURL. The launcher script supports both macOS and Linux environments. ```bash bash theme={null} curl https://get.trunk.io -fsSL | bash ``` ```bash bash (no prompts) theme={null} curl https://get.trunk.io -fsSL | bash -s -- -y ``` To allow your teammates to use `trunk` without installing anything, the launcher can be committed directly into your repo: ``` curl -fsSLO --retry 3 https://trunk.io/releases/trunk chmod +x ./trunk git commit ./trunk -m "Commit Trunk to our repo" ``` #### Other ways to install If your project uses a `package.json`, you can specify the Trunk Launcher as a dependency so your developers can start using Trunk after installing Node dependencies. ```sh theme={null} # npm npm install -D @trunkio/launcher # pnpm pnpm add -D @trunkio/launcher # yarn yarn add -D @trunkio/launcher # bun bun install -D @trunkio/launcher ``` Then add Trunk Launcher in your `package.json` as a script: ```json theme={null} { "scripts": { "trunk": "trunk", "lint": "trunk check", "fmt": "trunk fmt" } } ``` You can run the following command if you prefer to install this tool via [homebrew](https://brew.sh/). Keep in mind that other developers on your team will also have to install manually. ```bash theme={null} brew install trunk-io ``` From **`git-bash` or `msys2`**, download the Bash launcher and add it to your `PATH`: ```bash theme={null} curl https://get.trunk.io -fsSL | bash ``` From **`powershell`**, download the powershell launcher: ``` Invoke-RestMethod -Uri https://trunk.io/releases/trunk.ps1 -OutFile trunk.ps1 ``` Ensure you can execute powershell scripts: ``` Set-ExecutionPolicy Bypass -Scope CurrentUser ``` You can then execute trunk as `.\trunk.ps1`. **Compatibility** Only some versions of Trunk are compatible with Windows. See the compatibility page for [Windows](./getting-started/compatibility) to learn more. You will also need to install [C and C++ runtime libraries](https://aka.ms/vs/17/release/vc_redist.x64.exe) in order to run some linters. ### Initializing Trunk Before you can use Trunk, you need to initialize Trunk in your repo. Initializing Trunk will generate the necessary config files, recommend linters based on your project files, and configure githooks. Initialize Trunk by running the `init` command. ```bash theme={null} ./trunk init ``` Follow the wizard. You'll be prompted with the following options: 1. `Sign up or log in`: Connect the CLI with your Trunk account to enable all of Trunk's features. 2. Trunk will automatically [enable the most useful linters](#recommended-linters) based on the files in your repo. 3. `Trunk will manage your git hooks and enable some built-in hooks.`: This sets up Trunk to run automatically on commit and before you push, saving you time waiting for CI only to have it fail. 4. `Trunk will now run a local, one-time scan of your code and report any issues it finds`: This initial scan will give you a good overview of the problem areas in your code. Subsequent scans will only run on changed lines using hold-the-line. **Trunk is Git aware** Trunk speeds up your linting process by running on only the files that have changed in your branch compared to upstream. This means if you're using a base/trunk branch that's not `master` or `main`, you will need to specify it in your `.trunk/trunk.yaml` ```yaml theme={null} version: 0.1 cli: version: 1.22.2 repo: # develop is the branch that everyone's work is merged into trunk_branch: develop ... rest of configs ``` ### Run Linters After initialization, you can run the [recommended set of linters](./initialize-trunk#recommended-linters) by running: ``` ./trunk check ``` :tada: And just like that, you're ready to start using Trunk Code Quality. ### The .trunk Directory After initialization, a new folder `.trunk` will be generated with the following content. ``` .trunk ├── actions/ ├── configs/ # This is where linter configs live ├── logs/ # Logs for debugging ├── notifications/ ├── out/ ├── plugins/ ├── tools/ └── trunk.yaml # Top-level Trunk config ``` You will spend most of your time configuring Trunk Code Quality's linter definitions `trunk.yaml` and individual linter configurations in `configs`. ### Recommended Linters During initialization, Trunk Code Quality will recommend some linters based on files found in your project. Trunk Code Quality will recommend common linters for your language, but the [full list of supported linters can be found here](./linters/supported/). You can enable and disable individual linters by running: ```bash theme={null} trunk check enable trunk check disable ``` You can also see all linters and whether they're enabled by running: ```bash theme={null} trunk check list ``` ### IDE Integration Trunk Code Quality supports [VSCode](./ide-integration/vscode) and [Neovim](./ide-integration/neovim) through extensions. Using VSCode and Neovim will provide inline linter annotations as you code. ### Move Existing Configs If you have existing linter configs in your repo, you can move them into the `.trunk/configs` folder. These config files will be symlinked in during any `trunk check` run. If you're using an IDE Extension like `clangd` with an LSP that relies on those configs being in the root, you must create an additional symlink from the hidden config to the workspace root. ### Next Steps After initializing Trunk Code Quality, you can check for issues and configure Code Quality. The [next steps](./deal-with-existing-issues) in Setup & Installation will walk you through this process. # Licensing Source: https://docs.trunk.io/code-quality/overview/licensing ### Introduction Trunk Code Quality is a powerful metalinter that simplifies linting, formatting, and static analysis across your entire codebase. By integrating over 100 supported tools like ESLint, Prettier, Ruff, and more, it enables you to manage code quality with unified configuration and consistent reporting. Trunk Code Quality helps you install tools hermetically, run them efficiently, and integrate seamlessly with pull requests and CI pipelines. ### Licensing overview Trunk Code Quality is composed of a closed-source core complemented by open-source components that enhance extensibility and integration. Understanding the licensing terms for each part ensures compliance and optimal use. #### Closed-Source components * Trunk CLI: The core command-line tool is closed-source but free to use under specific conditions. * VS Code Extension: Integrates Trunk Code Quality directly into your development environment. Under the hood, all code-checking by the VS Code extension is completed via the Trunk CLI, which drives the VS Code extension. #### Open-Source components * Plugin System and Configurations: An extensible plugin system that allows you to define, extend, and share linter configurations. These plugins are open-source under the MIT License, enabling you to modify them or create new ones to integrate additional tools or customize behavior. * GitHub Action: Scripts that automate Trunk Code Quality checks in your GitHub workflows. GitHub Actions require the source code to be visible for transparency and security. Our GitHub Action is open-source under the MIT License, allowing you to review, modify, and ensure it meets your needs. By open-sourcing these components, we promote transparency, extensibility, and community collaboration. This approach encourages our community and customers to contribute to the ecosystem, enhancing Trunk Code Quality for everyone. #### Free usage You can use the Trunk CLI and access core functionalities for free under the following conditions: * Open-Source and Public Projects: Unlimited use in public repositories. * Private Repositories * Free for teams with up to 5 active non-bot committers. * An active committer is a non-bot user who has committed in the last 30 days. #### Paid licensing For private repositories with over 5 active committers, a paid license is required to comply with Trunk Code Quality’s licensing agreement. While all features remain accessible, payment is necessary to meet licensing obligations and support the continued development of the product. Compliance and Support * Licensing Compliance: Payment ensures your use of Trunk Code Quality aligns with the licensing terms for larger teams. * Dedicated Support: Paid customers receive prioritized support to help with integration, troubleshooting, and maximizing the benefits of Trunk Code Quality. #### How billing works Trunk Code Quality offers two billing options for paid licenses: **1. Team Plan - Monthly Self-Serve Billing** * Per-Seat Model: Billing is based on the monthly active committers in your private repositories. * User Count Calculation: * Counts non-bot users who have made commits in the last 30 days. * Calculated at the end of each billing period to adjust the next invoice. * Integration with GitHub App: Install the Trunk GitHub App to allow us to measure active monthly users. * Billing Cycle: Month-to-month billing with invoices reflecting the latest user count. **2. Enterprise Plan - Annual Site License** * Fixed User Count: Based on the number of active committers at the beginning of the licensing term. * Organization-Wide License: Provides a license for all users in the organization during the entire term without the need to purchase additional licenses for new employees. * Simplified Billing: One annual payment covers all users for the year. * Discount: Incentives available with annual plans for logo usage, case study, and/or scale. **Choosing the Right Option** * Team Plan: Appropriate for small teams that prefer flexibility and want to pay monthly with a credit card. * Enterprise Plan: Best for organizations that prefer predictable costs, to avoid the administrative overhead of tracking monthly user counts, and wish to benefit from the discounted rate. ### FAQs **What are the benefits of paying for Trunk Code Quality?** Paying for Trunk Code Quality offers several important benefits: * Licensing Compliance: For private repositories with 5 or more active committers, purchasing a license is required to comply with Trunk Code Quality’s licensing terms and continue using the product legally and effectively. * Dedicated Support: Receive prioritized assistance to help integrate, troubleshoot, and maximize the product’s benefits in your production environment. * Priority Feature Requests: Your requests for new features and plugin integrations receive high priority, allowing you to influence the product’s development to suit your needs better. * Expert Consultation: Access advisory services from our team to optimize your code quality setup and linting processes. * Onboarding Assistance: Receive support and best practices guidance during the integration of Trunk Code Quality into your workflows. Importantly, all features are available regardless of licensing status; you do not unlock additional features by purchasing a license. However, buying a license ensures compliance with the licensing terms, supports the continued development of Trunk Code Quality, and provides access to the dedicated support and benefits listed above. **Do you provide free Proofs of Concept (POCs)?** Yes, we are happy to provide 2–4 week free POCs for teams that want to evaluate our product's capabilities with their team and as part of their CI. We also provide dedicated support and guidance throughout the POC period. Email us to get started at: [sales@trunk.io](mailto:sales@trunk.io). **What happens if I exceed the free usage limits?** If you exceed the free tier limits (e.g., more than 5 active committers in a private repository), you must obtain a paid license to continue using Trunk Code Quality in compliance with the licensing agreement. **Is the Trunk CLI free to use?** The Trunk CLI is free for public repositories and private repositories with fewer than 5 active committers. For private repositories with 5 or more active committers, a paid license is required to comply with the licensing agreement. **Can I use Trunk Code Quality in CI/CD pipelines for free?** Yes, you can integrate the Trunk CLI into your CI/CD pipelines for free if you’re within the free usage limits (public repositories or private repositories with fewer than 5 active committers). Exceeding these limits requires a paid license. **Is support provided for free users?** Yes, free users can reach us at [support@trunk.io](mailto:support@trunk.io). See the [Support page](/setup-and-administration/support) for response-time details. **Why are some components open-source while the core is closed-source?** * Core Functionality: The Trunk CLI provides the core functionality and is closed-source to protect proprietary technology and ensure a consistent, reliable experience. * Open-Source Components: The plugin system and GitHub Action are open-source to promote transparency, security, and community-driven extensibility. This allows you to customize integrations and contribute to the development of plugins and workflows. **Do I need the Trunk CLI to use the open-source components?** Yes, the open-source components are designed to work with the Trunk CLI. They enhance and extend the functionality provided by the core tool but are not standalone applications. **How to Contribute to the Open-Source Components?** * Plugin Development: You can develop new plugins or improve existing ones by visiting our public GitHub repository at [github.com/trunk-io/plugins](https://github.com/trunk-io/plugins). * GitHub Action: Modify or fork our GitHub Action to better suit your CI workflows. The source code is available at [github.com/trunk-io/trunk-action](https://github.com/trunk-io/trunk-action). #### Contact us For licensing inquiries, to obtain a paid license, or to discuss which billing option is best for your organization, please contact [sales@trunk.io](mailto:sales@trunk.io). We’re here to help you ensure compliance and get the most out of Trunk Code Quality. # Configure linters Source: https://docs.trunk.io/code-quality/overview/linters/configure-linters Trunk Code Quality's linter integrations are fully configurable. This means that you can easily tune existing linters or leverage our caching and [hold-the-line](/code-quality/overview#hold-the-line) solution with your own custom linters. Here's an overview of the ways you can configure linters. ### Config hierarchy Linters can be configured at different places: 1. The source plugin repo usually `https://github.com/trunk-io/plugins`. 2. The repo-wide Trunk config file overrides the definitions in the plugin repos, `.trunk/trunk.yaml` 3. Local, per-user configuration in `.trunk/user.yaml` which is used for local overrides of `.trunk/trunk.yaml` and doesn't 4. Per linter configuration in linter config files such as `eslint.config.js` or `.prettierrc`. ### Plugin system Trunk defines linter configuration in a plugin system. By default, it'll point to the [Trunk plugin repo on GitHub](https://github.com/trunk-io/plugins). You can check if other custom plugin sources are specified in your `trunk.yaml` file for [shared-configs.md](./shared-configs.md). ```yaml theme={null} version: 0.1 cli: version: 1.22.2 # Trunk provides extensibility via plugins. (https://docs.trunk.io/cli/configuration/plugins) plugins: sources: - id: trunk ref: v1.6.1 uri: https://github.com/trunk-io/plugins ``` ### Linter definitions Each linter implemented in the Plugin Repo has its own linter definition. Let's take clang-tidy as an example, which ships with the following default configuration: ```yaml theme={null} definitions: ... - name: clang-tidy files: [c/c++-source] type: llvm commands: - output: llvm run: clang-tidy --export-fixes=- ${target} success_codes: [0] download: clang-tidy direct_configs: [.clang-tidy] disable_upstream: true include_scanner_type: compile_command environment: - name: PATH list: ["${linter}/bin"] ... ``` #### Linter definition reference You can find the default definitions for linters in the [Plugin Repo](https://github.com/trunk-io/plugins/tree/main/linters) and find references for these fields on the [Linter Definitions](../getting-started/configuration/lint/definitions) page. ### Overriding default linter definitions You may find while using Trunk that you want to modify one of these defaults: perhaps you want `clang-tidy` to not run on the upstream, or maybe you want the `node` runtime to include another environment variable. In these cases, you can specify the field in your `trunk.yaml` to override the default value. If you wanted to flip the value of `disable_upstream` to `false`, you could, in your own `trunk.yaml`, specify: ```yaml theme={null} definitions: ... - name: clang-tidy disable_upstream: false ... ``` Overriding definitions in your `trunk.yaml` file doesn't require you to specify the entire definition again. You only need to specify what's being overridden. #### Configure linter commands Some linters have multiple commands, such as [Ruff](./supported/ruff), which can run in different ways. By default, Ruff is configured to only run as a linter: ```yaml theme={null} lint: enabled: - ruff@: commands: [lint] ``` You can configure ruff to also run the format command by adding it to the commands tuple: ```yaml theme={null} lint: enabled: - ruff@: commands: [lint, format] ``` #### Configure linter platforms Similarly, some linters are configured to run differently on different platforms or at different versions. When overriding a command definition, overrides are applied on the tuple `[name, version, platforms]`. For example, if you wanted to disable batching when running [ktlint](https://github.com/trunk-io/plugins/blob/main/linters/ktlint/plugin.yaml) on Windows, you could consider its default configuration: ```yaml theme={null} definitions: ... - name: ktlint ... commands: - name: format platforms: [windows] run: java -jar ${linter}/ktlint.exe -F "${target}" output: rewrite cache_results: true formatter: true in_place: true batch: true success_codes: [0, 1] - name: format run: ktlint -F "${target}" output: rewrite cache_results: true formatter: true in_place: true batch: true success_codes: [0, 1] ... ``` And override it as such: ```yaml theme={null} definitions: ... - name: ktlint ... commands: - name: format platforms: [windows] batch: false ... ``` When executing linters, Trunk will execute the first matching command based on its compatible platforms and linter version. Note when overriding that new commands that don't match an existing tuple are prepended to the resulting commands list. Alternatively, consider the default `node` runtime: ```yaml theme={null} runtimes: definitions: - type: node download: node runtime_environment: - name: HOME value: ${home} - name: PATH list: ["${runtime}/bin"] linter_environment: - name: PATH list: ["${linter}/node_modules/.bin"] version: 16.14.2 version_commands: - run: "node --version" parse_regex: ${semver} ``` If you want to add `${home}/my/special/node/path` to `PATH`, you could specify the following: ```yaml theme={null} runtimes: - type: node runtime_environment: - name: HOME value: ${home} - name: PATH list: ["${home}/my/special/node/path", "${runtime}/bin"] ``` ### Blocking thresholds All issue severities low-high are considered blocking by default. In cases where you might want to slowly try out a new linter, we provide a mechanism to set specific thresholds for each linter. ```yaml theme={null} lint: threshold: - linters: [clang-tidy] level: high ``` Every entry in `threshold` defines a set of linters and the severity threshold that is considered blocking. In this example, we're saying that only `high` lint issues should be considered blocking for `clang-tidy`. | Key | Value | | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | linters | List of linters (e.g. `[black, eslint]`) or the special `[ALL]` tag | | level | Default `low`. Threshold at which issues are considered blocking. One of: `note`, `low`, `medium`, `high`, or `none` (this last option will result in issues never blocking) | ### Trigger rules Some linters do not operate on individual files. Instead, you must lint your entire repo at once. The way this is handled in Trunk is to set up a trigger rule. Most linters will not require the use of a trigger rule. Trigger rules work on 3 principles: 1. Input(s) that trigger the linters. These can be files, directories, or extended globs. 2. Linter(s) to run when a triggered file is modified. 3. Targets(s) to pass to the linters (can be files or directories). An example for ansible-lint: ```yaml theme={null} lint: enabled: - ansible-lint@5.3.2 triggers: - linters: - ansible-lint paths: - ansible # A directory targets: - ansible # A directory ``` Triggered linters will also be run when executing trunk check with `--all` so long as a file exists that matches one of the listed paths. You may use `.` as a target to run on the entire repo instead of an isolated directory. ### File size By default, Trunk only lints files up to 4 MiB in size. To override this globally, specify a `default_max_file_size` in `lint`: ```yaml theme={null} lint: default_max_file_size: 1048576 # Bytes ``` To override this for a specific linter, specify a `max_file_size` in its definition: ```yaml theme={null} lint: definitions: - name: prettier max_file_size: 2097152 # Bytes ``` ### Timeout Each linter has a default timeout of 10 minutes. If its execution takes longer than this amount of time, Trunk Code Quality will terminate the process and return an error to the user. To override the timeout for a specific linter, specify a `run_timeout` in its definition: ``` lint: definitions: - name: clang-tidy run_timeout: 5m ``` The `run_timeout` value can be specified in seconds (`s`), minutes (`m`), or hours (`h`). ### Local linter overrides Trunk can also be managed by the `.trunk/user.yaml` file in your repository. This file is optional, but it allows individual developers to customize how they want `trunk` to run on their machines. Simply configure `.trunk/user.yaml` as you would for `.trunk/trunk.yaml`. Be mindful that `.trunk/user.yaml` takes precedence over `.trunk/trunk.yaml`, so substantial modifications could violate hermeticity. ### Per linter definitions Trunk allows you to keep using your existing linter configs, and new linters recommended by Trunk will have their configs added in the `.trunk/configs` folder. These config files will be symlinked in during any `trunk check` run. If you're using an IDE Extension like clangd with an LSP that relies on those configs being in the root, you will need to create an additional symlink from the hidden config to the workspace root. #### Moving linters You can move existing linter config files into the `.trunk/config` folder. You can check which files are automatically symlinked by looking for the `direct_configs` of [each plugin's definition](https://github.com/trunk-io/plugins/). If there are config files not listed, you can add them by overriding the definition like this: ```yaml theme={null} lint: definitions: - name: some_linter_name direct_configs: - .custom_config.file ``` # Custom linters Source: https://docs.trunk.io/code-quality/overview/linters/custom-linters Trunk Code Quality allows you to define custom linters. If a linter is not within the [list of supported linters](./supported/) or you have a bespoke solution, you can define a custom linter. ### Defining a custom linter You can define linters right in your `.trunk/trunk.yaml` file in your repo. These definitions have the same configurable parameters as in our [public plugins repo](https://github.com/trunk-io/plugins/blob/main/CONTRIBUTING.md) or [your own plugins repo](../getting-started/configuration/plugins/external-repositories). #### Pass-Fail linter script example For example, you can define a simple [pass-fail linter](./custom-linters#pass-fail-linter-script-example) that runs a custom script file. The linter passes or fails based on the status code returned. ```yaml theme={null} version: 0.1 cli: version: 1.22.1 lint: enabled: - SampleLinter definitions: - name: SampleLinter files: [javascript, typescript] commands: - name: lint run: sh ${workspace}/.trunk/myscript.sh ${target} output: pass_fail success_codes: [0, 1] ``` #### Inline grep command example You can also define simple linters inline using tools like `grep`. This linter will grep against your custom regex pattern, format the output using sed, and then parse the output into pattern groups using a [regex output](../getting-started/configuration/lint/output#regex) for Trunk Code Quality to report. ```yaml theme={null} # This file controls the behavior of Trunk: https://docs.trunk.io/cli # To learn more about the format of this file, see https://docs.trunk.io/cli/configuration version: 0.1 cli: version: 1.22.1 lint: enabled: - SampleGrepLinter definitions: - name: SampleGrepLinter files: [ALL] commands: - name: lint run: bash -c "grep -o -E '' --line-number --with-filename ${target}" success_codes: [0, 1] read_output_from: stdout parser: run: 'sed -E "s/([^:]*):([0-9]+):(.*)/\1:\2:0: [error] Found \3 in line (numeric-\3)/"' output: regex parse_regex: "(?P.*):(?P-?\\d+):(?P-?\\d+): \\[(?P[^\\]]*)\\] (?P[^\\(]*) \\((?P[^\\)]*)\\)" ``` To see the configurable fields available [Linter Definition Reference](../getting-started/configuration/lint/definitions). ### Contributing a new linter The [Trunk Code Quality plugins repo](https://github.com/trunk-io/plugins/blob/main/CONTRIBUTING.md) is public and welcomes contributions. Feel free to open a PR if the new custom linter you defined could be useful to others. You can reach out to us at [support@trunk.io](mailto:support@trunk.io) if you need a hand. # Ignoring issues and files Source: https://docs.trunk.io/code-quality/overview/linters/ignoring-issues-and-files ## Ignoring parts of a file Sometimes we want to deliberately tell a linter that, yes, I know what I'm doing, and yes, in any other situation I should *not* do this, but in this specific case it's fine. Maybe there's a dummy private key you're using for a test stack, or fixing the lint issue will actually make your code less readable: whatever it is, you now need to figure out how to suppress a given lint issue. Trunk provides a simple, standardized mechanism to do this, saving you from having to look up the linter-specific syntax for doing so: ```cpp theme={null} struct FooBar { // trunk-ignore(clang-tidy/modernize-use-nullptr): load-bearing NULL, see ISSUE-832 void *ptr = NULL; }; ``` This tells Trunk that the `clang-tidy` linter found a `modernize-use-nullptr` issue on the highlighted line and that Trunk should suppress this linter issue. Comments may be omitted: ```cpp theme={null} struct FooBar { // trunk-ignore(clang-tidy/modernize-use-nullptr) void *ptr = NULL; }; ``` You can also omit the name of the check to simply tell Trunk that all issues from a given linter on a specific line should be suppressed: ```cpp theme={null} struct FooBar { // trunk-ignore(clang-tidy) void *ptr = NULL; }; ``` `trunk-ignore` directives can also be placed at the end of the line on which they're suppressing lint issues: ```cpp theme={null} struct FooBar { void *ptr1 = NULL; // trunk-ignore(clang-tidy/modernize-use-nullptr) void *ptr2 = NULL; // trunk-ignore(clang-tidy) }; ``` If you need to suppress issues from multiple linters, `trunk-ignore` supports that too: ```cpp theme={null} struct FooBar { // trunk-ignore(clang-tidy): ISSUE-914 explains why the `void *` type is needed // trunk-ignore(gitleaks,my-custom-linter/do-not-hardcode-passwords): see ISSUE-915 void *super_secret_password = (void *)("915dr~S$Pzqod~oR*CrQ$/SQ@hbtQBked:CL@z!y]"); }; ``` `trunk-ignore` directives can also apply to other `trunk-ignore`s if need be: ```ts theme={null} // trunk-ignore(eslint/max-line-length) // trunk-ignore(eslint/@typescript-eslint/no-unsafe-member-access,eslint/@typescript-eslint/no-unsafe-assignment) const version = parsedConfig.version; ``` ### Ignoring all issues/formatting in a file You can also ignore all issues or formatting in a file: ```cpp theme={null} // trunk-ignore-all(clang-tidy) struct FooBar { void *ptr1 = NULL; void *ptr2 = NULL; }; ``` `trunk-ignore-all` is not required to be the first line of a file, because we recognize that other constructs (shebangs, front matter, docstrings) may need to take precedence. ### Ignoring all issues in a code block Alternatively, you can ignore all matching issues in a code block: ```cpp theme={null} struct FooBar { // trunk-ignore-begin(clang-tidy) void *ptr1 = NULL; void *ptr2 = NULL; // trunk-ignore-end(clang-tidy) }; ``` ### Tracking unused ignores Trunk will alert you if your `trunk-ignore` directives are unused. This can happen due to user error or even innocuously over time, for example, if your internal APIs change or if a linter's output changes. ``` app/parse.ts:18:3 18:3 note trunk-ignore(eslint/@typescript-eslint/no-unsafe-member-access) trunk/ignore-does-nothing is not suppressing a lint issue ``` Hold the Line will continue to only surface ignore issues that you have introduced, and these issues will have a `note` [severity](./configure-linters#blocking-thresholds), indicating they are non-blocking by default. If you need to, you can ignore issues from unused `trunk-ignore` directives, using `trunk-ignore(trunk)`: ``` // trunk-ignore(trunk): This error will resurface after our API migration. // trunk-ignore(eslint/@typescript-eslint/no-unsafe-member-access) ``` ### Specification The syntax of a trunk-ignore directive is as follows: ``` ::= "(" ")" ::= "trunk-ignore" | "trunk-ignore-begin" | "trunk-ignore-end" | "trunk-ignore-all" ::= ::= "," ::= ::= "/" ::= ": " ``` ## Ignoring multiple files Some files are never meant to be checked, such as generated code. To ignore them, use the `ignore` key to your `.trunk/trunk.yaml` file: ```yaml theme={null} lint: ignore: - linters: [ALL] paths: # Ignore generated files - src/generated/** # Except for files ending in .foo - !src/generated/**/*.foo # Test data - test/test_data ``` Every entry in `ignore` defines both a set of linters and a set of paths to ignore. | Key | Value | | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | linters | List of linters (i.e. `[black, eslint]`) or the special `[ALL]` tag | | paths | List of [glob paths](https://en.wikipedia.org/wiki/Glob_\(programming\)), relative to the root of the repo, to ignore. If a path begins with a `!` then it represents an inverse ignore. This means that any file matching that glob will not be ignored, even if matched by other globs. | Trunk is `git`-aware, which means it ignores `gitignore'd` files by default. ### Known issues `trunk-ignore` does not currently support: * suppressing findings on lines 0 or 1 using inline/block directives If you need any of these to be supported, or you have another edge case, please contact us at [support@trunk.io](mailto:support@trunk.io). # Linters Source: https://docs.trunk.io/code-quality/overview/linters/index Trunk Code Quality supports over [100 different linters](./supported/) and formatters out of the box. This section covers how to run, manage, and configure these linters. ### Supported Linters Trunk supports 100+ different linters and formatters. See the [Supported Linters](./supported/) page to find the linters you need to maintain code quality in your repos. ### Run Linters Trunk Code Quality supports many flexible ways to run your installed linters, for every project and every occasion. [Learn the commands available ](./run-linters)for the Trunk CLI. ### Manage Linters Find and enable the linters you need to keep your code base healthy. Trunk helps you manage your long list of static analysis tools and runtimes through hermetic installs. [Learn how to discover, install, and upgrade linters](./#manage-linters) in your projects. ### Configure Linters Trunk Code Quality's linter integrations are fully configurable. This means that you can easily tune existing linters or leverage our caching and [hold-the-line](/code-quality/overview#hold-the-line) solution with your custom linters. [Learn to configure your linters](./configure-linters) to get the most out of Trunk Code Quality. ### Ignoring Issues and Files Trunk Code Quality lets you configure flexible ignore for your linters. You can ignore issues by line, by files, by path, by issue type, by severity level, by file extension, and more. [Learn to ignore irrelevant issues.](./ignoring-issues-and-files) ### Custom Linters Trunk lets you turn simple scripts into fully-powered linters by running these linters and giving them support for features like ignores, [hold-the-line,](/code-quality/overview#hold-the-line) and other powerful configurable features, [Learn to create your own Custom Linters.](./custom-linters) ### Shared Configs If your team has many repositories, many teams, and many languages, you would want to share a common set of config files to keep your **entire organization consistent**. [Learn to share configurations](./shared-configs) across your org. # Manage linters Source: https://docs.trunk.io/code-quality/overview/linters/manage-linters ### Using the CLI List all of the available linters ```sh theme={null} trunk check list ``` Enable a single linter ```sh theme={null} trunk check enable ``` Disable a single linter ```sh theme={null} trunk check disable ``` ### Using Trunk config files Trunk only runs linters listed in the `enabled` section; linters which are defined in `lint.definitions` but are not listed in `enabled` are not run. When enabling a linter, you must specify a version for the linter: ```yaml theme={null} lint: enabled: # enabling a version with a linter - gitleaks@7.6.1 - gofmt@1.16.7 - golangci-lint@1.41.1 - hadolint@2.6.0 ``` Custom linters are slightly different; see [those docs](./custom-linters) to learn more. ### Disable linters Trunk will continuously monitor your repository and make recommendations of additional new tools to run on your codebase. You can tell Trunk not to recommend a specific linter by adding it to the disabled list. ```yaml theme={null} lint: disabled: # disabled a linter tells trunk not to recommend it during upgrade scans - rufo - tflint ``` ### Upgrading linters Run `trunk upgrade` to update the Trunk CLI and all your plugins, linters, tools, and runtimes. # Run Linters Source: https://docs.trunk.io/code-quality/overview/linters/run-linters The main commands when running `trunk` from the command line are: ```bash theme={null} trunk check # runs the universal linter on all applicable files trunk fmt # runs all the enabled formatters and auto-applies changes ``` You can always find this list using `trunk check --help`. Trunk is git-aware. When you run `trunk check` it will **only run on files you've modified according to git**. To run on a sampling in your repo, run: `trunk check --sample 5` ### check `trunk check` runs linters & formatters on your changed files, prompting you to apply fixes. Without additional args, `trunk check` will run all applicable linters on all files changed in the current branch. ### fmt Run all applicable formatters as configured in `trunk.yaml`. `trunk fmt` is short-hand for running\ `trunk check` with a `--fix --filter` set to all formatters enabled in your repository. ## Options | options | | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------- | | `--all` | Run on all the files in the repository. Useful if trying to assess a new linter in the system, or to find and fix pre-existing issues | | `--fix` | Auto-apply all suggested fixes | | `--no-fix` | Surface, but do not prompt for autofixes | | `--filter` | List of comma-separated linters to run. Specify `--filter=-linter` to disable a linter. | | `--sample=N` | Run check on a [sampling](#sample) of all files in the repo | | `--help` | Output help information | ### Recipes | Check | Command | | ------------------------------------------------------------ | -------------------------------------------- | | all files | `trunk check --all --no-fix` | | a specific file | `trunk check some/file.py` | | all applicable files with flake8 | `trunk check --all --no-fix --filter=flake8` | | a selection of five files in the repo | `trunk check --sample 5` | | a selection of five files in the repo with a specific linter | `trunk check --sample 5 --filter=flake8` | | format the whole repo | `trunk fmt --all` | | format a specific file | `trunk fmt some/file.py` | | format all python code with `black` | `trunk fmt --all --filter=black` | # Shared configs Source: https://docs.trunk.io/code-quality/overview/linters/shared-configs ## Single repo Linters are automatically shared with all developers for a repository using the [`.trunk/trunk.yaml` file](../getting-started/configuration/). This file is committed to the repo, so whenever anyone checks out the code, they will get the same configuration and linters. See the [Trunk YAML guide](../getting-started/configuration/) for more details. ## Per user config If you wish to customize a linter for just one developer (say, disable a slow linter on a slow machine), you can create a per-user config in the `.trunk/user.yaml` file, which should **not** be committed to the repo. ## Multiple repos If you wish to share linters between different repos, copy the config manually or create a shared Plugin repo. This is a set of configuration and code that is imported into the `plugins` section of a project's `./trunk/trunk.yaml` . # Actionlint Source: https://docs.trunk.io/code-quality/overview/linters/supported/actionlint Explore our guide on Actionlint, the linter for GitHub Actions. Learn about its features, installation, and configuration. [**Actionlint**](https://github.com/rhysd/actionlint) is a linter for GitHub. You can enable the Actionlint linter with: ```shell theme={null} trunk check enable actionlint ``` ## Auto Enabling Actionlint will be auto-enabled if any *GitHub-workflow* files are present. ## Settings Actionlint supports the following config files: * `.github/actionlint.yaml` * `.github/actionlint.yml` Unlike with most tools under `trunk check`, these files cannot be moved. ## Links * [Actionlint site](https://github.com/rhysd/actionlint) * Actionlint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/actionlint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Ansible-lint Source: https://docs.trunk.io/code-quality/overview/linters/supported/ansible-lint Checks playbooks for practices and behavior that could potentially be improved and can fix some of the most common ones for you [**Ansible-lint**](https://github.com/ansible/ansible-lint) is a linter for Ansible. You can enable the Ansible-lint linter with: ```shell theme={null} trunk check enable ansible-lint ``` ## Auto Enabling Ansible-lint will never be auto-enabled. It must be enabled manually. ## Settings Ansible-lint supports the following config files: * `.ansible-lint` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes **Ansible-lint** must be configured with a trigger. See the [trigger rules](../#trigger-rules) documentation for more information. If your ansible setup is not contained within a single folder you would list all files and directories belonging to your ansible setup. ## Links * [Ansible-lint site](https://github.com/ansible/ansible-lint) * Ansible-lint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/ansible-lint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Autopep8 Source: https://docs.trunk.io/code-quality/overview/linters/supported/autopep8 Autopep8 automatically formats Python code to meet PEP 8 standards, using pycodestyle to identify and correct formatting issues for cleaner code. [**Autopep8**](https://github.com/hhatto/autopep8#readme) is a formatter for Python. You can enable the Autopep8 formatter with: ```shell theme={null} trunk check enable autopep8 ``` autopep8 example output ## Auto Enabling Autopep8 will be auto-enabled if a `.pep8` config file is present. ## Settings Autopep8 supports the following config files: * `.pep8` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [Autopep8 site](https://github.com/hhatto/autopep8#readme) * Autopep8 Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/autopep8) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Bandit Source: https://docs.trunk.io/code-quality/overview/linters/supported/bandit Bandit is a security linter for Python codebases. Bandit flags problems like hard-coded passwords, injection vulnerabilities, and the use of insecure libraries. [**Bandit**](https://github.com/PyCQA/bandit) is a linter for Python. You can enable the Bandit linter with: ```shell theme={null} trunk check enable bandit ``` bandit example output ## Auto Enabling Bandit will be auto-enabled if any *Python* files are present. ## Settings Bandit supports the following config files: * `.bandit` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [Bandit site](https://github.com/PyCQA/bandit) * Bandit Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/bandit) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Biome Source: https://docs.trunk.io/code-quality/overview/linters/supported/biome Biome is a linter for JavaScript and TypeScript, improving code quality by automatically fixing issues, enforcing standards, and ensuring consistency. [**Biome**](https://biomejs.dev/) is a linter for JavaScript, TypeScript, jsx and json. You can enable the Biome linter with: ```shell theme={null} trunk check enable biome ``` ## Auto Enabling Biome will be auto-enabled if any of its config files are present: *`biome.json`, `rome.json`*. ## Settings Biome supports the following config files: * `biome.json` * `rome.json` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [Biome site](https://biomejs.dev/) * Biome Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/biome) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Black Source: https://docs.trunk.io/code-quality/overview/linters/supported/black Discover Black, the Python code formatter. Learn how to integrate it with Trunk Check for seamless coding style enforcement. [**Black**](https://pypi.org/project/black/) is a formatter for Python. You can enable the Black formatter with: ```shell theme={null} trunk check enable black ``` black example output ## Auto Enabling Black will be auto-enabled if any *Python, Jupyter or Python-interface* files are present. ## Links * [Black site](https://pypi.org/project/black/) * Black Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/black) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Brakeman Source: https://docs.trunk.io/code-quality/overview/linters/supported/brakeman Brakeman is a static analysis tool designed for Ruby on Rails applications. It statically analyzes Rails application code to find security issues. [**Brakeman**](https://github.com/presidentbeef/brakeman) is a linter for Ruby. You can enable the Brakeman linter with: ```shell theme={null} trunk check enable brakeman ``` ## Auto Enabling Brakeman will be auto-enabled if any *Ruby* files are present. ## Settings Brakeman supports the following config files: * `brakeman.ignore` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [Brakeman site](https://github.com/presidentbeef/brakeman) * Brakeman Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/brakeman) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # buf Source: https://docs.trunk.io/code-quality/overview/linters/supported/buf buf is a linter for Protobuf [**buf**](https://github.com/bufbuild/buf#readme) is a linter for Protobuf. buf is composed of several linter commands. `buf-format` only runs the reformatting, not lint checking. You can enable the `buf-format` linter with: ```shell theme={null} trunk check enable buf-format ``` `buf-lint` only runs the lint checking, not reformatting. You can enable the `buf-lint` linter with: ```shell theme={null} trunk check enable buf-lint ``` `buf-breaking` only checks for breaking proto changes. You can enable the `buf-breaking` linter with: ```shell theme={null} trunk check enable buf-breaking ``` ## Auto Enabling buf will never be auto-enabled. It must be enabled manually. ## Settings buf supports the following config files: * `buf.yaml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [buf site](https://github.com/bufbuild/buf#readme) * buf Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/buf) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Buildifier Source: https://docs.trunk.io/code-quality/overview/linters/supported/buildifier Learn how to install, configure, and use buildifier effectively for Bazel build scripts. [**Buildifier**](https://github.com/rhysd/actionlint) is a linter for Bazel, Starlark. You can enable the Buildifier linter with: ```shell theme={null} trunk check enable buildifier ``` buildifier example output ## Auto Enabling Buildifier will be auto-enabled if any *Bazel or Starlark* files are present. ## Settings Buildifier supports the following config files: * `.buildifier.json` * `.buildifier-tables.json` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [Buildifier site](https://github.com/rhysd/actionlint) * Buildifier Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/buildifier) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # cfnlint Source: https://docs.trunk.io/code-quality/overview/linters/supported/cfnlint cfnlint is a linter for CloudFormation [**cfnlint**](https://github.com/aws-cloudformation/cfn-lint#readme) is a linter for CloudFormation. You can enable the cfnlint linter with: ```shell theme={null} trunk check enable cfnlint ``` ## Auto Enabling cfnlint will be auto-enabled if any *CloudFormation* files are present. ## Links * [cfnlint site](https://github.com/aws-cloudformation/cfn-lint#readme) * cfnlint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/cfnlint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Checkov Source: https://docs.trunk.io/code-quality/overview/linters/supported/checkov Checkov is a static code analysis tool for scanning infrastructure as code. It identifies misconfigurations in IaC files that could lead to security breaches. [**Checkov**](https://github.com/bridgecrewio/checkov) is a linter for CloudFormation, Security, Terraform and Docker. You can enable the Checkov linter with: ```shell theme={null} trunk check enable checkov ``` checkov example output ## Auto Enabling Checkov will be auto-enabled if any *Terraform, CloudFormation, Docker, Yaml or Json* files are present. ## Settings Checkov supports the following config files: * `.checkov.yml` * `.checkov.yaml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [Checkov site](https://github.com/bridgecrewio/checkov) * Checkov Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/checkov) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # circleci Source: https://docs.trunk.io/code-quality/overview/linters/supported/circleci circleci is a linter for CircleCI Config [**circleci**](https://github.com/CircleCI-Public/circleci-cli#readme) is a linter for CircleCI Config. You can enable the circleci linter with: ```shell theme={null} trunk check enable circleci ``` ## Auto Enabling circleci will never be auto-enabled. It must be enabled manually. ## Links * [circleci site](https://github.com/CircleCI-Public/circleci-cli#readme) * circleci Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/circleci) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # ClangFormat Source: https://docs.trunk.io/code-quality/overview/linters/supported/clang-format Clang Format is a set of tools to format code that is processed by the Clang compiler suite. [**ClangFormat**](https://clang.llvm.org/docs/ClangFormat.html) is a formatter for Protobuf and C, C++. You can enable the ClangFormat formatter with: ```shell theme={null} trunk check enable clang-format ``` ## Auto Enabling ClangFormat will be auto-enabled if a `.clang-format` config file is present. ## Settings ClangFormat supports the following config files: * `.clang-format` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes By default, Trunk uses ClangFormat to additionally format `.proto` files. However, for this to work, you need to have told `clang-format` to do so in your `.clang-format` config file. You can do that by adding the following to the end of your `.clang-format file`: ```yaml theme={null} --- Language: Proto ``` For example, you might have this for your entire `.clang-format` file: ```yaml theme={null} BasedOnStyle: Google ColumnLimit: 100 --- Language: Cpp DerivePointerAlignment: false --- Language: Proto ``` ## Links * [ClangFormat site](https://clang.llvm.org/docs/ClangFormat.html) * ClangFormat Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/clang-format) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # clang-tidy Source: https://docs.trunk.io/code-quality/overview/linters/supported/clang-tidy A clang-based C++ linter tool to provide an extensible framework for diagnosing and fixing programming errors that can be deduced via static analysis. ## clang-tidy [**clang-tidy**](https://clang.llvm.org/extra/clang-tidy/) is a linter for Protobuf and C, C++. You can enable the clang-tidy linter with: ```shell theme={null} trunk check enable clang-tidy ``` ### Auto Enabling clang-tidy will be auto-enabled if a `.clang-tidy` config file is present. ### Settings clang-tidy supports the following config files: * `.clang-tidy` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.clang-tidy` if your project does not already have one. ### Usage Notes We only support using clang-tidy from Bazel and CMake projects. In order to only see issues in your own code, not from library header files your code includes, add this to your `.clang-tidy` file: ```yaml theme={null} HeaderFilterRegex: \./.+ ``` You may have to build your project first if you depend on any generated header files. ## Linter Failures If a file you're linting does not compile, clang-tidy may fail to process it. In `trunk`, this will show up as a *Linter Failure*. The output you'll see will look like a compilation error. This can also happen if the pre-reqs to running clang-tidy haven't been met (see below). ## Using Bazel By default Trunk will query `bazel` for compile commands used to run `clang-tidy`. This requires no configuration. Trunk will build needed compilation pre-requisites before invoking `clang-tidy` on each file (e.g. generated protobuf headers). You can generate a local compilation database by running `trunk generate-compile-commands`. **Finding the bazel binary** Trunk will search for the `bazel` binary in two ways. * Paths relative to the workspace root. * Binaries in any of the directories in the PATH environment variable. First trunk will search all workspace root relative paths and then all system directories. If you override anything in `lint.bazel.paths` then we only search the paths you specify. By default the configuration is as follows. ```yaml theme={null} lint: bazel: paths: workspace: - tools/bazel - bazelisk system: - bazel - bazelisk ``` ## Using `compile_commands.json` generated by CMake Trunk supports using the `compile_commands.json` file generated by CMake. If you run `cmake` from a directory called `build` in the root of your project then Trunk will find the compile commands automatically. If you run it in some other directory then you will have to symlink the `compile_commands.json` in that directory to the root of your repo for trunk to find them. Note that Trunk does not currently support CMake out of tree builds. ## Another tool claims I have clang-tidy issues, but not Trunk. What gives? Trunk runs `clang-tidy` with a compile commands database so that we can guarantee clang-tidy produces the correct diagnostics about your code. Other tools, such as `clangd`, may use best-effort heuristics to guess a compile command for a given clang-tidy input file (for example, see [this discussion)](https://github.com/clangd/clangd/issues/519) and consequently produce incorrect clang-tidy findings because they guessed the compile command wrong. ### Links * [clang-tidy site](https://clang.llvm.org/extra/clang-tidy/) * clang-tidy Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/clang-tidy) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Clippy Source: https://docs.trunk.io/code-quality/overview/linters/supported/clippy A collection of lints to catch common mistakes and improve your Rust code. [**Clippy**](https://doc.rust-lang.org/clippy/) is a linter for Rust. You can enable the Clippy linter with: ```shell theme={null} trunk check enable clippy ``` ## Auto Enabling Clippy will be auto-enabled if any *Rust* files are present. ## Settings Clippy supports the following config files: * `clippy.toml` * `.clippy.toml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes Clippy is distributed with rust itself, so specify your rust version for your clippy version (for example `clippy@1.61.0`). ## Links * [Clippy site](https://doc.rust-lang.org/clippy/) * Clippy Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/clippy) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # cmake-format Source: https://docs.trunk.io/code-quality/overview/linters/supported/cmake-format Learn how to install, configure, and run CMake-Format with Trunk Check to ensure consistent formatting and best practices for your CMake scripts. [**cmake-format**](https://github.com/cheshirekow/cmake_format) is a formatter for C, C++. You can enable the cmake-format formatter with: ```shell theme={null} trunk check enable cmake-format ``` ## Auto Enabling cmake-format will be auto-enabled if any of its config files are present: *`.cmake-format.json`, `.cmake-format.py`, `.cmake-format.yaml`*. ## Settings cmake-format supports the following config files: * `.cmake-format.json` * `.cmake-format.py` * `.cmake-format.yaml` * `cmake-format.json` * `cmake-format.py` * `cmake-format.yaml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [cmake-format site](https://github.com/cheshirekow/cmake_format) * cmake-format Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/cmake-format) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # codespell Source: https://docs.trunk.io/code-quality/overview/linters/supported/codespell Codespell fixes common misspellings in text files. It's designed primarily to check misspelled words in source code. [**codespell**](https://github.com/codespell-project/codespell#readme) is a linter for All. You can enable the codespell linter with: ```shell theme={null} trunk check enable codespell ``` codespell example output ## Auto Enabling codespell will be auto-enabled if a `.codespellrc` config file is present. ## Settings codespell supports the following config files: * `.codespellrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [codespell site](https://github.com/codespell-project/codespell#readme) * codespell Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/codespell) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # cspell Source: https://docs.trunk.io/code-quality/overview/linters/supported/cspell CSpell is a linter for identifying and fixing spelling errors in source code, documentation, and configuration files, enhancing overall project quality. [**cspell**](https://github.com/streetsidesoftware/cspell#readme) is a linter for All. You can enable the cspell linter with: ```shell theme={null} trunk check enable cspell ``` cspell example output ## Auto Enabling cspell will never be auto-enabled. It must be enabled manually. ## Settings cspell supports the following config files: * `.cspell.json` * `cspell.json` * `.cSpell.json` * `cSpell.json` * `cspell.config.js` * `cspell.config.cjs` * `cspell.config.json` * `cspell.config.yaml` * `cspell.config.yml` * `cspell.yaml` * `cspell.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `cspell.yaml` if your project does not already have one. ## Links * [cspell site](https://github.com/streetsidesoftware/cspell#readme) * cspell Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/cspell) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # cue-fmt Source: https://docs.trunk.io/code-quality/overview/linters/supported/cue-fmt cue-fmt is a formatter for CUE files that improves consistency and readability. Learn how to install, configure, and run cue-fmt. [**cue-fmt**](https://cuelang.org) is a formatter for Cue. You can enable the cue-fmt formatter with: ```shell theme={null} trunk check enable cue-fmt ``` ## Auto Enabling cue-fmt will be auto-enabled if any *Cue* files are present. ## Links * [cue-fmt site](https://cuelang.org) * cue-fmt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/cue-fmt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # dart Source: https://docs.trunk.io/code-quality/overview/linters/supported/dart dart is a linter for Dart [**dart**](https://dart.dev/tools/dart-format) is a linter for Dart. You can enable the dart linter with: ```shell theme={null} trunk check enable dart ``` ## Auto Enabling dart will never be auto-enabled. It must be enabled manually. ## Links * [dart site](https://dart.dev/tools/dart-format) * dart Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/dart) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # deno Source: https://docs.trunk.io/code-quality/overview/linters/supported/deno deno is a linter for JavaScript, JSON, TypeScript and Markdown [**deno**](https://deno.land/manual) is a linter for JavaScript, JSON, TypeScript and Markdown. You can enable the deno linter with: ```shell theme={null} trunk check enable deno ``` ## Auto Enabling deno will be auto-enabled if any of its config files are present: *`deno.json`, `deno.jsonc`*. ## Settings deno supports the following config files: * `deno.json` * `deno.jsonc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [deno site](https://deno.land/manual) * deno Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/deno) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Detekt Source: https://docs.trunk.io/code-quality/overview/linters/supported/detekt Static code analysis for Kotlin [**Detekt**](https://github.com/detekt/detekt) is a linter for Kotlin. detekt is composed of several linter commands. `detekt` runs detekt with the built-in default config and any overrides in `.detekt.yaml`. You can enable the `detekt` linter with: ```shell theme={null} trunk check enable detekt ``` `detekt-explicit` disables the default config and uses `.detekt.yaml` as the source of truth. You can enable the `detekt-explicit` linter with: ```shell theme={null} trunk check enable detekt-explicit ``` `detekt-gradle` runs detekt using Gradle. Only use if you already are using Gradle for the rest of your build setup. You can enable the `detekt-gradle` linter with: ```shell theme={null} trunk check enable detekt-gradle ``` ## Auto Enabling Detekt will never be auto-enabled. It must be enabled manually. ## Settings Detekt supports the following config files: * `.detekt.yaml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes Detekt is usually invoked through gradle, which allows specifying additional configuration in `build.gradle`. We do not yet automatically parse your Gradle scripts to infer your `detekt` configuration; instead, what we do is this: * `detekt` invokes [`detekt-cli`](https://detekt.github.io/detekt/cli.html) with the `--build-upon-default-config` flag (this appears to be [more common](https://cs.github.com/?q=%2FbuildUponDefaultConfig.*%28true%29%2F+detekt) than the alternative). * `detekt-explicit` invokes [`detekt-cli`](https://detekt.github.io/detekt/cli.html) without the `--build-upon-default-config` flag. You will also need to provide a valid detekt config as `.detekt.yaml` (an empty `.detekt.yaml` is valid, if you don't want to configure `detekt`). If you already have a detekt config, then you can symlink it like so: ```bash theme={null} ln -s path/to/existing/detekt-config.yml .detekt-config.yaml ``` To use `./gradlew detekt` to invoke Detekt, you can add `detekt-gradle@SYSTEM` to your `enabled` list. Note that since you're running Detekt via Gradle, you should also add the paths to your Detekt configurations to `direct_configs`, e.g. ```undefined theme={null} direct_configs: ["lib/detekt.yaml"] ``` ## Links * [Detekt site](https://github.com/detekt/detekt) * Detekt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/detekt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # djlint Source: https://docs.trunk.io/code-quality/overview/linters/supported/djlint djlint is a linter for HTML Templates [**djlint**](https://github.com/Riverside-Healthcare/djlint#readme) is a linter for HTML Templates. You can enable the djlint linter with: ```shell theme={null} trunk check enable djlint ``` ## Auto Enabling djlint will be auto-enabled if a `.djlintrc` config file is present. ## Settings djlint supports the following config files: * `.djlintrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.djlintrc` if your project does not already have one. ## Links * [djlint site](https://github.com/Riverside-Healthcare/djlint#readme) * djlint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/djlint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # dotenv-linter Source: https://docs.trunk.io/code-quality/overview/linters/supported/dotenv-linter dotenv-linter is a linter for Dotenv [**dotenv-linter**](https://github.com/dotenv-linter/dotenv-linter#readme) is a linter for Dotenv. You can enable the dotenv-linter linter with: ```shell theme={null} trunk check enable dotenv-linter ``` ## Auto Enabling dotenv-linter will be auto-enabled if any *Dotenv* files are present. ## Links * [dotenv-linter site](https://github.com/dotenv-linter/dotenv-linter#readme) * dotenv-linter Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/dotenv-linter) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # dotnet-format Source: https://docs.trunk.io/code-quality/overview/linters/supported/dotnet-format dotnet-format is a linter for C# [**dotnet-format**](https://github.com/dotnet/format#readme) is a linter for C#. You can enable the dotnet-format linter with: ```shell theme={null} trunk check enable dotnet-format ``` ## Auto Enabling dotnet-format will never be auto-enabled. It must be enabled manually. ## Links * [dotnet-format site](https://github.com/dotnet/format#readme) * dotnet-format Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/dotnet-format) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # dustilock Source: https://docs.trunk.io/code-quality/overview/linters/supported/dustilock dustilock is a linter for Security [**dustilock**](https://github.com/Checkmarx/dustilock) is a linter for Security. You can enable the dustilock linter with: ```shell theme={null} trunk check enable dustilock ``` ## Auto Enabling dustilock will never be auto-enabled. It must be enabled manually. ## Links * [dustilock site](https://github.com/Checkmarx/dustilock) * dustilock Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/dustilock) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # ESLint Source: https://docs.trunk.io/code-quality/overview/linters/supported/eslint ESLint statically analyzes your code to quickly find problems. ## ESLint [**ESLint**](https://eslint.org/) is a linter for JavaScript, JSON and TypeScript. You can enable the ESLint linter with: ```shell theme={null} trunk check enable eslint ``` ### Auto Enabling ESLint will be auto-enabled if any of its config files are present: *`eslint.config.js`, `eslint.config.mjs`, `eslint.config.cjs`*. ### Settings ESLint supports the following config files: * `eslint.config.js` * `eslint.config.mjs` * `eslint.config.cjs` * `.eslintrc` * `.eslintrc.cjs` * `.eslintrc.js` * `.eslintrc.json` * `.eslintrc.mjs` * `.eslintrc.yaml` * `.eslintrc.yml` Unlike with most tools under `trunk check`, these files cannot be moved. ### Usage Notes ## ESLint >= 9.x As of ESLint v9, all of the formatters have been removed. We suggest using [prettier](/code-quality/overview/linters/supported/prettier) to format Javascript and Typescript code. The extra package mentioned below is no longer needed for ESLint v9 and higher. ## ESlint \< 8.x Most ESLint users use several plugins, custom parsers, etc. Trunk has turned off sandboxing and caching for ESLint so it can use your repo's installed packages for ESLint plugins, and other required ESLint packages. Trunk controls the ESLint version, but otherwise, ESLint looks for all plugins, configs, etc. based on the path of the source file it is linting. **This all means you do need to have npm/yarn installed in your repo as a prerequisite before running ESLint via trunk**. We recommend you disable all Prettier rules in your ESLint config and let Trunk run Prettier automatically on your files. It's much nicer to just autoformat a file than to see a lint error for every missing space. You can easily do this by: * adding the `eslint-config-prettier` package * adding `prettier` as the last element to the `extends` property in your ESLint config For example, your `extends` list might look like: ```yaml theme={null} extends: # Order matters, later configs purposefully override settings from earlier configs - eslint:recommended - airbnb - plugin:@typescript-eslint/recommended - plugin:import/recommended - plugin:import/typescript - plugin:node/recommended - plugin:mocha/recommended - plugin:react/recommended - prettier # this actually turns OFF all Prettier rules running via ESLint ``` ### Links * [ESLint site](https://eslint.org/) * ESLint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/eslint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Flake8 Source: https://docs.trunk.io/code-quality/overview/linters/supported/flake8 Uncover Flake8, a versatile Python linter for code style and error checking. Flake 8 checks against PEP 8 and more, with plugin support for broader analysis. [**Flake8**](https://flake8.pycqa.org/en/latest/) is a linter for Python. You can enable the Flake8 linter with: ```shell theme={null} trunk check enable flake8 ``` flake8 example output ## Auto Enabling Flake8 will be auto-enabled if a `.flake8` config file is present. ## Settings Flake8 supports the following config files: * `.flake8` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.flake8` if your project does not already have one. ## Usage Notes Flake8 has a plugin architecture where if you install a plugin, it gets used. You can enable Flake8 plugins via: ```yaml theme={null} enabled: - flake8@3.9.2: packages: - flake8-bugbear@21.4.3 ``` `flake8-bugbear` is probably the most popular **flake8** plugin, we recommend it!. Here are a few other popular flake8 plugins you should consider. * **flake8-comprehensions**: Helps in identifying unnecessary comprehensions in your code. * **flake8-docstrings**: Checks for compliance with Python docstring conventions. * **flake8-import-order**: Checks the order of your imports according to various configurable ordering styles. Here's an updated code snippet with the above Plugins enabled: ```undefined theme={null} enabled: - flake8@3.9.2: packages: - flake8-bugbear@21.4.3 - flake8-docstrings@1.7.0 - flake8-import-order@0.18.2 - flake8-comprehensions@3.14.0 ``` ## Links * [Flake8 site](https://flake8.pycqa.org/en/latest/) * Flake8 Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/flake8) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # git-diff-check Source: https://docs.trunk.io/code-quality/overview/linters/supported/git-diff-check git-diff-check is a linter for All [**git-diff-check**](https://git-scm.com/docs/git-diff) is a linter for All. You can enable the git-diff-check linter with: ```shell theme={null} trunk check enable git-diff-check ``` ## Auto Enabling git-diff-check will be auto-enabled if any *all* files are present. ## Links * [git-diff-check site](https://git-scm.com/docs/git-diff) * git-diff-check Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/git-diff-check) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Gitleaks Source: https://docs.trunk.io/code-quality/overview/linters/supported/gitleaks Explore Gitleaks, an open-source tool for identifying secrets in codebases. Learn about its file type support and integration with Trunk. [**Gitleaks**](https://gitleaks.io/) is a linter for All. You can enable the Gitleaks linter with: ```shell theme={null} trunk check enable gitleaks ``` gitleaks example output ## Auto Enabling Gitleaks will be auto-enabled if any of its config files are present: *`.gitleaks.config`, `.gitleaks.toml`, `.gitleaksignore`*. ## Settings Gitleaks supports the following config files: * `.gitleaks.config` * `.gitleaks.toml` * `.gitleaksignore` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes Gitleaks v7 only works with Go 1.16, not Go 1.18 while Gitleaks v8 works with 1.18. We recommend using v8, but if you specifically need to use v7 you can override the go runtime version like so: ```yaml theme={null} runtimes: enabled: - go@1.16.7 ``` Again, this is not recommended. Just use Gitleaks v8 or later with go 1.18 or later. ## Links * [Gitleaks site](https://gitleaks.io/) * Gitleaks Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/gitleaks) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Gofmt Source: https://docs.trunk.io/code-quality/overview/linters/supported/gofmt Gofmt simplifies Go coding by automatically formatting code to match Go's style guidelines, enhancing readability and teamwork without the manual hassle. [**Gofmt**](https://github.com/rhysd/actionlint) is a formatter for Go. You can enable the Gofmt formatter with: ```shell theme={null} trunk check enable gofmt ``` ## Auto Enabling Gofmt will be auto-enabled if any *Go* files are present. ## Links * [Gofmt site](https://github.com/rhysd/actionlint) * Gofmt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/gofmt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # gofumpt Source: https://docs.trunk.io/code-quality/overview/linters/supported/gofumpt gofumpt is a linter for Go [**gofumpt**](https://pkg.go.dev/mvdan.cc/gofumpt) is a linter for Go. You can enable the gofumpt linter with: ```shell theme={null} trunk check enable gofumpt ``` ## Auto Enabling gofumpt will never be auto-enabled. It must be enabled manually. ## Links * [gofumpt site](https://pkg.go.dev/mvdan.cc/gofumpt) * gofumpt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/gofumpt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # goimports Source: https://docs.trunk.io/code-quality/overview/linters/supported/goimports goimports is a linter for Go [**goimports**](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) is a linter for Go. You can enable the goimports linter with: ```shell theme={null} trunk check enable goimports ``` ## Auto Enabling goimports will never be auto-enabled. It must be enabled manually. ## Links * [goimports site](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) * goimports Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/goimports) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # gokart Source: https://docs.trunk.io/code-quality/overview/linters/supported/gokart gokart is a linter for Go [**gokart**](https://github.com/praetorian-inc/gokart) is a linter for Go. You can enable the gokart linter with: ```shell theme={null} trunk check enable gokart ``` ## Auto Enabling gokart will be auto-enabled if a `analyzers.yml` config file is present. ## Settings gokart supports the following config files: * `analyzers.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `analyzers.yml` if your project does not already have one. ## Links * [gokart site](https://github.com/praetorian-inc/gokart) * gokart Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/gokart) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # golangci-lint Source: https://docs.trunk.io/code-quality/overview/linters/supported/golangci-lint Golangci-lint is a fast Go linters runner. Learn how to install, configure, and use golangci-lint effectively for Go projects. [**golangci-lint**](https://github.com/golangci/golangci-lint) is a linter for Go. You can enable the golangci-lint linter with: ```shell theme={null} trunk check enable golangci-lint ``` ## Auto Enabling golangci-lint will be auto-enabled if any *Go* files are present. ## Settings golangci-lint supports the following config files: * `.golangci.json` * `.golangci.toml` * `.golangci.yaml` * `.golangci.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes Make sure your go version in `go.mod` matches Trunk's go runtime version. At the time of this writing, Trunk's default go runtime version is `1.21.0`. You can find out what it is via `trunk print-config`, and look for the `runtime` section, and you can override the default version in your `trunk.yaml` via: ```yaml theme={null} runtimes: enabled: - go@1.21.0 ``` ## Links * [golangci-lint site](https://github.com/golangci/golangci-lint) * golangci-lint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/golangci-lint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # golines Source: https://docs.trunk.io/code-quality/overview/linters/supported/golines golines is a linter for Go [**golines**](https://pkg.go.dev/github.com/segmentio/golines) is a linter for Go. You can enable the golines linter with: ```shell theme={null} trunk check enable golines ``` ## Auto Enabling golines will never be auto-enabled. It must be enabled manually. ## Links * [golines site](https://pkg.go.dev/github.com/segmentio/golines) * golines Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/golines) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # google-java-format Source: https://docs.trunk.io/code-quality/overview/linters/supported/google-java-format google-java-format is a linter for Java [**google-java-format**](https://github.com/google/google-java-format#readme) is a linter for Java. You can enable the google-java-format linter with: ```shell theme={null} trunk check enable google-java-format ``` ## Auto Enabling google-java-format will never be auto-enabled. It must be enabled manually. ## Links * [google-java-format site](https://github.com/google/google-java-format#readme) * google-java-format Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/google-java-format) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # graphql-schema-linter Source: https://docs.trunk.io/code-quality/overview/linters/supported/graphql-schema-linter graphql-schema-linter is a linter for GraphQL [**graphql-schema-linter**](https://github.com/cjoudrey/graphql-schema-linter#readme) is a linter for GraphQL. You can enable the graphql-schema-linter linter with: ```shell theme={null} trunk check enable graphql-schema-linter ``` ## Auto Enabling graphql-schema-linter will be auto-enabled if any of its config files are present: *`.graphql-schema-linter.config.js`, `.graphql-schema-linterrc`*. ## Settings graphql-schema-linter supports the following config files: * `.graphql-schema-linter.config.js` * `.graphql-schema-linterrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [graphql-schema-linter site](https://github.com/cjoudrey/graphql-schema-linter#readme) * graphql-schema-linter Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/graphql-schema-linter) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # hadolint Source: https://docs.trunk.io/code-quality/overview/linters/supported/hadolint hadolint is a linter for Docker [**hadolint**](https://github.com/hadolint/hadolint#readme) is a linter for Docker. You can enable the hadolint linter with: ```shell theme={null} trunk check enable hadolint ``` ## Auto Enabling hadolint will be auto-enabled if any *Docker* files are present. ## Settings hadolint supports the following config files: * `.hadolint.yaml` * `.hadolint.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.hadolint.yaml` if your project does not already have one. ## Links * [hadolint site](https://github.com/hadolint/hadolint#readme) * hadolint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/hadolint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # haml-lint Source: https://docs.trunk.io/code-quality/overview/linters/supported/haml-lint haml-lint is a linter for HAML [**haml-lint**](https://github.com/sds/haml-lint#readme) is a linter for HAML. You can enable the haml-lint linter with: ```shell theme={null} trunk check enable haml-lint ``` ## Auto Enabling haml-lint will be auto-enabled if any *Haml* files are present. ## Settings haml-lint supports the following config files: * `.haml-lint.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [haml-lint site](https://github.com/sds/haml-lint#readme) * haml-lint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/haml-lint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Supported Linters Source: https://docs.trunk.io/code-quality/overview/linters/supported/index Trunk Code Quality supports over 100 linters and formatters #### Our linter integrations are open-source! You can find them at [`trunk-io/plugins`](https://github.com/trunk-io/plugins), contributions are welcome! Enable any of the following tools with: ``` trunk check enable ``` | Technology | Linters | | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | All | [codespell](./codespell), [cspell](./cspell), [git-diff-check](./git-diff-check), [gitleaks](./gitleaks), [pre-commit-hooks](./pre-commit-hooks) | | Ansible | [ansible-lint](./ansible-lint) | | Apex | [pmd](./pmd) | | Bash | [shellcheck](./shellcheck), [shfmt](./shfmt) | | Bazel, Starlark | [buildifier](./buildifier) | | C# | [dotnet-format](./dotnet-format) | | C, C++ | [clang-format](./clang-format), [clang-tidy](./clang-tidy), [cmake-format](./cmake-format), [iwyu](./iwyu), [pragma-once](./pragma-once) | | CircleCI Config | [circleci](./circleci) | | CloudFormation | [cfnlint](./cfnlint), [checkov](./checkov) | | CSS, SCSS | [prettier](./prettier), [stylelint](./stylelint) | | Cue | [cue-fmt](./cue-fmt) | | Dart | [dart](./dart) | | Docker | [checkov](./checkov), [hadolint](./hadolint) | | Dotenv | [dotenv-linter](./dotenv-linter) | | GitHub | [actionlint](./actionlint) | | Go | [gofmt](./gofmt), [gofumpt](./gofumpt), [goimports](./goimports), [gokart](./gokart), [golangci-lint](./golangci-lint), [golines](./golines), [semgrep](./semgrep) | | GraphQL | [graphql-schema-linter](./graphql-schema-linter), [prettier](./prettier) | | HAML | [haml-lint](./haml-lint) | | HTML Templates | [djlint](./djlint) | | Java | [google-java-format](./google-java-format), [pmd](./pmd), [semgrep](./semgrep) | | JavaScript | [biome](./biome), [deno](./deno), [eslint](./eslint), [prettier](./prettier), [rome](./rome), [semgrep](./semgrep) | | JSON | [deno](./deno), [eslint](./eslint), [prettier](./prettier), [semgrep](./semgrep) | | json | [biome](./biome) | | jsx | [biome](./biome) | | Kotlin | [detekt](./detekt), [ktlint](./ktlint) | | Kubernetes | [kube-linter](./kube-linter) | | Lua | [stylua](./stylua) | | Markdown | [deno](./deno), [markdown-link-check](./markdown-link-check), [markdown-table-prettify](./markdown-table-prettify), [markdownlint](./markdownlint), [markdownlint-cli2](./markdownlint-cli2), [prettier](./prettier), [remark-lint](./remark-lint) | | Nix | [nixpkgs-fmt](./nixpkgs-fmt) | | package.json | [sort-package-json](./sort-package-json) | | Perl | [perlcritic](./perlcritic), [perltidy](./perltidy) | | PHP | [php-cs-fixer](./php-cs-fixer), [phpstan](./phpstan) | | PNG | [oxipng](./oxipng) | | PowerShell | [psscriptanalyzer](./psscriptanalyzer) | | Prisma | [prisma](./prisma) | | prose | [vale](./vale) | | Protobuf | [buf](./buf), [clang-format](./clang-format), [clang-tidy](./clang-tidy) | | Python | [autopep8](./autopep8), [bandit](./bandit), [black](./black), [flake8](./flake8), [isort](./isort), [mypy](./mypy), [pylint](./pylint), [pyright](./pyright), [ruff](./ruff), [semgrep](./semgrep), [sourcery](./sourcery), [yapf](./yapf) | | Rego | [opa](./opa), [regal](./regal) | | Renovate | [renovate](./renovate) | | Ruby | [brakeman](./brakeman), [rubocop](./rubocop), [rufo](./rufo), [semgrep](./semgrep), [standardrb](./standardrb) | | Rust | [clippy](./clippy), [rustfmt](./rustfmt) | | Scala | [scalafmt](./scalafmt) | | Security | [checkov](./checkov), [dustilock](./dustilock), [nancy](./nancy), [osv-scanner](./osv-scanner), [terrascan](./terrascan), [tfsec](./tfsec), [trivy](./trivy), [trufflehog](./trufflehog) | | SQL | [sql-formatter](./sql-formatter), [sqlfluff](./sqlfluff), [sqlfmt](./sqlfmt), [squawk](./squawk) | | SVG | [svgo](./svgo) | | Swift | [stringslint](./stringslint), [swiftformat](./swiftformat), [swiftlint](./swiftlint) | | Terraform | [checkov](./checkov), [terraform](./terraform), [terrascan](./terrascan), [tflint](./tflint), [tfsec](./tfsec), [tofu](./tofu) | | Terragrunt | [terragrunt](./terragrunt) | | Terrascan | [terrascan](./terrascan) | | Textproto | [txtpbfmt](./txtpbfmt) | | TOML | [taplo](./taplo) | | TypeScript | [biome](./biome), [deno](./deno), [eslint](./eslint), [prettier](./prettier), [rome](./rome), [semgrep](./semgrep) | | YAML | [prettier](./prettier), [semgrep](./semgrep), [yamllint](./yamllint) | #### Can't find a linter you need? Suggest ideas and contribute by opening an issue at [github.com/trunk-io](https://github.com/trunk-io). # isort Source: https://docs.trunk.io/code-quality/overview/linters/supported/isort isort is a Python utility for sorting imports alphabetically and automatically separating them into sections and by type. [**isort**](https://pycqa.github.io/isort/) is a formatter for Python. You can enable the isort formatter with: ```shell theme={null} trunk check enable isort ``` isort example output ## Auto Enabling isort will be auto-enabled if any *Python* files are present. ## Settings isort supports the following config files: * `.isort.cfg` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.isort.cfg` if your project does not already have one. ## Links * [isort site](https://pycqa.github.io/isort/) * isort Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/isort) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # iwyu Source: https://docs.trunk.io/code-quality/overview/linters/supported/iwyu iwyu is a linter for C, C++ [**iwyu**](https://github.com/include-what-you-use/include-what-you-use#readme) is a linter for C, C++. You can enable the iwyu linter with: ```shell theme={null} trunk check enable iwyu ``` ## Auto Enabling iwyu will never be auto-enabled. It must be enabled manually. ## Links * [iwyu site](https://github.com/include-what-you-use/include-what-you-use#readme) * iwyu Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/iwyu) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # ktlint Source: https://docs.trunk.io/code-quality/overview/linters/supported/ktlint ktlint is a linter for Kotlin [**ktlint**](https://github.com/pinterest/ktlint#readme) is a linter for Kotlin. You can enable the ktlint linter with: ```shell theme={null} trunk check enable ktlint ``` ## Auto Enabling ktlint will be auto-enabled if any *Kotlin* files are present. ## Links * [ktlint site](https://github.com/pinterest/ktlint#readme) * ktlint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/ktlint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # kube-linter Source: https://docs.trunk.io/code-quality/overview/linters/supported/kube-linter kube-linter is a linter for Kubernetes [**kube-linter**](https://github.com/stackrox/kube-linter#readme) is a linter for Kubernetes. You can enable the kube-linter linter with: ```shell theme={null} trunk check enable kube-linter ``` ## Auto Enabling kube-linter will never be auto-enabled. It must be enabled manually. ## Links * [kube-linter site](https://github.com/stackrox/kube-linter#readme) * kube-linter Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/kube-linter) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # markdown-link-check Source: https://docs.trunk.io/code-quality/overview/linters/supported/markdown-link-check markdown-link-check is a linter for Markdown [**markdown-link-check**](https://github.com/tcort/markdown-link-check#readme) is a linter for Markdown. You can enable the markdown-link-check linter with: ```shell theme={null} trunk check enable markdown-link-check ``` ## Auto Enabling markdown-link-check will never be auto-enabled. It must be enabled manually. ## Links * [markdown-link-check site](https://github.com/tcort/markdown-link-check#readme) * markdown-link-check Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/markdown-link-check) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # markdown-table-prettify Source: https://docs.trunk.io/code-quality/overview/linters/supported/markdown-table-prettify markdown-table-prettify is a linter for Markdown [**markdown-table-prettify**](https://github.com/darkriszty/MarkdownTablePrettify-VSCodeExt#readme) is a linter for Markdown. You can enable the markdown-table-prettify linter with: ```shell theme={null} trunk check enable markdown-table-prettify ``` ## Auto Enabling markdown-table-prettify will never be auto-enabled. It must be enabled manually. ## Links * [markdown-table-prettify site](https://github.com/darkriszty/MarkdownTablePrettify-VSCodeExt#readme) * markdown-table-prettify Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/markdown-table-prettify) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Markdownlint Source: https://docs.trunk.io/code-quality/overview/linters/supported/markdownlint Markdownlint is a tool designed to enforce consistency for Markdown files. It can include checks for headings, lists, line length, and syntax preferences. [**Markdownlint**](https://github.com/DavidAnson/markdownlint) is a linter for Markdown. You can enable the Markdownlint linter with: ```shell theme={null} trunk check enable markdownlint ``` ## Auto Enabling Markdownlint will be auto-enabled if any *Markdown* files are present. ## Settings Markdownlint supports the following config files: * `.markdownlint.json` * `.markdownlint.yaml` * `.markdownlint.yml` * `.markdownlintrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.markdownlint.yaml` if your project does not already have one. ## Usage Notes Older versions of `markdownlint` had a bug where it printed plaintext output even when run with `--json`. We rely on JSON output so we can parse and ingest the results from markdownlint. The package we use for markdownlint is actually [markdownlint-cli ](https://www.npmjs.com/package/markdownlint-cli)`>= 0.29.0` is verified to work. ## Links * [Markdownlint site](https://github.com/DavidAnson/markdownlint) * Markdownlint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/markdownlint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # markdownlint-cli2 Source: https://docs.trunk.io/code-quality/overview/linters/supported/markdownlint-cli2 markdownlint-cli2 is a linter for Markdown [**markdownlint-cli2**](https://github.com/DavidAnson/markdownlint-cli2) is a linter for Markdown. You can enable the markdownlint-cli2 linter with: ```shell theme={null} trunk check enable markdownlint-cli2 ``` ## Auto Enabling markdownlint-cli2 will be auto-enabled if any of its config files are present: *`.markdownlint-cli2.jsonc`, `.markdownlint-cli2.yaml`, `.markdownlint-cli2.cjs`*. ## Settings markdownlint-cli2 supports the following config files: * `.markdownlint-cli2.jsonc` * `.markdownlint-cli2.yaml` * `.markdownlint-cli2.cjs` * `.markdownlint-cli2.mjs` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [markdownlint-cli2 site](https://github.com/DavidAnson/markdownlint-cli2) * markdownlint-cli2 Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/markdownlint-cli2) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # mypy Source: https://docs.trunk.io/code-quality/overview/linters/supported/mypy mypy is a linter for Python [**mypy**](https://github.com/python/mypy#readme) is a linter for Python. You can enable the mypy linter with: ```shell theme={null} trunk check enable mypy ``` mypy example output ## Auto Enabling mypy will be auto-enabled if any of its config files are present: *`mypy.ini`, `.mypy.ini`*. ## Settings mypy supports the following config files: * `mypy.ini` * `.mypy.ini` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [mypy site](https://github.com/python/mypy#readme) * mypy Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/mypy) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # nancy Source: https://docs.trunk.io/code-quality/overview/linters/supported/nancy nancy is a linter for Security [**nancy**](https://github.com/sonatype-nexus-community/nancy#readme) is a linter for Security. You can enable the nancy linter with: ```shell theme={null} trunk check enable nancy ``` ## Auto Enabling nancy will never be auto-enabled. It must be enabled manually. ## Links * [nancy site](https://github.com/sonatype-nexus-community/nancy#readme) * nancy Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/nancy) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # nixpkgs-fmt Source: https://docs.trunk.io/code-quality/overview/linters/supported/nixpkgs-fmt nixpkgs-fmt is a linter for Nix [**nixpkgs-fmt**](https://github.com/nix-community/nixpkgs-fmt) is a linter for Nix. You can enable the nixpkgs-fmt linter with: ```shell theme={null} trunk check enable nixpkgs-fmt ``` ## Auto Enabling nixpkgs-fmt will be auto-enabled if any *Nix* files are present. ## Links * [nixpkgs-fmt site](https://github.com/nix-community/nixpkgs-fmt) * nixpkgs-fmt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/nixpkgs-fmt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # opa Source: https://docs.trunk.io/code-quality/overview/linters/supported/opa opa is a linter for Rego [**opa**](https://www.openpolicyagent.org/docs/latest/cli/#opa-fmt) is a linter for Rego. You can enable the opa linter with: ```shell theme={null} trunk check enable opa ``` ## Auto Enabling opa will never be auto-enabled. It must be enabled manually. ## Links * [opa site](https://www.openpolicyagent.org/docs/latest/cli/#opa-fmt) * opa Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/opa) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # OSV-Scanner Source: https://docs.trunk.io/code-quality/overview/linters/supported/osv-scanner OSV-Scanner is an open-source tool created by Google to detect vulnerabilities in projects by scanning dependencies against the OSV database. [**OSV-Scanner**](https://github.com/google/osv-scanner) is a linter for Security. You can enable the OSV-Scanner linter with: ```shell theme={null} trunk check enable osv-scanner ``` ## Auto Enabling OSV-Scanner will be auto-enabled if any *Lockfile* files are present. ## Settings OSV-Scanner supports the following config files: * `osv-scanner.toml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Moving `osv-scanner.toml` to `.trunk/configs` can cause issues because `osv-scanner.toml` is only applied to projects in the root folder by default. This can cause issues with any projects in subfolders, such as in a multi-module repository. To properly configure OSV scanner if you decide to move its config file, you can specify the path to `osv-scanner.toml` using the `--config` flag.\ \ Example override to add to `trunk.yaml` : ```yaml theme={null} commands: - name: scan run: | osv-scanner \ --lockfile=${target} \ --format json \ --config=.trunk/configs/osv-scanner.toml ``` ## Links * [OSV-Scanner site](https://github.com/google/osv-scanner) * [OSV-Scanner Configuration](https://google.github.io/osv-scanner/configuration/) * OSV-Scanner Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/osv-scanner) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Oxipng Source: https://docs.trunk.io/code-quality/overview/linters/supported/oxipng Oxipng is an open-source, CLI utility designed for optimizing PNG files. It applies lossless compression techniques to reduce file size. [**Oxipng**](https://github.com/shssoichiro/oxipng) is a formatter for PNG. You can enable the Oxipng formatter with: ```shell theme={null} trunk check enable oxipng ``` ## Auto Enabling Oxipng will be auto-enabled if any *PNG* files are present. ## Links * [Oxipng site](https://github.com/shssoichiro/oxipng) * Oxipng Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/oxipng) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # perlcritic Source: https://docs.trunk.io/code-quality/overview/linters/supported/perlcritic perlcritic is a linter for Perl [**perlcritic**](https://metacpan.org/pod/Perl::Critic) is a linter for Perl. You can enable the perlcritic linter with: ```shell theme={null} trunk check enable perlcritic ``` ## Auto Enabling perlcritic will be auto-enabled if a `.perlcriticrc` config file is present. ## Settings perlcritic supports the following config files: * `.perlcriticrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.perlcriticrc` if your project does not already have one. ## Links * [perlcritic site](https://metacpan.org/pod/Perl::Critic) * perlcritic Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/perlcritic) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # perltidy Source: https://docs.trunk.io/code-quality/overview/linters/supported/perltidy perltidy is a linter for Perl [**perltidy**](https://metacpan.org/dist/Perl-Tidy/view/bin/perltidy) is a linter for Perl. You can enable the perltidy linter with: ```shell theme={null} trunk check enable perltidy ``` ## Auto Enabling perltidy will be auto-enabled if a `.perltidyrc` config file is present. ## Settings perltidy supports the following config files: * `.perltidyrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.perltidyrc` if your project does not already have one. ## Links * [perltidy site](https://metacpan.org/dist/Perl-Tidy/view/bin/perltidy) * perltidy Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/perltidy) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # php-cs-fixer Source: https://docs.trunk.io/code-quality/overview/linters/supported/php-cs-fixer php-cs-fixer is a linter for PHP [**php-cs-fixer**](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) is a linter for PHP. You can enable the php-cs-fixer linter with: ```shell theme={null} trunk check enable php-cs-fixer ``` ## Auto Enabling php-cs-fixer will be auto-enabled if a `.php-cs-fixer.dist.php` config file is present. ## Settings php-cs-fixer supports the following config files: * `.php-cs-fixer.dist.php` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [php-cs-fixer site](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) * php-cs-fixer Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/php-cs-fixer) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # phpstan Source: https://docs.trunk.io/code-quality/overview/linters/supported/phpstan phpstan is a linter for PHP [**phpstan**](https://phpstan.org/) is a linter for PHP. You can enable the phpstan linter with: ```shell theme={null} trunk check enable phpstan ``` ## Auto Enabling phpstan will never be auto-enabled. It must be enabled manually. ## Settings phpstan supports the following config files: * `phpstan.neon` * `phpstan.neon.dist` * `phpstan.dist.neon` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [phpstan site](https://phpstan.org/) * phpstan Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/phpstan) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # pmd Source: https://docs.trunk.io/code-quality/overview/linters/supported/pmd pmd is a linter for Apex and Java [**pmd**](https://pmd.github.io/) is a linter for Apex and Java. You can enable the pmd linter with: ```shell theme={null} trunk check enable pmd ``` pmd example output ## Auto Enabling pmd will never be auto-enabled. It must be enabled manually. ## Links * [pmd site](https://pmd.github.io/) * pmd Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/pmd) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # pragma-once Source: https://docs.trunk.io/code-quality/overview/linters/supported/pragma-once pragma-once is a linter for C, C++ [**pragma-once**](https://github.com/trunk-io/plugins/blob/main/linters/pragma-once/README.md) is a linter for C, C++. You can enable the pragma-once linter with: ```shell theme={null} trunk check enable pragma-once ``` pragma-once example output ## Auto Enabling pragma-once will never be auto-enabled. It must be enabled manually. ## Links * [pragma-once site](https://github.com/trunk-io/plugins/blob/main/linters/pragma-once/README.md) * pragma-once Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/pragma-once) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # pre-commit-hooks Source: https://docs.trunk.io/code-quality/overview/linters/supported/pre-commit-hooks pre-commit-hooks is a linter for All [**pre-commit-hooks**](https://pre-commit.com/hooks.html) is a linter for All. You can enable the pre-commit-hooks linter with: ```shell theme={null} trunk check enable pre-commit-hooks ``` ## Auto Enabling pre-commit-hooks will never be auto-enabled. It must be enabled manually. ## Links * [pre-commit-hooks site](https://pre-commit.com/hooks.html) * pre-commit-hooks Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/pre-commit-hooks) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Prettier Source: https://docs.trunk.io/code-quality/overview/linters/supported/prettier Explore Prettier, the powerful code formatter. Learn how to install, configure, and effectively use Prettier to enhance your coding workflow. [**Prettier**](https://prettier.io/) is a formatter for CSS, SCSS, JavaScript, JSON, Markdown, TypeScript, GraphQL and YAML. You can enable the Prettier formatter with: ```shell theme={null} trunk check enable prettier ``` prettier example output ## Auto Enabling Prettier will be auto-enabled if any *TypeScript, YAML, CSS, PostCSS, Sass, HTML, Markdown, JSON, JavaScript, GraphQL or Prettier\_supported\_configs* files are present. ## Settings Prettier supports the following config files: * `.prettierrc` * `.prettierrc.json` * `.prettierrc.yml` * `.prettierrc.yaml` * `.prettierrc.json5` * `.prettierrc.js` * `.prettierrc.cjs` * `.prettierrc.mjs` * `prettier.config.js` * `prettier.config.cjs` * `prettier.config.mjs` * `.prettierrc.toml` * `.prettierignore` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes By default, Trunk uses Prettier to autoformat many languages/config formats, including markdown. To line wrap within markdown, you need to set the following in your [Prettier config](https://prettier.io/docs/en/configuration.html) `.prettierrc.yaml`, etc. ```yaml theme={null} proseWrap: always ``` You may also want to configure `printWidth` to your liking. ## Links * [Prettier site](https://prettier.io/) * Prettier Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/prettier) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # prisma Source: https://docs.trunk.io/code-quality/overview/linters/supported/prisma prisma is a linter for Prisma [**prisma**](https://github.com/prisma/prisma#readme) is a linter for Prisma. You can enable the prisma linter with: ```shell theme={null} trunk check enable prisma ``` ## Auto Enabling prisma will never be auto-enabled. It must be enabled manually. ## Links * [prisma site](https://github.com/prisma/prisma#readme) * prisma Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/prisma) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # psscriptanalyzer Source: https://docs.trunk.io/code-quality/overview/linters/supported/psscriptanalyzer psscriptanalyzer is a linter for PowerShell [**psscriptanalyzer**](https://github.com/PowerShell/PSScriptAnalyzer) is a linter for PowerShell. You can enable the psscriptanalyzer linter with: ```shell theme={null} trunk check enable psscriptanalyzer ``` ## Auto Enabling psscriptanalyzer will be auto-enabled if a `PSScriptAnalyzerSettings.psd1` config file is present. ## Settings psscriptanalyzer supports the following config files: * `PSScriptAnalyzerSettings.psd1` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [psscriptanalyzer site](https://github.com/PowerShell/PSScriptAnalyzer) * psscriptanalyzer Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/psscriptanalyzer) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Pylint Source: https://docs.trunk.io/code-quality/overview/linters/supported/pylint Learn about Pylint, the versatile Python linter for error detection, code smell elimination, and PEP 8 enforcement. [**Pylint**](https://pypi.org/project/pylint/) is a linter for Python. You can enable the Pylint linter with: ```shell theme={null} trunk check enable pylint ``` pylint example output ## Auto Enabling Pylint will be auto-enabled if any of its config files are present: *`pylintrc`, `.pylintrc`*. ## Settings Pylint supports the following config files: * `pylintrc` * `.pylintrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes You may specify additional pylint plugins in your `.pylintrc`, using the line `load-plugins=...` If you want to run the plugin `pylint-django` as part of your setup, you would add the line `load-plugins=pylint_django` to your `.pylintrc`, but you **also** need to tell trunk to install the package: ```yaml theme={null} - pylint@2.11.0: packages: - pylint-django@2.4.4 ``` ## Links * [Pylint site](https://pypi.org/project/pylint/) * Pylint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/pylint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # pyright Source: https://docs.trunk.io/code-quality/overview/linters/supported/pyright pyright is a linter for Python [**pyright**](https://github.com/microsoft/pyright) is a linter for Python. You can enable the pyright linter with: ```shell theme={null} trunk check enable pyright ``` ## Auto Enabling pyright will be auto-enabled if a `pyrightconfig.json` config file is present. ## Settings pyright supports the following config files: * `pyrightconfig.json` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [pyright site](https://github.com/microsoft/pyright) * pyright Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/pyright) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # regal Source: https://docs.trunk.io/code-quality/overview/linters/supported/regal regal is a linter for Rego [**regal**](https://github.com/StyraInc/regal) is a linter for Rego. You can enable the regal linter with: ```shell theme={null} trunk check enable regal ``` ## Auto Enabling regal will be auto-enabled if a `.regal/config.yaml` config file is present. ## Settings regal supports the following config files: * `.regal/config.yaml` Unlike with most tools under `trunk check`, these files cannot be moved. ## Links * [regal site](https://github.com/StyraInc/regal) * regal Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/regal) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # remark-lint Source: https://docs.trunk.io/code-quality/overview/linters/supported/remark-lint remark-lint is a linter for Markdown [**remark-lint**](https://github.com/remarkjs/remark-lint#readme) is a linter for Markdown. You can enable the remark-lint linter with: ```shell theme={null} trunk check enable remark-lint ``` ## Auto Enabling remark-lint will be auto-enabled if any of its config files are present: *`.remarkrc`, `.remarkrc.json`, `.remarkrc.cjs`*. ## Settings remark-lint supports the following config files: * `.remarkrc` * `.remarkrc.json` * `.remarkrc.cjs` * `.remarkrc.mjs` * `.remarkrc.js` * `.remarkrc.yaml` * `.remarkrc.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.remarkrc.yaml` if your project does not already have one. ## Links * [remark-lint site](https://github.com/remarkjs/remark-lint#readme) * remark-lint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/remark-lint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # renovate Source: https://docs.trunk.io/code-quality/overview/linters/supported/renovate renovate is a linter for Renovate [**renovate**](https://github.com/renovatebot/renovate#readme) is a linter for Renovate. You can enable the renovate linter with: ```shell theme={null} trunk check enable renovate ``` ## Auto Enabling renovate will be auto-enabled if any of its config files are present: *`renovate.json`, `renovate.json5`, `.github/renovate.json`*. ## Settings renovate supports the following config files: * `renovate.json` * `renovate.json5` * `.github/renovate.json` * `.github/renovate.json5` * `.gitlab/renovate.json` * `.gitlab/renovate.json5` * `.renovaterc` * `.renovaterc.json` * `.renovaterc.json5` Unlike with most tools under `trunk check`, these files cannot be moved. ## Links * [renovate site](https://github.com/renovatebot/renovate#readme) * renovate Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/renovate) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # rome Source: https://docs.trunk.io/code-quality/overview/linters/supported/rome rome is a linter for JavaScript and TypeScript [**rome**](https://github.com/rome/tools#readme) is a linter for JavaScript and TypeScript. You can enable the rome linter with: ```shell theme={null} trunk check enable rome ``` ## Auto Enabling rome will never be auto-enabled. It must be enabled manually. ## Settings rome supports the following config files: * `rome.json` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [rome site](https://github.com/rome/tools#readme) * rome Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/rome) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # rubocop Source: https://docs.trunk.io/code-quality/overview/linters/supported/rubocop rubocop is a linter for Ruby [**rubocop**](https://github.com/rubocop/rubocop#readme) is a linter for Ruby. You can enable the rubocop linter with: ```shell theme={null} trunk check enable rubocop ``` ## Auto Enabling rubocop will be auto-enabled if a `.rubocop.yml` config file is present. ## Settings rubocop supports the following config files: * `.rubocop.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [rubocop site](https://github.com/rubocop/rubocop#readme) * rubocop Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/rubocop) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Ruff Source: https://docs.trunk.io/code-quality/overview/linters/supported/ruff Discover Ruff, a speedy Python linter for large codebases. Integrates with CI/IDEs and supports .py, .pyi, and Jupyter Notebooks. [**Ruff**](https://github.com/astral-sh/ruff) is a linter for Python. ruff is composed of several linter commands. `ruff` is for formatting general python code. You can enable the `ruff` linter with: ```shell theme={null} trunk check enable ruff ``` `ruff-nbqa` is for extra support for Jupyter notebooks. You can enable the `ruff-nbqa` linter with: ```shell theme={null} trunk check enable ruff-nbqa ``` ## Auto Enabling Ruff will be auto-enabled if any *Python, Python-interface, Jupyter, Python, Python-interface, Python, Python-interface, Python, Python-interface, Python or Python-interface* files are present. ## Settings Ruff supports the following config files: * `ruff.toml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `ruff.toml` if your project does not already have one. ## Links * [Ruff site](https://github.com/astral-sh/ruff) * Ruff Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/ruff) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # rufo Source: https://docs.trunk.io/code-quality/overview/linters/supported/rufo rufo is a linter for Ruby [**rufo**](https://github.com/ruby-formatter/rufo#readme) is a linter for Ruby. You can enable the rufo linter with: ```shell theme={null} trunk check enable rufo ``` ## Auto Enabling rufo will be auto-enabled if a `.rufo` config file is present. ## Settings rufo supports the following config files: * `.rufo` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [rufo site](https://github.com/ruby-formatter/rufo#readme) * rufo Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/rufo) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # rustfmt Source: https://docs.trunk.io/code-quality/overview/linters/supported/rustfmt Rustfmt is a code formatting tool for Rust that helps ensure your code adheres to the community-driven coding standards and style guidelines. [**rustfmt**](https://github.com/rust-lang/rustfmt) is a formatter for Rust. You can enable the rustfmt formatter with: ```shell theme={null} trunk check enable rustfmt ``` ## Auto Enabling rustfmt will be auto-enabled if any *Rust* files are present. ## Settings rustfmt supports the following config files: * `rustfmt.toml` * `.rustfmt.toml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.rustfmt.toml` if your project does not already have one. ## Usage Notes We currently use the version of `rustfmt` packaged with rust, so for `rustfmt` version, specify your Rust version (for example `rustfmt@1.61.0`). If you have `edition` in your `cargo.toml`, `rustfmt` also needs the same information in `.rustfmt.toml` in your repo root. For example, your `.rustfmt.toml` might contain: ```toml theme={null} edition = "2021" ``` ## Links * [rustfmt site](https://github.com/rust-lang/rustfmt) * rustfmt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/rustfmt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # scalafmt Source: https://docs.trunk.io/code-quality/overview/linters/supported/scalafmt scalafmt is a linter for Scala [**scalafmt**](https://github.com/scalameta/scalafmt#readme) is a linter for Scala. You can enable the scalafmt linter with: ```shell theme={null} trunk check enable scalafmt ``` ## Auto Enabling scalafmt will be auto-enabled if a `.scalafmt.conf` config file is present. ## Settings scalafmt supports the following config files: * `.scalafmt.conf` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [scalafmt site](https://github.com/scalameta/scalafmt#readme) * scalafmt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/scalafmt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # semgrep Source: https://docs.trunk.io/code-quality/overview/linters/supported/semgrep semgrep is a linter for Go, Java, JavaScript, JSON, Python, Ruby, TypeScript and YAML [**semgrep**](https://github.com/returntocorp/semgrep#readme) is a linter for Go, Java, JavaScript, JSON, Python, Ruby, TypeScript and YAML. You can enable the semgrep linter with: ```shell theme={null} trunk check enable semgrep ``` ## Auto Enabling semgrep will be auto-enabled if any of its config files are present: *`.semgrep.yaml`, `.semgrep.yml`*. ## Settings semgrep supports the following config files: * `.semgrep.yaml` * `.semgrep.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [semgrep site](https://github.com/returntocorp/semgrep#readme) * semgrep Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/semgrep) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # ShellCheck Source: https://docs.trunk.io/code-quality/overview/linters/supported/shellcheck ShellCheck is a static analysis tool designed to identify and report syntax errors and potential issues in shell scripts [**ShellCheck**](https://www.shellcheck.net/) is a linter for Bash. You can enable the ShellCheck linter with: ```shell theme={null} trunk check enable shellcheck ``` shellcheck example output ## Auto Enabling ShellCheck will be auto-enabled if any *Shell* files are present. ## Settings ShellCheck supports the following config files: * `.shellcheckrc` * `shellcheckrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.shellcheckrc` if your project does not already have one. ## Links * [ShellCheck site](https://www.shellcheck.net/) * ShellCheck Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/shellcheck) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # shfmt Source: https://docs.trunk.io/code-quality/overview/linters/supported/shfmt shfmt is a linter for Bash [**shfmt**](https://github.com/mvdan/sh#readme) is a linter for Bash. You can enable the shfmt linter with: ```shell theme={null} trunk check enable shfmt ``` ## Auto Enabling shfmt will be auto-enabled if any *Shell* files are present. ## Links * [shfmt site](https://github.com/mvdan/sh#readme) * shfmt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/shfmt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # sort-package-json Source: https://docs.trunk.io/code-quality/overview/linters/supported/sort-package-json sort-package-json is a linter for package.json [**sort-package-json**](https://github.com/keithamus/sort-package-json#readme) is a linter for package.json. You can enable the sort-package-json linter with: ```shell theme={null} trunk check enable sort-package-json ``` ## Auto Enabling sort-package-json will never be auto-enabled. It must be enabled manually. ## Links * [sort-package-json site](https://github.com/keithamus/sort-package-json#readme) * sort-package-json Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/sort-package-json) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # sourcery Source: https://docs.trunk.io/code-quality/overview/linters/supported/sourcery sourcery is a linter for Python [**sourcery**](https://sourcery.ai/) is a linter for Python. You can enable the sourcery linter with: ```shell theme={null} trunk check enable sourcery ``` ## Auto Enabling sourcery will never be auto-enabled. It must be enabled manually. ## Settings sourcery supports the following config files: * `.sourcery.yaml` * `sourcery.yaml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [sourcery site](https://sourcery.ai/) * sourcery Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/sourcery) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # sql-formatter Source: https://docs.trunk.io/code-quality/overview/linters/supported/sql-formatter sql-formatter is a linter for SQL [**sql-formatter**](https://github.com/sql-formatter-org/sql-formatter#readme) is a linter for SQL. You can enable the sql-formatter linter with: ```shell theme={null} trunk check enable sql-formatter ``` ## Auto Enabling sql-formatter will never be auto-enabled. It must be enabled manually. ## Links * [sql-formatter site](https://github.com/sql-formatter-org/sql-formatter#readme) * sql-formatter Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/sql-formatter) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # SQLFluff Source: https://docs.trunk.io/code-quality/overview/linters/supported/sqlfluff SQLFluff is a dialect-flexible and configurable SQL linter. [**SQLFluff**](https://github.com/sqlfluff/sqlfluff) is a linter for SQL. You can enable the SQLFluff linter with: ```shell theme={null} trunk check enable sqlfluff ``` ## Auto Enabling SQLFluff will be auto-enabled if a `.sqlfluff` config file is present. ## Settings SQLFluff supports the following config files: * `.sqlfluff` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.sqlfluff` if your project does not already have one. ## Usage Notes Sqlfluff is only configured as a linter by default because its formatting capabilities are limited. To turn sqlfluff formatting on, enable its subcommand: ```yaml theme={null} lint: enabled: - sqlfluff@: commands: [lint, fix] ``` ## Links * [SQLFluff site](https://github.com/sqlfluff/sqlfluff) * SQLFluff Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/sqlfluff) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # sqlfmt Source: https://docs.trunk.io/code-quality/overview/linters/supported/sqlfmt sqlfmt is a linter for SQL [**sqlfmt**](https://github.com/tconbeer/sqlfmt#readme) is a linter for SQL. You can enable the sqlfmt linter with: ```shell theme={null} trunk check enable sqlfmt ``` ## Auto Enabling sqlfmt will never be auto-enabled. It must be enabled manually. ## Links * [sqlfmt site](https://github.com/tconbeer/sqlfmt#readme) * sqlfmt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/sqlfmt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Squawk Source: https://docs.trunk.io/code-quality/overview/linters/supported/squawk squawk is a linter for SQL [**Squawk**](https://github.com/sbdchd/squawk) is a linter for SQL. You can enable the Squawk linter with: ```shell theme={null} trunk check enable squawk ``` ## Auto Enabling Squawk will be auto-enabled if a `.squawk.toml` config file is present. ## Settings Squawk supports the following config files: * `.squawk.toml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [Squawk site](https://github.com/sbdchd/squawk) * Squawk Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/squawk) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # standardrb Source: https://docs.trunk.io/code-quality/overview/linters/supported/standardrb standardrb is a linter for Ruby [**standardrb**](https://github.com/testdouble/standard#readme) is a linter for Ruby. You can enable the standardrb linter with: ```shell theme={null} trunk check enable standardrb ``` ## Auto Enabling standardrb will be auto-enabled if a `.standard.yml` config file is present. ## Settings standardrb supports the following config files: * `.standard.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [standardrb site](https://github.com/testdouble/standard#readme) * standardrb Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/standardrb) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # stringslint Source: https://docs.trunk.io/code-quality/overview/linters/supported/stringslint stringslint is a linter for Swift [**stringslint**](https://github.com/dral3x/StringsLint#readme) is a linter for Swift. You can enable the stringslint linter with: ```shell theme={null} trunk check enable stringslint ``` ## Auto Enabling stringslint will be auto-enabled if any of its config files are present: *`.stringslint.yml`, `.stringslint.yaml`, `.stringslint`*. ## Settings stringslint supports the following config files: * `.stringslint.yml` * `.stringslint.yaml` * `.stringslint` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [stringslint site](https://github.com/dral3x/StringsLint#readme) * stringslint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/stringslint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # stylelint Source: https://docs.trunk.io/code-quality/overview/linters/supported/stylelint stylelint is a linter for CSS, SCSS [**stylelint**](https://github.com/stylelint/stylelint#readme) is a linter for CSS, SCSS. You can enable the stylelint linter with: ```shell theme={null} trunk check enable stylelint ``` ## Auto Enabling stylelint will be auto-enabled if any of its config files are present: *`stylelint.config.js`, `.stylelintrc.js`, `stylelint.config.mjs`*. ## Settings stylelint supports the following config files: * `stylelint.config.js` * `.stylelintrc.js` * `stylelint.config.mjs` * `.stylelintrc.mjs` * `stylelint.config.cjs` * `.stylelintrc.cjs` * `.stylelintrc.json` * `.stylelintrc.yml` * `.stylelintrc.yaml` * `.stylelintrc` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [stylelint site](https://github.com/stylelint/stylelint#readme) * stylelint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/stylelint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # stylua Source: https://docs.trunk.io/code-quality/overview/linters/supported/stylua stylua is a linter for Lua [**stylua**](https://github.com/JohnnyMorganz/StyLua/tree/main) is a linter for Lua. You can enable the stylua linter with: ```shell theme={null} trunk check enable stylua ``` ## Auto Enabling stylua will be auto-enabled if any of its config files are present: *`stylua.toml`, `.stylua.toml`*. ## Settings stylua supports the following config files: * `stylua.toml` * `.stylua.toml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `stylua.toml` if your project does not already have one. ## Links * [stylua site](https://github.com/JohnnyMorganz/StyLua/tree/main) * stylua Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/stylua) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # SVGO Source: https://docs.trunk.io/code-quality/overview/linters/supported/svgo SVGO, or Scalable Vector Graphics Optimizer, is a tool designed to optimize SVG files, making them smaller and more efficient without compromising on quality. [**SVGO**](https://github.com/svg/svgo) is a linter for SVG. You can enable the SVGO linter with: ```shell theme={null} trunk check enable svgo ``` ## Auto Enabling SVGO will be auto-enabled if any *SVG* files are present. ## Settings SVGO supports the following config files: * `svgo.config.js` * `svgo.config.mjs` * `svgo.config.cjs` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `svgo.config.js` if your project does not already have one. ## Links * [SVGO site](https://github.com/svg/svgo) * SVGO Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/svgo) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # swiftformat Source: https://docs.trunk.io/code-quality/overview/linters/supported/swiftformat swiftformat is a linter for Swift [**swiftformat**](https://github.com/nicklockwood/SwiftFormat#readme) is a linter for Swift. You can enable the swiftformat linter with: ```shell theme={null} trunk check enable swiftformat ``` ## Auto Enabling swiftformat will be auto-enabled if a `.swiftformat` config file is present. ## Settings swiftformat supports the following config files: * `.swiftformat` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [swiftformat site](https://github.com/nicklockwood/SwiftFormat#readme) * swiftformat Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/swiftformat) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # swiftlint Source: https://docs.trunk.io/code-quality/overview/linters/supported/swiftlint swiftlint is a linter for Swift [**swiftlint**](https://github.com/realm/SwiftLint#readme) is a linter for Swift. You can enable the swiftlint linter with: ```shell theme={null} trunk check enable swiftlint ``` ## Auto Enabling swiftlint will be auto-enabled if any of its config files are present: *`.swiftlint.yml`, `.swiftlint.yaml`, `.swiftlint`*. ## Settings swiftlint supports the following config files: * `.swiftlint.yml` * `.swiftlint.yaml` * `.swiftlint` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [swiftlint site](https://github.com/realm/SwiftLint#readme) * swiftlint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/swiftlint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # taplo Source: https://docs.trunk.io/code-quality/overview/linters/supported/taplo taplo is a linter for TOML [**taplo**](https://github.com/tamasfe/taplo#readme) is a linter for TOML. You can enable the taplo linter with: ```shell theme={null} trunk check enable taplo ``` ## Auto Enabling taplo will be auto-enabled if any *TOML* files are present. ## Settings taplo supports the following config files: * `.taplo.toml` * `taplo.toml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [taplo site](https://github.com/tamasfe/taplo#readme) * taplo Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/taplo) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Terraform Source: https://docs.trunk.io/code-quality/overview/linters/supported/terraform The command line interface to Terraform is the terraform command, which accepts a variety of subcommands such as terraform validate or terraform fmt [**Terraform**](https://developer.hashicorp.com/terraform/cli/commands) is a formatter for Terraform. You can enable the Terraform formatter with: ```shell theme={null} trunk check enable terraform ``` ## Auto Enabling Terraform will never be auto-enabled. It must be enabled manually. ## Usage Notes We currently support `terraform validate` and `terraform fmt`, but only `fmt` is enabled by default when you add `terraform` to your enabled list in `trunk.yaml`. To enable `validate`, add this to your `trunk.yaml`: ```yaml theme={null} lint: enabled: - terraform@: commands: [validate, fmt] ``` Note: you must run `terraform init` before running `trunk check` with `terraform validate` enabled (both locally, or on CI). ## Links * [Terraform site](https://developer.hashicorp.com/terraform/cli/commands) * Terraform Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/terraform) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # terragrunt Source: https://docs.trunk.io/code-quality/overview/linters/supported/terragrunt terragrunt is a linter for Terragrunt [**terragrunt**](https://terragrunt.gruntwork.io/docs/getting-started/quick-start/) is a linter for Terragrunt. You can enable the terragrunt linter with: ```shell theme={null} trunk check enable terragrunt ``` ## Auto Enabling terragrunt will never be auto-enabled. It must be enabled manually. ## Links * [terragrunt site](https://terragrunt.gruntwork.io/docs/getting-started/quick-start/) * terragrunt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/terragrunt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # terrascan Source: https://docs.trunk.io/code-quality/overview/linters/supported/terrascan terrascan is a linter for Terrascan, Security and Terraform [**terrascan**](https://github.com/tenable/terrascan#readme) is a linter for Terrascan, Security and Terraform. You can enable the terrascan linter with: ```shell theme={null} trunk check enable terrascan ``` ## Auto Enabling terrascan will never be auto-enabled. It must be enabled manually. ## Links * [terrascan site](https://github.com/tenable/terrascan#readme) * terrascan Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/terrascan) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # TFLint Source: https://docs.trunk.io/code-quality/overview/linters/supported/tflint TFLint is an essential linter designed for Terraform. It helps improve code quality, maintainability, and security in infrastructure as code (IaC) projects. [**TFLint**](https://github.com/rhysd/actionlint) is a linter for Terraform. You can enable the TFLint linter with: ```shell theme={null} trunk check enable tflint ``` ## Auto Enabling TFLint will be auto-enabled if any *Terraform* files are present. ## Settings TFLint supports the following config files: * `.tflint.hcl` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [TFLint site](https://github.com/rhysd/actionlint) * TFLint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/tflint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # tfsec Source: https://docs.trunk.io/code-quality/overview/linters/supported/tfsec tfsec is a linter for Security and Terraform [**tfsec**](https://github.com/aquasecurity/tfsec) is a linter for Security and Terraform. You can enable the tfsec linter with: ```shell theme={null} trunk check enable tfsec ``` ## Auto Enabling tfsec will never be auto-enabled. It must be enabled manually. ## Settings tfsec supports the following config files: * `tfsec.yml` * `tfsec.yaml` * `.tfsec/config.json` * `.tfsec/config.yml` * `.tfsec/config.yaml` Unlike with most tools under `trunk check`, these files cannot be moved. ## Links * [tfsec site](https://github.com/aquasecurity/tfsec) * tfsec Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/tfsec) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # tofu Source: https://docs.trunk.io/code-quality/overview/linters/supported/tofu tofu is a linter for Terraform [**tofu**](https://github.com/opentofu/opentofu) is a linter for Terraform. You can enable the tofu linter with: ```shell theme={null} trunk check enable tofu ``` ## Auto Enabling tofu will never be auto-enabled. It must be enabled manually. ## Links * [tofu site](https://github.com/opentofu/opentofu) * tofu Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/tofu) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Trivy Source: https://docs.trunk.io/code-quality/overview/linters/supported/trivy Explore our guide on Trivy, the comprehensive vulnerability scanner. Learn about its features, installation, and configuration. [**Trivy**](https://github.com/aquasecurity/trivy) is a linter for Security. You can enable the Trivy linter with: ```shell theme={null} trunk check enable trivy ``` trivy example output ## Auto Enabling Trivy will be auto-enabled if any of its config files are present: *`trivy.yaml`, `.trivyignore`, `.trivyignore.yaml`*. ## Settings Trivy supports the following config files: * `trivy.yaml` * `.trivyignore` * `.trivyignore.yaml` * `trivy-secret.yaml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Usage Notes Trivy has the following subcommands: * `config` * Runs `trivy config` ([docs) ](https://aquasecurity.github.io/trivy/latest/docs/scanner/misconfiguration/))to scan for misconfigurations in infrastructure-as-code files. Enabled by default * `fx-vuln` * Runs `trivy fs --scanners vuln` ([docs](https://aquasecurity.github.io/trivy/latest/docs/target/filesystem/)) to scan for security vulnerabilities. Disabled by default. * `fs-secret` * Runs `trivy fs --scanners secret` ([docs](https://aquasecurity.github.io/trivy/latest/docs/target/filesystem/)) to scan for secrets. Disabled by default. To enable/disable these, add the subcommands you want enabled in your `.trunk/trunk.yaml` as such: ```yaml theme={null} lint: enabled: - trivy@0.45.1: commands: [config, fs-vuln] ``` ## Links * [Trivy site](https://github.com/aquasecurity/trivy) * Trivy Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/trivy) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Trufflehog Source: https://docs.trunk.io/code-quality/overview/linters/supported/trufflehog Discover Trufflehog with our detailed guide. Learn installation, configuration, usage, and how to integrate it with other linters for optimal code security. [**Trufflehog**](https://github.com/trufflesecurity/trufflehog) is a linter for Security. trufflehog is composed of several linter commands. `trufflehog` runs trufflehog normally. You can enable the `trufflehog` linter with: ```shell theme={null} trunk check enable trufflehog ``` `trufflehog-git` also runs trufflehog on the git history. You can enable the `trufflehog-git` linter with: ```shell theme={null} trunk check enable trufflehog-git ``` ## Auto Enabling Trufflehog will be auto-enabled if any *all* files are present. ## Links * [Trufflehog site](https://github.com/trufflesecurity/trufflehog) * Trufflehog Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/trufflehog) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # txtpbfmt Source: https://docs.trunk.io/code-quality/overview/linters/supported/txtpbfmt txtpbfmt is a linter for Textproto [**txtpbfmt**](https://github.com/protocolbuffers/txtpbfmt/) is a linter for Textproto. You can enable the txtpbfmt linter with: ```shell theme={null} trunk check enable txtpbfmt ``` ## Auto Enabling txtpbfmt will be auto-enabled if any *Textproto* files are present. ## Links * [txtpbfmt site](https://github.com/protocolbuffers/txtpbfmt/) * txtpbfmt Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/txtpbfmt) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # vale Source: https://docs.trunk.io/code-quality/overview/linters/supported/vale vale is a linter for prose [**vale**](https://vale.sh/) is a linter for prose. You can enable the vale linter with: ```shell theme={null} trunk check enable vale ``` ## Auto Enabling vale will be auto-enabled if a `.vale.ini` config file is present. ## Settings vale supports the following config files: * `.vale.ini` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.vale.ini` if your project does not already have one. ## Links * [vale site](https://vale.sh/) * vale Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/vale) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Yamllint Source: https://docs.trunk.io/code-quality/overview/linters/supported/yamllint Yamllint is a linter that checks for formatting discrepancies, key-value pair issues, and syntax errors, ensuring your YAML files are syntactically correct. [**Yamllint**](https://github.com/adrienverge/yamllint) is a linter for YAML. You can enable the Yamllint linter with: ```shell theme={null} trunk check enable yamllint ``` ## Auto Enabling Yamllint will be auto-enabled if any *Yaml* files are present. ## Settings Yamllint supports the following config files: * `.yamllint` * `.yamllint.yaml` * `.yamllint.yml` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. Trunk Code Quality provides a default `.yamllint.yaml` if your project does not already have one. ## Links * [Yamllint site](https://github.com/adrienverge/yamllint) * Yamllint Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/yamllint) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # yapf Source: https://docs.trunk.io/code-quality/overview/linters/supported/yapf yapf is a linter for Python [**yapf**](https://github.com/google/yapf#readme) is a linter for Python. You can enable the yapf linter with: ```shell theme={null} trunk check enable yapf ``` ## Auto Enabling yapf will be auto-enabled if any of its config files are present: *`.style.yapf`, `.yapfignore`*. ## Settings yapf supports the following config files: * `.style.yapf` * `.yapfignore` You can move these files to `.trunk/configs` and `trunk check` will still find them. See [Moving Linters](../configure-linters#moving-linters) for more info. ## Links * [yapf site](https://github.com/google/yapf#readme) * yapf Trunk Code Quality [integration source](https://github.com/trunk-io/plugins/tree/main/linters/yapf) * Trunk Code Quality's [open source plugins repo](https://github.com/trunk-io/plugins/tree/main) # Upgrades Source: https://docs.trunk.io/code-quality/overview/linters/upgrades Run `trunk upgrade` to update the Trunk CLI and all your plugins, linters, tools, and runtimes. #### Upgrade scopes Upgrades can be filtered to different scopes by adding them to `trunk upgrade `. The scopes available are: | Scope | Description | | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | cli | Only upgrade the Trunk CLI to the latest version. | | plugins | Upgrade any that you have sourced to their latest public release. The latest version must be compatible with your current `cli` version in order for the upgrade to be applied. | | check | Upgrade any linters that you have enabled. Linters will be upgraded to the latest validated version that have passed tests in our [plugins](https://github.com/trunk-io/plugins) repo. Additional recommended linters can also be enabled by running with `-y`. | | tools | Upgrade any that you have enabled. Tools will be upgraded to their latest public release. Note that any enabled linters that share a name with an enabled tool must keep their versions synced. | | runtimes | Upgrade any that you have enabled. Runtimes will be upgraded to their recommended version for running linters, as specified by Trunk. | #### Automatic upgrades When running locally, Trunk automatically checks for upgrades in the background on a regular cadence. You'll see notifications for these upgrades appear in the VSCode Extension or at the end of a `trunk check` run. To stop seeing these notifications, you can run `trunk actions disable trunk-upgrade-available`. When running in single-player mode, Trunk will automatically upgrade itself in the background and stay up to date. #### Automatic upgrades with GitHub Actions You can configure a GitHub workflow to create PRs with the latest Trunk and tool versions automatically. Here's a sample GitHub Action: ```yaml theme={null} name: Nightly on: schedule: - cron: 0 8 * * 1-5 workflow_dispatch: {} permissions: read-all jobs: trunk_upgrade: name: Upgrade Trunk runs-on: ubuntu-latest permissions: contents: write # For trunk to create PRs pull-requests: write # For trunk to create PRs steps: - name: Checkout uses: actions/checkout@v3 # >>> Install your own deps here (npm install, etc) <<< - name: Trunk Upgrade uses: trunk-io/trunk-action/upgrade@v1 ``` Then, provide permissions for this GitHub Action to [create and approve pull requests](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#preventing-github-actions-from-creating-or-approving-pull-requests) by navigating to your repo's **Settings** → **Actions** → **General** → **Workflow permissions** → **Allow GitHub Actions to create and approve pull requests**.\ \ You can also set the `arguments` field to filter particular scopes to upgrade and set `base` to define the branch to create a PR against (default `main`). **Triggering further workflow runs** PRs created with this GitHub Action will not trigger further workflows by default. If you need the PRs created to trigger further GitHub Action Workflows, [follow the workarounds described here](https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs). #### Pinning versions If you don't want a linter, tool, or runtime to be upgraded, you can pin its version by appending `!` to the version in your `.trunk/trunk.yaml`. For example: ```yaml theme={null} lint: enabled: - pylint@2.17.5! ``` #### Plugin repositories and user.yaml By default, upgrades are only applied to your repo's `.trunk/trunk.yaml`. If you're using a plugin repo that enables linters/tools, or if you would like upgrades to be applied to your `.trunk/user.yaml` file, you can run `trunk upgrade --apply-to ` to see upgrades applied there. # Linting in CI Source: https://docs.trunk.io/code-quality/overview/prevent-new-issues/index Trunk Code Quality can be run in CI to prevent new issues form being introduced by PRs and on a nightly/scheduled cadence to report on existing issues. ### Configuring base branch Trunk operates in **hold-the-line** mode by default. This means Trunk will run linters only on the **files that have changed** according to Git, by comparing it to the appropriate upstream branch. If you're not using `main` or `master` as the base branch, make sure it's specified in `.trunk/trunk.yaml`. ```yaml theme={null} version: 0.1 cli: version: 1.22.2 repo: # specify the base branch for hold-the-line trunk_branch: develop ``` ### Linting on pull requests ```yaml theme={null} name: Trunk Code Quality on: push: branches: main pull_request: branches: main jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # ... other setup steps - name: Trunk Code Quality uses: trunk-io/trunk-action@v1 with: post-annotations: true # ... other CI steps ``` This step will automatically run Trunk Code Quality to reveal problems found when comparing the branch to `main` or another base branch you configured. If you want to run the `trunk check` command directly in your workflow, or you're not using GitHub, you can run the following commands: ```sh theme={null} curl -fsSLO --retry 3 https://trunk.io/releases/trunk \ chmod +x trunk \ ./trunk check --ci ``` Trunk Code Quality can be run in CI to prevent new issues form being introduced by PRs and on a nightly/scheduled cadence to report on existing issues. ### Configuring base branch Trunk operates in **hold-the-line** mode by default. This means Trunk will run linters only on the **files that have changed** according to Git, by comparing it to the appropriate upstream branch. If you're not using `main` or `master` as the base branch, make sure it's specified in `.trunk/trunk.yaml`. ```yaml theme={null} version: 0. cli: version: 1.22.2 repo: # specify the base branch for hold-the-line trunk_branch: develop ``` #### Manual configuration and Non-GitHub CI If you want to run the `trunk check` command directly in your workflow, or you're not using GitHub, you can run the following commands: ``` curl -fsSLO --retry 3 https://trunk.io/releases/trunk \ chmod +x trunk \ ./trunk check --ci ``` #### Skipping Trunk Code Quality on pull requests You can include `/trunk skip-check` in the body of a PR description (i.e. the first comment on a given PR) to mark Trunk Code Quality as "skipped". Trunk Code Quality will still run on your PR and report issues, but this will allow the PR to pass a GitHub-required status check on `Trunk Check`. This can be helpful if Code Quality is flagging known issues in a given PR that you don't want to ignore, which can come in handy if you're doing a large refactor. ### Caching and persistence * Trunk caches the version of `trunk` itself, linters, formatters, and lint results in `~/.cache/trunk` * If your build machines are persistent, make sure this directory is not wiped out between CI jobs for best performance. If Trunk has to re-download every linter for every job because this directory is wiped out, it will be very slow. * If your build machines are ephemeral, there are a few options for caching: * CI systems have support for caching between CI jobs on ephemeral runners: * [GitHub Actions](https://github.com/actions/cache) * [CircleCI](https://circleci.com/docs/caching/) * [Travis CI](https://docs.travis-ci.com/user/caching/) * You can include a seeded trunk cache in a regularly updated image used for CI by running `trunk check download`, which will download all requirements to `~/.cache/trunk` ### Hourly and nightly builds If you'd like to set Code Quality to run on an hourly/nightly CI, you can run ```yaml theme={null} name: Trunk Code Quality on: schedule: # Run at 4 PM UTC daily (cron uses UTC time) - cron: '0 16 * * *' jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # ... other setup steps - name: Trunk Code Quality uses: trunk-io/trunk-action@v1 with: check-mode: all # ... other CI steps ``` You can do the same without Trunk's GitHub Action using the following command: ```bash theme={null} curl -fsSLO --retry 3 https://trunk.io/releases/trunk \ chmod +x trunk \ ./trunk check --all --ci-progress --monitor=false ``` `--ci-progress` will print out the tool's progress every 30 seconds, whereas `--no-progress` will suppress any progress reporting. You can also explicitly set the upstream branch if needed via `--upstream`, but we do detect your main branch by default. # Autofix CI Failures Source: https://docs.trunk.io/flaky-tests/agents/autofix-ci-failures Automatically investigate and fix CI failures with Trunk's autofix agent. Trunk can return targeted information about CI failures, enabling AI agents and automation tools to analyze and fix issues automatically. ## Prerequisites To use the Autofix CI Failures feature, you'll need to have: * Your repository set up to [upload test results to Trunk](../get-started/index) ## Cursor CI Autofix You can set up a [Cursor Automation](https://cursor.com/automations) to automatically fix CI failures by connecting to Trunk's CI failure investigation data via MCP. This is an extension of the Cursor `CI Autofix` template. Configuration for Cursor Automation Set up the Trunk MCP using [Bearer Authentication](../reference/mcp-reference/configuration/bearer-auth). ```json theme={null} { "name": "CI Autofix v1", "description": "Detect CI failures on main and automatically open PRs", "triggers": [ { "git": { "ciCompleted": { "repos": [ "https://github.com/" ], "condition": 1, "ignoreBaseFailures": true } } } ], "actions": [ { "gitPr": {} }, { "mcp": { "server": { "name": "trunk" } } } ], "prompts": [ { "prompt": "Your task is to fix CI failures on PRs.\n\n# Deduplication\n\nTo avoid racing against other agents, before any investigation:\n1. Collect the names of ALL failing CI jobs/checks from the CI Status Report above.\n2. Calculate your memory filename: sort the failing jobs alphabetically, join with \"_\", then remove any characters that are not letters, digits, hyphens, underscores, or dots. Prepend \"ci-fail-\" and truncate to 64 characters total. This is the filename.\n3. Read the memory file with this filename.\n - If it exists and the timestamp inside is less than 30 minutes old, stop immediately — no branch, no Slack, no output.\n4. Else, write the memory file with the current unix timestamp.\n - If the write SUCCEEDS: you claimed this failure. Proceed with the investigation below.\n - If the write FAILS (version conflict): another agent claimed it first. Stop immediately — no branch, no Slack, no output.\n\n# Investigation\n\nRoot cause the CI failure. Call investigate-ci-failure on the trunk MCP in order to get information about the failing test by passing in the workflow URL. Use that to identify which tests to fix. Look at the error output returned by this tool. ONLY IF you need additional information, look at the CI run's logs.\n\n- If the CI failure is due to a bug introduced on that commit, create a new PR that fixes the bug. The PR should be stacked on the PR with the failure. Modify/ensure the base branch of the PR you create is the branch of the PR you are fixing.\n- If the CI failure is due to a flaky test, create a new PR that skips that test.\n- If you are not confident in either of these outcomes, then do nothing.\n\n# Output\n\nOutput your results in the following format:\n**CI Autofix Automation**\n\n**Failure logs**: \n**Broken by**: (cc @prAuthor)\n**Reason**: <1-2 sentence explanation of why CI broke>\n**Fixed by**: <1-2 sentence explanation of what fixed it>\n\nMake sure to push the PR but don't include a PR link in your output — the system will generate that for you." } ], "memoryEnabled": true, "scope": "team_editable_user", "templateId": "ci-autofix" } ``` We recommend the following conventions: * Version your Automation names for more clarity (e.g., "CI Autofix v1") * Refine the prompt to avoid scanning GitHub logs in order to save time and tokens * Be specific about your repository's conventions and common failure patterns Currently Cursor will create a pull request with a base of `main`. You will need to adjust the pull request base if you want to merge the fix into your PR. ## Claude Code Routines **Coming soon.** Set up Claude Routines to autofix CI failures # Autofix Flaky Tests Source: https://docs.trunk.io/flaky-tests/agents/autofix-flaky-tests Automatically investigate and fix flaky tests with Trunk's autofix agent. Trunk can automatically investigate flaky tests in your codebase and raise fix pull requests with suggested solutions. ## Prerequisites To use the Autofix Flaky Tests feature, you'll need: 1. Beta access via waitlist (reach out to us at [support@trunk.io](mailto:support@trunk.io)) 2. The "Investigate Flaky Tests" setting enabled in your workspace 3. Active installation of the [Trunk GitHub App](../../setup-and-administration/github-app-permissions) The "Investigate Flaky Tests" setting can only be changed by organization admins. Setting to enable Flaky Test investigation ## Auto-Investigate Flaky Tests Once enabled, any time that Trunk [detects a flaky test](../detection/index), Trunk analyzes the failure patterns, failure output, and git history of the test to provide a number of insights. Results of an automatic flaky tests analysis Flaky tests can also be analyzed manually via the UI and via the [MCP server](../reference/mcp-reference/fix-flaky-test). ### Skipped and failed analyses When Trunk skips or fails an analysis, the Analysis tab shows a banner explaining what happened. Common reasons an analysis is skipped: * **Monthly analysis limit reached.** Your repository has used all available analyses for the current billing period. The banner shows how long ago the skip occurred. * **Analysis already in progress.** A previous run is still queued; Trunk skips a new one to avoid duplicates. If an analysis fails due to an internal error, the banner notes the failure without exposing internal details. In either case, you can request a new analysis once the blocking condition clears. ### Autofix with Cursor Automations Whenever an investigation is completed, Trunk will emit a [webhook](../webhooks/index) for `test_case.investigation_completed`. Enable webhooks via [Svix](../webhooks/index). You can then set up a [Cursor Automation](https://cursor.com/automations) to trigger when webhooks are received. Configuration for Cursor Automation ```json theme={null} { "name": "Autofix Flaky Tests v1", "triggers": [ { "webhook": {} } ], "actions": [], "prompts": [ { "prompt": "Your task is to fix flaky tests in this repo using provided insights.\n\n# Filter\n\nIf the test does not include the repository html_url \"https://github.com/\", exit early and do nothing.\n\n# Root Cause\n\nThe payload will include metadata about the failing test as well as some insights about the flakiness.\n\n1. The markdown_summary field includes the most important insights and the first steps you should take to root cause the flaky tests.\n2. The facts field includes more findings from historical data about running the test.\n3. Remember that the test is flaky. Sometimes it passes and sometimes it fails. Use the investigation payload to target your analysis.\n4. Use the memory tool to capture any important findings as you analyze the codebase to root cause the flakiness, such as codebase structure or test patterns.\n\n## Antipatterns\n\n1. Identify the root cause of the flakiness of the test. Do not simply increase the test's timeout or change the assertion to be more generic.\n2. Do not attempt to fix flakiness in other tests, limit your analysis to this single test.\n3. Do not add new tests, fix the flaky test in the payload.\n4. If the test is not present on your stable branch, exit early.\n5. When modifying end to end tests, do not wait on internal API calls to resolve. Focus on the page state and what the end user sees.\n6. There may be additional reasons for test flakiness, such as nondeterministic seed data, noisy neighbors, or test order issues. Conduct a deep analysis for necessary evidence, do not terminate your analysis early.\n\n## Output\n\n1. Once you have identified the root cause of the test's flakiness, open a pull request to fix the PR.\n2. Title the Pull Request: \"[Cursor Fix Flaky Test]: \".\n3. Include 1 short paragraph about the fix and the supporting evidence in the pull request body. Include links to relevant files/pages that were relevant from the webhook payload and its facts.\n4. In a collapsible summary of the PR description, include the entire webhook payload you received." } ], "memoryEnabled": true, "scope": "private", "gitConfig": { "repo": "https://github.com/", "repos": [ "https://github.com/" ], "branch": "main" } } ``` We recommend the following conventions: * Version your Automation names for more clarity. * Configure the Svix endpoint with the Cursor Bearer token. * Webhooks are configured for your entire organization, so you will need to use [Svix transformations](https://docs.svix.com/transformations) or filter out events that are not for your intended repository. * Be specific about conventions and antipatterns for your repository. You will need to refine the Automation prompt to suit your needs. * If your CI setup allows it, prompt Cursor to run the tests to verify them. ## What's next? * Continue to monitor your tests to confirm the flaky test fixes are effective * Investigations can be triggered and applied via [MCP](../reference/mcp-reference/fix-flaky-test) **Coming soon.** Set up Claude Routines to autofix flaky tests # Agents Source: https://docs.trunk.io/flaky-tests/agents/index Use agents and AI workflows to investigate and fix flaky tests and CI failures. # Changelog Source: https://docs.trunk.io/flaky-tests/changelog Recent updates to Trunk Flaky Tests. ## 2026 ### August 2026 **[Flaky Tests: Asana ticketing integration](/changelog/2026-08-11-flaky-tests-asana-ticketing)** Trunk Flaky Tests now integrates with Asana — create, link, and automate tasks for flaky and broken tests alongside the existing Linear and Jira integrations. ### July 2026 **[Flaky Tests: Automatic ticketing for Linear and Jira](/changelog/2026-07-31-flaky-tests-automatic-ticketing)** Trunk can now create, reopen, and close Linear and Jira tickets automatically as your tests change status — no webhooks required. ### June 2026 **[Flaky Tests: Failure Details and Copy Prompt in the Browser Extension](/changelog/2026-06-17-flaky-tests-browser-extension-failure-details)** The browser extension now shows test failure details inline on PR pages, with a one-click button to copy an investigation prompt for your AI assistant. **[Flaky Tests: Test Details Panel in the Browser Extension](/changelog/2026-06-11-flaky-tests-extension-test-details)** The Trunk browser extension can now show per-commit test run results inline on GitHub pull request pages for repositories with Flaky Tests uploads. **[Flaky Tests: Pass-on-Retry Monitor Is Now Org-Scoped](/changelog/2026-06-11-flaky-tests-pass-on-retry-org-scoped)** Pass-on-retry monitors now belong to your organization and can optionally target specific repositories, simplifying detection management across multi-repo orgs. **[Flaky Tests: Multiple Pass-on-Retry Monitors Per Repository](/changelog/2026-06-09-flaky-tests-multiple-por-monitors)** You can now create more than one pass-on-retry monitor per repository, each with independent settings. **[Flaky Tests: Test Collections Have Quarantining On by Default](/changelog/2026-06-08-flaky-tests-collection-quarantine-default)** New test collections now start with quarantining enabled, so uploads are protected from day one without requiring a manual settings change. **[Flaky Tests: Monitor History Swimlane](/changelog/2026-06-08-flaky-tests-monitor-history-swimlane)** The Monitors tab on the test detail page now shows a swimlane visualization of each monitor's classification history over time. **[Flaky Tests: Jira Ticket Creation Improvements](/changelog/2026-06-05-flaky-tests-jira-assignee-improvements)** The Jira ticket creation flow now loads all assignable users, lists them alphabetically, and correctly populates the Components field. **[Flaky Tests: Configurable Minimum POR Count for the Pass-on-Retry Monitor](/changelog/2026-06-02-flaky-tests-por-count-monitor)** Require multiple pass-on-retry commits before flagging a test as flaky, reducing noise in high-retry CI environments. ### May 2026 **[Flaky Tests: Lifecycle & Performance Monitors](/changelog/2026-05-28-flaky-tests-lifecycle-and-performance-monitors)** Three new monitor types — new-test, skipped-test, and slow-test — apply labels to tests based on lifecycle and performance signals, without affecting health status. **[Flaky Tests: Linear Field Defaults and Link Existing Tickets](/changelog/2026-05-19-flaky-tests-linear-improvements)** Set per-repository defaults for auto-created Linear tickets, and link existing Linear tickets to a test without creating a duplicate. **[Flaky Tests: Failure Count Monitor](/changelog/2026-05-18-flaky-tests-failure-count-monitor)** Flag tests the moment they accumulate a configured number of failures on monitored branches. **[Flaky Tests: Fork PR Uploads Without Sharing Your Org Token](/changelog/2026-05-18-flaky-tests-fork-pr-uploads)** Opt a repository into uploading test results from fork pull requests using a non-secret public repo identifier instead of your organization API token. **[Flaky Tests: Apply Labels from Monitors](/changelog/2026-05-18-flaky-tests-monitor-label-actions)** Monitors can now apply labels to tests instead of classifying them as flaky or broken. **[Flaky Tests: Organization-Scoped Test Labels](/changelog/2026-05-18-flaky-tests-test-labels)** Tag, organize, and filter your test suite with org-wide labels. **[Flaky Tests: Switch a Monitor's Action Type After Creation](/changelog/2026-05-14-flaky-tests-monitor-action-types)** Change a monitor's action between Classify test status and Apply labels, or flip flaky and broken, without deleting and recreating it. **[Flaky Tests: Independent Result and Quarantined filters on run history](/changelog/2026-05-07-flaky-tests-run-history-filters)** Filter a test's run history by result and quarantine state with two independent controls instead of one combined picker. **[Flaky Tests: Branch Scope for the Pass-on-Retry Monitor](/changelog/2026-05-06-flaky-tests-pass-on-retry-branch-scope)** Restrict pass-on-retry detection to specific branches to cut noise from PR-branch retries. ### April 2026 **[Flaky Tests: Filterable Uploads History](/changelog/2026-04-28-flaky-tests-filterable-uploads-history)** Browse a filterable, paginated history of every CI test upload, with a daily status breakdown chart and multi-value filters. **[Flaky Tests: Linked Tickets Survive Linear Team and Jira Project Moves](/changelog/2026-04-15-flaky-tests-linked-tickets-survive-moves)** Tickets you have linked to Trunk no longer disappear when they are moved to a different Linear team or Jira project. **[Flaky Tests: Repositories Overview Dashboard](/changelog/2026-04-15-flaky-tests-repositories-overview-dashboard)** The Flaky Tests landing page now summarizes every repo's flaky test health instead of redirecting into a single repo. **[Flaky Tests: API Token Auth for the Trunk MCP Server](/changelog/2026-04-08-flaky-tests-mcp-api-token-auth)** The Trunk MCP server now accepts a Trunk organization API token via the Authorization: Bearer header, so you can use Trunk's MCP tools from CI jobs, scripts, and any client that doesn't support an OAuth flow. **[Flaky Tests: AI Investigations Delivered via Webhooks](/changelog/2026-04-06-flaky-tests-ai-investigations-webhooks)** AI-powered investigations run automatically when a test first becomes flaky, with the findings delivered to your configured webhook endpoint. **[Flaky Tests: No-Monitors Banner and Jira Custom Fields](/changelog/2026-04-06-flaky-tests-no-monitors-banner-jira-fields)** The Flaky Tests page now warns when a repository has no detection monitors configured, and the Jira ticketing integration supports custom fields. ### March 2026 **[Flaky Tests: Automatically Create Jira Issues from Webhooks](/changelog/2026-03-27-flaky-tests-automatically-create-jira-issues-from-webhooks)** A new Jira connector in your webhook settings creates issues in your Jira Cloud project whenever a test's status changes to flaky and impacts more than a configurable number of PRs. **[Flaky Tests: Configurable Threshold Monitors with Live Preview](/changelog/2026-03-24-flaky-tests-configurable-threshold-monitors-with-live-preview)** You now have full control over how flaky tests are detected. Threshold monitors let you define exactly when a test should be flagged as flaky or broken, set the failure rate threshold, time window,… **[Flaky Tests: Detect Consistently Failing Tests as Broken](/changelog/2026-03-10-flaky-tests-detect-broken-tests)** Threshold monitors can now classify consistently failing tests as Broken, distinct from Flaky. **[Flaky Tests: Flag Any Test as Flaky in One Click](/changelog/2026-03-10-flaky-tests-flag-as-flaky-one-click)** Flag any test as flaky directly from its detail page with a single click and an optional reason. ### February 2026 **[Flaky Tests: Infrastructure Failure Protection](/changelog/2026-02-02-flaky-tests-infrastructure-failure-protection)** When infrastructure issues like database outages, network problems, or CI runner failures cause a large number of tests to fail simultaneously, retrying those tests can trigger mass false flaky… ## 2025 ### November 2025 **[Flaky Tests: New API endpoints](/changelog/2025-11-18-flaky-tests-new-api-endpoints)** We’ve added three new endpoints to make it easier to investigate flaky tests, automate triage, and integrate test health into your workflows. ### September 2025 **[Flaky Test: Corrected CLI test failure reporting flag](/changelog/2025-09-09-flaky-test-corrected-cli-test-failure-reporting-flag)** Resolved an issue where test failures were not being reported or displayed when using the --disable-quarantining flag. **[Flaky Tests: Auto quarantine no longer applied to broken tests](/changelog/2025-09-09-flaky-tests-auto-quarantine-no-longer-applied-to-broken-tests)** Auto-quarantining test cases have been updated to target only 'flaky' tests specifically. Previously, both 'flaky' and 'broken' tests were subject to automatic quarantine. ### August 2025 **[Flaky Tests: New endpoint and XCode 26 support](/changelog/2025-08-25-flaky-tests-new-endpoint-and-xcode-26-support)** A new endpoint is available from the trunk api at /flaky-tests/list-unhealthy-tests for your CI/CD integrations. ### July 2025 **[Flaky Tests: Commit details in timeline](/changelog/2025-07-02-flaky-tests-commit-details-in-timeline)** We’ve added additional details about commits that trigger test status changes to test timelines in the Flaky Tests dashboard. ### June 2025 **[Flaky Tests: Manual test status overrides](/changelog/2025-06-25-flaky-tests-manual-test-status-overrides)** You can now manually set a test’s status to Flaky, Healthy, or Broken in the Flaky Tests dashboard. **[Flaky Tests: Test suite and class available on test details page](/changelog/2025-06-18-test-suite-and-class-available-on-test-details-page)** The names of a test’s suite and class are now visible on the test details page of the flaky test dashboard, along with a file search link for repos using either GitHub or Bitbucket as source control… **[Flaky Tests: test\_case.quarantining\_setting\_changed webhook](/changelog/2025-06-11-flaky-tests-test-case-quarantining-setting-changed-webhook)** We’re happy to announce that a new testcase.quarantiningsetting\_changed webhook is now available for all Flaky Tests users. ### May 2025 **[Flaky Tests: Improved test failure details](/changelog/2025-05-21-improved-test-failure-details)** More changes have landed on the Flaky Tests dashboard: unique failure details on the test details page are now available in a single table view. **[RSpec Plugin for Ruby repos](/changelog/2025-05-15-rspec-plugin-for-ruby-repos)** The new Flaky Tests RSpec plugin is the best way to run RSpec tests and upload the results to Trunk. ### April 2025 **[Flaky Tests: Linear integration](/changelog/2025-04-25-linear-integration)** We now have a built-in Linear integration that creates tickets with relevant test and failure information from your flaky tests. **[Flaky Tests: Link Ticket to Test Case API](/changelog/2025-04-25-link-ticket-to-test-case-api)** Today, we’re introducing a new Link Ticket to Test Case API that allows you to link your existing Linear or Jira tickets to tests in the Flaky Tests dashboard. **[Flaky Tests: Track environment-specific flakes with variants](/changelog/2025-04-17-track-environment-specific-flakes-with-variants)** Starting today, the --variant option should be used to upload test results when the same tests are run on different environments, also known as matrix builds. **[Flaky Tests: Test detail dashboard UI improvements](/changelog/2025-04-09-flaky-tests-test-detail-dashboard-ui-improvements)** The test details page in the Flaky Tests dashboard is getting a major UX overhaul. ### March 2025 **[Flaky Tests: Quarantined Tests API](/changelog/2025-03-26-flaky-tests-quarantined-tests-api)** A new Quarantined Tests API is now available to all Flaky Tests users. This API fetches a list of currently quarantined tests for a given repo, allowing organizations to implement custom workflows to… ### February 2025 **[Flaky Tests: Detailed Jira integration status updates](/changelog/2025-02-26-flaky-tests-detailed-jira-integration-status-updates)** We have an exciting update for teams using the Flaky Test Jira integration to create and track their tickets. **[Flaky Tests: Set a custom stable branch](/changelog/2025-02-14-flaky-tests-set-a-custom-stable-branch)** If your stable branch is not main, you can now set a custom stable branch for your repositories to improve flaky test detection. **[Flaky Tests: Weekly reports](/changelog/2025-02-10-flaky-tests-weekly-reports)** We're excited to introduce a new way to help your team stay on top of your repository's test health through weekly email reports. ### January 2025 **[Flaky Tests: Webhook Integration for Slack, Microsoft Teams, GitHub Issues, and Linear](/changelog/2025-01-29-flaky-tests-webhook-integration-for-slack-microsoft-teams-github-issues-and-linea)** We're excited to introduce webhook integrations for Slack, Microsoft Teams, GitHub Issues, and Linear. **[Flaky Tests: CODEOWNERS support](/changelog/2025-01-16-flaky-tests-codeowners-support)** We’re thrilled to announce support for CODEOWNERS in our Flaky Tests product, which is available for both GitHub and GitLab repositories. **[Flaky Tests: Support for Bazel build event protocol](/changelog/2025-01-14-flaky-tests-support-for-bazel-build-event-protocol)** Trunk Flaky Tests now supports uploading test results by parsing Bazel Build Event Protocol (BEP) files. **[Flaky Tests: Flaky test detection on merge branches](/changelog/2025-01-03-flaky-tests-flaky-test-detection-on-merge-branches)** We’re excited to announce improved flaky test detection for merge queue users. In a merge queue, a single flaky failure will force every enqueued PR behind it to be retested, affecting every engineer… ## 2024 ### December 2024 **[Flaky Tests: Webhooks for status changes](/changelog/2024-12-16-flaky-tests-webhooks-for-status-changes)** We’re excited to announce the addition of webhooks for flaky tests, designed to help you automate your workflows for better handling of flaky tests. ### November 2024 **[Flaky Tests: New onboarding flow](/changelog/2024-11-12-flaky-tests-new-onboarding-flow)** Hi everyone, we’ve introduced a new onboarding flow to make it easier to integrate your test framework and CI provider with Trunk. **[Flaky Tests: Added Flaky Test commands to Trunk CLI ](/changelog/2024-11-11-flaky-tests-added-flaky-test-commands-to-trunk-cli)** The Trunk CLI now includes commands for uploading and validating test results for Trunk Flaky Tests. **[Flaky Tests: Dashboard improvements](/changelog/2024-11-08-flaky-tests-dashboard-improvements)** We’re continually refining our UX with the help of our beta users’ feedback and we’ve made some changes to how Flaky Tests displays key information on the dashboards. **[Flaky Tests: Data uploads view](/changelog/2024-11-04-flaky-tests-data-uploads-view)** A common pain point during onboarding is the lack of transparency after the Trunk CLI uploads test results. ### October 2024 **[Flaky Tests: Improved support for iOS and Swift developers](/changelog/2024-10-28-flaky-tests-improved-support-for-ios-and-swift-developers)** Flaky Tests now supports the XCResults format outputted by Swift projects using XCTests. You can now upload the .xcresults format to Trunk directly, without configuring a JUnit XML reporter. **[Flaky Tests: PR test summaries](/changelog/2024-10-17-flaky-tests-pr-test-summaries)** We're excited to introduce a powerful new feature that will help you accelerate your PR iterations: PR Test Summaries! **[Flaky Tests: Quarantining](/changelog/2024-10-14-flaky-tests-quarantining)** We’re excited to provide a new way for you to mitigate the negative impact of flaky tests in your repo through quarantining. ### August 2024 **[Flaky Tests: Jira Integration](/changelog/2024-08-27-flaky-tests-jira-integration)** We’re excited to announce the latest enhancement: Jira integration for managing flaky tests. This update builds on our MVP by streamlining the issue management process within Jira. ### July 2024 **[Flaky Tests: Issue handling MVP](/changelog/2024-07-15-test-analytics-beta-issue-handling-mvp-copy-issue-details)** Today, we are releasing our first feature to support issue handling related to flaky tests. This MVP feature is designed to streamline reporting and managing flaky tests, saving valuable time and… ### June 2024 **[Flaky Tests: UX improvements](/changelog/2024-06-28-test-analytics-beta-ux-improvements-dashboard-test-details)** We are rolling out substantial UX improvements to the dashboard and detail views. These enhancements provide users with quick and easy access to critical information. # Dashboard Source: https://docs.trunk.io/flaky-tests/dashboard Learn to find flaky tests and understand their impact using the Flaky Tests dashboard Trunk Flaky Tests detects flaky tests by analyzing test results. The health of your tests is displayed in the Flaky Tests dashboard. Press K (macOS) or Ctrl K (Windows and Linux) anywhere in the Trunk app to open the command palette. Start typing to jump to Merge Queue, Flaky Tests, your account settings, or any connected repository by name. ## Repositories overview When you navigate to `//flaky-tests`, you land on a repositories overview showing all monitored repositories at a glance. Each repository row displays: | Column | Description | | -------------- | ------------------------------------------------------------------------- | | **Tests** | Total tracked test cases in the repository (60-day window) | | **Flaky** | Number of currently flaky test cases, with a 10-day trend sparkline | | **Broken** | Number of currently broken test cases, with a 10-day trend sparkline | | **Runs / Day** | Bar chart of test run volume over the last 10 days, with per-day tooltips | A quarantine status icon appears next to each repository name when quarantining is configured: | Icon | Meaning | | --------------------- | ---------------------------------------------------------------------- | | Shield | Quarantining is enabled for this repository — auto-quarantine is off | | Shield with checkmark | Auto-quarantine is enabled — flaky tests are quarantined automatically | Active repositories (with test data in the last 30 days) appear at the top of the list. Repositories with no recent data are collapsed under an **Inactive Repositories** section that you can expand to view. Selecting a repository opens its detailed dashboard. If your organization has no repositories connected yet, the page redirects to onboarding. See [Quarantining](./quarantining/) to learn how to configure quarantine settings. ## Key repository metrics Trunk Flaky Tests provides key repo metrics based on the detected health status of your tests. You'll find metrics for the following information at the top of the Flaky Tests dashboard. | Metric | Description | | --------------------------- | ------------------------------------------------- | | Flaky tests | Number of flaky test cases in your repo. | | PRs blocked by failed tests | PRs that have been blocked by failed tests in CI. | These numbers are important for understanding the overall health of your repo’s tests, how flaky tests impact your developer productivity, and the developer hours saved from quarantining tests. You can also view the trends in these numbers in the trend charts. The trend charts display the New Test Cases added by day, as well as Test Transitions and Quarantined Runs. Test Transitions represent the number of tests that have transitioned to a particular status on a particular day, excluding new test cases (which default to a status of Healthy). If a bar shows 5 Healthy, 10 Flaky, and 2 Broken on a single day, that indicates 5 tests transitioned to Healthy, 10 to Flaky, and 2 to Broken on that day. Quarantined Runs represents the number of runs of quarantined tests by day. ## Test cases overview You can view a table of all your test cases and their current status in Trunk Flaky Tests. Filters can also be set on the table to narrow test results down by test status, quarantine setting, ticket status, or by the name, file, or suite name of the test case. The table is sorted by default by the number of PRs impacted by the case, which is the best way to measure the impact of a flaky test. You can click on each test case to view [the test case’s details](./dashboard#test-case-details). | Column | Description | | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Tests | The variant, file path, and name of the test case. | | Status | The health status of the test case: **Healthy**, **Flaky**, or **Broken**. Broken indicates consistent high-rate failures; Flaky indicates intermittent failures. | | Failure Rate | The percentage of CI runs failed due to this test case. | | PRs Impacted | The number of PRs that have been affected by this test case failing in CI. | | Last Run | The most recent timestamp for an upload test run. | Test Deletion & History * Inactive tests disappear from the dashboard automatically after 30 days and are fully removed after 45 days. Tests cannot be manually deleted. * Changing test identifiers (e.g., adding file paths) creates new test entries — merging with old history isn’t supported. ## Test case details You can *click* on any of the test cases listed on the Flaky Tests dashboard to access the test case’s details. The test details page uses a tabbed layout: * **Summary**: Run result charts and failure types grouped by unique failure reason. * **Test History**: A searchable, paginated table of every individual test run with filtering and a detail panel. * **Monitors**: Detection monitors configured for this test (visible when the detection engine is enabled). * **Events**: A timeline of detection events, quarantine actions, ticketing events, and status transitions (Healthy, Flaky, Broken) for this test (visible when the detection engine is enabled). Use the category filter to scope to **Flake Detection** events to see which monitor triggered each transition. In addition to the tabbed content, the test details page shows the test’s current status (Healthy, Flaky, or Broken), ticket status, and codeowner information. The **Monitors** tab opens on a monitor history swimlane: one row per monitor, each showing a 30-day timeline of the classifications it produced. Bars are colored by status (or by the label's color for label monitors). By default the swimlane shows only monitors with recent activity; the **Show inactive and disabled monitors** toggle reveals rows for disabled monitors and monitors with no events in the last 30 days. A swimlane timeline on the Monitors tab with rows for Test Status, a failure-rate monitor, a pass-on-retry monitor, and a second failure-rate monitor, spanning May 27 to June 26. A swimlane timeline on the Monitors tab with rows for Test Status, a failure-rate monitor, a pass-on-retry monitor, and a second failure-rate monitor, spanning May 27 to June 26. ## Code owners If you have a codeowners file configured in your repos, you will see who owns each flaky test in the test details view. We support code owners for [GitHub](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) and [GitLab](https://docs.gitlab.com/ee/user/project/codeowners/) repos. This information will also be provided when creating a ticket with the [Jira integration](./management/ticketing/jira-integration) or [webhooks](./webhooks/). ## Summary tab The Summary tab shows an overview of the test’s recent run results and groups past failures by unique failure type. ### Failure types The Failure Types table shows the history of past test runs grouped by unique failure types. The Failure Type is a summary of the stack trace of the test run. You can click on the failure type to see a list of test runs labeled by branch, PR, Author, CI Job link, duration, and time. ### Failure details You can click on any of these test runs to see the detailed stack trace: You can flip through the stack traces of similar failures across different test runs by clicking the left and right arrow buttons. You can also see other similar failures on this and other tests. **Go to the CI job logs.** If you want to see full logging of the original CI job for an individual test failure, you can click **Logs** in the expanded failure details panel to go to the job’s page in your CI provider. ## Test History tab The Test History tab gives you full visibility into every individual run of a test. Use it to investigate patterns across branches, find specific failing runs, and drill into error details. The Test History tab with a result and quarantine filter bar, a daily runs chart, and a paginated table of individual test runs. The Test History tab with a result and quarantine filter bar, a daily runs chart, and a paginated table of individual test runs. ### Daily runs chart A stacked bar chart at the top of the tab shows daily test run counts. The legend identifies four categories: * **Green**: Pass * **Red**: Fail * **Blue**: Quarantined * **Gray**: Skipped Click and drag on the chart to select a date range, which scopes the table below to runs from the selected days. The selected range appears next to the legend with an X button to clear just the range. The **Reset** button on the filter bar clears all filters at once, including the date range. The **Result** and **Quarantined** filters from the filter bar also apply to the chart bars. When you filter to only passing runs, for example, the chart shows only green (Pass) bars. The chart and table always reflect the same set of runs. ### Filters A filter bar below the chart provides four independent controls: | Filter | Description | | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | Result | Segmented control with **All**, **Pass**, and **Fail** to scope the table to a specific outcome. | | Quarantined | Segmented control with **Include** (default), **Exclude**, and **Only** to control whether quarantined runs are mixed in, hidden, or shown exclusively. | | SHA | Filter by commit hash. Matches runs whose SHA starts with the entered text. | | Branch | Filter by branch name. Accepts exact names or glob patterns. Use `*` to match any sequence of characters and `?` to match a single character. | Branch filter examples: | Pattern | Matches | | --------------- | --------------------------------------------------------------- | | `main` | The branch named `main` exactly | | `release/*` | All release branches, e.g. `release/1.0`, `release/2.3` | | `feature-??` | Feature branches with a two-character suffix, e.g. `feature-v2` | | `trunk-merge/*` | All merge queue branches | All filters combine using AND logic, so you can use them together. For example, set **Result** to **Fail** and **Quarantined** to **Only** to surface only quarantined failures. The **Reset** button clears every filter at once, including the chart date range. Filter state is saved in the URL, so you can share or bookmark a filtered view. The Result filter accepts `result=pass` or `result=fail`. The Quarantined filter accepts `quarantined=include`, `quarantined=exclude`, or `quarantined=only`. ### Runs table The runs table displays a paginated list of individual test runs (25 per page) with the following columns: | Column | Description | | --------- | ----------------------------------------------------------------------------------------------------------------- | | Timestamp | When the test ran, displayed in your local time zone. | | Duration | How long the test took to execute. | | PR | The pull request number associated with the run, e.g. `#1234`. Empty for runs that aren't tied to a PR. | | Branch | The branch the test ran against, e.g. `main`, `feature/x`, or `trunk-merge/pr-1234/...` for merge queue branches. | | Commit | The first 7 characters of the commit SHA. | Each row has a colored left border indicating the run's outcome. Quarantined runs always show blue, regardless of whether the run passed or failed. For non-quarantined runs, the border is green for pass, red for fail, orange for error, and a neutral gray for any other state. ### Run detail panel Click any row in the runs table to open a detail panel on the right side of the page. The panel shows: * **Run header**: Timestamp, a result badge (Pass, Fail, Error, or Quarantined), and run duration. * **Source control**: A CI job link (with the provider's icon, the job name, and the CI duration), the linked pull request, branch, and commit. Merge queue runs also include a **View in Merge Queue** link. * **Error details**: For failed, errored, or quarantined runs, an optional AI summary of the failure followed by the raw error text or stack trace. ### Debugging a flaky test from the UI The Summary tab, failure details, and Test History tab give you most of what you need to investigate a flaky test. A few gaps come up often enough to call out, along with the workarounds that exist today. #### Drilling into the right parallel worker The CI job link in the run detail panel points to the parent build, not the specific worker that produced the failure. If your CI runs a single job, this is fine. If you fan out across many parallel workers (some customers run 40+), you'll have to click through workers in the CI provider to find the one whose log contains the failure. To shortcut this, capture the per-worker URL at test run time and include it in your JUnit output so it surfaces in the failure detail. Most CI providers expose an environment variable for the running job's URL: | CI provider | Environment variable | | -------------- | ------------------------------------------------------------------------- | | CircleCI | `CIRCLE_BUILD_URL` | | GitHub Actions | `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}` | | Buildkite | `BUILDKITE_BUILD_URL` | | GitLab CI | `CI_JOB_URL` | Read the value at the start of the test job and append it to a test property, log line, or system-out block in your JUnit XML. The link then appears alongside the failure in Trunk instead of routing to the parent build. #### Bundle Upload ID lookups When the `trunk-analytics-cli` uploads a bundle, it prints a Bundle Upload ID to the job log. This ID does not currently map to a URL in the web app — there's no search field for it in the dashboard. If you need to trace a specific upload back to its run data, contact support with the Bundle Upload ID. Uploads are processed periodically, not in real time, so a run you just uploaded may not appear immediately. If it isn't visible yet, wait and refresh before assuming the upload failed. #### CI artifact retention CI providers typically retain build artifacts (screenshots, videos, traces) for one to two days. Flaky test tickets often take longer than that to investigate and resolve, which means the artifacts that would have helped explain the failure may already be gone by the time you open the ticket. If artifacts matter for your debugging flow, store them outside the CI provider's retention window: * Upload screenshots, videos, and traces to S3 (or another long-lived store) as a CI step, and include the object URL in the JUnit output alongside the per-worker URL described above. * For especially noisy tests, attach the artifact URL to the Jira/Linear ticket Trunk opens via the [ticketing integration](./management/ticketing/jira-integration). #### Known limitations A few framework-specific quirks are worth knowing about up front. **RSpec `MultipleExceptionError`** When an example raises multiple exceptions (for example, an error in the test body plus a separate error in an `after` hook), RSpec wraps them in `RSpec::Core::MultipleExceptionError`. The `rspec_trunk_flaky_tests` gem already uploads the full set of captured exceptions; the failure detail view currently renders only one of them. To see all of them, check the CI job logs for the full exception list when you encounter this error type. **Go subtests with 0ms duration** `go test` reports the top-level test duration but does not always emit per-subtest durations. When a subtest's duration is reported as 0ms, timing-based signals — including the AI failure analysis — have less to work with for that case. If timing context matters for your investigation, post-process your JUnit XML to reflect real subtest durations before uploading, or rely on the raw stack trace rather than the AI summary. # Failure Count Monitor Source: https://docs.trunk.io/flaky-tests/detection/failure-count-monitor Detect flaky or broken tests as soon as they accumulate a configured number of failures The failure count monitor flags a test the moment it accumulates a configured number of failures on monitored branches within a rolling time window. Unlike the failure rate monitor, which requires a failure *rate* calculated over many runs, the failure count monitor reacts to individual failures without needing a minimum sample size or a percentage calculation. This makes it well-suited for stable branches like `main` where any test failure is unexpected and worth investigating immediately. ## When to Use This Monitor Use the failure count monitor when you want immediate visibility into test failures on branches that should be green. Common scenarios: * **Stable branch alerting:** Flag any test that fails on `main`, even once. On a branch where all tests should pass, a single failure is a meaningful signal. * **Post-merge regression detection:** Catch tests that start failing after a merge, before the failure rate accumulates enough data for a failure rate monitor to trigger. * **High-confidence branches:** Monitor merge queue or release branches where failures are suspicious by definition. If you need to detect patterns of intermittent failure over time (e.g., a test that fails 20% of the time), use a [failure rate monitor](./failure-rate-monitor) instead. If you want to catch tests that fail and then pass on retry within a single commit, [pass-on-retry](./pass-on-retry-monitor) handles that automatically. ## How It Works The monitor counts the number of test failures on configured branches within a rolling time window. When a test reaches the configured failure count, the monitor activates and runs its configured [action](#action) — by default, flagging the test as flaky or broken. ### Example You configure a failure count monitor with: | Setting | Value | | ------------------ | ---------- | | Detection type | Broken | | Failure count | 1 | | Window | 30 minutes | | Resolution timeout | 2 hours | | Branches | `main` | A developer merges a change that breaks `test_checkout`. Here is what happens: 1. `test_checkout` fails on the next CI run on `main`. 2. The monitor sees 1 failure within the 30-minute window, which meets the configured failure count of 1. 3. `test_checkout` is immediately flagged as **broken**. 4. The developer identifies the issue and merges a correction. 5. Two hours pass with no new failures for `test_checkout`. 6. The monitor automatically resolves the test back to **healthy**. If another test, `test_signup`, also failed during that window, it would be flagged independently. Each test is evaluated on its own. ## Configuration ### Failure Count The number of failures required to trigger detection. The default is **1**, meaning any single failure on a monitored branch flags the test. Setting this higher (e.g., 3) requires multiple failures before the monitor reacts. This is useful if you want to filter out one-off infrastructure blips while still catching tests that fail repeatedly in a short window. ### Window Duration The rolling time window over which failures are counted. Only test failures within this window contribute to the failure count. A shorter window (e.g., 30 minutes) limits detection to very recent failures. A longer window (e.g., 6 hours) catches failures that are spread out over time but still accumulating. The window should be long enough to capture the failures you care about but short enough that old failures roll off naturally. For a monitor with a failure count of 1, the window mainly controls how quickly a detection event is created after a failure. In practice, the pipeline evaluates frequently, so detection is near-immediate regardless of window size. ### Resolution Timeout How long a flagged test must go without any new failures before it is automatically resolved. This is the only way a failure count monitor resolves — there is no "recovery rate" or sample-based resolution like the failure rate monitor, and no stale timeout. If a test stops running entirely (e.g., it was deleted or renamed), it stays flagged until the resolution timeout elapses from its last observed failure. For example, with a resolution timeout of 2 hours, a test that was flagged at 3:00 PM will resolve at 5:00 PM if no new failures occur. If a new failure arrives at 4:30 PM, the clock resets, and the test will not resolve until 6:30 PM. The resolution timeout must be at least as long as the detection window. If the window is 30 minutes, the resolution timeout should be 30 minutes or longer. Choose a resolution timeout that gives your team enough time to verify a fix has landed. A short timeout (e.g., 30 minutes) resolves quickly but may prematurely clear tests that fail intermittently. A longer timeout (e.g., 24 hours) is more conservative and ensures the test stays flagged until it has been clean for a full day. ### Branch Scope Which branches the monitor evaluates. You can specify branch names or glob patterns. Only test failures on matching branches count toward the failure count. Branch patterns work the same way as [failure rate monitor branch patterns](./failure-rate-monitor#branch-pattern-syntax), including glob syntax and merge queue patterns. Refer to that section for pattern syntax, examples, and tips. ### Action What happens when the monitor activates on a test. You pick the action at creation and can switch it at any time. **Classify test status (default).** The test's status is set according to the monitor's **detection type**, and restored to healthy when the monitor resolves. The detection type is either: * **Flaky** — appropriate when failures on the monitored branch are likely non-deterministic. A test that fails once on `main` but passes on retry is probably flaky. * **Broken** — appropriate when failures indicate a real regression. If a test fails on `main` and you expect it to keep failing until someone fixes it, broken is the right classification. **Apply labels.** The configured labels are added to the test while the monitor is active. The test's health status is not changed by this monitor. See [Automatic labeling from monitors](../management/test-labels#automatic-labeling-from-monitors) for how to configure and what to expect. ## Preview Panel When you create or edit a failure count monitor, a **Preview** panel appears on the right side of the dialog on larger screens. The preview updates as you adjust the monitor's settings, giving you a live look at what the monitor would detect against your current branch data. Once the monitor configuration produces detections, the panel shows a **Failing tests** list. Each row displays the test name as a link to its detail page, along with its failure count. Counts that meet or exceed your configured failure count are highlighted in red; counts below appear in muted text. You can search the list by test name or parent test name. The search is case-insensitive and filters as you type. If no tests match your search term, the list shows a "No tests match" message. When more than 100 tests are detected, only the first 100 are shown with a notice to narrow your search. ### Status Filter A **status filter dropdown** in the preview panel lets you filter the test list to any combination of statuses: **Healthy**, **Flaky**, and **Broken**. By default, all statuses are shown. Filtering to **Healthy** is the most useful view: it shows tests that are currently healthy but would be flagged by this monitor if created with the current settings. This lets you see the new coverage the monitor adds without noise from tests already detected by other monitors. Selecting multiple statuses (for example, Healthy and Flaky) shows tests matching any of the selected statuses. When a status filter is active, the info tooltip in the panel header shows "X of Y tests" to indicate how many tests are visible relative to the total that match the monitor configuration. If no tests match the active filter, the empty state includes a hint to clear the filter. ### Large Repo Truncation For repositories with a large number of matching tests, preview results may be truncated. When this happens, an amber warning appears in the panel. The truncation applies to the list of tests shown, not to the underlying detection logic — the monitor evaluates all matching tests when active. ## Muting You can temporarily mute a failure count monitor for a specific test case. See [Muting monitors](./index#muting-monitors) for details. ## Choosing Between Monitors | Scenario | Recommended monitor | | ---------------------------------------------------- | ---------------------------------------------------- | | Any failure on `main` should be flagged immediately | **Failure count** with count = 1 | | Tests failing at an elevated rate over many runs | **Threshold** with appropriate activation percentage | | A test fails then passes on retry in the same commit | **Pass-on-retry** (enabled by default) | | Consistently failing tests (80%+ failure rate) | **Threshold** with broken detection type | | Quick alerting on merge queue failures | **Failure count** scoped to merge queue branches | # Failure Rate Monitor Source: https://docs.trunk.io/flaky-tests/detection/failure-rate-monitor Detect flaky or broken tests based on failure rate over a configurable time window The failure rate monitor detects tests based on failure rate over a rolling time window. Unlike pass-on-retry, which looks for a specific pattern on a single commit, the failure rate monitor identifies tests that fail too often over a period of time, even if no individual failure looks like a retry. You can create multiple failure rate monitors with different configurations. This is how you tailor detection to different branches, test volumes, and sensitivity levels. ## How It Works The monitor periodically calculates the failure rate for each test within a time window you define. If the rate meets or exceeds your activation threshold and the test has enough runs to be statistically meaningful, the monitor activates on the test and runs its configured [action](#action) — by default, flagging the test as flaky or broken. Test runs resolve pass or fail while a failure-rate meter rises past the 30% activation line and is flagged flaky, then falls below the 15% resolution line and resolves to healthy. ### Example You configure a failure rate monitor with: | Setting | Value | | -------------------- | ------- | | Detection type | Flaky | | Activation threshold | 30% | | Window | 6 hours | | Minimum sample size | 50 runs | | Branches | `main` | Over the last 6 hours, here's what the monitor observes: | Test | Runs | Failures | Failure rate | Meets min sample? | Result | | --------------- | ---- | -------- | ------------ | ----------------- | ------------------------------------------------- | | `test_checkout` | 120 | 42 | 35% | Yes (120 ≥ 50) | **Flagged as flaky** — rate exceeds 30% threshold | | `test_signup` | 8 | 3 | 37.5% | No (8 \< 50) | **Not flagged** — insufficient data | `test_checkout` is flagged because its 35% failure rate exceeds the 30% threshold and it has enough runs to be statistically meaningful. `test_signup` has a higher failure rate but is skipped entirely — the monitor needs at least 50 runs before making a call. ## Configuration ### Activation Threshold The failure rate that triggers detection, expressed as a percentage. A test is flagged when its failure rate meets or exceeds this value within the time window. For flaky monitors, setting this lower (e.g., 10%) catches more intermittent failures but may produce false positives. Setting it higher (e.g., 50%) is more conservative and only flags tests that fail frequently. For broken monitors, a high threshold (e.g., 80–100%) is appropriate — you want to catch tests that are consistently failing, not ones with occasional failures. ### Resolution Threshold The failure rate a test must drop below to be resolved. If not set, it defaults to the activation threshold, meaning a test resolves as soon as its failure rate drops below the activation level. Setting this lower than the activation threshold creates a buffer that prevents tests from flapping between flagged and resolved. For example, if you activate at 30% and resolve at 15%, a test flagged at 30% must improve to below 15% before it's marked healthy again. A test hovering at 20% failure rate stays flagged rather than flipping back and forth. The gap between activation (30%) and resolution (15%) is the buffer zone. A test with a failure rate in this range keeps its current status: a healthy test won't be flagged, but a test already flagged won't be resolved either. ### Window Duration The rolling time window (in hours) over which failure rate is calculated. Only test runs within this window are considered. A shorter window (e.g., 1 hour) reacts quickly to recent failures but may miss patterns that play out over longer periods. A longer window (e.g., 24 hours) smooths out short-term spikes and gives a more stable picture, but takes longer to detect new issues and longer to resolve. ### Minimum Sample Size The minimum number of test runs required within the time window before the monitor will evaluate a test. Tests with fewer runs are skipped entirely. They won't be flagged or resolved until enough data accumulates. This prevents the monitor from making decisions on insufficient data. A test that ran 3 times with 2 failures is a 66% failure rate, but that's not enough data to be confident. The right minimum depends on how often a test actually runs on the branches you're monitoring. To get a sense of run frequency, open the test's **Test History** and filter to the branch you care about — this shows how many runs accumulate over any given period. If your tests run hundreds of times per day, a minimum of 50 to 100 is reasonable. If tests only run a few times per day, a lower minimum may be necessary, but lower minimums mean less statistical confidence. ### Stale Timeout How long (in hours) a flagged test can go without any runs before it's automatically resolved as stale. This clears out tests that have been deleted, renamed, or are no longer part of your test suite. When not set, flagged tests remain in their detected state indefinitely until they run enough times to recover through the normal threshold check. Setting a stale timeout (e.g., 24 hours) keeps abandoned tests from cluttering your test list. To remove a previously set stale timeout, clear the field when editing the monitor. The monitor will then keep tests flagged indefinitely until they recover through the normal threshold check. A test resolved as stale is no longer being tracked by this monitor. If the test starts running again and exceeds the activation threshold, it will be re-flagged. Skipped tests count as not being run. If you have a stale timeout configured and a test starts being skipped rather than executed, the monitor will treat it as having no runs and resolve it as stale once the timeout elapses. ### Branch Scope Which branches the monitor evaluates. You can specify up to 10 branch patterns. Only test runs on matching branches are included in the failure rate calculation. Runs across all matching patterns are pooled together — the failure rate is calculated from the combined set of runs, not evaluated per-pattern individually. This means a monitor scoped to `main` and `release/*` will look at all runs on any of those branches together when determining the failure rate. **Branch pattern syntax.** Branch patterns use glob-style matching with two special characters: | Character | Meaning | Regex equivalent | | --------- | -------------------------------------------- | ---------------- | | `*` | Zero or more of any character, including `/` | `.*` | | `?` | Exactly one of any character | `.` | All other characters are matched literally. Special regex characters (like `.`, `+`, `(`, `)`, `[`, `]`) are treated as literal characters in patterns, not as regex operators. You don't need to escape them. Unlike some glob implementations, `*` matches across `/` separators. The pattern `feature/*` matches both `feature/login` and `feature/api/auth`. **Pattern examples:** | Pattern | Matches | Does not match | | --------------- | ----------------------------------- | ------------------------------------------------------ | | `main` | `main` | `main-v2`, `maint` | | `feature/*` | `feature/login`, `feature/api/auth` | `feature` (no trailing path), `features/x` | | `release-?.?.?` | `release-1.2.3` | `release-10.2.3` (10 is two characters), `release-1.2` | | `*-hotfix` | `prod-hotfix`, `release/v1-hotfix` | `hotfix`, `hotfix-1` | | `*` | All branches | | A pattern with no special characters matches that exact branch name only. For example, `main` matches the branch named `main` and nothing else. **Stable branch patterns.** For your main or stable branch, use the exact branch name: | Your stable branch | Pattern | | ------------------ | --------- | | `main` | `main` | | `master` | `master` | | `develop` | `develop` | **Merge queue branch patterns.** If you use a merge queue, your queue creates temporary branches to test changes before merging. Each merge queue product uses a different branch naming convention: | Merge queue | Branch pattern | Example branches matched | | -------------------- | --------------------- | ------------------------------------------ | | Trunk Merge Queue | `trunk-merge/*` | `trunk-merge/main/1`, `trunk-merge/main/2` | | GitHub Merge Queue | `gh-readonly-queue/*` | `gh-readonly-queue/main/pr-123-abc` | | Graphite Merge Queue | `graphite-merge/*` | `graphite-merge/main/1` | GitLab Merge Trains run on the target branch directly rather than creating separate branches. To monitor merge train runs, scope your monitor to the target branch (e.g., `main`). **Tips for branch scoping:** * You can add up to **10 patterns** per monitor. A test run is included if its branch matches any of the patterns. * Since patterns can't express "everything except a branch," a practical approach is to create **separate monitors**: one scoped to `main` with strict settings, and another scoped to your PR branch naming patterns (e.g., `feature/*`, `fix/*`) with more lenient settings. * `**` is treated as two consecutive `*` wildcards, which is functionally identical to a single `*`. There is no special multi-segment matching behavior. ### Action What happens when the monitor activates on a test. You pick the action at creation and can switch it at any time. **Classify test status (default).** The test's status is set according to the monitor's **detection type**, and restored to healthy when the monitor resolves. The detection type is either: * **Flaky** — for tests that fail intermittently (e.g., 20–50% failure rate). These are typically caused by timing issues, shared state, or non-deterministic behavior. Flaky tests are often quarantined while you investigate the root cause. * **Broken** — for tests that fail consistently at a high rate (e.g., 80%+ failure rate). These usually indicate a real regression — something in the code or environment is genuinely broken and needs a fix. Broken tests represent real failures that should be fixed, not hidden. **Apply labels.** The configured labels are added to the test while the monitor is active. The test's health status is not changed by this monitor. See [Automatic labeling from monitors](../management/test-labels#automatic-labeling-from-monitors) for how to configure and what to expect. ## Preview Panel When creating or editing a failure rate monitor, a preview panel shows which tests the current configuration would flag based on recent data. The panel is split into two sections: **Current** and **Proposed**. * **Current** shows tests flagged by the existing configuration (if editing an existing monitor). * **Proposed** shows tests that would be flagged with the settings currently entered in the form. The Current section is collapsed by default, so the Proposed view is immediately visible when you open the form. ### Status Filter A **status filter dropdown** in the preview panel lets you filter the test list to any combination of statuses: **Healthy**, **Flaky**, and **Broken**. By default, all statuses are shown. Filtering to **Healthy** shows tests that are currently healthy but would be flagged by this monitor — the new coverage it adds beyond tests already detected. Filtering to other statuses, or combining them, adjusts the visible list without affecting the underlying detection counts. When a filter is active, the info tooltip shows "X of Y tests" to indicate how many tests are visible relative to the total matching the configuration. If no tests match the active filter, the empty state includes a hint to clear the filter. The status filter applies to the **Proposed** section. The not-in-window count in the Current section reflects the full unfiltered result set and is not affected by the filter. ## Muting You can temporarily mute a failure rate monitor for a specific test case. See [Muting monitors](./index#muting-monitors) for details. ## Recommended Configurations A common setup is to pair two failure rate monitors — one to catch broken tests quickly and one to catch flaky tests over a longer window: | Monitor | Detection type | Activation threshold | Window | Purpose | | -------------- | -------------- | -------------------- | ----------- | -------------------------------------------------------------------------------------- | | Broken on main | Broken | 80–100% | 1–6 hours | Catch tests that are reliably failing — real regressions that need immediate attention | | Flaky on main | Flaky | 20–50% | 12–72 hours | Catch intermittently failing tests — candidates for investigation or quarantine | You can create as many monitors as you need. For example, you might want separate monitors for your main branch and pull request branches, or different thresholds for different levels of severity. The following sections provide starting points for common scenarios. **Choosing a window:** The window duration should match how often tests run on the branches you're monitoring. A window needs enough runs to reach the minimum sample size before it can flag anything. If tests run infrequently, a longer window is necessary to accumulate enough data. A narrower window reacts more quickly — spikes of failures roll off faster, and tests recover to healthy more quickly once the underlying problem is resolved. ### Main Branch: Catch Flakiness Early Failures on your stable branch are a strong signal. Tests should be passing before code is merged, so failures here are unexpected and likely indicate flakiness. | Setting | Suggested value | Why | | -------------------- | ------------------------------------- | ---------------------------------------------------------------- | | Activation threshold | 10 to 20% | Low threshold catches subtle flakiness early | | Resolution threshold | 5 to 10% | Requires clear improvement before resolving | | Window | 6 to 24 hours | Long enough to accumulate data, short enough to catch new issues | | Min sample size | 20 to 50 | Depends on how often your tests run on main | | Branches | `main` (or `master`, `develop`, etc.) | Use the exact name of your stable branch | ### Pull Requests: Catch Broken Tests On PR branches, tests are expected to fail — that's part of active development. Analyzing failure rate for flakiness on PRs is generally not productive because a new failing test is likely caused by the code change under review, not non-deterministic behavior. Pass-on-retry already handles real flakiness on PRs: if a test fails and then passes on retry within the same commit, it will be detected regardless of branch. If you do want a failure rate monitor on PRs, scope it to catch **broken** tests rather than flaky ones — tests that are consistently failing at a high rate across many PRs, which may indicate a persistent regression or a broken test environment. | Setting | Suggested value | Why | | -------------------- | ------------------------------------ | ----------------------------------------------------------------------------- | | Detection type | Broken | Focus on consistently failing tests, not intermittent ones | | Activation threshold | 70 to 90% | High threshold distinguishes real breakage from expected development failures | | Resolution threshold | 40 to 50% | Wide buffer prevents flapping | | Window | 12 to 24 hours | Longer window smooths out short-lived development failures | | Min sample size | 30 to 100 | Higher minimum avoids flagging tests that only ran a few times on PRs | | Branches | `feature/*`, `fix/*`, `dependabot/*` | Match your team's PR branch naming conventions | Since branch patterns can't express "everything except main," create one monitor scoped to `main` with strict settings and a second monitor scoped to your PR branch naming patterns with more lenient settings. ### Merge Queue: Strict Monitoring Merge queue branches test code that has already passed PR checks. Failures here are suspicious. If you use a merge queue, consider a dedicated monitor with settings similar to or stricter than your main branch monitor. When sizing your window and minimum sample size, consider how many PRs your repo merges per day. For example, if your team merges 10 PRs per day, a 12-hour window will accumulate roughly 5 merge queue runs — setting a minimum sample size of 10 would mean the rule never has enough data to evaluate. Match your minimum sample size to a realistic run count within your chosen window. | Setting | Suggested value | Why | | -------------------- | ---------------------------------------- | --------------------------------------------------------------- | | Activation threshold | 10 to 15% | Low threshold, failures here are unexpected | | Resolution threshold | 5% | Strict recovery | | Window | 6 to 12 hours | Shorter window for faster detection | | Min sample size | 5 to 15 | Size to how many merge queue runs accumulate in your window | | Branches | `trunk-merge/*` or `gh-readonly-queue/*` | Use the pattern for your merge queue provider (see table above) | Common branch patterns for merge queues: | Merge queue | Branch pattern | | ------------------ | --------------------- | | Trunk Merge Queue | `trunk-merge/*` | | GitHub Merge Queue | `gh-readonly-queue/*` | ### Other Patterns * **Release branches:** A monitor scoped to `release/*` with strict thresholds catches flakiness before it ships. * **Nightly or scheduled builds:** If you run comprehensive test suites on a schedule, a monitor with a longer window and higher minimum sample size can catch slow-burn flakiness that doesn't show up in faster CI runs. # Flag as Flaky Source: https://docs.trunk.io/flaky-tests/detection/flag-as-flaky Manually mark a test as flaky from the test detail page Manually mark a test as flaky when you know it's unreliable but automated monitors haven't detected it yet — or when you want to keep a test classified as flaky while monitors consider it healthy. ## When to Use It * A test is intermittently failing but hasn't been flagged by threshold or pass-on-retry monitors. * You want to immediately quarantine a test while investigating. * You've identified a flaky test through code review or local observation. ## How It Works ### Flagging a Test 1. Navigate to the test detail page for the test you want to flag. 2. Click the **Flag as Flaky** button in the header row, next to the status badge. 3. In the popover that appears, optionally add a reason (up to 256 characters) explaining why you're flagging it. 4. Click **Flag** to confirm. Once flagged: * The test is immediately marked as **flaky**, even if no automated monitor has detected it. * An amber banner appears below the header showing who flagged it, when, and the reason (if provided). * The flag is additive — if automated monitors later detect the test as flaky too, both signals coexist. A manual flag does not override a **broken** status. Broken always takes precedence over flaky, so if an active monitor classifies the test as broken, the test shows as broken until that monitor resolves or is [muted](./index#muting-monitors). While a test is broken, the **Flag as Flaky** button is disabled — if you believe the broken classification is incorrect, [mute the monitor](./index#muting-monitors) or update its configuration instead. You can still remove an existing flag while the test is broken. ### Removing the Flag 1. On the test detail page, find the amber "Manually flagged as flaky" banner. 2. Click the **Remove flag** button on the right side of the banner. 3. Confirm by clicking **Remove flag** in the popover. After removing: * The test's status reverts to whatever the automated monitors determine. * If monitors are still detecting the test as flaky, it remains flaky. The flag removal only clears the manual override. ## Relationship to Monitors The "Flag as Flaky" action is separate from automated monitors (threshold-based, pass-on-retry) and does not appear in the Monitors tab, but it participates in the same [status resolution](./index#how-monitors-work) as health classification monitors: the most severe status wins, and broken outranks flaky. If a test's status looks wrong — for example, it shows as broken when you believe it's merely flaky — [mute](./index#muting-monitors) or reconfigure the monitor responsible rather than reaching for the flag. | Scenario | Test status | | --------------------------------------------- | -------------------------------- | | No monitors active, no flag | Healthy | | Flaky monitors active, no flag | Flaky (detected) | | No monitors active, flag set | Flaky (manually flagged) | | Flaky monitors active, flag set | Flaky (both) | | Broken monitor active, flag set | Broken (broken takes precedence) | | Broken monitor resolves or is muted, flag set | Flaky (manually flagged) | | Flag removed, flaky monitors still active | Flaky (detected) | | Flag removed, monitors inactive | Healthy | ## Flag History All flag and unflag actions are recorded as events. You can view the history by opening the Flag History panel from the test detail page. Each entry shows who performed the action, when, and the reason (if one was provided). # Flake Detection Source: https://docs.trunk.io/flaky-tests/detection/index Learn how Trunk detects and labels flaky and broken tests Flake Detection automatically identifies problematic tests in your test suite by monitoring test behavior over time. Instead of a single set of built-in detection rules, Trunk uses **monitors**, independent detectors that each watch for a specific pattern. When a monitor activates on a test, it runs the **action** you configured on the monitor — either classifying the test as flaky or broken, or [applying labels](../management/test-labels#automatic-labeling-from-monitors) to it. ## How Monitors Work Each monitor independently observes your test runs and tracks two states per test: **active** (problematic behavior detected) or **inactive** (no problematic behavior). When a monitor transitions to active, it executes its configured action; when it resolves, it undoes that action (restoring health status, or removing the labels it applied). For monitors whose action is **Classify test status** (referred to below as *health classification monitors*), the test's overall status is determined by combining all such monitors, with the most severe status winning: | Priority | Status | Condition | | -------- | ----------- | ---------------------------------------------------------------------------------------- | | Highest | **Broken** | Any enabled broken-type monitor (failure rate or failure count) is active for this test | | Middle | **Flaky** | Any enabled flaky-type monitor (failure rate, failure count, or pass-on-retry) is active | | Lowest | **Healthy** | No active health classification monitor | If a test triggers both a broken monitor and a flaky monitor simultaneously, it shows as **Broken**. When the broken monitor resolves (e.g., you fix the regression and the failure rate drops), the test transitions to **Flaky** if a flaky monitor is still active, or to **Healthy** if no health classification monitors remain active. A test stays in its detected state until every health classification monitor that flagged it has independently resolved. Monitors configured to apply labels do not contribute to this status calculation — they only add or remove labels. ### Disabling or Deleting a Monitor When you select **Disable** or **Delete** from a monitor's context menu, a confirmation dialog appears first. The dialog describes the concrete effect on affected tests before the change fires. You can re-enable a disabled monitor at any time. When you disable or delete a monitor, it is immediately set to **resolved** for every test case in the repo. For a health classification monitor, this triggers a status re-evaluation for all affected tests: if the disabled monitor was the only active health classification monitor for a test, that test transitions to healthy; if others are still active, the test remains in the most severe active state. For a labeling monitor, the labels it had applied are removed (subject to its **Remove these labels when the monitor resolves** setting). For example, if you have a broken failure rate monitor and a flaky pass-on-retry monitor, and you disable the broken monitor, any test that was only flagged by the broken monitor will become healthy. A test flagged by both will transition from broken to flaky (because pass-on-retry is still active). Each affected test case records a **Monitor disabled** or **Monitor deleted** event in its [Events tab](../dashboard#test-case-details), attributed to the person who performed the action. These events are visible under the **Monitors** filter category and show the same monitor name and type as the original detection events, making it straightforward to trace why a test transitioned back to healthy. ## Monitor Types Trunk groups monitors into two categories based on what they do when they activate: * **Health classification monitors** determine a test's overall health status (healthy, flaky, or broken). When one activates, the test's status changes across the dashboard, CI annotations, and notifications. * **Lifecycle and performance monitors** apply labels to tests based on lifecycle events or performance characteristics. They do not affect health status. These monitors appear in a separate section of the monitors page. ### Health Classification Monitors | Monitor | What it detects | Available actions | Default state | | -------------------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------- | | [**Pass-on-Retry**](./pass-on-retry-monitor) | A test fails then passes on the same commit (retry after failure) | Classify (flaky) or [apply labels](../management/test-labels#automatic-labeling-from-monitors) | Enabled | | [**Failure Rate**](./failure-rate-monitor) | Failure rate exceeds a configured percentage over a time window | Classify (flaky or broken) or [apply labels](../management/test-labels#automatic-labeling-from-monitors) | Disabled | | [**Failure Count**](./failure-count-monitor) | A test accumulates a configured number of failures in a rolling window | Classify (flaky or broken) or [apply labels](../management/test-labels#automatic-labeling-from-monitors) | Disabled | ### Lifecycle and Performance Monitors These monitors apply labels based on lifecycle events or performance characteristics. They do not classify tests as flaky or broken, and they do not contribute to the test's overall health status. | Monitor | What it detects | Available actions | Default state | | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------- | | [**New Test**](./new-test-monitor) | A test case seen for the first time, tracked for a configurable grace period | [Apply labels](../management/test-labels#automatic-labeling-from-monitors) | Disabled | | [**Skipped Test**](./skipped-test-monitor) | A test is consistently skipped across runs within a time window | [Apply labels](../management/test-labels#automatic-labeling-from-monitors) | Disabled | | [**Slow Test**](./slow-test-monitor) | A test's average duration exceeds a configured threshold | [Apply labels](../management/test-labels#automatic-labeling-from-monitors) | Disabled | | [**Timeout Inflation**](./timeout-inflation-monitor) | A test's typical failure duration is much larger than its passing duration, exposing an inflated timeout | [Apply labels](../management/test-labels#automatic-labeling-from-monitors) | Disabled | You can run multiple monitors simultaneously. For example, you might use pass-on-retry to catch classic retry-based flakiness while also running failure rate monitors scoped to different branches. A common pattern is to pair a broken-type failure rate monitor (catching consistently failing tests) with a flaky-type failure rate monitor (catching intermittently failing tests). See [Failure Rate Monitor: Recommended Configurations](./failure-rate-monitor#recommended-configurations) for details. The [failure count monitor](./failure-count-monitor) complements failure rate monitors by reacting to individual failures rather than failure rates. Use it on branches where any failure is a meaningful signal, like `main` or merge queue branches. If you need to manually flag a test that automated monitors haven't caught, use [Flag as Flaky](./flag-as-flaky) from the test detail page. ## Dry-Running with Labels You can preview how a new health classification monitor would behave by deploying it as a labeling monitor first. Because **Apply labels** attaches labels without changing health status, you can let the monitor run on live test data, see which tests it activates on, refine the settings, and only flip it to **Classify test status** once you trust the configuration. The flow is typically: 1. Create the monitor with **Apply labels** and a dedicated label (e.g., `would-be-flaky`). 2. Let the monitor run for a few cycles and observe which tests pick up the label. 3. Refine the settings until the labeled set matches what you want classified. 4. Switch the monitor's action to **Classify test status**. The Preview Panel on each monitor config form shows a static snapshot at configuration time, but a label dry-run validates the monitor against live runs without committing to a status change. ## Branch-Aware Detection Tests often behave differently depending on where they run. Failures on `main` are usually unexpected and signal flakiness. Failures on PR branches may be expected during active development. Merge queue failures are suspicious because the code has already passed PR checks. Rather than applying a single set of branch rules automatically, Trunk gives you control over how detection treats different branches through **branch scoping** on failure rate monitors. You can create separate monitors with different thresholds and windows for your stable branch, PR branches, and merge queue branches. See [Failure Rate Monitor: Recommended configurations](./failure-rate-monitor#recommended-configurations) for specific guidance. Pass-on-retry detection is branch-agnostic. It flags any test that fails and passes on the same commit, regardless of which branch the test ran on. ## Muting Monitors You can temporarily mute a monitor for a specific test case. A muted monitor continues to run and record detections, but it won't contribute to the test's flaky status until the mute expires. This is useful when you know a test is flaky but want to suppress the signal temporarily, for example while a fix is in progress or during a known infrastructure issue. Unlike [Flag as Flaky](./flag-as-flaky), which is a persistent user override, muting preserves the detection history and automatically re-enables itself after the mute period. ### How Muting Works You can mute a monitor from the test case view in the Trunk app. When muting, you choose a duration: | Duration | | -------- | | 1 hour | | 4 hours | | 24 hours | | 7 days | | 30 days | While muted, the monitor is excluded from the test's status calculation. If the muted monitor was the only active health classification monitor, the test transitions from flaky to healthy for the duration of the mute. When the mute expires, the monitor is automatically included in the next status evaluation. If it's still active, the test will be flagged again. You can also unmute a monitor early from the test case view. You can only mute a monitor that has already detected flaky behavior for a test. If a monitor has never been active for a test, the mute option is disabled. ### When to Mute vs. Other Options | Situation | Recommended action | | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Fix is in progress and you want to suppress noise temporarily | **Mute** the monitor for a few days | | Test is flaky but no automated monitor has caught it | Use [**Flag as Flaky**](./flag-as-flaky) to mark it as flaky | | A test shows as **Broken** (or Flaky) and you believe the classification is wrong | **Mute** the monitor that's driving the status, or update its configuration (thresholds, branch scope) so it stops misfiring — a [Flag as Flaky](./flag-as-flaky) can't override a broken status | | You want to stop a monitor from evaluating a test permanently | Adjust the monitor's branch scope or thresholds instead | | You want to suppress all flaky signals for a test | Mute each active monitor individually, or address the root cause | ## Variants If you run the same tests across different environments or architectures, you can use [variants](../reference/cli-reference) to separate these runs into distinct test cases. This lets monitors detect environment-specific flakes. For example, a test might be flaky on iOS but stable on Android. Using variants, monitors isolate flakes on the iOS variant instead of marking the test as flaky across all environments. See the [Trunk Analytics CLI docs](../reference/cli-reference) for details on how to upload with variants. ## Detection Time Detection of flaky tests is run automatically when test uploads are processed. From the time that a test with configured flake detection is uploaded, it will take at most 20 minutes for the flakiness to be detected. # Infrastructure Failure Protection Source: https://docs.trunk.io/flaky-tests/detection/infrastructure-failure-protection Prevent false Trunk Flaky Tests detections during CI outages and infrastructure failures. When infrastructure issues like database outages, network problems, or CI runner failures cause a large number of tests to fail simultaneously, retrying those tests can trigger mass false flaky detections. Infrastructure Failure Protection identifies these scenarios and excludes them from flakiness detection. Configuration for Infrastructure Failure Protection and Failure Threshold ## How it works Trunk monitors the failure rate of each test upload. If the percentage of failing tests exceeds your configured threshold, that upload is flagged as an infrastructure failure and excluded from Trunk Flaky Tests detection. For example, if your threshold is set to 80% and a CI run has 85% of tests failing (this could be due to a database being unavailable or similar infrastructure issue, etc.), that entire run will be excluded from Trunk Flaky Tests detection. This prevents tests from being incorrectly marked as flaky when they're retried and pass. Uploads excluded due to infrastructure failure protection will appear in the **Uploads** tab with the status **"Upload Skipped Due to Infrastructure Error."** ## Configuring Infrastructure Failure Protection Administrators can enable this feature in repository settings: 1. Click on your profile and open **Settings** 2. Select your repository from the left navigation 3. Locate **Infrastructure Failure Protection** under Flaky Tests 4. Toggle **Enable Protection** to on 5. Set your **Failure Threshold** percentage (default: 80%) The threshold determines what percentage of test failures triggers infrastructure failure detection. A threshold of 80% is a reasonable starting point for most repositories—adjust based on your test suite size and typical failure patterns. ## Trade-offs When a test upload is excluded due to infrastructure failure protection: **Uploads are still recorded:** * The upload appears in the Uploads tab with "Upload Skipped Due to Infrastructure Error" status **Failures are excluded from analysis:** * Failures do not impact flakiness detection * Failures do not contribute to failure rate metrics * Stack traces from that run are not visible in test case history This is generally an acceptable trade-off since infrastructure failures don't reflect the actual behavior of individual test cases. ## When to use this Enable Infrastructure Failure Protection if you experience: * Database or service outages that cause mass test failures * CI runner infrastructure issues * Network failures during test runs * Any scenario where a large percentage of tests fail for reasons unrelated to code changes If you're using test quarantine, this feature is especially important to prevent infrastructure issues from automatically quarantining large numbers of tests. ## Next steps * Learn more about how Trunk [detects flaky tests](./index) * View excluded uploads in the Uploads tab * Configure [test quarantine](../quarantining/#enable-quarantining) to automatically skip flaky tests # New Test Monitor Source: https://docs.trunk.io/flaky-tests/detection/new-test-monitor Track recently added tests and apply labels until they have an established history. The new test monitor identifies test cases the first time they are seen in your test uploads and keeps them labeled for a configurable number of days. It is designed for visibility, not classification: the monitor does not mark tests as flaky or broken. Instead, it applies the labels you configure so your team can distinguish brand-new tests from established ones during triage. ## When to Use This Monitor * **New test tracking:** Apply a `new-test` label automatically so reviewers know a failing test may simply lack history. * **Coverage audits:** Identify which tests were added in the last sprint without manually diffing test suites. * **Noise reduction during ramp-up:** Suppress new tests from triggering alerts by combining this monitor's label with quarantine or alert filter rules. ## How It Works When a test upload contains a test case ID that has never appeared before, the monitor records its first-seen timestamp. For the next `newDays` days, that test is considered "active" by this monitor and the configured labels are applied. After `newDays` days have passed since the first observation, the monitor resolves the test and the labels are removed. The monitor runs every five minutes. Detection lookback is capped at six hours per run to keep each pass bounded, so a test seen for the first time will be labeled within at most twenty minutes of its upload being processed. ## Configuration | Setting | Description | Default | | -------- | ----------------------------------------------------------------------------------------- | ------------ | | New days | Number of days after first observation before the monitor resolves and labels are removed | Required | | Action | Apply labels (the only available action — this monitor does not classify) | Apply labels | ### New Days Set `newDays` to how long you want the "new" label to stay on a test. A value of 7 means any test added in the last week carries the label. A value of 30 gives a full month of ramp-up coverage before the label drops. ### Action The new test monitor is a performance-type monitor. It applies labels only and does not change a test's health status (flaky or broken). Choose which labels to apply in the monitor configuration. When the monitor resolves, those labels are removed according to the monitor's label removal setting. ## Resolution The monitor resolves a test automatically once `newDays` days have elapsed since `first_seen_at`. There is no manual resolution step — once the window passes, the label is removed on the next detection cycle. If a test is deleted and re-uploaded with the same test case ID, the original `first_seen_at` timestamp is used. The monitor does not reset the clock for re-appearing tests. ## Choosing Between Monitors | Goal | Recommended monitor | | -------------------------------------------- | --------------------- | | Label brand-new tests for a grace period | New test monitor | | Detect tests that consistently skip runs | Skipped test monitor | | Flag tests whose runtime exceeds a threshold | Slow test monitor | | Detect tests that fail then pass on retry | Pass-on-retry monitor | | Alert on tests failing at a sustained rate | Failure rate monitor | # Pass-on-Retry Monitor Source: https://docs.trunk.io/flaky-tests/detection/pass-on-retry-monitor Detect tests that fail then pass on retry within the same commit The pass-on-retry monitor detects the most common flakiness pattern: a test fails, is retried, and passes on the same commit. This indicates the failure wasn't caused by a code change and that the test is unreliable. By default, this monitor evaluates test runs on all branches. You can scope it to specific branches to focus detection where pass-on-retry behavior is actually meaningful. ## How It Works The monitor continuously scans your test runs looking for commits where a test has both a failure and a success. When it finds one, the monitor activates on that test and runs its configured [action](#action): by default, the test is flagged as flaky. Once active, the monitor stays active on the test until no pass-on-retry behavior has been observed for a configurable recovery period. This prevents tests from bouncing between flaky and healthy if they only fail intermittently. A test fails on attempt 1 and passes on retry on the same commit, gets flagged flaky, then passes on each of the next 7 days and resolves to healthy. ### Example Your CI retries failed tests automatically. On commit `abc123`: 1. `test_login` fails on the first attempt 2. `test_login` passes on retry The monitor detects that `test_login` had both a failure and success on the same commit and flags it as flaky. Seven days later (assuming default settings), if `test_login` hasn't exhibited any more retry behavior, the monitor resolves and the test returns to healthy. ## Configuration | Setting | Description | Default | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | | **Enabled** | Whether the monitor is active | On | | **Recovery days** | Days without pass-on-retry behavior before a test is resolved as healthy. Range: 1 to 15 days. | 7 | | **Branch scope** | Which branches the monitor evaluates. Accepts branch names and glob patterns. | All branches (`*`) | | **Minimum POR count** | The minimum number of distinct commits that must show pass-on-retry behavior before the monitor activates. Increase this to reduce noise from occasional retries. | 1 | | **Action** | What happens when the monitor activates. Either classify the test as flaky or apply labels. | Classify as flaky | ### Multiple monitors per repository You can create more than one pass-on-retry monitor for the same repository. Each monitor runs independently with its own settings, so you can apply different recovery periods, branch scopes, or actions to different parts of your test suite. A common pattern is to run one monitor scoped to stable branches (like `main`) with a shorter recovery period for fast feedback, and a second monitor scoped to `release/*` branches with a longer recovery period for builds where intermittent failures are more expensive to re-investigate. To add a monitor, navigate to **Settings** in the Trunk web app, open the repository, open the **Monitors** tab, and click **Add monitor**. Each monitor you create appears as a separate row in the monitors table and can be individually enabled, disabled, or deleted. The repository Monitors tab showing a pass-on-retry monitor, two failure-rate monitors, and lifecycle monitors, each as a separate row with an Add Monitor control. The repository Monitors tab showing a pass-on-retry monitor, two failure-rate monitors, and lifecycle monitors, each as a separate row with an Add Monitor control. ### What Recovery Days Controls A shorter recovery period (e.g., 1 to 3 days) returns tests to healthy quickly, which is useful if you fix flaky tests promptly and want fast feedback. A longer recovery period (e.g., 10 to 15 days) is more conservative. It keeps tests flagged longer to account for flaky behavior that only surfaces occasionally. ### Branch Scope Use the **Branch scope** setting to restrict the monitor to a specific set of branches. This is useful when PR branches generate too much noise. CI often retries tests on pull request branches automatically; if those retries aren't meaningful signals for your team, you can limit detection to stable branches like `main`. Branch scope uses the same glob syntax as [failure rate monitor branch patterns](./failure-rate-monitor#branch-pattern-syntax) and accepts up to 10 patterns. Type a pattern and press **Enter** or comma to add it as a chip. For example: * `main`: only stable branch runs * `main` and `release/*`: stable plus release branches * `*` (default): all branches Changes to branch scope take effect for newly detected events. Previously detected flaky tests are not re-evaluated. ### Minimum POR Count By default, a single commit where a test fails and then passes on retry is enough to activate the monitor. A minimum of 1 means: as soon as one commit shows the pattern, the test is flagged. Raising the minimum (for example, to 2 or 3) requires the same test to show that pattern on multiple distinct commits within the detection window before the monitor activates. This reduces false positives in environments where CI retries most failures automatically, producing one-off retry events for otherwise reliable tests. Set a higher minimum when your retry rate is high enough that a single commit's retry event is not a reliable flakiness signal. ### Action You pick the action at creation and can switch it at any time. * **Classify test status** (default) — flags the test as **flaky** while the monitor is active and restores it to healthy when the monitor resolves. Pass-on-retry only classifies as flaky; there is no broken option. * **Apply labels** — adds the configured labels to the test while the monitor is active. The test's health status is not changed by this monitor. See [Automatic labeling from monitors](../management/test-labels#automatic-labeling-from-monitors). ## When Detection Happens Pass-on-retry detection runs continuously as new test results arrive. A failure and its corresponding retry don't need to arrive at exactly the same time. Resolution is evaluated daily. If a test hasn't shown pass-on-retry behavior within the recovery window, it resolves on the next daily check. ## Muting You can temporarily mute the pass-on-retry monitor for a specific test case. See [Muting monitors](./index#muting-monitors) for details. ## Edge Cases **Failure without a retry yet:** If a test fails but hasn't been retried, no detection occurs. If the retry arrives later (even hours or days later on the same commit), the monitor will pick it up. **Multiple retries on one commit:** If a test fails and is retried several times on the same commit, the monitor treats it as a single detection for that commit. # Skipped Test Monitor Source: https://docs.trunk.io/flaky-tests/detection/skipped-test-monitor Detect tests that are consistently being skipped and apply labels to surface them for review. The skipped test monitor tracks test cases that accumulate a configured number of skipped runs within a time window. It applies labels to those tests so your team can identify tests that are being silently ignored, rather than classifying them as flaky or broken. ## When to Use This Monitor * **Surface suppressed tests:** Find tests that someone marked as skip (`.skip`, `xtest`, `xit`) and never re-enabled. * **Track intentional skips:** Apply a `skipped` label so dashboards reflect tests that are excluded from runs, giving a more accurate picture of suite coverage. * **Scope to specific branches:** Detect skips on main or release branches where a skipped test represents a gap in coverage rather than a development convenience. ## How It Works The monitor counts the number of skipped runs for each test case within a configurable time window (in minutes). When a test accumulates at least `minSkippedCount` skipped runs in that window, the monitor activates and applies the configured labels. Resolution occurs after `resolutionDays` days pass with no new skipped runs recorded for that test on any monitored branch. ## Configuration | Setting | Description | Default | | ----------------- | ------------------------------------------------------------------------- | ------------ | | Window | Time window (minutes) over which skipped runs are counted | Required | | Min skipped count | Number of skipped runs in the window required to activate | Required | | Resolution days | Days without a new skipped run before the monitor resolves | Required | | Branch scope | Branch names or glob patterns to monitor | All branches | | Action | Apply labels (the only available action — this monitor does not classify) | Apply labels | ### Window The time window controls how far back the monitor looks when counting skipped runs. A shorter window (e.g., 60 minutes) catches tests skipped in a burst around a specific CI run. A longer window (e.g., 2 days, 2880 minutes) catches tests that are habitually skipped across many runs. ### Min Skipped Count Set this to 1 to flag any test the moment it skips a single run in the window. Set it higher to require repeated skips, filtering out tests that are skipped once for a legitimate reason (such as a flaky environment that resolves itself). ### Resolution Days After a test stops being skipped, the monitor waits `resolutionDays` before resolving. This prevents the label from flickering on and off for tests that skip intermittently. ### Branch Scope Use branch patterns to limit detection to branches where a skipped test is significant. For example, monitoring only `main` means tests skipped on feature branches do not trigger the monitor. ## Choosing Between Monitors | Goal | Recommended monitor | | -------------------------------------------- | --------------------- | | Detect tests consistently being skipped | Skipped test monitor | | Track recently added tests | New test monitor | | Flag tests whose runtime exceeds a threshold | Slow test monitor | | Detect tests that fail then pass on retry | Pass-on-retry monitor | | Alert on tests failing at a sustained rate | Failure rate monitor | # Slow Test Monitor Source: https://docs.trunk.io/flaky-tests/detection/slow-test-monitor Flag tests whose duration percentile exceeds a configured threshold. The slow test monitor detects test cases whose measured duration exceeds a threshold you set, evaluated over a configurable percentile, time window, and sample size. It applies labels to slow tests so your team can identify and prioritize performance improvements without classifying tests as flaky or broken. ## When to Use This Monitor * **Identify tests slowing down CI:** Surface the specific tests adding the most wall time to your pipeline. * **Enforce duration budgets:** Label any test that exceeds an acceptable runtime so it gets reviewed before merging. * **Track regressions:** Catch tests that were fast but became slow after a code change. ## How It Works The monitor evaluates test duration at a configured percentile across runs in a rolling time window. When a test's percentile duration meets or exceeds the configured threshold and enough sample runs have been collected, the monitor activates and applies the configured labels. Resolution happens when the test's measured duration drops back below the threshold over subsequent runs. If `staleAfterMinutes` is set, the monitor also resolves any active test that has had no recent runs on monitored branches — this prevents labels from persisting on tests that have been removed from the suite. Once the monitor activates, detection evidence (the specific runs that triggered it) is visible in the **Events** tab on the test details page. ## Configuration | Setting | Description | Default | | ------------------ | -------------------------------------------------------------------------------------------- | ------------ | | Duration threshold | Duration (milliseconds) at the configured percentile that triggers detection | Required | | Percentile | Which duration percentile to evaluate, as a value between 0 and 1 (for example, 0.5 for p50) | Required | | Window | Time window (minutes) over which duration is measured | Required | | Sample size | Minimum number of runs required before the monitor can activate | Required | | Stale after | Minutes without any run on monitored branches before an active test resolves (optional) | Disabled | | Branch scope | Branch names or glob patterns to monitor | All branches | | Action | Apply labels (the only available action — this monitor does not classify) | Apply labels | ### Duration Threshold Set the threshold in milliseconds. With the percentile set to 0.5 (p50), a value of 5000 flags any test whose median run exceeds 5 seconds. Tune this based on your acceptable CI budget — tighter thresholds surface more tests but may require more review bandwidth. ### Percentile The percentile controls which point on the duration distribution is compared to the threshold. * **p95** means 95% of a test's runs are at or below the measured duration. A test only needs occasional slow runs to push its p95 above the threshold, making this a less strict setting that catches intermittent slowness. * **p50** means 50% of a test's runs are at or below the measured duration. A test must have the majority of its runs be slow before it triggers, making this a stricter setting that filters out one-off spikes. Choose a higher percentile (p75, p90, p95) to catch tests with sporadic slowness. Choose a lower percentile (p50) to surface only tests that are consistently slow. ### Window and Sample Size The window controls how far back duration samples are collected. Sample size sets the minimum number of runs needed before the monitor will activate. This prevents a single slow run from triggering the monitor on a test with no history. For example, a window of 1440 minutes (one day) and a sample size of 5 means the monitor evaluates the configured percentile over the last day's runs and requires at least five before drawing a conclusion. The preview panel shows up to 1000 tests that ran within the configured window. ### Stale After When set, any test that has been active (labeled slow) but stops running on monitored branches for `staleAfterMinutes` minutes will be automatically resolved. Use this to clean up labels after a slow test is removed from the suite or renamed. ### Branch Scope Scope the monitor to branches where test duration matters most, such as `main` or merge queue branches. Tests running on feature branches may have intentionally limited execution or variable infrastructure and may not represent a genuine slowness concern. ## Choosing Between Monitors | Goal | Recommended monitor | | ------------------------------------------------------------- | -------------------------------------------------------- | | Flag tests that are taking too long | Slow test monitor | | Flag tests whose timeouts are far larger than they need to be | [Timeout inflation monitor](./timeout-inflation-monitor) | | Track recently added tests | New test monitor | | Detect tests consistently being skipped | Skipped test monitor | | Detect tests that fail then pass on retry | Pass-on-retry monitor | | Alert on tests failing at a sustained rate | Failure rate monitor | # The Importance of PR Test Results Source: https://docs.trunk.io/flaky-tests/detection/the-importance-of-pr-test-results Why uploading test results from pull requests is required for accurate flaky test detection, quarantining, and impact measurement. Uploading test results from pull requests (PRs) is a critical step for enabling Trunk Flaky Tests. This data provides a primary signal for *detecting* flaky tests and is the key metric for *measuring* their impact. Without it, you lose the most significant source of information for identifying and prioritizing these disruptive tests. Here's a breakdown of the key features that depend on PR test results: ## Crucial Flakiness Detection The most common and critical signal for identifying a flaky test happens on PRs. Flakiness is detected when a test produces different results on the same git commit. This typically happens when: 1. A developer opens a PR, and a test fails. 2. The developer reruns the exact same tests without changing any code. 3. The test now passes. This "fail then pass" sequence on the same commit is a clear indication of non-deterministic, or "flaky," behavior. Since the majority of test runs occur during the development and review cycle, PRs are the largest source of this vital signal. ## Measuring Test Impact The Flaky Tests dashboard is designed to help you prioritize which tests to fix first. The single most important metric for this is `PRs Impacted`. By default, the overview table is sorted by this metric because it's the best way to measure a flaky test's true impact on developer productivity. If you don't upload test results from PRs: * The `PRs Impacted` count for every test will be zero. * You will have no way to determine which flaky tests are causing the most disruption. * You lose the ability to prioritize fixes based on real-world data, potentially wasting time on less important issues. ## Unblocking Developers with Quarantining Quarantining is one of the most important features of Trunk Flaky Tests. Its core purpose is to prevent known flaky tests from blocking developers and breaking CI pipelines, especially merge queues. The entire quarantining workflow is predicated on analyzing test results from PRs. Without PR data, you cannot: * **Identify tests as flaky from PR test runs:** The system needs to see a test pass and fail on the same commit (a signal primarily gathered from PRs) to classify it as flaky. * **Apply Quarantine Logic at Runtime:** Uploading a test result and checking if it should be quarantined are part of the same, single step in your CI job. When a test fails on a PR, the `Trunk Analytics CLI` uploads the failure and, in the same operation, checks with the Trunk service to see if that test is on the quarantine list. If it is, the CLI overrides the job's exit code, allowing the build to pass. Without running the `Trunk Analytics CLI` on your PR jobs, this real-time check cannot occur, and even known flaky tests will continue to block your PRs. ## Immediate CI Feedback and Error Summaries The `Trunk Analytics CLI` provides a detailed summary directly in the CI job's output log. This is the fastest, most immediate feedback a developer gets about their test run. Without uploading PR results, you lose: * A Clear Test Report Summary: A quick overview of `Total`, `Pass`, `Fail`, and `Quarantined` tests. * In-Log Failure Details: A snippet of the stack trace and assertion error for any failed test, providing immediate context without digging through full CI logs. * Actionable Exit Codes: The CLI intelligently determines the job's outcome. * When a real test fails, it exits with a non-zero code: `Not all test failures were quarantined, using exit code 1 from command` * When *only* a known flaky test fails, it passes the job: `All test failures were quarantined, overriding exit code to be exit_success` This immediate, in-CI feedback loop is invaluable for developers trying to quickly understand why their build failed. ## Enabling Developer Productivity Features Trunk Flaky Tests offers features directly within the developer workflow that depend entirely on PR data, most significantly the automated pull request comment. These comments provide a summary of all tests run on a specific PR, highlighting failures and indicating whether they are due to a known flaky test. This feature prevents developers from wasting time investigating a failure that is already identified as flaky. Without uploading PR test results, this valuable, time-saving context is completely lost. ## Next Steps: Enable PR Uploads Now that you understand why uploading test results from pull requests is essential, the next step is to configure your CI pipeline. This single step is the key to accurate flakiness detection, true impact measurement, and features like quarantining. Our documentation provides step-by-step guides for all major CI providers to make this setup simple. [Find your CI provider and start uploading test results](../get-started/ci-providers/index) # Timeout Inflation Monitor Source: https://docs.trunk.io/flaky-tests/detection/timeout-inflation-monitor Flag tests whose failure times sit far above their passing times, exposing timeouts that have ratcheted up beyond what the test actually needs. The timeout inflation monitor detects tests whose failure durations are much larger than their passing durations. When a test consistently passes in a few seconds at p95 but takes ten times longer to fail, its failures aren't slow runs of a working test - they're a broken test sitting on an inflated timeout. The monitor surfaces these tests so you can bring the timeout down to something anchored in reality and get fast failure signal back. ## When to Use This Monitor * **Tighten inflated timeouts:** Find tests where the configured timeout is far larger than the test ever needs when healthy, so you can ratchet the timeout back down. * **Speed up broken-build feedback:** Cut the wall-clock cost of a broken test that fails, retries, and hangs against its timeout on every attempt. * **Audit Playwright and other UI automation suites:** These suites tend to accumulate the largest timeouts and benefit the most from surfacing inflation. ## How It Works For each test case, the monitor looks at recent runs within a configurable window and computes two durations: * The **passing duration** at a configured percentile (default p95) — a conservative upper bound on how long a healthy run takes. * The **failing duration** at a configured percentile (default p50) — the typical case when the test goes red. If the failing duration is at least X times larger than the passing duration, and the absolute gap between the two exceeds the minimum absolute gap, the monitor activates and applies the configured labels. Stacking the slowest reasonable success against the typical failure means a single slow outlier can't fool the detector - the failures have to consistently land above the passes. ## Configuration | Setting | Description | Default | | ---------------- | --------------------------------------------------------------------------------------------------------------- | ------------ | | Pass percentile | Percentile of passing-run durations used as the healthy upper bound, as a value between 0 and 1 | 0.95 | | Fail percentile | Percentile of failing-run durations compared against the passing baseline | 0.5 | | Activation ratio | How many times larger the failing percentile must be than the passing percentile to activate | 2 | | Min absolute gap | Minimum absolute gap (milliseconds) between the failing and passing percentiles before the monitor can activate | 3000 | | Min pass samples | Minimum number of passing runs required inside the window before the monitor can activate | 5 | | Min fail samples | Minimum number of failing runs required inside the window before the monitor can activate | 3 | | Window | Time window (hours) over which passing and failing durations are collected | 168 | | Resolution ratio | Ratio at or below which an active test automatically resolves | 1.5 | | Branch scope | Branch names or glob patterns to monitor | All branches | | Action | Apply labels (the only available action — this monitor does not classify) | Apply labels | ### Pass and Fail Percentiles The pass percentile controls what counts as a realistic upper bound on a healthy run. p95 means 95% of a test's passing runs finish at or below the measured duration, so it captures the slowest reasonable success without being thrown off by a single outlier. The fail percentile controls what counts as a typical failure. p50 means half of a test's failing runs finish at or below the measured duration, so a small number of unusually fast failures can't hide a broken test that usually hangs on its timeout. Using p95 for passes and p50 for failures is deliberately conservative: it compares the slowest reasonable success against the typical failure and requires a clean gap between the two. ### Activation Ratio and Minimum Absolute Gap The activation ratio is how much larger the fail percentile has to be than the pass percentile before the monitor flags the test. The default of 2 means failures have to typically take at least twice as long as the slowest reasonable pass. Raise it to only surface the worst offenders; lower it to catch milder inflation earlier. The minimum absolute gap is a floor in milliseconds so tiny durations don't trip the monitor. A test that passes in 10ms and fails in 30ms is technically a 3x ratio but not worth flagging. The default of 3000ms keeps sub-second tests quiet while still catching the multi-second inflation that dominates real CI cost. ### Sample Sizes and Window The window is how far back the monitor looks for passing and failing runs. The default of 168 hours (one week) keeps the signal tied to recent behavior rather than ancient history. The minimum pass and fail sample sizes prevent the monitor from acting on thin data. Defaults are 5 passes and 3 failures inside the window, so a test needs enough of both outcomes for the percentile comparison to be meaningful. ### Resolution Ratio Once a test is active, the monitor watches the fail/pass ratio on subsequent runs. When the ratio drops to or below this ratio, the monitor resolves the test and removes the labels it applied. The default of 1.5 means the test has to come back well under the activation threshold - not just barely - before it clears, which prevents flapping around the activation line. ### Branch Scope Scope the monitor to branches where timeout inflation matters most, such as `main` or merge queue branches. Feature branches often have intentionally partial test runs or unusual infrastructure and are less useful for measuring inflation. ## What to Do About an Inflated Timeout When the monitor flags a test, the fix is usually to bring the timeout down to something anchored in the test's real behavior. If the test passes in 2 seconds at p95, it does not need a 60 second timeout — a 3 second timeout gives it 50% more time than it ever uses when healthy, and future breakages will fail fast instead of hanging against the old ceiling. Bringing the timeout down turns a three-minute retry-and-hang cycle into a few seconds of actual signal, which is the point of the test suite in the first place. # Atlassian Bamboo Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/atlassian-bamboo Configure Atlassian Bamboo to upload test results to Trunk Flaky Tests Trunk Flaky Tests integrates with your CI by adding a step in your Bamboo Plans to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step as [Bamboo plan variables](https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html). Name them `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively, and mark `TRUNK_API_TOKEN` as a **Secret** variable in the Bamboo UI to prevent it from appearing in build logs. ## Upload to Trunk Add an `Upload Test Results` step after running tests in each of your Bamboo jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your [stable branches](../../detection#stable-branches), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection#stable-branches), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection) ### Example Bamboo Plan Spec The following is an example of a [Bamboo Plan Spec](https://confluence.atlassian.com/bamboo/bamboo-specs-894743906.html) that uploads test results after your tests run. The upload step is placed under `final-tasks` so it runs even when tests fail. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [frameworks](../frameworks/) docs. ```yaml XML theme={null} version: 2 plan: project-key: key: name: Run Tests and Upload to Trunk.io Run Tests and Upload to Trunk: key: tasks: - checkout: description: Checkout Source Code - script: name: Run Tests body: | # Your test command here final-tasks: - script: name: Upload Test Results to Trunk.io body: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload \ --junit-paths "" \ --org-url-slug ${bamboo.TRUNK_ORG_URL_SLUG} \ --token ${bamboo.TRUNK_API_TOKEN} variables: TRUNK_ORG_URL_SLUG: TRUNK_API_TOKEN: ``` ```yaml Bazel theme={null} version: 2 plan: project-key: key: name: Run Tests and Upload to Trunk.io Run Tests and Upload to Trunk: key: tasks: - checkout: description: Checkout Source Code - script: name: Run Tests body: | # Your test command here final-tasks: - script: name: Upload Test Results to Trunk.io body: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload \ --bazel-bep-path \ --org-url-slug ${bamboo.TRUNK_ORG_URL_SLUG} \ --token ${bamboo.TRUNK_API_TOKEN} variables: TRUNK_ORG_URL_SLUG: TRUNK_API_TOKEN: ``` ```yaml XCode theme={null} version: 2 plan: project-key: key: name: Run Tests and Upload to Trunk.io Run Tests and Upload to Trunk: key: tasks: - checkout: description: Checkout Source Code - script: name: Run Tests body: | # Your test command here final-tasks: - script: name: Upload Test Results to Trunk.io body: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload \ --xcresult-path \ --org-url-slug ${bamboo.TRUNK_ORG_URL_SLUG} \ --token ${bamboo.TRUNK_API_TOKEN} variables: TRUNK_ORG_URL_SLUG: TRUNK_API_TOKEN: ``` ### Uploading from Pull Request Builds To detect flaky tests on pull requests, configure your plan to create [plan branches](https://confluence.atlassian.com/bamboo/using-plan-branches-289276872.html) for pull requests. Add the following to your Plan Spec: ```yaml theme={null} branches: create: for-pull-request: accept-fork: false ``` Bamboo automatically sets the `bamboo_repository_pr_key` variable on PR builds, which the Trunk Analytics CLI uses to associate uploads with the correct pull request. **PR number not detected?** If your Bamboo setup does not set `bamboo_repository_pr_key`, you can override it by passing the `--pr-number` flag or setting the `TRUNK_PR_NUMBER` environment variable when running the upload command. The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # Azure DevOps Pipelines Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/azure-devops-pipelines Upload test results from Azure DevOps Pipelines to Trunk for flaky test detection. Trunk Flaky Tests integrates with your CI by adding a step in your Azure DevOps Pipelines to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step in your Azure DevOps Pipelines as new variables named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an upload step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Add Uploader to Testing Pipelines The following is an example of a workflow step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [Test Frameworks](/flaky-tests/get-started/frameworks) docs. ```yaml XML theme={null} trigger: - main pool: vmImage: ubuntu-latest steps: # ... Omitted steps - script: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --junit-paths "" \ --org-url-slug $(TRUNK_ORG_URL_SLUG) \ --token $(TRUNK_API_TOKEN) condition: always() # this should always run displayName: Upload test results to Trunk.io ``` ```yaml Bazel theme={null} trigger: - main pool: vmImage: ubuntu-latest steps: # ... Omitted steps - script: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --bazel-bep-path \ --org-url-slug $(TRUNK_ORG_URL_SLUG) \ --token $(TRUNK_API_TOKEN) condition: always() # this should always run displayName: Upload test results to Trunk.io ``` ```yaml XCode theme={null} trigger: - main pool: vmImage: ubuntu-latest steps: # ... Omitted steps - script: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --xcresult-path \ --org-url-slug $(TRUNK_ORG_URL_SLUG) \ --token $(TRUNK_API_TOKEN) condition: always() # this should always run displayName: Upload test results to Trunk.io ``` ```yaml RSpec plugin theme={null} trigger: - main pool: vmImage: ubuntu-latest steps: # ... Omitted steps - script: | TRUNK_ORG_URL_SLUG=$(TRUNK_ORG_URL_SLUG) \ TRUNK_API_TOKEN=$(TRUNK_API_TOKEN) \ bundle exec rspec displayName: Run RSpec tests and upload results to Trunk.io ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. [Learn more about cleaning up artifacts in Azure DevOps Pipelines](https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/pipeline-options-for-git?view=azure-devops\&tabs=yaml#clean-the-local-repo-on-the-agent) ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # BitBucket Pipelines Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/bitbucket-pipelines Upload test results from Bitbucket Pipelines to Trunk for flaky test detection. Trunk Flaky Tests integrates with your CI by adding a step in your BitBucket Pipelines to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step in your BitBucket as a new variable named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an `after-script` step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Add Uploader to Testing Pipelines The following is an example of a workflow step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the JUnit XML files the uploader needs, see the instructions for your test framework in the [Test Frameworks](/flaky-tests/get-started/frameworks) docs. ```yaml XML theme={null} image: pipelines: default: - step: # ... omitted setup and build steps - step: name: Run Tests and Upload Results script: - after-script: # trunk upload runs even if the test script fails - | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --junit-paths "**/junit.xml" \ --org-url-slug $TRUNK_ORG_URL_SLUG \ --token $TRUNK_API_TOKEN ``` ```yaml Bazel theme={null} image: pipelines: default: - step: # ... omitted setup and build steps - step: name: Run Tests and Upload Results script: - after-script: # trunk upload runs even if the test script fails - | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --bazel-bep-path \ --org-url-slug $TRUNK_ORG_URL_SLUG \ --token $TRUNK_API_TOKEN ``` ```yaml XCode theme={null} image: pipelines: default: - step: # ... omitted setup and build steps - step: name: Run Tests and Upload Results script: - after-script: # trunk upload runs even if the test script fails - | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --xcresult-path \ --org-url-slug $TRUNK_ORG_URL_SLUG \ --token $TRUNK_API_TOKEN ``` ```yaml RSpec plugin theme={null} image: pipelines: default: - step: # ... omitted setup and build steps - step: name: Run Tests and Upload Results script: - | TRUNK_ORG_URL_SLUG=$TRUNK_ORG_URL_SLUG \ TRUNK_API_TOKEN=$TRUNK_API_TOKEN \ bundle exec rspec ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. You can do this by omitting the `artifacts` definitions in the test steps of your configuration. [Learn more about artifacts in BitBucket Pipelines](https://support.atlassian.com/bitbucket-cloud/docs/use-artifacts-in-steps/). ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # Buildkite Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/buildkite Configure Buildkite jobs to upload test results to Trunk Flaky Tests Trunk Flaky Tests integrates with your CI by adding a step in your Buildkite Pipelines to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step in your as a new [Buildkite CI secret](https://buildkite.com/docs/pipelines/security/secrets/managing) named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an `Upload Test Results` step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Example Buildkite Pipeline The following is an example of a Buildkite step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [frameworks](../frameworks/) docs. ```yaml XML theme={null} steps: - label: Run Tests command: ... key: tests - label: Upload Test Results to Trunk.io commands: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --junit-paths "" --org-url-slug --token $TRUNK_API_TOKEN key: upload depends_on: - tests ``` ```yaml Bazel theme={null} steps: - label: Run Tests command: ... key: tests - label: Upload Test Results to Trunk.io commands: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --bazel-bep-path --org-url-slug --token $TRUNK_API_TOKEN key: upload depends_on: - tests ``` ```yaml XCode theme={null} steps: - label: Run Tests command: ... key: tests - label: Upload Test Results to Trunk.io commands: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --xcresult-path --org-url-slug --token $TRUNK_API_TOKEN key: upload depends_on: - tests ``` ```yaml RSpec plugin theme={null} steps: - label: Run Tests and Upload Results to Trunk.io command: TRUNK_ORG_URL_SLUG=$TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN=$TRUNK_API_TOKEN bundle exec rspec key: tests ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # CircleCI Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/circleci Configure CircleCI jobs to upload test results to Trunk Flaky Tests Trunk Flaky Tests integrates with your CI by adding a step in your CircleCI Pipelines to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store your Trunk slug and API token in your CircleCI project settings under **Environment Variables** as new variables named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an `Upload Test Results` step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your main or [stable branches](../../detection/), for example, `main`, `master`, or `develop`. The Trunk Analytics CLI automatically detects PR context from CircleCI environment variables, including the pull request number. No additional configuration is needed to associate test uploads with the correct PR in Trunk. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Example CircleCI workflow The following is an example of a workflow step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [Test Frameworks](/flaky-tests/get-started/frameworks) docs. ```yaml XML theme={null} jobs: test-node: # Install node dependencies and run tests executor: node/default steps: - run: name: Run Tests command: ... - run: name: Upload Test Results to Trunk.io command: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --junit-paths "**/junit.xml" --org-url-slug --token ${TRUNK_API_TOKEN} ``` ```yaml Bazel theme={null} jobs: test-node: # Install node dependencies and run tests executor: node/default steps: - run: name: Run Tests command: ... - run: name: Upload Test Results to Trunk.io command: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --bazel-bep-path --org-url-slug --token ${TRUNK_API_TOKEN} ``` ```yaml XCode theme={null} jobs: test-node: # Install node dependencies and run tests executor: node/default steps: - run: name: Run Tests command: ... - run: name: Upload Test Results to Trunk.io command: | curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --xcresult-path --org-url-slug --token ${TRUNK_API_TOKEN} ``` ```yaml RSpec plugin theme={null} jobs: test-node: # Install node dependencies and run tests executor: node/default steps: - run: name: Run Tests and Upload Results to Trunk.io command: TRUNK_ORG_URL_SLUG=${TRUNK_ORG_URL_SLUG} TRUNK_API_TOKEN=${TRUNK_API_TOKEN} bundle exec rspec ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [Uploader CLI Reference](../../reference/cli-reference) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # Drone CI Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/droneci Configure Flaky Tests using Drone CI Trunk Flaky Tests integrates with your CI by adding a step in your Drone CI Pipelines to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store your Trunk slug and API token in your Drone CI project settings as new variables named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an upload step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Add Uploader to Testing Pipelines The following is an example of a workflow step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [Test Frameworks](/flaky-tests/get-started/frameworks) docs. ```yaml XML theme={null} kind: pipeline type: docker name: test steps: - name: Run Tests commands: ... - name: Upload Test Results to Trunk.io environment: TRUNK_ORG_URL_SLUG: from_secret: TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN: from_secret: TRUNK_API_TOKEN commands: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --junit-paths --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml Bazel theme={null} kind: pipeline type: docker name: test steps: - name: Run Tests commands: ... - name: Upload Test Results to Trunk.io environment: TRUNK_ORG_URL_SLUG: from_secret: TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN: from_secret: TRUNK_API_TOKEN commands: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --bazel-bep-path --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml XCode theme={null} kind: pipeline type: docker name: test steps: - name: Run Tests commands: ... - name: Upload Test Results to Trunk.io environment: TRUNK_ORG_URL_SLUG: from_secret: TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN: from_secret: TRUNK_API_TOKEN commands: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --xcresult-path --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml RSpec plugin theme={null} kind: pipeline type: docker name: test steps: - name: Run Tests and Upload Results to Trunk.io environment: TRUNK_ORG_URL_SLUG: from_secret: TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN: from_secret: TRUNK_API_TOKEN commands: - TRUNK_ORG_URL_SLUG=$TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN=$TRUNK_API_TOKEN bundle exec rspec ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # GitHub Actions Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/github-actions Configure Flaky Tests detection using a GitHub Action Trunk Flaky Tests integrates with your CI by adding a step in your GitHub Action workflow to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). Before you start these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing Trunk-compatible reports for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as secrets in GitHub Actions} /> Configure GitHub Actions to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add Your Trunk Token and Organization Slug as Secrets Store the Trunk slug and API token obtained in the previous step in your repo as [GitHub secrets](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions) named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an `Upload Test Results` step after running tests in each of your CI jobs that run tests. This should minimally include all jobs that run on pull requests, as well as jobs that run on your main or [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Example GitHub Actions Workflow The following is an example of a GitHub Actions workflow step to upload test results after your tests using Trunk's [**Analytics Uploader Action**](https://github.com/trunk-io/analytics-uploader). To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [**Test Frameworks**](../frameworks/) docs. ```yaml JUnit XML theme={null} jobs: test: name: Upload Tests runs-on: ubuntu-latest steps: - name: Run Tests run: ... - name: Upload Test Results to Trunk.io if: ${{ !cancelled() }} # Upload the results even if the tests fail continue-on-error: true # don't fail this job if the upload fails uses: trunk-io/analytics-uploader@v2 with: junit-paths: **/junit.xml org-slug: token: ${{ secrets.TRUNK_API_TOKEN }} ``` ```yaml XCResult Path theme={null} jobs: test: name: Upload Tests runs-on: ubuntu-latest steps: - name: Run Tests run: ... - name: Upload Test Results to Trunk.io if: ${{ !cancelled() }} # Upload the results even if the tests fail continue-on-error: true # don't fail this job if the upload fails uses: trunk-io/analytics-uploader@v2 with: xcresult-path: ./test-results.xcresult org-slug: token: ${{ secrets.TRUNK_API_TOKEN }} ``` ```yaml Bazel BEP JSON theme={null} jobs: test: name: Upload Tests runs-on: ubuntu-latest steps: - name: Run Tests run: ... - name: Upload Test Results to Trunk.io if: ${{ !cancelled() }} # Upload the results even if the tests fail continue-on-error: true # don't fail this job if the upload fails uses: trunk-io/analytics-uploader@v2 with: bazel-bep-path: ./build_events.json org-slug: token: ${{ secrets.TRUNK_API_TOKEN }} ``` ```yaml RSpec plugin theme={null} jobs: test: name: Run and Upload Tests runs-on: ubuntu-latest steps: - name: Run Tests and Upload Results to Trunk.io run: TRUNK_ORG_URL_SLUG=${{ secrets.TRUNK_ORG_URL_SLUG }} TRUNK_API_TOKEN=${{ secrets.TRUNK_API_TOKEN }} bundle exec rspec ``` See the [GitHub Actions Reference page](https://github.com/trunk-io/analytics-uploader) for all available CLI arguments and usage. ### Enable quarantining You can quarantine flaky tests by wrapping the test command or as a follow-up step. Using the Trunk Analytics Uploader Action in your GitHub Actions Workflow files, may need modifications to your workflow files to support quarantining. If you upload your test results as a second step after you run your tests, **you need to add** `continue-on-error: true` **on your test step so your CI** job will continue even on failures. Here's an example file. ```yaml highlight={12,13} theme={null} name: Run Tests And Upload Results on: workflow_dispatch: jobs: upload-test-results: runs-on: ubuntu-latest timeout-minutes: 60 steps: - name: Run Tests id: unit_tests shell: bash run: # command to run tests goes here continue-on-error: true # allow CI job to continue to upload step on errors - name: Upload test results if: always() uses: trunk-io/analytics-uploader@v2 with: junit-paths: org-slug: my-trunk-org-slug token: ${{ secrets.TRUNK_API_TOKEN }} ``` If you want to run the test command and upload in a single step, the test command must be **run via the Analytics Uploader** through the `run: ` parameter. This will override the response code of the test command. Make sure to set `continue-on-error: false` so un-quarantined tests are blocking. ```yaml highlight={16} theme={null} name: Run Tests And Upload Results on: workflow_dispatch: jobs: upload-test-results: runs-on: ubuntu-latest timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v3 - name: Run tests and upload results uses: trunk-io/analytics-uploader@v2 with: junit-paths: run: # command to run tests goes here org-slug: my-trunk-org-slug token: ${{ secrets.TRUNK_API_TOKEN }} ``` **Using Flaky Tests as a separate step** If you upload your test results as a second step after you run your tests, you need to make sure your test step **continues on errors** so the upload step that's run after can quarantine failed tests. When quarantining is enabled, the `trunk-analytics-cli upload` command will **return an error** if there are unquarantined failures and return a status code 0 if all tests are quarantined. ```sh theme={null} || true # doesn't fail job on failure | ./trunk-analytics-cli upload \ --org-url-slug $TRUNK_ORG_URL_SLUG \ --token $TRUNK_API_TOKEN \ --junit-paths $JUNIT_PATH ``` **Using Flaky Tests as a single step** You can also wrap the test command with the Trunk Analytics CLI. When wrapping the command with the Trunk Analytics CLI, if there are unquarantined tests, the command will return an error. If there are no unquarantined tests, the command will return a status code `0`. ```bash theme={null} ./trunk-analytics-cli test \ --org-url-slug \ --token $TRUNK_API_TOKEN \ --junit-paths $JUNIT_PATH \ --allow-empty-test-results \ ``` ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your workflow has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check the action logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the repo running the workflow. ## Getting Direct Links to Job Logs **Direct Links to Job Logs is an optional configuration, and relies on a** [**third-party actions dependency**](https://github.com/marketplace/actions/get-action-job-id)**.** By default, Trunk Flaky Tests links to your overall workflow run when you click "Logs" on a test failure. However, GitHub Actions makes it difficult to get a direct link to the specific job where the test ran. If you want **direct links to individual job logs** instead of the workflow run, you can manually set the `JOB_URL` environment variable using a third-party action to extract the job ID. ### Setup 1. **Add the job ID extraction step** to your workflow using a community action: ```yaml highlight={9-16} theme={null} jobs: run_tests: runs-on: ubuntu-latest name: Run Tests # This name is important - use it in the next step steps: - name: Checkout uses: actions/checkout@v3 # Extract the job ID - name: Get Job ID id: get-job-id uses: ayachensiyuan/get-action-job-id@v1.6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: job-name: Run Tests # Must match the job 'name' above ``` 2. **Pass the job URL** when uploading test results: ```yaml highlight={13-14} theme={null} - name: Run Tests id: unit_tests run: continue-on-error: true - name: Upload test results if: always() uses: trunk-io/analytics-uploader@v2 with: junit-paths: org-slug: my-trunk-org-slug token: ${{ secrets.TRUNK_API_TOKEN }} env: JOB_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ steps.get-job-id.outputs.jobId }} ``` ### Complete Example Here's a full workflow example with direct job linking: ```yaml theme={null} name: Run Tests And Upload Results on: push: pull_request: jobs: test-suite: runs-on: ubuntu-latest name: Test Suite steps: - name: Checkout uses: actions/checkout@v3 - name: Get Job ID id: get-job-id uses: ayachensiyuan/get-action-job-id@v1.6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: job-name: Test Suite - name: Run Tests run: npm test continue-on-error: true - name: Upload test results if: always() uses: trunk-io/analytics-uploader@v2 with: junit-paths: junit.xml org-slug: my-trunk-org-slug token: ${{ secrets.TRUNK_API_TOKEN }} env: JOB_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ steps.get-job-id.outputs.jobId }} ``` ### How It Works * The `ayachensiyuan/get-action-job-id` [action](https://github.com/marketplace/actions/get-action-job-id) extracts the GitHub Actions job ID * We construct the full job URL using: `https://github.com/{repo}/actions/runs/{run_id}/job/{job_id}` * This URL is passed to Trunk via the `JOB_URL` environment variable * When you click "Logs" on a test failure in Trunk, you'll go directly to that job's logs instead of the workflow overview ### Notes * The `job-name` parameter must **exactly match** your job's `name` field * The `GITHUB_TOKEN` must have appropriate permissions to read workflow job information * If the job ID extraction fails, Trunk will fall back to linking to the workflow run # GitLab Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/gitlab Configure Flaky Tests using GitLab CI Trunk Flaky Tests integrates with your CI by adding a step in your GitLab CI/CD pipelines to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step in your GitLab CI/CD pipelines as new [GitLab Variables](https://docs.gitlab.com/ee/ci/variables/index.html#for-a-project) named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an `upload_test_results` step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your main or [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Example GitLab Pipeline The following is an example of a GitLab pipeline step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [frameworks](../frameworks/) docs. ```yaml XML theme={null} image: node:latest stages: # List of stages for jobs, and their order of execution - test - flaky-tests unit_test_job: # This job runs the tests stage: test script: ... upload_test_results: # This job uploads tests results run in the last stage to Trunk.io stage: flaky-tests script: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --junit-paths "" --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml Bazel theme={null} image: node:latest stages: # List of stages for jobs, and their order of execution - test - flaky-tests unit_test_job: # This job runs the tests stage: test script: ... upload_test_results: # This job uploads tests results run in the last stage to Trunk.io stage: flaky-tests script: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --bazel-bep-path --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml XCode theme={null} image: node:latest stages: # List of stages for jobs, and their order of execution - test - flaky-tests unit_test_job: # This job runs the tests stage: test script: ... upload_test_results: # This job uploads tests results run in the last stage to Trunk.io stage: flaky-tests script: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --xcresult-path --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml RSpec plugin theme={null} image: node:latest stages: # List of stages for jobs, and their order of execution - test unit_test_job: # This job runs the tests and uploads the results to Trunk.io stage: test script: - TRUNK_ORG_URL_SLUG=$TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN=$TRUNK_API_TOKEN bundle exec rspec ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # Google Cloud Build Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/google-cloud-build Configure Google Cloud Build to upload test results to Trunk Flaky Tests Trunk Flaky Tests integrates with your CI by adding a step in your Google Cloud Build configuration to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Store your token in GCP Secret Manager} /> Connect your GitHub repos to Cloud Build} /> Create Cloud Build triggers for PR and push events} /> Configure your cloudbuild.yaml to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Store the Trunk Token in GCP Secret Manager Store your Trunk API token in [GCP Secret Manager](https://console.cloud.google.com/security/secret-manager) so Cloud Build can securely access it during builds. 1. Open **GCP Console** → **Secret Manager**. 2. Click **Create Secret**. 3. Name the secret (for example, `trunk-api-token`) and paste your Trunk organization API token as the value. 4. Click **Create**. You'll reference this secret in your `cloudbuild.yaml` using the `availableSecrets` and `secretEnv` fields. ## Connect GitHub Repos to Cloud Build Ensure your GitHub repositories are connected to Cloud Build through the [Cloud Build GitHub App](https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github). 1. Open **GCP Console** → **Cloud Build** → **Repositories**. 2. Connect your GitHub repository using the Cloud Build GitHub App. ## Create Cloud Build Triggers Create two Cloud Build triggers for each repository you want to upload test results from: 1. Open **GCP Console** → **Cloud Build** → **Triggers**. 2. Create a trigger for **pull request events** — this uploads test results from PR branches. 3. Create a trigger for **push events** to your stable branch (for example, `main`) — this uploads test results from your stable branch. It is important to upload test results from CI runs on [**stable branches**](../../detection#stable-branches), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection) ## Upload to Trunk Add an upload step in your `cloudbuild.yaml` that runs after your test steps. The Trunk CLI automatically detects Google Cloud Build when the `TRIGGER_NAME` environment variable is set. Google Cloud Build does not automatically provide environment variables to build steps. You must explicitly pass the required substitution variables in your `cloudbuild.yaml` using the `env` field. Without these variables, the CLI cannot detect your CI platform or link uploads to the correct branches and pull requests. ### Required Environment Variables The following environment variables must be passed to the upload step: | Variable | Description | | -------------- | -------------------------------------------------------------------- | | `TRIGGER_NAME` | Name of the Cloud Build trigger (used for CI platform detection) | | `PROJECT_ID` | GCP project ID (used to construct the CI job link) | | `BUILD_ID` | Unique ID of the Cloud Build run (used to construct the CI job link) | | `BRANCH_NAME` | Git branch being built (used for push/stable branch uploads) | | `_HEAD_BRANCH` | Head branch for PR-triggered builds | | `_PR_NUMBER` | Pull request number for PR-triggered builds | ### Example `cloudbuild.yaml` The following is an example of a `cloudbuild.yaml` configuration that runs tests and uploads results to Trunk. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [Test Frameworks](../frameworks/) docs. ```yaml XML theme={null} steps: - name: gcr.io/cloud-builders/npm id: run-tests script: | #!/bin/bash set -euo pipefail npm install npm test timeout: 600s allowExitCodes: [0, 1] - name: gcr.io/cloud-builders/gcloud id: upload-test-results script: | #!/bin/bash set -euo pipefail curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli ./trunk-analytics-cli upload \ --junit-paths "" \ --org-url-slug \ --token "${TRUNK_API_TOKEN}" waitFor: - run-tests timeout: 300s env: - "PROJECT_ID=${PROJECT_ID}" - "BUILD_ID=${BUILD_ID}" - "TRIGGER_NAME=${TRIGGER_NAME}" - "BRANCH_NAME=${BRANCH_NAME}" - "_HEAD_BRANCH=${_HEAD_BRANCH}" - "_PR_NUMBER=${_PR_NUMBER}" secretEnv: ["TRUNK_API_TOKEN"] options: logging: CLOUD_LOGGING_ONLY timeout: 1200s availableSecrets: secretManager: - versionName: projects/${PROJECT_ID}/secrets//versions/latest env: TRUNK_API_TOKEN ``` ```yaml Bazel theme={null} steps: - name: gcr.io/cloud-builders/bazel id: run-tests args: ['test', '//...', '--build_event_json_file=bep.json'] timeout: 600s allowExitCodes: [0, 1] - name: gcr.io/cloud-builders/gcloud id: upload-test-results script: | #!/bin/bash set -euo pipefail curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli ./trunk-analytics-cli upload \ --bazel-bep-path bep.json \ --org-url-slug \ --token "${TRUNK_API_TOKEN}" waitFor: - run-tests timeout: 300s env: - "PROJECT_ID=${PROJECT_ID}" - "BUILD_ID=${BUILD_ID}" - "TRIGGER_NAME=${TRIGGER_NAME}" - "BRANCH_NAME=${BRANCH_NAME}" - "_HEAD_BRANCH=${_HEAD_BRANCH}" - "_PR_NUMBER=${_PR_NUMBER}" secretEnv: ["TRUNK_API_TOKEN"] options: logging: CLOUD_LOGGING_ONLY timeout: 1200s availableSecrets: secretManager: - versionName: projects/${PROJECT_ID}/secrets//versions/latest env: TRUNK_API_TOKEN ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. **Important:** Set `allowExitCodes: [0, 1]` on your test step so the upload step runs even when tests fail. Without this, Cloud Build stops the pipeline on test failures and your results won't be uploaded. Replace the following placeholders in the example: | Placeholder | Description | | ---------------------- | ------------------------------------------------------------------------------------ | | `` | Glob pattern matching your JUnit XML test report files (for example, `**/junit.xml`) | | `` | Your Trunk organization slug | | `` | The name of the secret you created in GCP Secret Manager | See the [Trunk Analytics CLI](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # CI Providers Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/index You can easily integrate Flaky Tests from any CI Provider Trunk Flaky Tests integrates with your CI by adding a `Upload Test Results` step in each of your testing CI jobs via the [Trunk Analytics CLI](../../reference/cli-reference). See the [Test Frameworks](../frameworks/) docs for instructions on producing test reports for your test runner, which Trunk can ingest. **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. ## Quickstart # Jenkins Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/jenkins Configure Flaky Tests using Jenkins Trunk Flaky Tests integrates with your CI by adding a step in your Jenkins Pipelines to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step in your Jenkins as new credentials named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an `Upload Test Results` step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your main or [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Example Jenkins Pipeline The following is an example of a Jenkins pipeline step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [Test Frameworks](../frameworks/) docs ```groovy XML theme={null} pipeline { environment { TRUNK_API_TOKEN = credentials('TRUNK_API_TOKEN') } stages { stage('Run Tests'){ ... } stage('Upload Test Results'){ sh 'curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli' sh './trunk-analytics-cli upload --junit-paths "" --org-url-slug --token $TRUNK_API_TOKEN' } } } ``` ```yaml Bazel theme={null} pipeline { environment { TRUNK_API_TOKEN = credentials('TRUNK_API_TOKEN') } stages { stage('Run Tests'){ ... } stage('Upload Test Results'){ sh 'curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli' sh './trunk-analytics-cli upload --bazel-bep-path --org-url-slug --token $TRUNK_API_TOKEN' } } } ``` ```yaml XCode theme={null} pipeline { environment { TRUNK_API_TOKEN = credentials('TRUNK_API_TOKEN') } stages { stage('Run Tests'){ ... } stage('Upload Test Results'){ sh 'curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli' sh './trunk-analytics-cli upload --xcresult-path --org-url-slug --token $TRUNK_API_TOKEN' } } } ``` ```groovy RSpec plugin theme={null} pipeline { environment { TRUNK_ORG_URL_SLUG = credentials('TRUNK_ORG_URL_SLUG') TRUNK_API_TOKEN = credentials('TRUNK_API_TOKEN') } stages { stage('Run Tests and Upload Results to Trunk.io'){ sh 'TRUNK_ORG_URL_SLUG=$TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN=$TRUNK_API_TOKEN bundle exec rspec' } } } ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # Other CI Providers Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/otherci Configure Flaky Tests using any CI Provider Trunk Flaky Tests integrates with your CI provider by adding an upload step in each of your testing CI jobs via the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing JUnit XML output for your test runner, supported by virtually all test frameworks, which is what Trunk ingests. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step in your CI provider as a secret, environment variable, or an equivalent concept and name them `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an `Upload Test Results` step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your main or [stable branches](../../detection/), for example,`main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Example Upload Script The following is an example of a script to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [frameworks](../frameworks/) docs. You can install the Trunk Analytics CLI locally like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ``` Then, you can validate the results using the `trunk-analytics-cli validate` command like this: ```bash theme={null} ./trunk-analytics-cli validate --junit-paths ``` See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Environment Variables Set these environment variables before running `trunk-analytics-cli upload` on unsupported CI systems: **Config Requirement:** `CUSTOM` must be set to `true` for environment variables to take effect and override the auto-detection of CI. All other variables are optional but recommended. | Variable | Description | Example | | ---------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------- | | `CUSTOM` | Set to `true` to indicate this CI system is not one of our supported providers | `CUSTOM=true` | | `JOB_URL` | Direct link to the CI job/build page. This is the link users will click when viewing test failure logs in Trunk. | `https://ci.example.com/builds/12345` | | `JOB_NAME` | Name of the CI job or test suite | `unit-tests` | | `AUTHOR_EMAIL` | Email address of the commit author | `dev@example.com` | | `AUTHOR_NAME` | Full name of the commit author | `Jane Developer` | | `COMMIT_BRANCH` | Git branch being tested | `main` | | `COMMIT_MESSAGE` | Commit message for the tested commit | `Fix authentication bug` | | `PR_NUMBER` | Pull request number (if applicable) | `123` | | `PR_TITLE` | Pull request title (if applicable) | `Add new feature` | ### About JOB\_URL The `JOB_URL` variable controls where the "Logs" link in Trunk Flaky Tests points to. When users click "Logs" on a test failure, they'll be taken to this URL to view the complete CI job output. **Best practice:** Provide the most specific link possible: * Direct link to the specific job/build where the test ran * Link that shows the full logs and test output * **Avoid** dashboard or workflow overview links (less helpful for debugging) **For GitHub Actions users:** While GitHub Actions is auto-detected, you can override the default workflow URL with a direct job URL. See [GitHub Actions - Getting Direct Links to Job Logs](./github-actions#getting-direct-links-to-job-logs) for instructions. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # Semaphore CI Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/semaphoreci Configure Flaky Tests using Semaphore CI Trunk Flaky Tests integrates with your CI by adding a step in your Semaphore CI Pipeline to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step in your Semaphore CI Pipelines as new secrets named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add an upload step after running tests in each of your CI jobs that run tests. This should be minimally all jobs that run on pull requests, as well as from jobs that run on your main or [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Example Semaphore CI Workflow The following is an example of a Semaphore CI workflow step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [Test Frameworks](/flaky-tests/get-started/frameworks) docs. ```yaml XML theme={null} version: v1.0 name: Semaphore JavaScript Example Pipeline blocks: - name: Tests task: secrets: - name: TRUNK_API_TOKEN env_vars: - name: NODE_ENV value: test - name: CI value: "true" prologue: commands: - checkout - nvm use - node --version - npm --version jobs: - name: Run Tests commands: ... epilogue: always: commands: # Upload results to trunk.io - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --junit-paths "" --org-url-slug --token ${TRUNK_API_TOKEN} ``` ```yaml Bazel theme={null} version: v1.0 name: Semaphore JavaScript Example Pipeline blocks: - name: Tests task: secrets: - name: TRUNK_API_TOKEN env_vars: - name: NODE_ENV value: test - name: CI value: "true" prologue: commands: - checkout - nvm use - node --version - npm --version jobs: - name: Run Tests commands: ... epilogue: always: commands: # Upload results to trunk.io - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --bazel-bep-path --org-url-slug --token ${TRUNK_API_TOKEN} ``` ```yaml XCode theme={null} version: v1.0 name: Semaphore JavaScript Example Pipeline blocks: - name: Tests task: secrets: - name: TRUNK_API_TOKEN env_vars: - name: NODE_ENV value: test - name: CI value: "true" prologue: commands: - checkout - nvm use - node --version - npm --version jobs: - name: Run Tests commands: ... epilogue: always: commands: # Upload results to trunk.io - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --xcresult-path --org-url-slug --token ${TRUNK_API_TOKEN} ``` ```RSpec plugin theme={null} version: v1.0 name: Semaphore JavaScript Example Pipeline blocks: - name: Tests task: secrets: - name: TRUNK_API_TOKEN - name: TRUNK_ORG_URL_SLUG env_vars: - name: NODE_ENV value: test - name: CI value: "true" prologue: commands: - checkout - nvm use - node --version - npm --version jobs: - name: Run Tests commands: - TRUNK_ORG_URL_SLUG=${TRUNK_ORG_URL_SLUG} TRUNK_API_TOKEN=${TRUNK_API_TOKEN} bundle exec rspec ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # Travis CI Source: https://docs.trunk.io/flaky-tests/get-started/ci-providers/travisci Configure Flaky Tests using Travis CI Trunk Flaky Tests integrates with your CI by adding a step in your Travis CI Pipelines to upload tests with the [Trunk Analytics CLI](../../reference/cli-reference). **Not using GitHub for source control?** Flaky Test support for source control providers like GitLab and BitBucket is still experimental. If you're using a source control provider other than GitHub, [**contact us**](mailto:support@trunk.io) **to get started**. Before you start on these steps, see the [Test Frameworks](../frameworks/) docs for instructions on producing a Trunk-compatible output for your test framework. ## Setup steps Work through the steps below in order. Once you've finished the last one, you're set up — navigate to [app.trunk.io](https://app.trunk.io) to see your results. Get your Trunk organization slug and token} /> Set your slug and token as a variable in CI} /> Configure your CI to upload to Trunk} /> Validate your uploads in Trunk} /> ## Trunk Organization Slug and Token Before setting up uploads to Trunk, you must sign in to [app.trunk.io](https://app.trunk.io/login?intent=flaky%20tests) and obtain your Trunk organization slug and token. ### Trunk Slug You can find your organization slug under **Settings** → **Organization** → **General**. You'll save this as a variable in CI in a later step. ### Trunk Token You can find your token under **Settings** → **Organization** → **General**, in the **API** section. Since this is a secret, do not leak it publicly. Ensure you get your *organization token*, not your project/repo token. ## Add the Trunk Token as a Secret Store the Trunk slug and API token obtained in the previous step as new secrets named `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN` respectively. ## Upload to Trunk Add a script step after running tests in each of your CI jobs that run tests. This should be run on pull requests, as well as from jobs that run on your main or [stable branches](../../detection/), for example, `main`, `master`, or `develop`. It is important to upload test results from CI runs on [**stable branches**](../../detection/), such as `main`, `master`, or `develop`. This will give you a stronger signal about the health of your code and tests. Trunk can also detect test flakes on PR and merge branches. To best detect flaky tests, it is recommended to upload test results from stable, PR, and merge branch CI runs. [Learn more about detection](../../detection/) ### Example Travis CI Workflow The following is an example of a Travis CI workflow step to upload test results after your tests run. Note: you must either run `trunk` from the repo root when uploading test results or pass a `--repo-root` argument. To find out how to produce the report files the uploader needs, see the instructions for your test framework in the [Test Frameworks](/flaky-tests/get-started/frameworks) docs. Note that TravisCI requires a recent version of Linux to use the current NodeJS runtimes. You may need to set the `dist` to `jammy` or later. See this [forum note](https://travis-ci.community/t/node-lib-x86-64-linux-gnu-libm-so-6-version-glibc-2-27-not-found-required-by-node/13655/2) for more details. ```yaml XML theme={null} language: node_js dist: jammy node_js: - 20 script: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --junit-paths "" --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml Bazel theme={null} language: node_js dist: jammy node_js: - 20 script: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --bazel-bep-path --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml XCode theme={null} language: node_js dist: jammy node_js: - 20 script: - curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli - ./trunk-analytics-cli upload --xcresult-path --org-url-slug --token $TRUNK_API_TOKEN ``` ```yaml RSpec plugin theme={null} language: node_js dist: jammy node_js: - 20 script: - TRUNK_ORG_URL_SLUG=$TRUNK_ORG_URL_SLUG TRUNK_API_TOKEN=$TRUNK_API_TOKEN bundle exec rspec ``` The examples above use the Linux x64 binary. If your CI runs on a different platform, see the [Trunk Analytics CLI](../../reference/cli-reference#manual-download) page for all available platform downloads. See the [uploader.md](../../reference/cli-reference.md) for all available command line arguments and usage. ### Stale files Ensure you report every test run in CI and **clean up stale files** produced by your test framework. If you're reusing test runners and using a glob like `**/junit.xml` to upload tests, stale files not cleaned up will be included in the current test run, throwing off detection of flakiness. You should clean up all your results files after every upload step. ## Validate Your Uploads Once your pipeline has run on a stable branch, navigate to [app.trunk.io](https://app.trunk.io) and confirm Trunk received your results. * The **Uploads** tab lists every report Trunk has ingested, with status and any warnings (missing file paths, malformed XML, and so on). * The **Tests** tab shows individual test cases once an upload has been processed. If a recent run isn't showing up, check your CI logs for upload errors and confirm your `TRUNK_API_TOKEN` and `TRUNK_ORG_URL_SLUG` secrets are set on the project running the pipeline. # Android Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/android A guide for generating Trunk-compatible test reports for Android projects You can automatically [detect and manage flaky tests](../../detection/) in your Android projects by integrating with Trunk. This document explains how to configure Android to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating reports Android tests run with Gradle, typically using `./gradlew test` in CI. This will generate JUnit XML output by default, which you can further configure in your `build.gradle.kts` or `build.gradle`. ### Report file path By default, Android projects will produce a directory with JUnit XML reports under `./app/build/test-results`. You can customize the report output location in your `build.gradle.kts` or `build.gradle`, for example, writing the reports to `./app/junit-reports`. ```groovy Groovy theme={null} android { testOptions { unitTests { all { reports { junitXml { outputLocation = file("./junit-reports") } } } } } } ``` ```kotlin Kotlin theme={null} android { testOptions { unitTests { all { reports { junitXml.outputLocation.set(file("./junit-reports")) } } } } } ``` When you configure your CI provider to upload reports in later steps, you will be uploading the reports using a glob such as `./junit-reports/*.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. If you've enabled retries using a plugin like the [test-retry-gradle-plugin](https://github.com/gradle/test-retry-gradle-plugin), disable it when running tests for Trunk Flaky Tests. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit-reports/*.xml" \ --org-url-slug \ --token ``` ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Bazel Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/bazel A guide for generating Trunk-compatible test reports with Bazel You can automatically [detect and manage flaky tests](../../detection/) in your Bazel projects by integrating with Trunk. This document explains how to configure Bazel to output compatible reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Test uploads locally} /> ## Generating Reports Trunk can parse JSON serialized [Build Event Protocol (BEP) ](https://bazel.build/remote/bep)files to detect flaky tests. You can run tests with Bazel in CI with the `--nobuild_event_json_file_path_conversion` option to produce a serialized BEP file. ### Report File Path You can specify the path of the generated report through the `build_event_json_file` option: ```sh theme={null} bazel test \ --nobuild_event_json_file_path_conversion \ --build_event_json_file=build_events.json ``` Trunk can parse the `build_events.json` file to locate your test reports. You will still need to **configure your test runners to output compatible reports**, and you can refer to the guides for [individual test frameworks](./). Trunk accepts BEP files in both JSON and binary formats. Each output format has its own path-conversion flag, so pick the pair that matches the file you generate: * JSON: `--build_event_json_file` with `--nobuild_event_json_file_path_conversion` * Binary protobuf: `--build_event_binary_file` with `--nobuild_event_binary_file_path_conversion` Pass whichever file you generated to the analytics CLI's `--bazel-bep-path`. The CLI detects the format automatically, so you don't need to tell it which one you used. ## Bazel flags These Bazel flags affect whether Trunk receives complete test reports. Review them before configuring uploads. ### Build Without the Bytes If your CI environment is set up to [build without the bytes](https://blog.bazel.build/2023/10/06/bwob-in-bazel-7.html), you will need the following flag to pull the reports from the remote execution engine: ```sh theme={null} --remote_download_regex='.*/test.xml' ``` ### Keep Going After Test Failures Avoid setting `--test_keep_going=false` (or `--notest_keep_going`) if you intend to quarantine tests. Leave it at its default (`true`). When `--test_keep_going` is `false`, Bazel stops at the first failing test, so later tests never run and never reach the BEP report. If that first failure is a quarantined test, Trunk sees only an already-quarantined failure and marks the run as passing. The tests that never ran might have failed, and the PR merges anyway. ## Try It Locally ### The Validate Command ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --bazel-bep-path=build_events.json ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --bazel-bep-path=build_events.json ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --bazel-bep-path=build_events.json ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --bazel-bep-path=build_events.json ``` ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --bazel-bep-path=build_events.json \ --org-url-slug \ --token ``` ### Codeowners and Bazel Targets If your test cases don't have file paths that can be matched against your CODEOWNERS file, you can pass `--use-bazel-target-for-codeowners` to fall back to the Bazel target name (e.g. `//path/to:target`) when associating test cases to owners: ```sh theme={null} ./trunk-analytics-cli upload --bazel-bep-path=build_events.json \ --org-url-slug \ --token \ --use-bazel-target-for-codeowners ``` When using the [Analytics Uploader GitHub Action](https://github.com/trunk-io/analytics-uploader), set the `use-bazel-target-for-codeowners: true` input alongside `bazel-bep-path`. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Behave Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/behave A guide for generating Trunk-compatible test reports for Behave You can automatically [detect and manage flaky tests](../../detection/) in your projects running Behave by integrating with Trunk. This document explains how to configure Behave to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. Behave can output JUnit XML reports which are compatible with Trunk. You can do so with the `--junit` option: ```sh theme={null} behave --junit ``` ### Report File Path You can customize the file path of the reports using the `--junit-directory` option. ```sh theme={null} behave --junit --junit-directory ./junit-reports ``` Behave outputs multiple XML reports under the JUnit directory. You can locate these when uploading the reports in CI with the `"./junit-reports/*.xml"` glob. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. You must remove the [rerun formatter](https://behave.readthedocs.io/en/latest/formatters/#formatters) from your `behave.ini` file if it is being used to automatically rerun failed tests. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit-reports/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Cypress Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/cypress A guide for generating Trunk-compatible test reports for Cypress tests You can automatically [detect and manage flaky tests](../../detection/) in your Cypress projects by integrating with Trunk. This document explains how to configure Cypress to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Cypress has a built-in Mocha JUnit reporter which outputs XML test reports. However, the built-in reporter does not include file paths in test case elements, which means Trunk cannot match tests to code owners or enable file-based filtering in the dashboard. ### Recommended: Use cypress-junit-plugin for file paths For full functionality including code owner detection and file-based search, use the [`cypress-junit-plugin`](https://github.com/saucelabs/cypress-junit-plugin) reporter. It outputs test cases with the correct nested structure and file path attributes that Trunk expects. Install the plugin: ```bash theme={null} npm install --save-dev @saucelabs/cypress-junit-plugin ``` Update your Cypress config: ```javascript title="cypress.config.js" theme={null} const { defineConfig } = require('cypress') const { setupJUnitPlugin } = require('@saucelabs/cypress-junit-plugin') module.exports = defineConfig({ e2e: { setupNodeEvents(on, config) { setupJUnitPlugin(on, config, { filename: './junit.xml' }) return config }, }, }) ``` ### Alternative: Built-in Mocha reporter If you don't need file path matching or code owner detection, you can use the built-in reporter. Uploads will still work, but you will see warnings about missing file paths and won't be able to search by file in the dashboard. ```javascript title="cypress.config.js" theme={null} const { defineConfig } = require('cypress') module.exports = defineConfig({ reporter: 'junit', reporterOptions: { mochaFile: './junit.xml', toConsole: true, }, }) ``` The built-in Mocha JUnit reporter places the `file` attribute on `` elements but not on individual `` elements. Trunk requires file paths on test cases for code owner matching. If you see warnings like "report has test cases with missing file or filepath", switch to the `cypress-junit-plugin` above. ### Report File Path The JUnit report location is specified by the `filename` option passed to `setupJUnitPlugin` (or the `mochaFile` property when using the built-in reporter). In the above examples, the file will be at `./junit.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You can disable retries by setting `retries: 0` in your Cypress config file. ```javascript title="cypress.config.js" theme={null} module.exports = defineConfig({ retries: 0, }) ``` ## Try It Locally ### The Validate Command ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Step Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Dart Test Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/dart-test A guide for generating Trunk-compatible test reports for Dart tests You can automatically [detect and manage flaky tests](../../detection/) in your Dart projects by integrating with Trunk. This document explains how to configure Dart to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Before you can upload to Trunk, you need to output a Trunk-compatible report. Dart supports JUnit outputs by using the `tojunit` library. You can install the `tojunit` library using the following command: ```sh theme={null} dart pub global activate junitreport ``` Then, you can convert test reports to a JUnit format by piping it to `tojunit`and piping the output to a file like this: ```sh theme={null} dart test --reporter json | tojunit > junit.xml ``` ### Report File Path The JUnit report is written to the location specified by the `tojunit >` pipe. In the example above, the test results will be written to `./junit.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. Dart provides retries through the [retry class annotations](https://pub.dev/documentation/test/latest/test/Retry-class.html). Disable retry, use Trunk to [detect](../../detection/)[ flaky tests](../../detection/), and use Quarantining to isolate flaky tests dynamically at run time. ## Try It Locally ### The Validate Command ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # GoogleTest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/googletest A guide for generating Trunk-compatible test reports for GoogleTest You can automatically [detect and manage flaky tests](../../detection/) in your GoogleTest projects by integrating with Trunk. This document explains how to configure GoogleTest to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Before you can integrate with Trunk, you need to generate a Trunk-compatible report. For GoogleTest, the built in XML reporter will work. You can use the [`--gtest_output=xml`](https://google.github.io/googletest/advanced.html#generating-an-xml-report) argument when you run your built test project: ```shell theme={null} ./build/run_test --gtest_output=xml ``` ### Report File Path By default, the JUnit report will be written to a `test_detail.xml` file. You can specify a custom directory and filename with: ```bash theme={null} --gtest_output=xml: ``` For example, the following argument writes a JUnit report to `./junit.xml`: ```bash theme={null} --gtest_output=xml:junit.xml ``` ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. Omit the[ ](https://docs.pytest.org/en/stable/how-to/cache.html)[`--gtest_repeat`](https://google.github.io/googletest/advanced.html#repeating-the-tests) argument if you've previously configured your CI with these options to disable retries. ## Try It Locally ### The Validate Command ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Go Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/gotestsum A guide for generating Trunk-compatible test reports for Go tests You can automatically [detect and manage flaky tests](../../detection/) in your Go projects by integrating with Trunk. This document explains how to configure Go to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Why an Extra Step for `go test`? The standard Go test runner, `go test`, is excellent for executing tests and providing immediate feedback to developers. However, it does not natively produce test reports in the JUnit XML format that Trunk Flaky Tests requires for ingestion and analysis. Therefore, an additional tool is needed to convert the output of `go test` into this compatible format. This intermediate step allows Trunk to accurately process your test results and identify flaky tests. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report (JUnit XML)} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating JUnit XML Reports from Go Tests Before integrating with Trunk, you need to generate a Trunk-compatible report. For Go, `go test` does not output JUnit XML by default, so you must use a tool to format it. Update your existing `go test` usage to generate json and use [**go-junit-report**](https://github.com/jstemmer/go-junit-report) to convert your standard Go testing output into JUnit XML. ``` go install github.com/jstemmer/go-junit-report/v2@latest ``` Then pipe `go test` into the `go-junit-report`: ``` go test -json 2>&1 | go-junit-report -parser gojson -out junit_report.xml ``` Install gotestsum into your project:\ \ `go install gotest.tools/gotestsum@latest`\ \ Call `gotestsum` to both execute your tests and generate the junit.xml file ``` gotestsum [path-to-tests-to-run] --junitfile ./junit.xml ``` ### Report File Path The tools will write a JUnit test report to the file specified (e.g., `junit.xml` or `junit_report.xml`). You'll need this path when configuring uploads to Trunk. If a subtest's top-level duration is reported as 0ms, timing-based analysis in the dashboard has less to work with for that case. See [Known limitations](../../dashboard#known-limitations) for the recommended workaround. #### Disable Retries Regardless of the tool chosen, you need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests.\ \ If you're using a package like [**retry**](https://pkg.go.dev/github.com/hashicorp/consul/sdk/testutil/retry), disable it to get more accurate results from Trunk. ## Try It Locally ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ## Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Gradle Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/gradle A guide for generating Trunk-compatible test reports for Gradle You can automatically [detect and manage flaky tests](../../detection/) in your Gradle projects by integrating with Trunk. This document explains how to configure Gradle to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Tests run with Gradle will generate JUnit XML reports by default and are compatible with Trunk. You can further [configure reporting behavior](https://docs.gradle.org/8.10.2/userguide/java_testing.html#test_reporting) in your `build.gradle.kts` or `build.gradle`. ### Report File Path By default, Android projects will produce a directory with JUnit XML reports under `./app/build/test-results/test`. You can locate these files with the glob `"./app/build/test-results/test/*.xml"`. If you wish to override the default test result path, you can do so in the `build.gradle.kts` or `build.gradle` files: ```groovy title="build.gradle" theme={null} java.testResultsDir = layout.buildDirectory.dir("junit-reports") ``` ```kotlin title="build.gradle.kts" theme={null} java.testResultsDir = layout.buildDirectory.dir("junit-reports") ``` This example will write report files to `"./app/build/junit-reports/test/*.xml"` The `validate` and `upload` commands below use the default path. If you apply this override, point `--junit-paths` at `./app/build/junit-reports/test/*.xml` instead. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. If you've enabled retries using a plugin like the [test-retry-gradle-plugin](https://github.com/gradle/test-retry-gradle-plugin), disable it when running tests for Trunk Flaky Tests. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./app/build/test-results/test/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./app/build/test-results/test/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./app/build/test-results/test/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./app/build/test-results/test/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./app/build/test-results/test/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Test frameworks Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/index Guides for generating Trunk-compatible test results from various test frameworks Trunk Flaky Tests uses test results uploaded from your CI jobs to detect flaky tests. Follow one of the guides below to configure your test framework to output compatible test reports and integrate with Trunk. # Jasmine Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/jasmine A guide for generating Trunk-compatible test reports for Jasmine tests You can automatically [detect and manage flaky tests](../../detection/) in your Jasmine projects by integrating with Trunk. This document explains how to configure Jasmine to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Before integrating with Trunk, you need to generate Trunk-compatible reports. For Jasmine, the easiest approach is to generate XML reports. First, install the [`jasmine-reporters`](https://www.npmjs.com/package/jasmine-reporters) package: ```shell theme={null} npm install --save-dev jasmine-reporters ``` ### In-Browser tests When used for in-browser tests, the reporters are registered on a `jasmineReporters` object in the global scope (i.e. `window.jasmineReporters`). You can register it like this in your Jasmine config under `/spec/support/jasmine.mjs`: ```javascript title="/spec/support/jasmine.mjs" theme={null} import jasmineReporters from 'jasmine-reporters'; var junitReporter = new jasmineReporters.JUnitXmlReporter({ savePath: "test-reports", consolidateAll: false }); jasmine.getEnv().addReporter(junitReporter); ``` ### NodeJS In Node.js, `jasmine-reporters` exports an object with all the reporters. You can register it like this in your Jasmine config under `/spec/support/jasmine.mjs`: ```javascript theme={null} var reporters = require('jasmine-reporters'); var junitReporter = new reporters.JUnitXmlReporter({ savePath: "test-reports", consolidateAll: false }); jasmine.getEnv().addReporter(junitReporter) ``` ### Report File Path Jasmine will generate an XML report at the location specified by the `savePath` property. In the examples above, the XML report can be located with the glob `test-reports/*.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. If you're using a package like [protractor-flake](https://www.npmjs.com/package/protractor-flake), disable it to get more accurate results from Trunk. Instead, you can mitigate flaky tests using the [Quarantining](../../quarantining/) feature in Trunk. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./test-reports/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Jest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/jest A guide for generating Trunk-compatible test reports for Jest tests You can automatically [detect and manage flaky tests](../../detection/) in your Jest projects by integrating with Trunk. This document explains how to configure Jest to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating XML reports from your test runs. To generate a Trunk-compatible XML report, install the `jest-junit` package: ```bash theme={null} npm install --save-dev jest-junit ``` Update your Jest config to add `jest-junit` as a reporter: ```json title="jest.config.json" theme={null} { "reporters": [ [ "jest-junit", { "outputDirectory": "./", "outputName": "junit.xml", "addFileAttribute": "true", "reportTestSuiteErrors": "true" } ] ] } ``` ### Report File Path The `outputDirectory` and `outputName` options specify the path of the XML report. You'll need this path later when configuring automatic uploads to Trunk. ### Using `filePathPrefix` In a monorepo with `pnpm` workspaces (or similar), Jest runs from within the package directory, so the file paths it records in the XML report are relative to that package — not to the repository root. For example, a test at `packages/my-package/src/__tests__/foo.test.js` would be recorded as `src/__tests__/foo.test.js`. This causes codeowners matching to fail because Trunk compares test file paths against the codeowners file at the repo root, which uses full repo-relative paths. To fix this, set the `filePathPrefix` option to the path of the package within the repo: ```json title="jest.config.json" theme={null} { "reporters": [ [ "jest-junit", { "outputDirectory": "./", "outputName": "junit.xml", "addFileAttribute": "true", "reportTestSuiteErrors": "true", "filePathPrefix": "packages/my-package" } ] ] } ``` With `filePathPrefix` set, `jest-junit` will prepend the given path to every file path in the XML output, producing repo-root-relative paths that Trunk can correctly match against your codeowners file. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. If you have retries configured using the [jest.retryTimes method](https://jestjs.io/docs/jest-object#jestretrytimesnumretries-options), disable them for more accurate results. ## Try It Locally ### The Validate Command ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Karma Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/karma A guide for generating Trunk-compatible test reports for Karma tests You can automatically [detect and manage flaky tests](../../detection/) in your Karma projects by integrating with Trunk. This document explains how to configure Karma to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating XML reports from your test runs. To generate a Trunk-compatible XML report, install the `karma-junit-reporter` package: ```shell theme={null} npm install --save-dev karma-junit-reporter ``` Add the `junit` reporter to your karma config file: ```javascript title="karma.conf.js" theme={null} module.exports = function(config) { config.set( { reporters: ['junit'], junitReporter: { outputDir: 'test-reports', } } ) } ``` ### Report File Path The `outputDir` specifies the location of the JUnit test report. In the example above, the JUnit would be at `./test-reports/{$browserName}.xml`. You can locate the reports during uploads with the glob `./test-reports/*.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. Karma doesn't support retries out of the box, but if you implemented retries, remember to disable them. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./test-reports/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Kotest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/kotest A guide for generating Trunk-compatible test reports for Kotest You can automatically [detect and manage flaky tests](../../detection/) in your Kotest projects by integrating with Trunk. This document explains how to configure Kotest to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Steps for generating JUnit XML reports for Kotest depend on the build system you use for your project: Tests run with Gradle will generate Trunk-compatible JUnit XML reports by default. You can further [configure reporting behavior](https://docs.gradle.org/8.10.2/userguide/java_testing.html#test_reporting) in your `build.gradle.kts` or `build.gradle`. Kotest projects using Maven require the following to be added to a project's `pom.xml` so JUnit XML reports can be generated: * the `maven-surefire-plugin` must be added to the `plugins` section of `pom.xml` ```xml title="pom.xml" theme={null} org.apache.maven.plugins maven-surefire-plugin 3.2.2 ``` * the `kotest-extensions-junitxml` must be added to the `dependencies` section of `pom.xml` ```xml title="pom.xml" theme={null} io.kotest kotest-extensions-junitxml-jvm 5.9.0 test ``` ### Report File Path You can configure the path for generated JUnit XML files: By default, Kotlin projects will produce a directory with JUnit XML reports under `./app/build/test-results/test`. You can locate these files with the glob `"./app/build/test-results/test/*.xml"`. If you wish to override the default test result path, you can do so in the `build.gradle.kts` or `build.gradle` files: ```kotlin title="build.gradle.kts (Kotlin) or build.gradle (Groovy)" theme={null} java.testResultsDir = layout.buildDirectory.dir("junit-reports") ``` You can change the report file path by configuring the `reportsDirectory` in your `maven-surefire-plugin` in your `pom.xml` file: ```xml title="pom.xml" theme={null} org.apache.maven.plugins maven-surefire-plugin 3.2.2 ${project.build.directory}/junit/ ``` The example above will output JUnit XML reports that can be located with the `/target/junit/*.xml` glob. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. If you've enabled retries using a plugin like the [test-retry-gradle-plugin](https://github.com/gradle/test-retry-gradle-plugin), disable it when running tests for Trunk Flaky Tests. Maven uses the `maven-surefire-plugin` to run tests, which allows you to control the test retry behavior. You can disable retries by specifying 0 retries: ``` mvn -Dsurefire.rerunFailingTestsCount=0 test ``` ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: The `validate` and `upload` examples below use the **Gradle default** output path. Point `--junit-paths` at the glob that matches your build: * **Gradle** (default): `./app/build/test-results/test/*.xml` * **Gradle** with the `testResultsDir` override shown above: `./app/build/junit-reports/test/*.xml` * **Maven**: `./target/junit/*.xml` ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./app/build/test-results/test/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./app/build/test-results/test/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./app/build/test-results/test/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./app/build/test-results/test/*.xml" ``` Make sure to specify the path to your JUnit XML test reports. **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./app/build/test-results/test/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Maven Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/maven A guide for generating Trunk-compatible test reports for Maven You can automatically [detect and manage flaky tests](../../detection/) in your Maven projects by integrating with Trunk. This document explains how to configure Maven to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Maven uses the `maven-surefire-plugin` by default to output JUnit XML reports, which is Trunk compatible. You can configure the plugin in your project's `pom.xml`. ### Report File Path You can change the report file path by configuring the `maven-surefire-plugin` plugin in your `pom.xml` file: ```xml title="pom.xml" theme={null} org.apache.maven.plugins maven-surefire-plugin 3.2.2 ${project.build.directory}/junit/ ``` The example above will output JUnit XML reports that can be located with the `./target/junit/*.xml` glob. ### Using Kotlin and Kotest If you have a Kotlin project and are using the Kotest test framework, you also need to include `kotest-extensions-junitxml` in your project's `pom.xml`. This allows Kotest to generate JUnit XML reports. ```xml title="pom.xml" theme={null} io.kotest kotest-extensions-junitxml-jvm 5.9.0 test ``` ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. Maven uses the `maven-surefire-plugin` to run tests, which allows you to control the test retry behavior. You can disable retries by specifying 0 retries: ``` mvn -Dsurefire.rerunFailingTestsCount=0 test ``` ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./target/junit/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./target/junit/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./target/junit/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./target/junit/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./target/junit/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # minitest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/minitest A guide for generating Trunk-compatible test reports for minitest You can automatically [detect and manage flaky tests](../../detection/) in your minitest projects by integrating with Trunk. This document explains how to configure minitest to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating Trunk-compatible XML reports from your test runs. To generate XML reports, install the `minitest-reporters` gem: ```shell theme={null} gem install minitest-reporters ``` Configure the `JUnitReporter` reporter in your `test_helper.rb` file: ```ruby title="test_helper.rb" theme={null} require "minitest/reporters" Minitest::Reporters.use! Minitest::Reporters::JUnitReporter.new ``` ### Report File Path You can specify a file path for your minitest results with the `MINITEST_REPORTERS_REPORTS_DIR` environment variable: ```sh theme={null} MINITEST_REPORTERS_REPORTS_DIR="./results" ruby -Ilib:test ``` This will automatically write all test results to JUnit XML files in the `results` directory. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. Minitest doesn't support retries out of the box, but if you implemented retries or imported a package, remember to disable them. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./results/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./results/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./results/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./results/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./results/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Mocha Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/mocha A guide for generating Trunk-compatible test reports for Mocha You can automatically [detect and manage flaky tests](../../detection/) in your Mocha projects by integrating with Trunk. This document explains how to configure Mocha to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Before integrating with Trunk, you need to generate Trunk-compatible reports. For Mocha, the easiest approach is to generate XML reports. First, install the `mocha-junit-reporter` package: ```shell theme={null} npm install --save-dev mocha-junit-reporter ``` You can then generate reports when you run your tests by providing the `--reporter` and `--reporter-options` options when you run your tests: ```sh theme={null} mocha --reporter mocha-junit-reporter --reporter-options mochaFile=./junit.xml ``` You can configure your Mocha runner to use the reporter programmatically as well: ```javascript theme={null} var mocha = new Mocha({ reporter: 'mocha-junit-reporter', reporterOptions: { mochaFile: './junit.xml' } }); ``` ### Report File Path The resulting JUnit XML file will be written to the location specified by the `mochaFile` property in `reporterOptions`. In the examples above, the results would be at `./junit.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You can disable retry by omitting the `--retries` CLI option and [removing retries for individual tests](https://mochajs.org/#retry-tests). ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Nightwatch Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/nightwatch A guide for generating Trunk-compatible test reports for Nightwatch You can automatically [detect and manage flaky tests](../../detection/) in your Nightwatch projects by integrating with Trunk. This document explains how to configure Nightwatch to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Nightwatch will automatically report test results in multiple formats. You can configure the output location by updating the `nightwatch.conf.cjs` config file. ```javascript theme={null} module.exports = { output_folder: 'test-reports', ... } ``` You can also specify output at runtime with the command line option `--output `: ```sh theme={null} nightwatch --output ./test-reports ``` ### Report File Path Nightwatch outputs multiple reports for each test suite under the specified output folder. If you configured your output folder to be under `./test-reports`, the JUnit XML files will be found under `./test-reports/**`. You can upload multiple JUnit reports by using a glob like `./test-reports/**/*.xml`. **Duplicate Uploads** When using globs, it's important to clean up old test reports between test runs. If your glob path contains old JUnit files, uploading old test results can cause tests to be mislabeled. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. Nightwatch doesn't implement any form of automatic retry for failed or flaky tests by default. If you have a custom implementation of retries, remember to disable them. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/**/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/**/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/**/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./test-reports/**/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./test-reports/**/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # NUnit Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/nunit A guide for generating Trunk-compatible test reports for NUnit You can automatically [detect and manage flaky tests](../../detection/) in your NUnit projects by integrating with Trunk. This document explains how to configure NUnit to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating Trunk-compatible XML reports from your test runs. You can do this in dotnet with the NUnit's built-in JUnit reporter: ```sh theme={null} dotnet test -o build -- NUnit.TestOutputXml="junit" ``` ### Report File Path .NET will output each build to the path specified by `-o ` and test results under a sub-folder of `/test-reports`, specified by the `-- NUnit.TestOutputXml=""` option. In the example command from the [Generating Reports step](./nunit#generating-reports), the XMLs will be located under `./build/test-reports/junit/*.xml`. This is also the glob you'll use to locate the results when uploading test results. ### Disable Retries You need to disable automatic retries if you previously included them. Retries compromise the accurate detection of flaky tests. Omit `[Retry(n)]` from tests to disable retries. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./build/test-reports/junit/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./build/test-reports/junit/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./build/test-reports/junit/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./build/test-reports/junit/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./build/test-reports/junit/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Other Test Frameworks Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/other-test-frameworks A guide for generating Trunk-compatible test reports with other test frameworks Trunk Flaky Tests is designed to be test framework agnostic. If you don't see a guide for your test framework, you can still use Flaky Tests. To use Flaky Tests, you will need to report test results in a format that Trunk understands and upload them to Trunk in CI. This guide will explain how to integrate your test framework with Trunk. ## 1. Generate JUnit Trunk detects flaky tests by analyzing each test case's results over time. Trunk currently supports the JUnit XML and XCResult report formats. You will need to configure your test runner to report in one of these formats using a plugin or your own test result reporter. Make sure your test reports accurately report the file name, test name, and stack trace of each test result. Make sure the test names are not randomized. These details help Trunk better detect and display your test cases' health status. ## 2. Output Location You'll need to validate and upload the generated JUnit files to Trunk later during the setup process. Make sure the reports are generated with a **consistent name** and aren't **cached or committed** to Git. ## 3. Validate Your Reports Since you'll be generating JUnit reports using a new plugin or custom reporter, you should use the Trunk Analytics CLI to validate your results and fix any warnings or errors. You can install the Trunk Analytics CLI locally like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ``` Then, you can validate the results using the `trunk-analytics-cli validate` command like this: ```bash theme={null} ./trunk-analytics-cli validate --junit-paths ``` ## Next Step You'll need to upload the JUnit reports generated by your CI jobs to Trunk so Trunk can [detect flaky tests](../../detection/) and [report them to the dashboard](../../dashboard). See [CI Providers](../ci-providers/) for a guide on how to upload test results to Trunk. # Pest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/pest A guide for generating Trunk-compatible test reports for Pest You can automatically [detect and manage flaky tests](../../detection/) in your PHP projects by integrating with Trunk. This document explains how to configure Pest to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating Trunk-compatible XML reports from your test runs. To generate XML reports, append `--log-junit junit.xml` to your `pest` test command: ```bash theme={null} pest --log-junit junit.xml ``` ### Report File Path The JUnit report is written to the location specified by `--log-junit`. In the example above, the test results will be written to `./junit.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. Pest doesn't support retries out of the box, but if you implemented retries, remember to disable them. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # PHPUnit Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/phpunit A guide for generating Trunk-compatible test reports for PHPUnit You can automatically [detect and manage flaky tests](../../detection/) in your PHP projects by integrating with Trunk. This document explains how to configure PHPUnit to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating Trunk-compatible XML reports from your test runs. To generate XML reports, append `--log-junit junit.xml` to your `phpunit` test command: ```bash theme={null} phpunit ./tests --log-junit junit.xml ``` ### Report File Path The JUnit report is written to the location specified by `--log-junit`. In the example above, the test results will be written to `./junit.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. PHPUnit doesn't support retries out of the box, but if you implemented retries, remember to disable them. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Playwright Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/playwright A guide for generating Trunk-compatible test reports for Playwright You can automatically [detect and manage flaky tests](../../detection/) in your Playwright projects by integrating with Trunk. This document explains how to configure Playwright to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Playwright has multiple built-in reporters, including JUnit XML which Trunk can ingest. To get XML reports, add the following to your Playwright config: ```typescript title="playwright.config.ts" theme={null} import { defineConfig } from '@playwright/test'; export default defineConfig({ reporter: [ ['junit', { outputFile: 'junit.xml' }] ], }); ``` Alternatively, you can specify reporting behavior inline in your CI: ```sh theme={null} npx playwright test --reporter=junit ``` ### Report File Path You can specify the report's output location with the `PLAYWRIGHT_JUNIT_OUTPUT_FILE` environment variable: ```sh theme={null} export PLAYWRIGHT_JUNIT_OUTPUT_FILE=junit.xml ``` You can also specify the report's location in your `playwright.config.ts` file: ```typescript theme={null} export default defineConfig({ reporter: [ ['junit', { outputFile: 'junit.xml' }] ], }); ``` ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. You can disable retries in Playwright by omitting the `--retries` command line option and [removing retries in your `playwright.config.ts` file](https://playwright.dev/docs/test-retries#retries). ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Step Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Pytest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/pytest A guide for generating Trunk-compatible test reports for Pytest You can automatically [detect and manage flaky tests](../../detection/) in your Pytest projects by integrating with Trunk. This document explains how to configure Pytest to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating JUnit XML reports from your test runs. In your CI job, update your `pytest` command to include the `--junit-xml` and `junit_family=xunit1` arguments to generate XML reports: ```shell theme={null} pytest --junit-xml=junit.xml -o junit_family=xunit1 ``` The `junit_family=xunit1` is necessary so that the generated XML report includes file paths for each test case. File paths for test cases are used for features that use code owners like the [Jira integration](../../management/ticketing/jira-integration) and [webhooks](../../webhooks/). ### Report File Path The `--junit-xml` argument specifies the path of the JUnit report. You'll need this path later when configuring automatic uploads to Trunk. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. Omit the [`--lf` or `--ff` options](https://docs.pytest.org/en/stable/how-to/cache.html) if you've previously configured your CI with these options to disable retries. ## Try It Locally You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Robot Framework Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/robot-framework A guide for generating Trunk-compatible test reports for Robot Framework You can automatically [detect and manage flaky tests](../../detection/) in your projects running tests with Robot by integrating with Trunk. This document explains how to configure Robot to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating Trunk-compatible XML reports from your test runs. To output compatible reports, add the `--xunit` argument to your `robot` command: ```shell theme={null} robot --xunit=junit.xml TestSuite.robot ``` ### Report File Path The JUnit report will be written to the location specified by the `--xunit` argument. In the example above, it would be at `./junit.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable them and prefer using the [Quarantine](../../quarantining/) feature to mitigate the negative impact of Flaky Tests. Omit the [`--rerunfailed`](https://docs.robotframework.org/docs/flaky_tests#re-execute-failed-tests-and-merge-results) flag and remove any [RetryFailed Listeners](https://docs.robotframework.org/docs/flaky_tests#retryfailed-listener) previously configured to run as part of your CI pipeline to disable retries. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # RSpec Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/rspec/index A guide for generating Trunk-compatible test reports for RSpec using Trunk's RSpec plugin You can automatically [detect and manage flaky tests](../../../detection/) in your projects running RSpec by integrating with Trunk. This document explains how to use Trunk's RSpec plugin to upload test results to Trunk. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../../ci-providers/). Set up and install Trunk's RSpec plugin} /> Disable retries for better detection accuracy} /> Test uploads locally} /> Using the plugin is the best way to accurately detect flaky RSpec tests. You can also [manually generate and upload](./manual-uploads) test results in RSpec, however, **manual RSpec uploads are not recommended.** ## Installing the plugin Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this for your Rspec tests using Trunk's RSpec plugin. To install the plugin in your project, add the `rspec_trunk_flaky_tests` gem to your `Gemfile`: ```shell title="Gemfile" theme={null} gem "rspec_trunk_flaky_tests" ``` Install the plugin: ```sh theme={null} bundle install ``` Then, load the plugin in `spec_helper.rb`: ```shell title="spec/spec_helper.rb" theme={null} require "trunk_spec_helper" ``` ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. If you have a step in CI to rerun failed tests with the `--only-failures` option, or you're using a package like [rspec-retry](https://github.com/NoRedInk/rspec-retry), remember to disable them. ### Versions and Updating the Plugin You can find the Gem for `rspec_trunk_flaky_tests` [here](https://rubygems.org/gems/rspec_trunk_flaky_tests), along with its version history. This plugin is periodically updated with improved support and bug fixes. If you're encountering something unexpected, first try: ``` bundle update rspec_trunk_flaky_tests ``` If a failing test raises `RSpec::Core::MultipleExceptionError`, only one of the captured exceptions appears in the failure detail view today. See [Known limitations](../../../dashboard#known-limitations) for the current status and workaround. ### Environment Variables These optional environment variables can be set in your project to change the behavior of the RSpec plugin. ### Repository metadata variables: | Argument | Description | | ------------------------------ | ----------------------------------------------------------------------------------------- | | `TRUNK_REPO_ROOT` | Path to repository root | | `TRUNK_REPO_URL` | Repository URL (e.g., [https://github.com/org/repo.git](https://github.com/org/repo.git)) | | `TRUNK_REPO_HEAD_SHA` | HEAD commit SHA | | `TRUNK_REPO_HEAD_BRANCH` | HEAD branch name | | `TRUNK_REPO_HEAD_COMMIT_EPOCH` | HEAD commit timestamp (seconds since epoch) | | `TRUNK_REPO_HEAD_AUTHOR_NAME` | HEAD commit author name | ### Configuration variables: | Argument | Description | | --------------------------------- | --------------------------------------------------------- | | `TRUNK_CODEOWNERS_PATH` | Path to CODEOWNERS file | | `TRUNK_VARIANT` | Variant name for test results (e.g., 'linux', 'pr-123') | | `TRUNK_DISABLE_QUARANTINING` | Set to 'true' to disable quarantining | | `TRUNK_ALLOW_EMPTY_TEST_RESULTS` | Set to 'true' to allow empty results | | `TRUNK_DRY_RUN` | Set to 'true' to save bundle locally instead of uploading | | `TRUNK_USE_UNCLONED_REPO` | Set to 'true' for uncloned repo mode | | `TRUNK_LOCAL_UPLOAD_DIR` | Directory to save test results locally (disables upload) | | `DISABLE_RSPEC_TRUNK_FLAKY_TESTS` | Set to 'true' to completely disable Trunk | ## Try It Locally ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} TRUNK_ORG_URL_SLUG= \ TRUNK_API_TOKEN= \ bundle exec rspec ``` You can find your Trunk organization URL slug and token in the **Settings** or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the test report uploaded by the plugin has issues. You do not need to download the `trunk-analytics-cli` when using the Trunk RSpec plugin. Uploads are handled for you as long as you have set `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN`. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # RSpec (Manual Uploads) Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/rspec/manual-uploads A guide for generating Trunk-compatible test reports for RSpec without using Trunk's RSpec plugin You can automatically [detect and manage flaky tests](../../../detection/) in your projects running RSpec by integrating with Trunk. This document explains how to configure RSpec to output JUnit XML reports that can be uploaded to Trunk for analysis. We highly recommend using [Trunk's RSpec plugin](./) to upload test results for the best accuracy when detecting flaky tests. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this for your Rspec tests by generating JUnit XML reports from your test runs. To generate Trunk-compatible reports, install the `rspec_junit_formatter`: ```shell theme={null} gem install rspec_junit_formatter ``` You can use `rspec_junit_formatter` like this: ```shell theme={null} rspec --format RspecJunitFormatter --out junit.xml ``` ### Report File Path The JUnit report will be written to the location specified by the `--out` argument. In the example above, the report would be at `./junit.xml`. You will need this when you update your CI config to integrate with Trunk. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. If you have a step in CI to rerun failed tests with the `--only-failures` option, or you're using a package like [rspec-retry](https://github.com/NoRedInk/rspec-retry), remember to disable them. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # cargo-nextest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/rust A guide for generating Trunk-compatible test reports for Rust You can automatically [detect and manage flaky tests](../../detection/) in your Rust projects by integrating with Trunk. This document explains how to configure cargo-nextest to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports `cargo-nextest` has built-in reporting for JUnit XML reports, which is trunk-compatible. You can enable JUnit reporting by adding the following to your nextest config: ```toml title=".config/nextest.toml" theme={null} [profile.ci.junit] path = "junit.xml" ``` You can invoke this profile when running tests with: ```sh theme={null} cargo nextest run --profile ci ``` ### Report File Path `cargo-nextest` outputs artifacts at `target/nextest` by default. When you provide a profile and a file name via the config example above, it produces a report at `target/nextest/ci/junit.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. Omit the `--retries` option. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./target/nextest/ci/junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./target/nextest/ci/junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./target/nextest/ci/junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./target/nextest/ci/junit.xml" ``` This will not upload anything to Trunk. To improve detection accuracy, you should address all errors and warnings before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./target/nextest/ci/junit.xml" \ --org-url-slug \ --token ``` ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Swift Testing Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/swift-testing A guide for generating Trunk-compatible test reports with Swift Testing You can automatically [detect and manage flaky tests](../../detection/) in your Swift projects by integrating with Trunk. This document explains how to configure Swift Testing to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating Trunk-compatible XML reports from your test runs. To output a compatible report, add the `--xunit-output` argument to your Swift test command: ```shell theme={null} swift test --xunit-output junit.xml --parallel ``` Due to a [known bug](https://github.com/swiftlang/swift-package-manager/issues/4752) with Swift, you must include the `--parallel` flag for the XML report to output properly. ### Report File Path The test report will be written to the location specified by the `--xunit-output` argument. In the example above, it would be at `./junit.xml`. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. Swift Testing doesn't support retries out of the box, but if you implemented retries or imported a package, remember to disable them. ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Testplan Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/testplan A guide for generating Trunk-compatible test reports for Testplan You can automatically [detect and manage flaky tests](../../detection/) in your projects running Testplan by integrating with Trunk. This document explains how to configure Testplan to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. Testplan can output JUnit XML reports which are compatible with Trunk. You can do so with the `--xml` option: ```sh theme={null} ./test_plan.py --xml ``` ### Report file path You can specify the file path for the reports with the `--xml` option. ```sh theme={null} ./test_plan.py --xml ./junit-reports ``` Testplan outputs multiple XML reports under the JUnit directory. You can locate these when uploading the reports in CI with the `"./junit-reports/*.xml"` glob. ```python Python theme={null} @test_plan(name='SamplePlan', xml_dir='junit-reports') def main(plan): ... ``` ## Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. ### Task-level Retries If you're using execution pools (ThreadPool, ProcessPool) and have configured tasks with the rerun parameter, you should remove this configuration: ```python theme={null} # Remove or set rerun=0 task = Task(target='make_multitest', module='tasks', rerun=2) plan.schedule(task, resource='MyPool') # Instead, use: task = Task(target='make_multitest', module='tasks') plan.schedule(task, resource='MyPool') ``` ### Thread Pool Retries If you're using ThreadPools, tasks retries can be disabled at the pool level, you should remove this configuration: ```python theme={null} # Set allow_task_rerun=FALSE pool = ThreadPool(name="MyPool", allow_task_rerun=True) # Instead, use: pool = ThreadPool(name="MyPool", allow_task_rerun=False) ``` ## Try It Locally ### The Validate Command You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit-reports/*.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} ./trunk-analytics-cli upload --junit-paths "./junit-reports/*.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Steps Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Vitest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/vitest A guide for generating Trunk-compatible test reports with Vitest You can automatically [detect and manage flaky tests](../../detection/) in your Vitest projects by integrating with Trunk. This document explains how to configure Vitest to output JUnit XML reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Trunk detects flaky tests by analyzing test results automatically uploaded from your CI jobs. You can do this by generating Trunk-compatible XML reports from your test runs. You can configure Vitest to produce a Trunk-compatible JUnitXML report by updating your `vitest.config.ts`. ```javascript title="vitest.config.ts" theme={null} import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { reporters: [ ['junit', { outputFile: './junit.xml', addFileAttribute: true }], ], }, }); ``` **Important**: The `addFileAttribute: true` option is required for the JUnit report to pass `trunk-analytics-cli` validation. This option adds file path information to each test case in the XML output, which Trunk uses to associate test results with source files. ### Report File Path The `outputFile: './junit.xml'` option specifies the path of the JUnit report. You'll need this path later when configuring automatic uploads to Trunk. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. If you've enabled retries, you can disable them following the [Vitest docs](https://vitest.dev/api/) for more accurate results. **Note**: Configuration errors can sometimes mask themselves as consistent test failures. If you're seeing file-level test entries instead of individual test cases, resolve configuration issues first before adjusting retry settings. A properly configured test suite should show individual test case names in the JUnit output, not file names. ## Troubleshooting **Configuration Errors and File-Level Test Failures** **Issue**: You might see Trunk identifying flaky tests with names that match your test file names (e.g., `auth.test.ts` instead of `should login successfully`) rather than individual test case names. **Root Cause**: This typically occurs when Vitest encounters configuration errors that prevent it from properly parsing or running the tests in a file. Common scenarios include: * TypeScript configuration errors in `tsconfig.json` * Missing dependencies or import resolution failures * Syntax errors in test setup files * Invalid Vitest configuration options **What Happens**: When Vitest cannot execute the individual tests within a file due to configuration issues, it generates a single JUnit test case entry named after the file itself, regardless of how many actual test cases exist in that file. **How to Diagnose**: 1. Run your tests locally with verbose output: `vitest --reporter=verbose` 2. Check for configuration warnings or errors in the test output 3. Look for test files that show as single entries in your JUnit report when they should contain multiple test cases **How to Fix**: 1. **Check TypeScript Configuration**: Ensure your `tsconfig.json` is valid and includes all necessary paths 2. **Verify Dependencies**: Make sure all imported modules are properly installed and accessible 3. **Review Setup Files**: Check any test setup files referenced in your Vitest config for errors 4. **Validate Vitest Config**: Make sure your `vitest.config.ts` doesn't contain invalid options ## Try It Locally ### Validate Test Execution First Before validating your JUnit reports with Trunk, make sure Vitest can properly execute your tests: ```bash theme={null} # Run tests with detailed output to catch configuration issues vitest run --reporter=verbose # Check that individual test cases appear in output, not just file names vitest run --reporter=json | jq '.testResults[].assertionResults' ``` If you see test files listed as single entries rather than individual test cases, you likely have configuration issues that need to be resolved before proceeding. You can validate your test reports using the [Trunk Analytics CLI](../../reference/cli-reference). If you don't have it installed already, you can install and run the `validate` command like this: ### The Validate Command ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli validate --junit-paths "./junit.xml" ``` **This will not upload anything to Trunk**. To improve detection accuracy, you should **address all errors and warnings** before proceeding to the next steps. ### Test Upload Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```sh theme={null} curl -fL --retry 3 "https://github.com/trunk-io/analytics-cli/releases/latest/download/trunk-analytics-cli-x86_64-unknown-linux.tar.gz" | tar -xz && chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --junit-paths "./junit.xml" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Step Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # XCTest Source: https://docs.trunk.io/flaky-tests/get-started/frameworks/xctest A guide for generating Trunk-compatible test reports for XCode and xcodebuild You can automatically [detect and manage flaky tests](../../detection/) in your XCTest projects by integrating with Trunk. This document explains how to configure XCTest to output XCResult reports that can be uploaded to Trunk for analysis. ## Setup steps Work through the steps below in order. Once you've finished the last one, you'll be ready to move on to [configure uploads in CI](../ci-providers/). Generate a compatible test report} /> Configure the report file path or glob} /> Disable retries for better detection accuracy} /> Test uploads locally} /> ## Generating Reports Running XCTests from `xcodebuild` produces a `.xcresult` in an obscure directory by default. You can specify a `-resultBundlePath` option to generate the results locally: ```sh theme={null} xcodebuild test -scheme \ -resultBundlePath ./test-results.xcresult ``` You can upload `.xcresult` directories directly to Trunk Flaky Tests. Only XCode versions 16 or higher are supported. ### Report File Path The test reports will be written to the `./test-results.xcresult` directory when running tests with the `-resultBundlePath ./test-results.xcresult`option. You will need this path when uploading results to Trunk in CI. ### Disable Retries You need to disable automatic retries if you previously enabled them. Retries compromise the accurate detection of flaky tests. You should disable retries for accurate detection and use the [Quarantining](../../quarantining/) feature to stop flaky tests from failing your CI jobs. If you run tests in CI with [the `-retry-tests-on-failure` option](https://keith.github.io/xcode-man-pages/xcodebuild.1.html#retry-tests-on-failure), disable it for more accurate results. ## Try It Locally Before modifying your CI jobs to automatically upload test results to Trunk, try uploading a single test run manually. You make an upload to Trunk using the following command: ```bash Linux (x64) theme={null} SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --xcresult-path "./test-results.xcresult" \ --org-url-slug \ --token ``` ```bash Linux (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --xcresult-path "./test-results.xcresult" \ --org-url-slug \ --token ``` ```bash macOS (arm64) theme={null} SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --xcresult-path "./test-results.xcresult" \ --org-url-slug \ --token ``` ```bash macOS (x64) theme={null} SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz" curl -fL --retry 3 \ "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \ | tar -xz chmod +x trunk-analytics-cli ./trunk-analytics-cli upload --xcresult-path "./test-results.xcresult" \ --org-url-slug \ --token ``` You can find your Trunk organization slug and token in the settings or by following these [instructions](/flaky-tests/get-started/ci-providers/otherci#id-1.-store-a-trunk_token-secret-in-your-ci-system). After your upload, you can verify that Trunk has received and processed it successfully in the **Uploads** tab. Warnings will be displayed if the report has issues. ## Next Step Configure your CI to upload test runs to Trunk. Find the guides for your CI framework below: # Getting Started Source: https://docs.trunk.io/flaky-tests/get-started/index Set up Trunk Flaky Tests by configuring test result output, uploading from CI, and enabling flake detection monitors. Trunk Flaky Tests detects flaky tests by analyzing test results from your CI runs. Setup requires configuring test result output and CI upload integration. ## Prerequisites * Account at [app.trunk.io](https://app.trunk.io) * Ability to modify repository CI configuration and add secrets * Tests running in CI on both PRs and stable branches (e.g., main, master, or develop) ### Step 1: Ensure JUnit XML output Trunk ingests test results in JUnit XML format. If your CI already generates JUnit XML, note the file paths and skip to Step 2. If not, configure your test frameworks to output JUnit XML: * See [**Test Frameworks**](./frameworks/) for framework-specific configuration * Supports multiple frameworks simultaneously ### Step 2: Configure CI uploads Add test result uploads to all CI jobs that run tests. 1. See [**CI Providers**](./ci-providers/) for integration instructions 2. Configure uploads in jobs that run on: * Pull request branches * Stable branches (`main`, `master`, `develop`, etc.) * Merge queue branches (if applicable) Uploads from both PRs and stable branches are required for Trunk Flaky Tests to accurately detect flaky tests. Trunk automatically recognizes `main`, `master`, and `develop` as stable branches. If your primary branch uses a different name, configure uploads from that branch the same way and Trunk will classify it correctly. ### Step 3: Verify integration 1. Push your changes and trigger a CI run 2. Check CI logs for successful upload confirmation 3. Results typically appear within a few minutes. Verify uploads appear at [app.trunk.io](https://app.trunk.io) → your repo → **Flaky Tests** → **Uploads** ### Step 4: Configure flake detection After uploads are flowing, navigate to your repo → **Flaky Tests** → **Monitors** to set up detection. **Pass-on-retry** is enabled by default and is the recommended baseline for everyone. It catches the most common flakiness pattern — a test that fails and then passes on retry within the same commit — without any configuration needed. **Failure rate monitors** let you detect flakiness based on failure rate over a rolling time window. How you configure them depends on your CI setup: * **If tests must pass before merging to main**, set up a failure rate monitor scoped to `main` to catch an elevated failure rate. For example, if you run tests 5 times per day on `main`, a 24-hour rolling window with a minimum of 4 runs and a failure threshold of 25% is a reasonable starting point. This gives the monitor enough data before flagging anything. * **If you use a merge queue**, consider a dedicated monitor scoped to your merge queue branches (e.g., `trunk-merge/*` or `gh-readonly-queue/*`). Failures here are especially suspicious since the code has already passed PR checks, so a low threshold is appropriate. [How failure rate monitors work →](../detection/failure-rate-monitor) ### Quarantining Quarantining suppresses failures from known flaky tests, preventing them from forcing CI re-runs or blocking your merge queue. Flaky tests continue to run and report results — they just don't cause pipeline failures while your team works on fixes. This is especially valuable for unblocking merge queues and keeping development velocity high. [Configure Quarantining →](../quarantining/) # Multiple Repositories and Forks Source: https://docs.trunk.io/flaky-tests/get-started/multiple-repositories Learn how Trunk identifies repositories, track tests across forks and multiple repositories, and enable test uploads from fork PR workflows. Trunk Flaky Tests identifies repositories by their **git remote URL**, not by the API token. You can safely use the same organization API token across multiple repositories, including forks, without mixing test results. ## How Repository Identification Works When the Trunk Analytics CLI uploads test results, it reads the git remote URL from your CI environment and parses it into three components: * **Host**: `github.com`, `gitlab.com`, or your self-hosted instance * **Owner**: The organization or user (e.g., `your-company`) * **Name**: The repository name (e.g., `your-repo`) These three components together uniquely identify the repository in Trunk. The API token determines which *organization* the upload belongs to, but does not affect which *repository* the results are associated with. ### Uploading from Fork Pull Requests Fork pull requests can't upload with your org API token. GitHub Actions workflows triggered by `pull_request` events from a fork run with read-only permissions and can't read repository secrets, so `$TRUNK_API_TOKEN` isn't available. Trunk solves this with a per-repo opt-in that mints a non-secret **public repo identifier** the fork workflow uses instead. This is intended for public repositories that accept external contributions. For private repositories or internal forks, keep using the standard `$TRUNK_API_TOKEN` approach. **Enable fork PR uploads.** In the Trunk web app, navigate to **Settings** → **Repositories** → **\[your repo]** → **Flaky Tests** and toggle on **Fork PR Uploads**. Copy the **Public Repo Identifier** that appears below the toggle — an 8-character alphanumeric code scoped to that one repository. The Fork PR Uploads setting in a repository's Flaky Tests settings, showing the enabled toggle and the public repo identifier The identifier persists across toggles. Disabling stops accepting fork PR uploads, but re-enabling reuses the same identifier rather than generating a new one. **Use the identifier in your fork workflow.** Pass it in place of the org API token. With the Trunk uploader action, set the `public-repo-id` input: ```yaml theme={null} jobs: test: runs-on: ubuntu-latest steps: - name: Run Tests run: ... - name: Upload Test Results to Trunk.io if: ${{ !cancelled() }} continue-on-error: true uses: trunk-io/analytics-uploader@v2 with: junit-paths: "**/junit.xml" org-slug: ${{ vars.TRUNK_ORG_SLUG }} public-repo-id: ``` If you call the CLI directly instead of the action, pass `--public-repo-id ` (or set the `TRUNK_PUBLIC_REPO_ID` environment variable). Either way the CLI sends the value on the `X-Trunk-Public-Repo-Id` header. The public repo identifier is not a secret. It is safe to commit directly in your workflow file. Do not use your org API token in fork PR workflows. **How authorization works.** The identifier is a routing and rate-limiting key, not a credential. Trunk accepts a fork PR upload only when two independent checks both pass: 1. The repository has **Fork PR Uploads** enabled in settings. 2. The upload targets the repository the identifier belongs to. An identifier only authorizes uploads to its own repository; an upload aimed at any other repository is rejected. The identifier alone does not grant upload access. To stop accepting fork PR uploads, disable **Fork PR Uploads** in settings. ### Using Trunk with Forks If you run tests from a fork, Trunk automatically keeps test results separate based on the fork's remote URL. For example, if your company forks `metabase/metabase` to `your-company/metabase-fork`: | Repository | Remote URL | Trunk Repo ID | | ---------- | --------------------------------------- | ---------------------------- | | Original | `github.com/metabase/metabase` | `metabase/metabase` | | Your fork | `github.com/your-company/metabase-fork` | `your-company/metabase-fork` | You can use the same organization API token for both repositories. Trunk creates separate repo entries and keeps all test data isolated. No special configuration is needed for forks. As long as your fork has a different remote URL (which it does by default), Trunk keeps the data separate automatically. ## Verifying Your Remote URL Before setting up uploads, verify your CI job is using the correct remote URL: ```bash theme={null} git remote -v # origin git@github.com:your-company/metabase-fork.git (fetch) # origin git@github.com:your-company/metabase-fork.git (push) ``` Some CI providers set environment variables like `GITHUB_REPOSITORY` that may differ from your git remote. The CLI reads the git remote URL by default. If your CI environment modifies the remote, use the `--repo-url` flag to override repository detection. ## Overriding Repository Detection In some CI environments, you may need to manually specify the repository URL: * The git remote is not available or is incorrect * You are uploading results from a build artifact without a git checkout * A shallow clone has modified remotes Override the repository URL with the `--repo-url` flag: ```bash theme={null} ./trunk-analytics-cli upload \ --junit-paths "test_output.xml" \ --org-url-slug \ --token $TRUNK_API_TOKEN \ --repo-url "https://github.com/your-company/your-repo.git" ``` You can also set the repository URL via the `TRUNK_REPO_URL` environment variable: ```bash theme={null} export TRUNK_REPO_URL="https://github.com/your-company/your-repo.git" ./trunk-analytics-cli upload \ --junit-paths "test_output.xml" \ --org-url-slug \ --token $TRUNK_API_TOKEN ``` See the [Trunk Analytics CLI](/flaky-tests/reference/cli-reference) reference for the full list of override flags. ## Monorepo with Multiple Test Suites To track different test suites within the same repository separately, use the `--variant` flag: ```bash theme={null} # Frontend tests ./trunk-analytics-cli upload \ --junit-paths "frontend/test_output.xml" \ --variant "frontend" \ --org-url-slug \ --token $TRUNK_API_TOKEN # Backend tests ./trunk-analytics-cli upload \ --junit-paths "backend/test_output.xml" \ --variant "backend" \ --org-url-slug \ --token $TRUNK_API_TOKEN ``` ## Troubleshooting ### Test results appearing in wrong repository 1. **Check your git remote**: Run `git remote -v` in your CI job to verify the URL. 2. **Check CI environment variables**: Some CI providers override git configuration. 3. **Use explicit override**: Set `--repo-url` to force the correct repository. ### Duplicate repositories in dashboard This can happen if the same repository is uploaded with different URL formats (e.g., HTTPS vs SSH). To resolve: 1. Standardize the remote URL format across all CI jobs. 2. Use `--repo-url` to set a consistent URL. 3. Contact [support@trunk.io](mailto:support@trunk.io) to merge duplicate repository entries. ## FAQ | Question | Answer | | ------------------------------------------------ | ------------------------------------------------------------------- | | Can I use the same API token for multiple repos? | Yes. The token is org-scoped, not repo-scoped. | | Will fork test results mix with upstream? | No. Repos are identified by remote URL, not by token. | | Do I need separate tokens for forks? | No. The same token works for all repos in your organization. | | Can I override the detected repository? | Yes. Use `--repo-url` or the `TRUNK_REPO_URL` environment variable. | # Pull request comments Source: https://docs.trunk.io/flaky-tests/management/github-pull-request-comments Flaky Tests provides summary analytics about tests running on Pull Requests Flaky Tests can post comments on GitHub pull requests that summarize test results across CI jobs. These comments indicate which failures are flaky and include the test’s failure history and related context. **Note:** Flaky Tests will only post a comment when there are failing tests. Each GitHub comment includes a summary report showing all tests that passed, failed, flaked, were skipped, or were quarantined on the PR. Each test case includes the full stack trace when expanded, and the job run link takes you to the complete CI logs. ## Configuration Install the [Trunk GitHub App](../../setup-and-administration/github-app-permissions) and [upload JUnit XML](../get-started/frameworks/) test results on pull requests. Once both are in place, expect to start seeing comments on your pull requests soon. ## Disable commenting Pull Request comments are enabled by default. If you wish to disable the comments, you can do so by navigating to **Settings** → **Repositories** → **\[your repository]** → **Flaky Tests** and toggling the **Summary Flaky Tests Reports** setting. ## Troubleshooting At any point, feel free to reach out to our team at [support@trunk.io](mailto:support@trunk.io). # Flaky test management Source: https://docs.trunk.io/flaky-tests/management/index Organize, triage, and coordinate follow-up for detected flaky tests. # Managing detected flaky tests Source: https://docs.trunk.io/flaky-tests/management/managing-detected-flaky-tests A step-by-step guide for building an automated process to manage detected flaky tests. It is important to have a follow-up process in place to manage detected flaky tests. A good process makes sure flaky tests do not slow down CI for your development team and prevents flakes from accumulating over time. This guide walks through Trunk's recommended best practices for building a process around detected flaky tests in your organization. Flaky tests will be [automatically detected](../detection/) by Trunk after you: * [Set up your test framework](../get-started/frameworks/) to produce test reports * [Integrated with your CI provider](../get-started/ci-providers/) to upload those reports on CI runs. Go through these guides first to start detecting flaky tests. ## Prerequisites * A Trunk organization with Flaky Tests enabled and at least one repo connected * Your [test framework set up to produce test reports](../get-started/frameworks/) and your [CI provider uploading those reports](../get-started/ci-providers/) * Member access to the Trunk app to view and edit tests; Admin access if you also need to configure ticketing or webhook integrations ### Step 1: Organize tests with labels Test labels let you categorize and group related flaky tests within Trunk. Labels are useful for tracking tests by team, component, root cause, or any grouping that fits your workflow. To assign or remove labels on a test: 1. Open the test detail page in the Trunk app. 2. In the **Metadata** section at the top of the page, click the **Labels** field. 3. Select labels from the picker or type to create new ones. Remove labels by clicking the **x** on any applied label. Labels you apply are visible on the test detail page. Use them to filter and prioritize your backlog of flaky tests. ### Step 2: Create tickets for flaky tests Creating Linear or Jira tickets for detected flaky tests helps to integrate flaky test fixes into your existing workflows. * Start by [connecting to Linear or Jira](./ticketing/). You can also set default labels or teams for flaky test tickets. * Once connected, you can click **Create Ticket** on a test detail page in Trunk. Trunk will create the ticket with context, including the test ID, flake rate, and the last failure stack trace and reason. * The ticket status and assignee will be visible on the test details page in Trunk, and these details will stay in sync with changes to the ticket. ### Step 3: Broadcast flakes It is important to keep the team informed on all status changes for flaky tests . This allows for fast follow-up when a test is marked as flaky. * Use the [built-in Slack or Microsoft Teams webhook integrations](../webhooks/) to transform webhook payloads into messages. * Trunk's built-in templates help you get started and test the connection. * You can then customize the transformation to update the message format and content, including @-mentioning test owners so they can follow up right away. ### Step 4: Mute monitors If a flaky test has a known issue or a fix in progress, you can mute the monitor that flagged it. A muted monitor continues to run and record detections, but it does not contribute to the test's flaky status until the mute expires or is manually removed. To mute a monitor: 1. Navigate to the test case detail page in the Trunk app. 2. Find the monitor that flagged the test. 3. Click **Mute** and select a duration. | Duration | Description | | -------- | ---------------------------------------- | | 1 hour | Quick suppression for transient issues | | 4 hours | Short-term suppression | | 24 hours | Suppress for a full day | | 7 days | Suppress for a week | | 30 days | Suppress for a month | | Forever | Mute indefinitely until manually unmuted | The **Forever** option mutes the monitor with no expiration. The monitor stays muted until you explicitly unmute it from the test case detail page. This is useful when a test has a known flake that your team has accepted, or when a fix is planned but not yet scheduled. For timed durations, the monitor automatically unmutes when the period expires. If the monitor is still detecting flaky behavior at that point, the test will be flagged as flaky again. You can optionally provide a reason when muting a monitor. This helps your team understand why the monitor was muted and makes it easier to review muted monitors later. You can unmute a monitor at any time from the test case detail page, regardless of the selected duration. Muting suppresses the monitor's contribution to the test's status. If the muted monitor was the only active monitor for a test, the test transitions from flaky to healthy for the duration of the mute. ### Step 5: Flag flaky tests If automated detection hasn't caught a test you know is flaky, you can manually [flag it as flaky](../detection/flag-as-flaky) from the test detail page. Flagged tests are treated as flaky even when no monitor detects them, and the flag can be removed at any time. Note that active broken monitors will take precedence over the manual flaky flag. ### Step 6: Quarantine flaky tests Flaky tests slow down CI and have a high negative impact on merge queue throughput. You can minimize or eliminate this CI slowdown by [quarantining](../quarantining/) flaky tests at runtime. * Enable quarantining for your repo at **Settings** → **\[your repo]** → **Enable Test Quarantining**. * Manually quarantine flaky tests by going to the test details page, clicking **Quarantine**, and setting the status to **Always**. Leave a comment detailing why you are quarantining this test to keep your team informed. The comment and quarantine status change will appear in the timeline on the test details page. After quarantining a test, Trunk will ignore the test result (pass/fail) on CI runs, preventing this flaky test from failing CI. **Broken tests are not quarantine candidates.** Only tests with a **Flaky** status are eligible for quarantine. If a test is marked as Broken (consistently failing at a high rate), it represents a real regression that should be investigated and fixed rather than hidden. See [detection](../detection/) to understand the difference between flaky and broken tests. ### Step 7: Automation Trunk has [webhooks](../webhooks/) and [Flaky Tests APIs](../reference/api-reference) that can be used to build custom workflows around ticket creation, linking existing tickets to Trunk, sending notifications, and dealing with quarantined tests. There is also built-in automation support that handles tasks such as assigning flaky test ownership, ticket creation, and quarantining (so that unblocking CI is not a manual process). * [`CODEOWNERS` files](../dashboard#code-owners) can automatically assign ownership of test flakes. * Tickets can be [auto-created using webhooks](../webhooks/) as triggers, similar to Slack or MS Teams notifications. * Automatically quarantine flaky tests by enabling **Settings** → **\[your repo]** → **Auto-Quarantine Flaky Tests**. You can customize how flaky and quarantined tests are handled to suit your team and organization best. ### Step 8: Review existing flakes and broken tests It is important to track and triage existing flaky and broken tests over time. Trunk collects historical failure logs and stack traces, providing developers as much information as possible for debugging high-impact test failures. * Review all new flaky and broken tests to determine their impact and the urgency of a fix. Broken tests (consistently failing at a high rate) should typically be prioritized over flaky tests as they represent real regressions. * Review existing quarantined tests regularly to decide which tests should be fixed and which tests should be deleted from your test suite. * Trunk can send weekly email reports with information such as your total number of flaky tests and the number of PRs blocked, and how those numbers have changed week over week. Frequently failing tests will also be highlighted in the report. Contact [support@trunk.io](mailto:support@trunk.io) to ask about enabling weekly reports for your organization. ## In summary: Build a process around managing flaky tests Building processes for dealing with flaky tests helps decrease or eliminate their impact on CI and reduce the amount of developer time lost to debugging flakes and CI reruns. Trunk allows you to customize this process to fit into your existing tooling and workflows, and automates manual tasks such as notifications and ticket creation. Contact [support@trunk.io](mailto:support@trunk.io) to chat about how to structure a process for managing flaky tests across your team or organization. # Test Labels Source: https://docs.trunk.io/flaky-tests/management/test-labels Organize and categorize test cases with organization-scoped labels. Test labels are organization-scoped tags you can apply to individual test cases to organize, filter, and categorize your test suite. Labels can be applied [manually from the test detail page](#apply-and-remove-labels-on-a-test-case) or [automatically by a monitor](#automatic-labeling-from-monitors). Labels applied to a test on details page Labels applied to a test on details page ## Manage labels Labels are created, edited, and deleted at **Settings** → **Organization** → **Test Labels**. Each label has a name, an optional description, and a color used for its chip in the UI. The settings page also shows how many test cases each label is currently applied to. Any organization member can create, edit, assign, and unassign labels. Only organization admins can delete labels — the Delete option in each label's menu is disabled for non-admins. Deleting a label removes it from every test case it's applied to; this cannot be undone. A label that is referenced by a monitor's [label action](#automatic-labeling-from-monitors) cannot be deleted — the settings page lists the monitors that still reference it so you can clear those references first. Settings page to manage test labels ## Apply and remove labels on a test case You apply and remove labels from a test case using the label picker on the test case detail page. The picker lets you search existing labels, toggle them on or off, and create a new label inline if one doesn't already exist. Each assignment records who applied the label and when. Label picker on test details page ## Filter tests by label On the tests list, you can filter the table down to test cases that have a particular label applied. This makes labels useful for slicing the view by the categories your team cares about. Filter tests to those that have specified label applied ## Automatic labeling from monitors The [pass-on-retry](../detection/pass-on-retry-monitor), [failure rate](../detection/failure-rate-monitor), and [failure count](../detection/failure-count-monitor) monitors can be configured to apply one or more labels to a test instead of classifying it as flaky or broken. Use this when you want a monitor to surface a pattern (for example, *fails on retry on PR branches*) for triage or filtering without changing the test's health status. The same setup also works as a [dry-run](../detection/#dry-running-with-labels) while you tune a new monitor before flipping it to classify. ### Choose the monitor's action When you create or edit one of these monitors, the **Action** section asks what happens when the monitor activates: * **Classify test status** (the default) — marks the test as flaky or broken while the monitor is active, and restores the test to healthy when the monitor resolves. This is the original behavior. * **Apply labels** — adds the configured labels to the test while the monitor is active. The test's health status is not changed by this monitor. A monitor uses one action or the other, not both. ### Configure the label action After selecting **Apply labels**, pick one or more labels from your organization's label set. You can create a new label inline if the one you need doesn't exist yet — the new label is added to the org-wide set in [**Settings** → **Organization** → **Test Labels**](#manage-labels). By default, the labels are removed when the monitor resolves. Turn off **Remove these labels when the monitor resolves** to keep them on the test after the monitor stops reporting. ### How monitor-applied labels appear Monitor-applied labels show up in the same places as manually applied labels: as chips on the [tests list](#filter-tests-by-label) and on the test detail page. Hovering a label tells you whether a user, one or more monitors, or a combination applied it, along with when it was first applied. When the same label is applied to a test by multiple sources (for example, by a user and by a monitor, or by two different monitors), the label stays on the test until every source removes it. Removing the source (such as disabling the monitor or switching its action away from **Apply labels**) clears that source's contribution on the next evaluation. ## Related * [Managing detected flaky tests](./managing-detected-flaky-tests) — a step-by-step process for handling detected flaky tests * [Flake Detection](../detection/) — monitors that watch for problematic test behavior # Asana integration Source: https://docs.trunk.io/flaky-tests/management/ticketing/asana-integration Triage your flaky tests faster by creating automatically assigned and labeled tasks with the Asana integration When Trunk Flaky Tests [detects a flaky test](../../detection/index), you can create an automatically generated Asana task for your team to pick up and fix the test. Asana tasks are created in a single project that you choose during setup. Throughout this page, "ticket" and "task" mean the same thing — Trunk calls it a ticket, Asana calls it a task. ## Connecting to Asana To connect an Asana project: 1. In the Trunk app, navigate to **Settings** → **Repositories** → **\[your repository]** → **Ticketing**. 2. Click **Connect** on the **Asana** row. 3. Add an [Asana personal access token](#personal-access-token) and click **Connect**. 4. In the **Configuration** section that appears, select a **Workspace**, then select a **Project**, and click **Update**. Connecting happens in two steps because Trunk cannot list your workspaces until the token works. Until you save the token, the form shows only the **Asana Connection** section — the **Configuration** section, with its **Workspace** and **Project** dropdowns, appears once the token is accepted. The integration is not usable until you have selected both. A fully connected integration shows all three sections: ### Personal access token Create a personal access token from your [Asana developer console](https://app.asana.com/0/my-apps). Asana personal access tokens have no granular scopes — a token acts as the person who created it, with that person's permissions. The token must belong to someone who can see the workspace and project you want to file tickets in, and who can create tasks there. Tickets are created and updated by the token's owner, so that person appears as the author of every automated ticket and comment. Use a service account if you would rather the activity not be attributed to an individual. ## Statuses are project sections Asana has no workflow states. Trunk uses your project's **sections** — the columns on a board, such as `To do`, `In progress`, and `Done` — as the ticket status. A ticket's status is whichever section it sits in. Asana tracks completion separately from sections: a task has a **Completed** checkbox that is independent of which column it is in. Trunk treats a ticket as closed only when **both** are true: * the task is marked complete, **and** * the task sits in the section you configured as the close target. This matches exactly what Trunk does when it closes a ticket itself, so a ticket that Trunk closed always reads as closed. It also means a task somebody ticks complete while leaving it in another column is not treated as closed, and neither is a card dragged to the close column without being completed. Because Asana sections carry no built-in meaning, Trunk cannot tell which of your columns represents "done". Both the close and reopen dropdowns list every section in the project, and you choose. A column named `Shipped` or `Released` works exactly as well as one named `Done`. ## Ticket automation Once the integration is fully configured, you can enable [automatic ticketing](./automatic-ticketing) from the same settings page: Trunk will create Asana tasks when tests become flaky or broken, reopen them on regression, and close them when tests return to healthy. When Trunk closes a ticket, it marks the task complete and moves it to your configured close section. When it reopens one, it clears the completed flag and moves the task to your configured reopen section. ## Create a new ticket You can create a new ticket for any test listed in Flaky Tests. There are 2 ways to create a new ticket in the Flaky Tests dashboard: * Click on the options menu for any test case on the repo overview dashboard * Use the Create ticket button in the top left corner of the [test case details](../../dashboard#test-case-details) page. Before you create the ticket, you get a preview of the title and description. ### Create with Asana If you are connected to Asana, you can click the **Create Asana Ticket** button at the end of the modal to create a task in the configured project with any field defaults you have set. ## Field defaults After selecting a project, you can configure default values that pre-populate whenever a new Asana task is created from Flaky Tests. The available fields are your project's **custom fields**. Trunk supports these Asana custom field types: | Asana field type | Behavior | | ----------------- | -------------------------------- | | **Single-select** | Choose one option as the default | | **Multi-select** | Choose one or more options | | **Text** | Free text | | **Number** | Numeric value | | **People** | Choose one or more people | Date and reference fields are not supported and do not appear in the list. Formula and custom-ID fields are also omitted — Asana calculates those and rejects any attempt to write them. Custom fields belong to a project, so changing the selected **Project** clears every configured default. Choose the project first, then set defaults. Field defaults are saved per repository. When you open the **Create Ticket** modal, all configured defaults are pre-filled and can be overridden before submitting. ### Requiring fields at ticket creation For each field, you can check **Require user to fill at creation** instead of setting a default value. When this option is on, the field appears in the **Create Ticket** modal as a required input, and the create button stays disabled until the user fills every required field. This is useful for fields whose right value depends on the specific test being triaged and should not be pre-set globally. Automatic ticketing cannot answer a create-time prompt. If you turn on auto-create, every required field needs a default, and Trunk blocks the save until they have one. ## Link existing tickets to tests If you already have an Asana task for a test, you can link it directly from the Test Details page without creating a new one. **From the UI:** 1. Open the test case details page. 2. Click **Link Ticket** in the top-left corner. 3. Enter the Asana task ID and click **Link Ticket**. The task ID is the long number in the task's URL. For `https://app.asana.com/1/12345/project/67890/task/1217199000848901`, the task ID is `1217199000848901`. The task must be in the project you configured. Linking a task from a different project is rejected, because Trunk reads its status from that project's sections and would have no status to show. **Via API:** You can also link tickets programmatically using the [Link Ticket to Test Case API](../../reference/api-reference#post-flaky-tests-link-ticket-to-test-case). ## How linked tickets appear On the test case details page, a linked Asana ticket shows as **Ticket** with its current status and assignee, linking out to the task in Asana. Asana has no short human-readable key like Jira's `TRUNK-123`, and the generated task name (`[Flaky Test] `) is too long to display, so Trunk shows a generic label rather than a truncated title. # Automatic ticketing Source: https://docs.trunk.io/flaky-tests/management/ticketing/automatic-ticketing Automatically create, reopen, and close tickets as your tests change status — no webhooks or custom automation required Trunk can manage the full lifecycle of a test's ticket for you. When a test's status changes, Trunk automatically: * **Creates a ticket** when a test becomes flaky or broken * **Reopens the existing ticket** (or creates a fresh one) when a fixed test regresses * **Closes the ticket** when the test returns to healthy Automatic ticketing works with the built-in [Linear](./linear-integration), [Jira](./jira-integration), and [Asana](./asana-integration) integrations and produces the same rich tickets as manual creation — full [ticket content](./index#ticket-content) (failure history, impact, common failure reasons, code owners), your configured [field defaults](./jira-integration#custom-fields), and complete dashboard support: linked tickets appear on the test case details page, and every automated action is recorded in the test's [Events tab](/flaky-tests/dashboard#test-case-details). ## Enabling ticket automation Navigate to **Settings** → **Repositories** → **\[your repository]** → **Ticketing**. Once your Linear, Jira, or Asana integration is fully configured, the **Ticket automation** section becomes available. The three toggles are independent — you can enable any combination: | Setting | Behavior | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | **Auto-create tickets for flaky tests** | When a test's status changes to flaky, automatically create a ticket and link it to the test. | | **Auto-create tickets for broken tests** | When a test's status changes to broken, automatically create a ticket and link it to the test. | | **Auto-close tickets for healthy tests** | When a test returns to healthy, automatically close its linked ticket. The link is kept so the same ticket can be reopened if the test regresses. | All settings default to off. Automatic creation fills tickets from your configured [field defaults](./jira-integration#custom-fields) with nobody in the loop. Every field your project requires must have a default set — fields marked **Require user to fill at creation** are prompted for in the manual create-ticket modal, which automatic creation can't do. Auto-close applies to whatever ticket is linked to the test — including tickets you created manually or linked yourself — not just tickets the automation created. ### Close and reopen target statuses When auto-close is enabled, you can pick which status closed tickets move to (for example `Done` vs. `Won't Fix` in Jira, a specific workflow state in Linear, or a project section in Asana). Similarly, reopened tickets can target a specific status. If you don't pick one, Trunk uses a sensible provider default: the first "done"-category status for closing, and a "to do"-style status for reopening. ## Reopen behavior When a test becomes flaky or broken again after its linked ticket was closed, the **Reopen behavior** setting decides what happens: | Option | Behavior | | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Reopen recent tickets** (default) | If the ticket was closed within the reopen window (default 30 days, configurable 1–99), reopen it with a comment noting the re-detection. If it was closed longer ago, unlink it and create a fresh ticket. | | **Always create a new ticket** | The closed ticket stays closed; a new ticket is created and linked each time. *Only one ticket can be linked to a Trunk test at a time.* | | **Do nothing** | The closed ticket stays closed and no new ticket is created. | The reopen window is measured from the ticket's close date in your ticketing system, so it behaves correctly whether Trunk or a person closed the ticket. ## How the automation behaves * **One ticket per test.** Each test case has at most one linked ticket at a time. Previous tickets remain visible in the test's [event history](./index#ticket-event-history). * **Ticket content stays fresh.** Auto-created tickets have their description refreshed as the test's status evolves — for example when a flaky test escalates to broken — so the ticket always reflects current data. Title edits made by your team are preserved, and tickets you created or linked manually are never edited by Trunk (only closed or reopened per your settings). * **Quiet updates.** Status escalations update the ticket description in place rather than posting comments, so flip-flopping tests don't generate notification noise. Comments are only posted on reopen and close, where the context matters. * **Clearly attributed.** Auto-created tickets are badged in the dashboard, and every automated action appears in the test's Events tab attributed to Trunk automation — so it's always clear whether Trunk or a teammate acted on a ticket. * **Resilient to spikes.** A mass status change (for example, a bad merge flipping many tests at once) is absorbed and drained at a pace that respects your ticketing provider's rate limits. For Jira, the configured close/reopen target status must be reachable in a single workflow transition from the ticket's current status. If your Jira workflow requires intermediate steps, the automation records the issue in the test's event history and skips the transition rather than guessing. ## Legacy webhook-based ticket autocreation Before automatic ticketing, the recommended way to auto-create tickets was a [webhook integration](/flaky-tests/webhooks). Webhooks remain fully supported and are still the right tool for custom workflows and unsupported platforms, but the built-in automation is the better default for Linear, Jira, and Asana: | | Automatic ticketing | Webhooks | | ---------------- | --------------------------------------------------------------------------------------- | ---------------------------------------------------------- | | Setup | Toggles on the Ticketing settings page | Svix endpoint + provider API transformation | | Ticket body | Full Trunk ticket content: failure history, impact, common failure reasons, code owners | Whatever your transformation builds from the event payload | | Lifecycle | Create, reopen, and close managed end to end | Create only, unless you build the rest | | Dashboard | Tickets linked to test cases, events recorded, auto-created badge | Tickets are not linked back to Trunk | | Custom platforms | Linear, Jira, and Asana | Anything with an API | # Ticketing Source: https://docs.trunk.io/flaky-tests/management/ticketing/index Triage your flaky tests faster by creating automatically assigned and labeled tickets in your ticketing system You can integrate directly with your ticketing systems to automatically create tickets when Trunk [detects a flaky test](/flaky-tests/detection). ## Automatic ticketing With a connected Linear, Jira, or Asana integration, Trunk can manage ticket lifecycle automatically: create a ticket when a test becomes flaky or broken, reopen it if a fixed test regresses, and close it when the test returns to healthy. See [Automatic ticketing](./automatic-ticketing) for setup and behavior. ## Ticket content Flaky Tests automatically generates tickets complete with a title and description. If you’re connected to Linear, Jira, or Asana, you can also assign default issue types, teams, projects, or assignees. The ticket description contains the following information: * Identifier of the test * Since when has the test been labeled flaky * The last time this test failed * The impact when run on PRs * The impact when run on branches * Quarantine status * Most common failure reasons * Code owners, according to the [CODEOWNERS](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) file in your repository ## Ticket event history When you unlink a ticket and re-link a test case to a different ticket, all events from the previous ticket association are preserved. The test case's [Events tab](/flaky-tests/dashboard#test-case-details) shows the full history — creation, updates, and status changes — across all tickets the test has ever been linked to, not just the current one. ## Integration setup Ticket Creation supports integrations with Linear, Jira, and Asana. For any other platform, the generated ticket content is formatted in Markdown and can be copied across — see [Other ticketing platforms](./other-ticketing-platforms). # Jira integration Source: https://docs.trunk.io/flaky-tests/management/ticketing/jira-integration Triage your flaky tests faster by creating automatically assigned and labeled tickets with the Jira integration When Trunk Flaky Tests [detects a flaky test](../../detection/index), you can create an automatically generated Jira ticket for your team to pick up and fix the test. Webhook payloads will also contain ticket information when a Jira ticket is created with the integration or when [existing tickets are linked](./jira-integration#link-existing-tickets-to-tests). ## Connecting to Jira To connect a Jira Cloud project, navigate to **Settings** → **Repositories** → **\[your repository]** → **Ticketing** and select **Jira** as your Ticketing System. Then complete the form and click Connect to Jira Cloud with the following information. | Field Name | Description | Examples | | ---------------------------------------- | ----------------------------------------------------------------------------------------------- | -------------------------------- | | Jira URL | The URL to your Jira Cloud project. | `https://trunk-io.atlassian.net` | | Project Key | The project key for your Jira project. | `KAN` | | Email | The email associated with your Jira API token. | `johndoe@example.com` | | [Jira API token](#api-token-permissions) | [Create your Jira API token here.](https://id.atlassian.com/manage-profile/security/api-tokens) | `ATATT*****19FNY5Q` | | Default label(s) for new tickets | Labels applied to new Jira tickets created through Trunk Flaky Tests | `flaky-test, debt` | Jira labels cannot contain spaces — the Trunk UI enforces this restriction in the labels field. After connecting to Jira, you can specify a default issue type for new tickets and a default assignee for new tickets. ### API Token permissions Your Jira user account must have the following project permissions to create a Jira API token that allows Trunk to read, create, and assign tickets automatically: * *Create issues* * *Assign issues* OR *Browse users and groups* (global permission) * *Browse projects* * If issue-level security is configured, issue-level security permissions must be granted to read issues. You need to create an API token with the following scopes: * Required scopes (classic) * `read:jira-work` * `write:jira-work` * `read:jira-user` * Required scopes (granular): * `read:issue:jira` * `read:issue-meta:jira` * `read:issue-security-level:jira` * `read:issue.vote:jira` * `read:issue.changelog:jira` * `read:avatar:jira` * `read:status:jira` * `read:user:jira` * `read:field-configuration:jira` * `read:application-role:jira` * `read:group:jira` * `read:issue-type:jira` * `read:project:jira` * `read:project.property:jira` * `read:issue-type-hierarchy:jira` * `read:project-category:jira` * `read:project-version:jira` * `read:project.component:jira` * `read:permission:jira` * `write:issue:jira` * `write:comment:jira` * `write:comment.property:jira` * `write:attachment:jira` Jira tokens cannot last longer than 365 days. Once the token expires, you will need to generate a new API token. ## Ticket automation Once the integration is fully configured, you can enable [automatic ticketing](./automatic-ticketing) from the same settings page: Trunk will create Jira tickets when tests become flaky or broken, reopen them on regression, and close them when tests return to healthy. ## Create a new ticket You can create a new ticket for any test listed in Trunk Flaky Tests. There are 2 ways to create a new ticket in the Flaky Tests dashboard: * Click on the options menu for any test case on the repo overview dashboard * Use the Create ticket button in the top left corner of the [test case details](../../dashboard#test-case-details) page. Before you create the ticket, you will have a preview of the title and description. ### Create with Jira If you are connected to Jira, you can click the **Create Jira Ticket** button at the end of the modal, which will automatically create a ticket with the configured labels and assignees. ### Link existing tickets to tests If you already have a ticket in Jira that you want to link to a test in the dashboard, you can use the [Link Ticket to Test Case API](../../reference/api-reference#post-flaky-tests-link-ticket-to-test-case). ## Custom Fields Some Jira projects require additional fields beyond the standard fields (summary, description, and issue type) when creating tickets. Trunk supports configuring default values for any Jira field on a per-issue-type basis. Users can also override those defaults when creating a ticket. ### Configuring custom fields In the Jira integration settings (**Settings** → **Repositories** → **\[your repository]** → **Ticketing**), select an issue type. Trunk fetches all available fields for that issue type from the Jira API and displays inputs for each supported field. For each field, you can: * Set a default value that pre-fills the field when a ticket is created * Check **Require user to fill at creation** to leave the field blank in settings and prompt the user to fill it in the create ticket modal instead Trunk automatically detects required fields (as marked by your Jira project) and shows a validation error if no default is set and the field is not marked for user input. Fields are rendered using an appropriate input type based on the Jira field schema: | Jira schema | Input type | | -------------------------------- | ----------------------------------------- | | `string` | Text input | | `number` | Number input | | `option` | Searchable dropdown | | `user` | User picker dropdown | | `array` of `string` | Chip input (comma or Enter to add values) | | `text` / `string` with text hint | Text input | The `reporter` field is treated as optional even when Jira marks it as required. Jira automatically assigns the API token owner as reporter if the field is not specified. The following fields are always excluded from the custom field configuration because they are managed elsewhere in the ticket creation flow: `summary`, `description`, `project`, `issuetype`, `attachment`, `issuelinks`, `parent` ### Overriding defaults at ticket creation When creating a ticket from the Flaky Tests dashboard, the create ticket modal shows inputs for any field that has a configured default or is marked for user input. Users can edit pre-filled defaults before submitting. # Linear integration Source: https://docs.trunk.io/flaky-tests/management/ticketing/linear-integration Triage your flaky tests faster by creating automatically assigned and labeled tickets with the Linear integration When Trunk Flaky Tests [detects a flaky test](../../detection/index), you can create an automatically generated Linear ticket for your team to pick up and fix the test. Webhook payloads will also contain ticket information when a Linear ticket is created with the integration or when [existing tickets are linked](./linear-integration#link-existing-tickets-to-tests). ## Connecting to Linear To connect a Linear project: 1. Navigate to **Settings** → **Repositories** → **\[your repository]** → **Ticketing**. 2. Select **Linear** as your Ticketing System. 3. Add a [Linear API key](./linear-integration#api-token-permissions) 4. Select a Team and **Connect to Linear**. After connecting, you can configure field defaults for auto-created tickets — including Priority, Labels, Estimate, Project, and Assignee — all scoped to the selected team. See [Field defaults](#field-defaults) below. ### API Key permissions The following project permissions must be granted to your Linear API key so Trunk can read, create, and assign tickets automatically: * *Read* * *Create issues* Selecting *Full Access* will also grant the required permissions. ## Ticket automation Once the integration is fully configured, you can enable [automatic ticketing](./automatic-ticketing) from the same settings page: Trunk will create Linear issues when tests become flaky or broken, reopen them on regression, and close them when tests return to healthy. ## Create a new ticket You can create a new ticket for any test listed in Flaky Tests. There are 2 ways to create a new ticket in the Flaky Tests dashboard: * Click on the options menu for any test case on the repo overview dashboard * Use the Create ticket button in the top left corner of the [test case details](../../dashboard#test-case-details) page. Before you create the ticket, you get a preview of the title and description. ### Create with Linear If you are connected to Linear, you can click the **Create Linear Ticket** button at the end of the modal to automatically create a ticket with the configured team and any field defaults you have set. Note: You can use [Flaky Tests webhooks](../../webhooks/linear-integration) to automate ticket creation, or if you need more control over how tickets are created in Linear. This integration is not required when using webhooks. ## Field defaults After selecting a team, you can configure default values that pre-populate whenever a new Linear ticket is created from Flaky Tests: | Field | Description | | ------------ | -------------------------------------------------------------------------------------------------------------------- | | **Priority** | Default issue priority (Urgent, High, Medium, Low, No priority) | | **Labels** | One or more team-level or workspace-level labels to apply | | **Estimate** | Default story point estimate (scale matches your team's estimation type: Fibonacci, T-shirt, linear, or exponential) | | **Project** | Default Linear project, filtered to projects accessible by the selected team | | **Assignee** | Default assignee, chosen from team members | Changing the selected team clears and reloads all field options automatically. Field defaults are saved per repository. When you open the **Create Ticket** modal, all configured defaults are pre-filled and can be overridden before submitting. ### Requiring fields at ticket creation For each field, you can check **Require user to fill at creation** instead of setting a default value. When this option is on, the field appears in the **Create Ticket** modal as a required input. The **Create Linear Ticket** button stays disabled until the user fills every required field. This is useful for fields like **Project** or **Assignee** where the right value depends on the specific test being triaged and should not be pre-set globally. ## Link existing tickets to tests If you already have a Linear ticket for a test, you can link it directly from the Test Details page without creating a new one. **From the UI:** 1. Open the test case details page. 2. Click **Link Ticket** in the top-left corner. 3. Enter the Linear ticket URL or ID and click **Submit**. The ticket appears on the test details page and its metadata (title, status, assignee) syncs from Linear. **Via API:** You can also link tickets programmatically using the [Link Ticket to Test Case API](../../reference/api-reference#post-flaky-tests-link-ticket-to-test-case). # Other ticketing platforms Source: https://docs.trunk.io/flaky-tests/management/ticketing/other-ticketing-platforms Triage your flaky tests faster by manually creating tickets from generated markdown If you have not set up an integration, Trunk Flaky Tests can still generate a ticket title and description so you can copy and paste the details into your project management software. ## Create a new ticket You can create a new ticket for any test listed in Trunk Flaky Tests. There are 2 ways to create a new ticket in the Flaky Tests dashboard: * Click on the options menu for any test case on the repo overview dashboard * Use the Create ticket button in the top left corner of the [test case details](../../dashboard#test-case-details) page. Before you create the ticket, you will have a preview of the title and description. Now you can copy and paste the ticket title and description into your project management or ticketing platform. # Overview Source: https://docs.trunk.io/flaky-tests/overview Detect, quarantine, and eliminate flaky tests from your codebase Trunk Flaky Tests lets your teams detect, track, quarantine, and fix **flaky tests** in your codebase. Trunk can also identify **broken tests** — tests failing consistently at a high rate that indicate real regressions needing immediate fixes, not just quarantining. Flaky Tests is language, environment, and framework-agnostic. Let's explore how Trunk Flaky Tests' features help you tackle flaky tests. If you can't wait to try Trunk, follow our [getting started guide](/flaky-tests/get-started). You can see an overview of Trunk Flaky Tests in this video.