[Trunk Check Guide: Implement Third-Party Linter]

Description

In this article, we will explore the process of integrating a third-party linter with Trunk that is not supported by default. This enables you to leverage Trunk's capabilities while using custom linters tailored to your project's specific needs.


Usage

In our case, we want to add a linter Spectral for linting openapi and asyncapi specs.

Pre-configuration

1. Install Trunk on your machine

curl https://get.trunk.io -fsSL | bash

➡️ Additional Trunk installation documentation

2. Initialize Trunk in your project

trunk init

3. Prepare linter configuration file

Create a .spectral.yaml file in the .trunk/configs directory with the following content:

extends: [spectral:oas, spectral:asyncapi]

Trunk setup

Since we can install this linter using a standard package manager – node/npm in our case, we will use the appropriate way to integrate the linter.

So let's modify your .trunk/trunk.yaml:

1. Check the runtime version for your linter and set the appropriate version in the runtime Trunk configuration block

version: 0.1
---
runtimes:
  enabled:
    - [email protected]

2. You need to declare a new tool in the main Trunk configuration file

In tools block we declare:

  • name – a unique name for this tool
  • runtime – linter execution environment
  • package – the name of the package in which the linter for the package manager is supplied
  • shims – the name of the adapter to call the linter in Trunk
  • known_good_version – linter version

All fields are required.

version: 0.1
---
tools:
  definitions:
    - name: spectral-lint
      runtime: node
      package: "@stoplight/spectral-cli"
      shims: [spectral]
      known_good_version: 6.11.0

➡️ Addition Trunk tools documentation

3. You need to declare a definition for your tool in the main Trunk configuration file

In the lint: definitions block, we define how and with what parameters the linter will be launched by the Trunk. There are things to note here:

◻️ name – a unique name for this linter

◻️ files – the list of file types that this linter applies to

◻️ type – the way to print the linter output to the Trunk console after executing trunk check

◻️ tools – the name of the tool that we defined in step 1

◻️ suggest_if – this field determines when the linter should be enabled/recommended. In our case, we will enable it automatically if Trunk finds a configuration file for this linter

◻️ direct_configs – the path to the linter configuration file. By default, Trunk will look for a linter configuration file in the .trunk/configs directory, so we will simply create a .spectral.yaml configuration file there

◻️ commands – the list of commands exposed by this linter. It includes:

⠀⠀◽️name – a unique name for this command

⠀⠀◽️output – which type of output this linter produces. In our case, both Trunk and Spectral support output in sarif format

⠀⠀◽️read_output_from – this field tell Trunk parser where to expect output from for reading

⠀⠀◽️run – the command to run a linter

⠀⠀◽️success_codes – the list of exit codes that indicates linter ran successfully

version: 0.1
---
lint:
  definitions:
    - name: spectral
      files: [yaml]
      type: rewrite
      commands:
        - name: lint
          output: sarif
          read_output_from: stdout
          run: spectral lint ${target} --format=sarif --ignore-unknown-format
          success_codes: [0, 1]
      tools: [spectral-lint]
      suggest_if: config_present
      direct_configs: [.spectral.yaml]

➡️ Additional Trunk linter definition documentation

➡️ Additional Trunk linter commands documentation

4. Finally, we can enable the linter

version: 0.1
...
lint:
  ...
  enabled:
    # OpenAPI linter
    - spectral

5. (Optional) You can add files or directories that the linter will ignore. In our case, this was necessary because the current version of the linter could not work with asyncapi specs version 3.x.x

version: 0.1
...
lint:
  ...
  ignore:
    - linters: [spectral]
      paths:
        # Ignore asyncapi v3.x.x
        - "**/*_asyncapi.yaml"

➡️ Additional Trunk ignore documentation


Complete Trunk configuration file

version: 0.1
cli:
  version: 1.22.1
plugins:
  sources:
    - id: trunk
      ref: v1.5.0
      uri: https://github.com/trunk-io/plugins
runtimes:
  enabled:
    - [email protected]
tools:
  definitions:
    - name: spectral-lint
      runtime: node
      package: "@stoplight/spectral-cli"
      shims: [spectral]
      known_good_version: 6.11.0
lint:
  definitions:
    - name: spectral
      files: [yaml]
      type: rewrite
      commands:
        - name: lint
          output: sarif
          read_output_from: stdout
          run: spectral lint ${target} --format=sarif --ignore-unknown-format
          success_codes: [0, 1]
      tools: [spectral-lint]
      suggest_if: config_present
      direct_configs: [.spectral.yaml]
  enabled:
    # OpenAPI linter
    - spectral
  ignore:
    - linters: [spectral]
      paths:
        # Ignore asyncapi v3.x.x
        - "**/*_asyncapi.yaml"

Conclusion

This setup allows us to leverage Trunk's robust capabilities while utilizing Spectral for linking OpenAPI and AsyncAPI specs. With the complete configuration in place, Trunk will automatically detect and use Special for relevant files, will use caching, and will scan only changed files. By incorporating third-party linters into Trunk, you can maintain a high standard of code quality and streamline your development workflow, all while benefiting from the flexibility and power of Trunk's integration system.