Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sbt plugin for OpenAPI Generator #5406

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions modules/openapi-generator-sbt-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# sbt-openapi-generator

A Sbt plugin to support the OpenAPI generator project

# Usage

Add to your `project/plugins.sbt`:

```sbt
addSbtPlugin("org.openapitools" % "sbt-openapi-generator" % "4.3.0")
```

# Configuration

Configuration based on project module is recommended way to separate specifications by modules.

You must define one of the settings `openApiInputSpec` or `openApiConfigFile` to able run plugin to generate.

Settings will be picked up from `openApiConfigFile` first if defined and then will be overwritten with module specified settings

With the next example module `generated` will be defined as:

```sbt
lazy val generated = project.in(file("generated"))
.settings(
inConfig(OpenApiCodegen) {
Seq(
openApiInputSpec := "openapi.yaml",
openApiConfigFile := "config.yaml"
)
}
)
```

There is a helpers to have boolean settings more readable. Instead of `Some(true)` you can do next:
```sbt
openApiValidateSpec := SettingDisabled,
openApiGenerateModelTests := SettingEnabled,
```
# Execution

To print all available languages use
```shell script
sbt openApiGenerators
```

To run generation process
```shell script
sbt openApiGenerate
```
or per defined module
```shell script
sbt generated/openApiGenerate
```

# Settings


