Linting OpenAPI specs using Spectral

Lalitha
4 min readMay 9, 2021

Introduction

This post details on linting swagger specification using spectral. When it comes to following standards, its always conversational and prone to deviations with human aspect. How good would it be to automate the verification of standards.

Its such a relief to hear about a positive move towards lint option on json and yaml variant of API specs. Yes, Spectral provides lint’n options to json or yaml objects. Unlike regular linters which checks for syntax, spectral provides an option to create your own ruleset to apply on the openapi swagger specification file.

Spectral comes with built-in functions with provision to create custom functions. These custom functions can perform pattern checks, parameter checks, provided keys in an object and many more.

Usage

There are a few options available for installation and usage based on requirements. Lets look into these

  • node

npm install -g @stoplight/spectral

  • yarn

yarn global add @stoplight/spectral

  • run as binaries
curl -L 
https://raw.githack.com/stoplightio/spectral/master/scripts/install.sh | sh
  • docker

Running docker image locally requires file to be copied on to volume mount

docker run --rm -it -v $(pwd):/tmp stoplight/spectral lint "/tmp/file.yaml"

If you want to run docker from CI, use docker command

docker run --rm -it stoplight/spectral lint "${url}"

Example:

Let me show simple usage of running docker locally on employee-openapi-spec.yaml using the command

docker run --rm -it -v $(pwd):/tmp stoplight/spectral lint "/tmp/employee-openapi-spec.yaml
openapi: 3.0.1
info:
title: Employees API Spec
description: Working with employee details
version: v1
servers:
- url: http://localhost:8080/employees
description: The employee api
tags:
- name: employee details api spec
paths:
/api/v1/employees:
summary: Employees
description: API to work with employee details
get:
tags:
- employees
summary: Get list of employees
description: Retrieve the list of employees and their details
operationId: getEmployees
responses:
"200":
description: request to get list of employees
content:
application/json:
schema:
$ref: '#/components/schemas/EmployeeResponse'

And the output looks like this

OpenAPI 3.x detected/tmp/employee-openapi-spec.yaml
2:6 warning info-contact Info object should contain `contact` object.
17:9 warning operation-tag-defined Operation tags should be defined in global tags.
✖ 2 problems (0 errors, 2 warnings, 0 infos, 0 hints)

Features

With the ability to add linter enables to detect issues with API early on, as early as design phase. Isn’t this an amazing benefit to shift left on design issues and save time for more precious work later.

Spectral has three key building blocks:

  • Rulesets — act as a container for rules and functions.
  • Rules — filters the object to a set of target values and specifies the function that is used to evaluate these values.
  • Functions — accept a value and return any issues with its value.

As mentioned earlier, spectral comes with basic set of functions and a predefined set of style guides for openapi specs. Rules are created using one or more of these basic in-built functions to add onto the style guides. These additional ones could be organisational guardrails which can be centrally managed and enforced onto all the APIs being designed. These could be anything from

HTTP Basic is not allowed at this company

to checking

Are all operations secured with a security schema

Working with Rulesets

Let’s dive into exploring rulesets and working with custom functions. Since spectral supports linting of json and yaml objects, rulesets can also be in either of the formats. Often the ruleset filename goes like .spectral.yaml which consists of two parts, rules and functions.

In-built Spectral “oas” ruleset, OAS being shorthand for the OpenAPI Specification. In the above example, we saw a warning on info-contact. This is one of the default ruleset of oas.

Simple ruleset example

The rule is applied on the json element tags defined under given and the function is truthy with reporting severity as error. This means, if any of the specification tags doesn't contain description, linter will throw error.

Just by adding extends statement to the spec, you can import other default rulesets.

Custom ruleset

Change the severity — update the default severity of rule by overwriting it

Different severity levels that can be used are error, warn, info, hint, and off.

Here all the default spectral rules are enabled and only custom rule my-rule-one is disabled.

This is quite opposite to disabling a rule. Default rules are all disabled using off flag and only my-rule-one is enabled.

Conclusion

There are a few more options to customise the rules to cover most of the organisational requirements. Also, it is a good start to see a working lint option available for swagger which removes the overhead of manually verifying and controlling the common design pattern for APIs. I’m pretty impressed and suggest trying this to see the benefit of automating early design flaw detection. Hope you find this useful.

References

Spectral documentation
OpenAPI Rules

Originally published at https://dev.to on May 9, 2021.

--

--