standardlint
Version:
Extensible standards linter and auditor.
292 lines (171 loc) ⢠10.7 kB
Markdown
# StandardLint š
 [](https://sonarcloud.io/summary/new_code?id=mikaelvesavuori_standardlint) [](https://codescene.io/projects/34030) [](https://codescene.io/projects/34030) [](https://codecov.io/gh/mikaelvesavuori/standardlint) [](https://codeclimate.com/github/mikaelvesavuori/standardlint/maintainability)
## Extensible standards auditing and linting tool. Nags like your mother but is probably a lot more technical.
---
With StandardLint, you use _Checks_ to inform what standards you want to inspect, in effect being your standards _yardstick_:
> A fact or standard by which you can judge the success or value of something.
> āĀ [Cambridge Dictionary](https://dictionary.cambridge.org/dictionary/english/standardlint)
StandardLint makes it convenient and easy to set up guardrails and guidelines for development teams and making sure they follow your house conventions.
The result of a run could look like this:
```text
ā
PASS: Diagrams
ā
PASS: Changelog
šļø No custom path assigned to check "Diagrams" - Using default path "diagrams"...
ā ļø WARN: Diagrams
ā
PASS: Lock files
ā
PASS: License
ā FAIL: Code owners
ā FAIL: Contribution information
šļø No custom path assigned to check "IAC configuration" - Using default path "serverless.yml"...
ā
PASS: IAC configuration
šļø No custom path assigned to check "SLOs" - Using default path "manifest.json"...
ā ļø WARN: SLOs
šļø No custom path assigned to check "Tags" - Using default path "manifest.json"...
ā
PASS: Tags
šļø No custom path assigned to check "CI configuration" - Using default path ".github/workflows/main.yml"...
ā
PASS: CI configuration
ā
PASS: Security information
šļø No custom path assigned to check "Service metadata" - Using default path "manifest.json"...
ā
PASS: Service metadata
```
### Relation to projects like ESLint
The majority of StandardLint checks are meant to assess the overall architecture, for example presence of certain files or documentation. While StandardLint has a few checks that inspect code (throwing errors and using `console`), the majority of such use cases are better handled with something like [ESLint](https://eslint.org).
## StandardLint GitHub Action
There's a ready-to-use [StandardLint GitHub Action](https://github.com/marketplace/actions/standardlint-action) in the Marketplace if you really want the minimum hassle. Plus, you get a great visual overview of your checks!
## Usage
### Installation
Install StandardLint with `npm install standardlint`.
### Configuration
Before running StandardLint you need a configuration. This is a basic JSON file with the name `standardlint.json`. Place it in the root of your project.
The format is:
```json
{
"basePath": "",
"checks": [],
"defaultSeverity": ""
}
```
| Key | Required | Default | Example | Description |
| ----------------- | -------- | --------------- | ----------------------------------------- | ----------------------------------------------------------------------- |
| `basePath` | No | `.` | `./project_dir/` | Sets the base path for any file lookups. |
| `ignorePaths` | No | `[]` | `["/tests/", "/src/problematic-file.ts"]` | Paths that will be ignored for some checks. Does not support globbing. |
| `checks` | Yes | - | `["checkForPresenceLicense"]` | A list of checks to run, either using string or object form. |
| `defaultSeverity` | No | `error` | `warn` | Sets the default severity level for any issues. |
| `path` | No | Multiple values | `api/schema.yml` | Sets the exact path to a resource. Only used optionally by some checks. |
#### Base path
If you for some reason keep your project files "lower" than in the root where you want to do file lookups, you can add this optional argument.
_It's recommended you do not change this unless you know what you are doing._
#### Ignore paths
This provides the possibility to ignore certain paths.
These paths will be respected and discarded by the following checks:
- `checkForConsoleUsage`
- `checkForPresenceTests`
- `checkForThrowingPlainErrors`
#### Checks
Checks can be provided in string form or object form:
- String format: `["checkForDefinedTags"]`
- Object format: `[{ "name": "checkForPresenceContributing", "severity": "warn" }]`
You need to use the object form if you want to override the overall severity level, and use the check's `severity` level.
You can also combine the formats for different checks.
- `["checkForDefinedTags", { "name": "checkForPresenceContributing", "severity": "warn" }]`
Some checks also provide the optional `path` key. Use this when you want to override default values, for example to the location of an API schema.
- `[{ "name": "checkForPresenceApiSchema", "path": "api/schema.yml" }]`
#### Default severity
This can be either `warn` or `error` (the default value). Using it in `error` mode means that any failure will produce an error, while the `warn` mode simply warns for any non-compliance.
### Usage
#### From the command line
It's super easy to use StandardLint from the CLI! Just run `npx standardlint` and it will use the configuration in your project.
##### Outputting results into a JSON file
To output the results into `standardlint.results.json`, run `npx standardlint --output`.
#### Importing StandardLint as a Node package
You can also import and use StandardLint like a conventional Node package.
It exposes a factory function to vend a new `StandardLint` instance with a `check()` method.
If using it as an imported package, you will need to provide either a configuration file (for example loaded with `fs`) or the actual configuration as an object.
```ts
import { createNewStandardLint } from 'standardlint';
const config = {
checks: [
{ name: 'checkForPresenceContributing', severity: 'warn' },
{ name: 'checkForPresenceLicense', severity: 'error' }
]
};
const standardLint = createNewStandardLint(config);
const results = standardLint.check();
console.log(results);
```
#### Using static file trees instead of reading from disk
If you want to use a static representation of paths rather than actually checking on disk, then this is possible using the `filetree` parameter.
```ts
const standardlint = createNewStandardLint(config, ['path/to/file.js']);
```
##### Outputting results into a JSON file
To output the results into `standardlint.results.json`, run:
```ts
const standardLint = createNewStandardLint(config);
const results = standardLint.check(true); // <--- Adding true here will output the results to disk
```
## Available checks
_Service metadata definition checks assume you are using [Catalogist](https://github.com/mikaelvesavuori/catalogist) or something with the same manifest file structure._
Any check with a `default` value can be overridden using the `path` argument.
### `all`
Runs all checks.
### `checkForConflictingLockfiles`
Checks if there are conflicting Node package lock files (i.e. both a Yarn lock file and an NPM lock file).
### `checkForConsoleUsage`
Checks if `console` is used, e.g. `console.log()` and similar. This is useful when you want to ensure a more comprehensive logging approach is used.
Note that this uses a naive solution so even just a mention of console.log() (or similar) will fail this check.
**Will respect `ignorePaths` options.**
**Default**: `src`
### `checkForDefinedRelations`
Checks if the service metadata defines system relations.
**Default**: `manifest.json`
### `checkForDefinedServiceLevelObjectives`
Checks if the service metadata defines Service Level Objectives.
**Default**: `manifest.json`
### `checkForDefinedTags`
Checks if the service metadata defines tags.
**Default**: `manifest.json`
### `checkForPresenceApiSchema`
Checks if there is an API schema.
**Default**: `api/schema.json`
### `checkForPresenceChangelog`
Checks if there is a `CHANGELOG.md` file.
### `checkForPresenceCiConfig`
Checks if there is a CI/CD configuration file.
**Default**: `.github/workflows/main.yml`
### `checkForPresenceCodeowners`
Checks if there is a `CODEOWNERS` file.
### `checkForPresenceContributing`
Checks if there is a `CONTRIBUTING.md` file.
### `checkForPresenceDiagramsFolder`
Checks if there is a diagrams folder with diagram files in it. The check assumes `.drawio` files.
**Default**: `diagrams`
### `checkForPresenceIacConfig`
Checks if there is Infrastructure-as-Code configuration present.
**Default**: `serverless.yml`
### `checkForPresenceLicense`
Checks if there is a `LICENSE.md` file.
### `checkForPresenceReadme`
Checks if there is a `README.md` file.
### `checkForPresenceSecurity`
Checks if there is a `SECURITY.md` file.
### `checkForPresenceServiceMetadata`
Checks if there a service metadata file present.
**Default**: `manifest.json`
### `checkForPresenceTemplateIssues`
Checks if there is a template for GitHub issues.
**Default**: `.github/ISSUE_TEMPLATE/issue.md`
### `checkForPresenceTemplatePullRequests`
Checks if there is a template for GitHub Pull Requests.
**Default**: `.github/ISSUE_TEMPLATE/pull_request.md`
### `checkForPresenceTests`
Checks if there are any tests in the provided location. This will match anything ending in `(test|spec).(ts|js)`.
**Default**: `tests`
**Will respect `ignorePaths` options.**
### `checkForThrowingPlainErrors`
Checks if any file uses `throw Error` or `throw new Error`. This is meant to push toward the use of actual loggers, rather than plain console output.
**Will respect `ignorePaths` options.**
---
## Ideas for improvements
- Service metadata: Do you link to observability resources (logs/metrics/traces/dashboards etc.)?
- Support for external config