diff --git a/README.md b/README.md index 75365bd..ea08fd3 100644 --- a/README.md +++ b/README.md @@ -314,6 +314,25 @@ OpenAPI.stop_swagger_editor(; ) ``` +### Spectral Linter + +[Spectral](https://stoplight.io/open-source/spectral) is an open-source API style guide enforcer and linter. OpenAPI.jl includes a convenience method to use the Spectral OpenAPI linter from Julia. + +```julia +# specify a specification file to start with +OpenAPI.lint( + spec::AbstractString; # the OpenAPI specification to use + use_sudo::Bool=false # whether to use sudo while invoking docker +) + +# specify a folder and specification file name to start with +OpenAPI.lint( + spec_dir::AbstractString; # folder containing the specification file + spec_file::AbstractString; # the specification file + use_sudo::Bool=false # whether to use sudo while invoking docker +) +``` + ## TODO Not all OpenAPI features are supported yet, e.g.: diff --git a/src/tools.jl b/src/tools.jl index ce4b20c..dfbefc9 100644 --- a/src/tools.jl +++ b/src/tools.jl @@ -128,3 +128,39 @@ function swagger_editor(; port::Int=8080, use_sudo::Bool=false) cmd = `$docker run -d --rm -p $port:8080 $(SwaggerImage.Editor)` return _start_swagger(cmd, port) end + +""" + lint(spec; use_sudo=false) + lint(spec_dir, spec_file; use_sudo=false) + +Lint an OpenAPI spec file using Spectral. + +Optional arguments: +- `use_sudo`: Whether to use `sudo` to run Docker commands. Defaults to false. +""" +function lint(spec::AbstractString; use_sudo::Bool=false) + spec = abspath(spec) + spec_dir = dirname(spec) + spec_file = basename(spec) + return lint(spec_dir, spec_file; use_sudo=use_sudo) +end + +function lint(spec_dir::AbstractString, spec_file::AbstractString; use_sudo::Bool=false) + docker = docker_cmd(; use_sudo=use_sudo) + if isfile(joinpath(spec_dir, ".spectral.yaml")) + @debug("linting with existing configuration") + cmd = `$docker run --rm -v $spec_dir:/spec:ro -w /spec stoplight/spectral:latest lint /spec/$spec_file` + run(cmd) + else + # generate a default configuration file + @debug("linting with default configuration") + mktempdir() do tmpdir + open(joinpath(tmpdir, ".spectral.yaml"), "w") do f + write(f, """extends: ["spectral:oas", "spectral:asyncapi"]""") + end + cp(joinpath(spec_dir, spec_file), joinpath(tmpdir, spec_file)) + cmd = `$docker run --rm -v $tmpdir:/spec:ro -w /spec stoplight/spectral:latest lint /spec/$spec_file` + run(cmd) + end + end +end \ No newline at end of file