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:
Discovering the
gruft.yaml
configuration file starting with the current working directory, then recursively scanning parent directories if it does not findgruft.yaml
.- A default configuration is used if
gruft.yaml
is not found, or merged withgruft.yaml
if found. - If an
.editorconfig
file is found, it will take precedence over the default configuration for the relevant properties.
- A default configuration is used if
If configuration version does not match installed CLI version, move to bootstrap stage.
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 aJSON
formatter. - A blocklist is maintained to skip automatically generated files. e.g.
package-lock.json
orpnpm-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:
Check if CLI version is already downloaded.
- If not, download and add it to the shim path.
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:
- Receiving a configuration and a list of files.
- Piping the contents to the correct formatter and linter.
- 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.