How-to guidesLint and format API descriptions

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 shows how.

Run the linter

Without configuration the linter applies the recommended ruleset:

apigenie lint openapi.yaml
  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 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:

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-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 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:

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

Add a rule of your own

House rules that no ruleset has are written the way Spectral rules are: a JSONPath expression selects the values, and a function checks each of them.

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.

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:

apigenie format openapi.yaml

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

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:

apigenie format --check openapi.yaml

Check every pull request

The GitHub Action runs both commands and shows the issues as annotations on the lines of the pull request:

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.

Next steps