| Setting | Type | Description |
|----------|--------|--------------------------|
| openApiGeneratorName | `String` | The name of the generator which will handle codegen. (see \"openApiGenerators\" task) |
| openApiInputSpec| `String` | The Open API 2.0/3.x specification location |
| openApiOutputDir| `String` | The output target directory into which code will be generated |
| openApiConfigFile| `String` | Path to json configuration file |
| openApiAdditionalProperties | `Map[String, String]` | Sets additional properties that can be referenced by the mustache templates in the format of name=value,name=value. You can also have multiple occurrences of this option |
| openApiSystemProperties | `Map[String, String]` |Sets specified system properties |
| openApiVerbose | `Option[Boolean]` | The verbosity of generation |
| openApiValidateSpec | `Option[Boolean]` | Whether or not an input specification should be validated upon generation |
| openApiTemplateDir | `String` | The template directory holding a custom template |
| openApiAuth | `String` | Adds authorization headers when fetching the OpenAPI definitions remotely. Pass in a URL-encoded string of name:header with a comma separating multiple values |
| openApiSkipOverwrite | `Option[Boolean]` | Specifies if the existing files should be overwritten during the generation |
| openApiPackageName | `String` | Package for generated classes (where supported) |
| openApiApiPackage | `String` | Package for generated api classes |
| openApiModelPackage | `String` | Package for generated models |
| openApiModelNamePrefix | `String` | Prefix that will be prepended to all model names |
| openApiModelNameSuffix | `String` | Suffix that will be appended to all model names |
| openApiInstantiationTypes | `Map[String, String]` | Sets instantiation type mappings |
| openApiTypeMappings | `Map[String, String]` | Sets mappings between OpenAPI spec types and generated code types |
| openApiServerVariables | `Map[String, String]` | Sets server variable for server URL template substitution, in the format of name=value,name=value. You can also have multiple occurrences of this option |
| openApiLanguageSpecificPrimitives | `List[String]` | Specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double |
| openApiImportMappings | `Map[String, String]` | Specifies mappings between a given class and the import that should be used for that class |
| openApiInvokerPackage | `String` | Root package for generated code |
| openApiGroupId | `String` | groupId in generated pom.xml/build.sbt |
| openApiId | `String` | artifactId in generated pom.xml/build.sbt. This also becomes part of the generated library's filename |
| openApiLibrary | `String` | library template (sub-template) |
| openApiGitHost | `String` |Git host, e.g. gitlab.com |
| openApiGitUserId | `String` | Git user ID, e.g. openapitools |
| openApiGitRepoId | `String` | Git repo ID, e.g. openapi-generator |
| openApiReleaseNote | `String` | Release note, default to 'Minor update' |
| openApiHttpUserAgent | `String` | HTTP user agent, e.g. codegen_csharp_api_client, default to 'OpenAPI-Generator/{packageVersion}}/{language}' |
| openApiReservedWordsMappings | `Map[String, String]` | ]("Specifies how a reserved name should be escaped to |
| openApiIgnoreFileOverride | `String` | Specifies an override location for the .openapi-generator-ignore file. Most useful on initial generation. |
| openApiRemoveOperationIdPrefix | `Option[Boolean]` | Remove prefix of operationId, e.g. config_getId => getId |
| openApiApiFilesConstrainedTo | `List[String]` | Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all) |
| openApiModelFilesConstrainedTo | `List[String]` | Defines which model-related files should be generated. This allows you to create a subset of generated files (or none at all) |
| openApiSupportingFilesConstrainedTo | `List[String]` | Defines which supporting files should be generated. This allows you to create a subset of generated files (or none at all |
| openApiGenerateModelTests | `Option[Boolean]` | Specifies that model tests are to be generated |
| openApiGenerateModelDocumentation | `Option[Boolean]` | Defines whether or not model-related _documentation_ files should be generated |
| openApiGenerateApiTests | `Option[Boolean]` | Specifies that api tests are to be generated |
| openApiGenerateApiDocumentation | `Option[Boolean]` | Defines whether or not api-related _documentation_ files should be generated |
| openApiWithXml | `Option[Boolean]` | A special-case setting which configures some generators with XML support. In some cases, this forces json OR xml, so the default here is false |
| openApiLogToStderr | `Option[Boolean]` | To write all log messages (not just errors) to STDOUT |
| openApiEnablePostProcessFile | `Option[Boolean]` | Enable post-processing file using environment variables | \
| openApiSkipValidateSpec | `Option[Boolean]` | To skip spec validation. When true, we will skip the default behavior of validating a spec before generation |
| openApiGenerateAliasAsModel | `Option[Boolean]` | Generate model implementation for aliases to map and array schemas |

# Examples

Please see [an sbt-test configuration](src/sbt-test) for using the plugin.
Do not run those examples directly, please copy them to separate place first.

# Contribution and Tests

Write plugin integration tests under [src/sbt-test](src/sbt-test)

Execute next to run tests:

```shell script
sbt scripted
```

More information how to write and execute tests [is here](https://www.scala-sbt.org/1.x/docs/Testing-sbt-plugins.html)
51 changes: 51 additions & 0 deletions modules/openapi-generator-sbt-plugin/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
lazy val `sbt-openapi-generator` = Project("sbt-openapi-generator", file("."))
resolvers ++= Seq(
Resolver.sbtPluginRepo("snapshots"),
Resolver.sonatypeRepo("snapshots")
)
scalaVersion := "2.12.10"

name := "sbt-openapi-generator"
description := """
This plugin supports common functionality found in Open API Generator CLI as a sbt plugin.

This gives you the ability to generate client SDKs, documentation, new generators, and to validate Open API 2.0 and 3.x
specifications as part of your build. Other tasks are available as command line tasks.
"""
homepage := Some(url("https://openapi-generator.tech"))

organization := "org.openapitools"
organizationName := "OpenAPI-Generator Contributors"
organizationHomepage := Some(url("https://github.com/OpenAPITools"))

licenses += ("The Apache Software License, Version 2.0", url("https://www.apache.org/licenses/LICENSE-2.0.txt"))

developers += Developer(
id = "openapitools",
name = "OpenAPI-Generator Contributors",
email = "[email protected]",
url = url("https://github.com/OpenAPITools")
)

scmInfo := Some(
ScmInfo(
browseUrl = url("https://github.com/OpenAPITools/openapi-generator"),
connection = "scm:git:git://github.com/OpenAPITools/openapi-generator.git",
devConnection = "scm:git:ssh://[email protected]:OpenAPITools/openapi-generator.git")
)

bintrayOrganization := Some("sbt")
bintrayRepository := "sbt-plugins"
bintrayReleaseOnPublish in ThisBuild := false

crossScalaVersions := Seq(scalaVersion.value, "2.11.12")
crossSbtVersions := List("0.13.17", "1.3.8")

libraryDependencies += "org.openapitools" % "openapi-generator" % version.value

enablePlugins(SbtPlugin)

scriptedLaunchOpts := {
scriptedLaunchOpts.value ++ Seq("-Xmx1024M", "-Dplugin.version=" + version.value)
}
scriptedBufferLog := false
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.3.8
2 changes: 2 additions & 0 deletions modules/openapi-generator-sbt-plugin/project/plugin.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value
addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.6")
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package sbtopenapigenerator

import org.openapitools.codegen.CodegenConstants
import sbt.taskKey
import sbt.settingKey
import sbt.File

trait OpenApiGeneratorKeys {
final val openApiGenerate = taskKey[Seq[File]]("Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents.")
final val openApiGenerators = taskKey[Unit]("Print list of available generators")

final val openApiInputSpec = settingKey[String]("The Open API 2.0/3.x specification location.")
final val openApiOutputDir = settingKey[String]("The output target directory into which code will be generated.")
final val openApiConfigFile = settingKey[String]("Path to json configuration file.\n" +
"File content should be in a json format { \"optionKey\":\"optionValue\", \"optionKey1\":\"optionValue1\"...}\n" +
"Supported options can be different for each language. Run config-help -g {generator name} command for language specific config options.")
final val openApiAdditionalProperties = settingKey[Map[String, String]]("Sets additional properties that can be referenced by the mustache templates in the format of name=value,name=value.\n" +
"You can also have multiple occurrences of this option.")
final val openApiSystemProperties = settingKey[Map[String, String]]("Sets specified system properties.")

final val openApiVerbose = settingKey[Option[Boolean]]("The verbosity of generation")
final val openApiValidateSpec = settingKey[Option[Boolean]]("Whether or not an input specification should be validated upon generation.")
final val openApiGeneratorName = settingKey[String]("The name of the generator which will handle codegen. (see \"openApiGenerators\" task)")
final val openApiTemplateDir = settingKey[String]("The template directory holding a custom template.")
final val openApiAuth = settingKey[String]("Adds authorization headers when fetching the OpenAPI definitions remotely.\n" +
"Pass in a URL-encoded string of name:header with a comma separating multiple values")
final val openApiSkipOverwrite = settingKey[Option[Boolean]]("Specifies if the existing files should be overwritten during the generation.")
final val openApiPackageName = settingKey[String](CodegenConstants.PACKAGE_NAME_DESC)
final val openApiApiPackage = settingKey[String](CodegenConstants.API_PACKAGE_DESC)
final val openApiModelPackage = settingKey[String](CodegenConstants.MODEL_PACKAGE_DESC)
final val openApiModelNamePrefix = settingKey[String](CodegenConstants.MODEL_NAME_PREFIX_DESC)
final val openApiModelNameSuffix = settingKey[String](CodegenConstants.MODEL_NAME_SUFFIX_DESC)
final val openApiInstantiationTypes = settingKey[Map[String, String]]("Sets instantiation type mappings.")
final val openApiTypeMappings = settingKey[Map[String, String]]("Sets mappings between OpenAPI spec types and generated code types.")
final val openApiServerVariables = settingKey[Map[String, String]]("Sets server variable for server URL template substitution, in the format of name=value,name=value.\n"
+ "You can also have multiple occurrences of this option.")

final val openApiLanguageSpecificPrimitives = settingKey[List[String]]("Specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double.")
final val openApiImportMappings = settingKey[Map[String, String]]("Specifies mappings between a given class and the import that should be used for that class.")
final val openApiInvokerPackage = settingKey[String](CodegenConstants.INVOKER_PACKAGE_DESC)
//TODO: change to sbt organization
final val openApiGroupId = settingKey[String](CodegenConstants.GROUP_ID_DESC)
//TODO: change to sbt name
final val openApiId = settingKey[String](CodegenConstants.ARTIFACT_ID_DESC)

final val openApiLibrary = settingKey[String](CodegenConstants.LIBRARY_DESC)
final val openApiGitHost = settingKey[String](CodegenConstants.GIT_HOST_DESC)
final val openApiGitUserId = settingKey[String](CodegenConstants.GIT_USER_ID_DESC)
final val openApiGitRepoId = settingKey[String](CodegenConstants.GIT_REPO_ID_DESC)
final val openApiReleaseNote = settingKey[String](CodegenConstants.RELEASE_NOTE_DESC)
final val openApiHttpUserAgent = settingKey[String](CodegenConstants.HTTP_USER_AGENT_DESC)
final val openApiReservedWordsMappings = settingKey[Map[String, String]]("Specifies how a reserved name should be escaped to.")
final val openApiIgnoreFileOverride = settingKey[String](CodegenConstants.IGNORE_FILE_OVERRIDE_DESC)
final val openApiRemoveOperationIdPrefix = settingKey[Option[Boolean]]("Remove prefix of operationId, e.g. config_getId => getId")

/**
* Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all).
*
* This option enables/disables generation of ALL api-related files.
*
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
*/
final val openApiApiFilesConstrainedTo = settingKey[List[String]]("Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all).")

/**
* Defines which model-related files should be generated. This allows you to create a subset of generated files (or none at all).
*
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
*/
final val openApiModelFilesConstrainedTo = settingKey[List[String]]("Defines which model-related files should be generated. This allows you to create a subset of generated files (or none at all).")

/**
* Defines which supporting files should be generated. This allows you to create a subset of generated files (or none at all).
*
* Supporting files are those related to projects/frameworks which may be modified
* by consumers.
*
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
*/
final val openApiSupportingFilesConstrainedTo = settingKey[List[String]]("Defines which supporting files should be generated. This allows you to create a subset of generated files (or none at all).")

/**
* Defines whether or not model-related _test_ files should be generated.
*
* This option enables/disables generation of ALL model-related _test_ files.
*
* For more control over generation of individual files, configure an ignore file and
* refer to it via [ignoreFileOverride].
*/
final val openApiGenerateModelTests = settingKey[Option[Boolean]](CodegenConstants.GENERATE_MODEL_TESTS_DESC)

/**
* Defines whether or not model-related _documentation_ files should be generated.
*
* This option enables/disables generation of ALL model-related _documentation_ files.
*
* For more control over generation of individual files, configure an ignore file and
* refer to it via [ignoreFileOverride].
*/
final val openApiGenerateModelDocumentation = settingKey[Option[Boolean]]("Defines whether or not model-related _documentation_ files should be generated.")

/**
* Defines whether or not api-related _test_ files should be generated.
*
* This option enables/disables generation of ALL api-related _test_ files.
*
* For more control over generation of individual files, configure an ignore file and
* refer to it via [ignoreFileOverride].
*/
final val openApiGenerateApiTests = settingKey[Option[Boolean]](CodegenConstants.GENERATE_API_TESTS_DESC)

/**
* Defines whether or not api-related _documentation_ files should be generated.
*
* This option enables/disables generation of ALL api-related _documentation_ files.
*
* For more control over generation of individual files, configure an ignore file and
* refer to it via [ignoreFileOverride].
*/
final val openApiGenerateApiDocumentation = settingKey[Option[Boolean]]("Defines whether or not api-related _documentation_ files should be generated.")
final val openApiWithXml = settingKey[Option[Boolean]]("A special-case setting which configures some generators with XML support. In some cases, this forces json OR xml, so the default here is false.")

final val openApiLogToStderr = settingKey[Option[Boolean]]("To write all log messages (not just errors) to STDOUT")

/**
* To enable the file post-processing hook. This enables executing an external post-processor (usually a linter program).
* This only enables the post-processor. To define the post-processing command, define an environment variable such as
* LANG_POST_PROCESS_FILE (e.g. GO_POST_PROCESS_FILE, SCALA_POST_PROCESS_FILE). Please open an issue if your target
* generator does not support this functionality.
*/
final val openApiEnablePostProcessFile = settingKey[Option[Boolean]](CodegenConstants.ENABLE_POST_PROCESS_FILE_DESC)

final val openApiSkipValidateSpec = settingKey[Option[Boolean]]("To skip spec validation. When true, we will skip the default behavior of validating a spec before generation.")

/**
* To generate alias (array, list, map) as model. When false, top-level objects defined as array, list, or map will result in those
* definitions generated as top-level Array-of-items, List-of-items, Map-of-items definitions.
* When true, A model representation either containing or extending the array,list,map (depending on specific generator implementation) will be generated.
*/
final val openApiGenerateAliasAsModel = settingKey[Option[Boolean]](CodegenConstants.GENERATE_ALIAS_AS_MODEL_DESC)

}
Loading