# Lint and format API descriptions

Source: https://apigenie.pl/docs/guides/lint-and-format-api-descriptions

This guide sets up `apigenie lint` and `apigenie format` for a repository of API descriptions: a
shared configuration, the first clean run, your own rules, and a check on every pull request. It
uses an OpenAPI file, `openapi.yaml`; AsyncAPI, Swagger 2.0, Protobuf and GraphQL files work the
same way.

You need the CLI installed; the [Quickstart](/docs/quickstart) shows how.

## Run the linter

Without configuration the linter applies the `recommended` ruleset:

```sh
apigenie lint openapi.yaml
```

```text
  764:6   warning  Unused shared component                                 unused-shared-component
  781:8   error    Schema with integer type does not define proper format  schema-format-defined

  2 issues (1 error, 1 warning)
  0 errors, 1 warning are potentially auto-fixable
```

Each line gives the position, the severity, the message and the rule. Every rule has a page in the
[linter rules](/docs/linter) that says what it checks and why. Errors make the command exit with
status 1; warnings and hints are reported but don't fail it.

Let the linter fix what has a safe fix. The files keep their comments:

```sh
apigenie lint --fix openapi.yaml
```

## Write down your rules

Put an `apigenie.yaml` at the root of the repository. Every command finds it in the current
directory or a parent, up to the root of the Git repository, so the whole team and CI use the same
rules. The first line lets editors that use the YAML language server complete and check the file.

```yaml
# yaml-language-server: $schema=https://apigenie.pl/schemas/apigenie-config/latest.json
version: '1.0'
commands:
  lint:
    extends: [recommended]
    rules:
      info-defined: off
      paths-max-count: [error, 30]
      tags-unique: error
```

`extends` picks the rulesets to start from: `recommended`, `strict`, `all`, or a ruleset of the
[catalog](/docs/linter/openapi) such as `privacy`. `rules` changes the severity of a rule (`error`,
`warning`, `hint` or `off`), or its severity and options. `apigenie config` prints the settings in
effect, and `apigenie config check` checks the file.

When a part of a document has a good reason to break a rule, disable the rule there, as close to
the problem as you can:

```yaml
info:
  x-apigenie-lint-disable:
    - contact-defined
```

## Add a rule of your own

House rules that no ruleset has are written the way [Spectral](https://docs.stoplight.io/docs/spectral)
rules are: a JSONPath expression selects the values, and a function checks each of them.

```yaml
commands:
  lint:
    extends: [recommended]
    rules:
      operation-summary:
        description: Operations must have a summary
        message: "{{property}} is missing at {{path}}"
        severity: error
        given: "$.paths[*][get,put,post,delete,patch]"
        then:
          field: summary
          function: truthy
```

The core functions of Spectral are built in, and JavaScript functions written for Spectral mostly
work unchanged; see [custom rules](/docs/reference/cli/lint#custom-rules).

## Format the files

The formatter puts the files in one style without changing what they mean: indentation, line
endings, the order of properties and the YAML styles of values. It writes the files in place:

```sh
apigenie format openapi.yaml
```

Its settings go in the same `apigenie.yaml`. Start from the `recommended` preset and override what
your team does differently:

```yaml
commands:
  format:
    extends: [recommended]
    openapi:
      newline: crlf
      style_overrides:
        - fields: [description]
          string: literal
```

`--check` writes nothing and exits with status 1 when a file would change, which is what CI needs:

```sh
apigenie format --check openapi.yaml
```

## Check every pull request

The [GitHub Action](/docs/ci/github-action) runs both commands and shows the issues as annotations
on the lines of the pull request:

```yaml
on: pull_request
jobs:
  api:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: mykulyak/api-genie-action@v0
        with:
          command: lint
          files: api/**/*.yaml
      - uses: mykulyak/api-genie-action@v0
        with:
          command: format
          files: api/**/*.yaml
```

On other CI systems, run the commands and read their exit statuses. For dashboards, `lint
--formatter` writes SARIF (GitHub code scanning), JUnit, checkstyle, TAP, JSON or HTML; see
[formatting results](/docs/reference/cli/lint#formatting-results).

## Next steps

- [Linter rules](/docs/linter): every rule and ruleset of the five linters.
- [lint](/docs/reference/cli/lint) and [format](/docs/reference/cli/format): every option and
  setting.
- [Catch breaking changes in CI](/docs/guides/catch-breaking-changes-in-ci): the next check for
  the same pull requests.
