Skip to content

Architecture

This documentation covers the general internals of how gruft works.

WARNING

Note that the project is somewhat experimental and therefore there is a lot that can be changed in the future.

Overview

The gruft pipeline is split into three stages: scanning, bootstrapping and executing the formatters and linters.

Scanning

The scanning stage comprises of:

  1. Discovering the gruft.yaml configuration file starting with the current working directory, then recursively scanning parent directories if it does not find gruft.yaml.

    1. A default configuration is used if gruft.yaml is not found, or merged with gruft.yaml if found.
    2. If an .editorconfig file is found, it will take precedence over the default configuration for the relevant properties.
  2. If configuration version does not match installed CLI version, move to bootstrap stage.

  3. Discovering what files are available and their relevant file extensions to determine what tools to call for the execute stage.

Notes about scanning
  • A fixed list of known files is manually maintained that resolve to a specific formatter e.g. .babelrc maps to a JSON formatter.
  • A blocklist is maintained to skip automatically generated files. e.g. package-lock.json or pnpm-lock.yaml.
  • If no configuration is found, the installed tool version will be used and no bootstrap stage will be called.

Bootstrap

The bootstrap stage comprises of:

  1. Check if CLI version is already downloaded.

    1. If not, download and add it to the shim path.
  2. Use CLI version requested from configuration (we skip searching for the configuration again by directly setting the --config flag).

Notes about bootstrap
  • We use CalVer for versioning our CLIs as every update may be breaking in some way as they can have slightly different formatting or linting due to upstream rule additions, changes or bug fixes.
  • We rely on a shim to manage versions. Refer to the shim documentation for more information.

Execute

The execute stage comprises of:

  1. Receiving a configuration and a list of files.
  2. Piping the contents to the correct formatter and linter.
  3. Diff-checking and writing updated files to disk.
Notes about execute
  • Rust libraries are compiled into WASM that are embedded into the CLI whilst Go libraries are simply imported into the CLI tool directly.
  • While discouraged, the CLI supports calling native executables as part of the process. This is usually avoided and discouraged.
  • If the tool cannot be compiled into WASM/native or called via a Go import, it will not be supported.