forked from loafle/openapi-generator-original
[gradle-plugin] Initial implementation (#162)
* [gradle-plugin] Initial commit * Clarify comments on file constraints When a user sets the models, apis, or supportingFiles environment variables, any one of these being set disables generation for the other two. This could be confusing to users, so I've added some clarification text in the comments for these properties. In addition, I've cleaned up the extension on Property.ifNotEmpty, to avoid using Suppress annotations where it's not necessary. The change creates a local variable of type T?, allowing Kotlin to track the variable's nullable state at compile time. * Move gradle plugin under modules * Move kt files under kotlin source set. Add sample. * [gradle] map-like options as maps * Add tests for gradle validate task * Apply gradle plugin to mvn install phase * [gradle] Testing remaining gradle tasks * Add gradle plugin to the integration doc * Update gradle plugin README with task options * Gradle readme formatting
This commit is contained in:
parent
7dfd940023
commit
b6b8c0db87
@ -1,8 +1,19 @@
|
|||||||
## Workflow Integration (Maven, Github, CI/CD)
|
## Workflow Integration (Maven, Github, CI/CD)
|
||||||
|
|
||||||
|
### Gradle Integration
|
||||||
|
|
||||||
|
See the [openapi-generator-gradle-plugin README](../modules/openapi-generator-gradle-plugin/README.adoc) for details related to configuring and using the Gradle Plugin.
|
||||||
|
|
||||||
|
Supported tasks include:
|
||||||
|
|
||||||
|
* Listing generators
|
||||||
|
* Validation of Open API 2.0 and 3.0 Specs
|
||||||
|
* Generating "Meta" generators
|
||||||
|
* Generating all generators supported by OpenAPI Generator
|
||||||
|
|
||||||
### Maven Integration
|
### Maven Integration
|
||||||
|
|
||||||
You can use the [openapi-generator-maven-plugin](../modules/openapi-generator-maven-plugin/README.md) for integrating with your workflow, and generating any codegen target.
|
See the [openapi-generator-maven-plugin README](../modules/openapi-generator-maven-plugin/README.md) for details related to configuring and using the Maven Plugin.
|
||||||
|
|
||||||
### GitHub Integration
|
### GitHub Integration
|
||||||
|
|
||||||
|
152
modules/openapi-generator-gradle-plugin/.gitignore
vendored
Normal file
152
modules/openapi-generator-gradle-plugin/.gitignore
vendored
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/gradle,kotlin,intellij,linux,osx
|
||||||
|
|
||||||
|
### Intellij ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.xml
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-debug/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Ruby plugin and RubyMine
|
||||||
|
/.rakeTasks
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
### Intellij Patch ###
|
||||||
|
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||||
|
|
||||||
|
# *.iml
|
||||||
|
# modules.xml
|
||||||
|
# .idea/misc.xml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
.idea/sonarlint
|
||||||
|
|
||||||
|
### Kotlin ###
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### OSX ###
|
||||||
|
*.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### Gradle ###
|
||||||
|
.gradle
|
||||||
|
**/build/
|
||||||
|
|
||||||
|
# Ignore Gradle GUI config
|
||||||
|
gradle-app.setting
|
||||||
|
|
||||||
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Cache of project
|
||||||
|
.gradletasknamecache
|
||||||
|
|
||||||
|
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||||
|
# gradle/wrapper/gradle-wrapper.properties
|
||||||
|
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/gradle,kotlin,intellij,linux,osx
|
452
modules/openapi-generator-gradle-plugin/README.adoc
Normal file
452
modules/openapi-generator-gradle-plugin/README.adoc
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
= OpenAPI Generator Gradle Plugin
|
||||||
|
|
||||||
|
This document describes the gradle plugin for OpenAPI Generator.
|
||||||
|
|
||||||
|
== Tasks
|
||||||
|
|
||||||
|
Tasks are listed under the "OpenAPI Tools" tasks heading.
|
||||||
|
|
||||||
|
|
||||||
|
.OpenAPI Tools Tasks
|
||||||
|
|===
|
||||||
|
|task name |description
|
||||||
|
|
||||||
|
|*openApiGenerate*
|
||||||
|
|Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents.
|
||||||
|
|
||||||
|
|*openApiGenerators*
|
||||||
|
|Lists generators available via Open API Generators.
|
||||||
|
|
||||||
|
|*openApiMeta*
|
||||||
|
|Generates a new generator to be consumed via Open API Generator.
|
||||||
|
|
||||||
|
|*openApiValidate*
|
||||||
|
|Validates an Open API 2.0 or 3.x specification document.
|
||||||
|
|===
|
||||||
|
|
||||||
|
== Plugin Setup
|
||||||
|
|
||||||
|
[source,groovy]
|
||||||
|
----
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "org.openapitools:openapi-generator-gradle-plugin:3.0.0-SNAPSHOT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'org.openapi.generator'
|
||||||
|
----
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
The gradle plugin is not currently published to https://plugins.gradle.org/m2/.
|
||||||
|
====
|
||||||
|
|
||||||
|
== Configuration
|
||||||
|
|
||||||
|
=== openApiGenerate
|
||||||
|
|
||||||
|
.Options
|
||||||
|
|===
|
||||||
|
|Key |Data Type |Default |Description
|
||||||
|
|
||||||
|
|verbose
|
||||||
|
|Boolean
|
||||||
|
|false
|
||||||
|
|The verbosity of generation
|
||||||
|
|
||||||
|
|generatorName
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|The name of the generator which will handle codegen.
|
||||||
|
|
||||||
|
|outputDir
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|The output target directory into which code will be generated.
|
||||||
|
|
||||||
|
|inputSpec
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|The Open API 2.0/3.x specification location.
|
||||||
|
|
||||||
|
|templateDir
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|The template directory holding a custom template.
|
||||||
|
|
||||||
|
|auth
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Adds authorization headers when fetching the OpenAPI definitions remotely. Pass in a URL-encoded string of name:header with a comma separating multiple values.
|
||||||
|
|
||||||
|
|systemProperties
|
||||||
|
|Map(String,String)
|
||||||
|
|None
|
||||||
|
|Sets specified system properties.
|
||||||
|
|
||||||
|
|configFile
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Path to json configuration file. See OpenAPI Generator readme for structure details.
|
||||||
|
|
||||||
|
|skipOverwrite
|
||||||
|
|Boolean
|
||||||
|
|false
|
||||||
|
|Specifies if the existing files should be overwritten during the generation.
|
||||||
|
|
||||||
|
|apiPackage
|
||||||
|
|String
|
||||||
|
|(generator specific)
|
||||||
|
|Package for generated api classes.
|
||||||
|
|
||||||
|
|modelPackage
|
||||||
|
|String
|
||||||
|
|(generator specific)
|
||||||
|
|Package for generated model classes.
|
||||||
|
|
||||||
|
|modelNamePrefix
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Prefix that will be prepended to all model names.
|
||||||
|
|
||||||
|
|modelNameSuffix
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Suffix that will be appended to all model names.
|
||||||
|
|
||||||
|
|instantiationTypes
|
||||||
|
|Map(String,String)
|
||||||
|
|None
|
||||||
|
|Sets instantiation type mappings.
|
||||||
|
|
||||||
|
|typeMappings
|
||||||
|
|Map(String,String)
|
||||||
|
|None
|
||||||
|
|Sets mappings between OpenAPI spec types and generated code types.
|
||||||
|
|
||||||
|
|additionalProperties
|
||||||
|
|Map(String,String)
|
||||||
|
|None
|
||||||
|
|Sets additional properties that can be referenced by the mustache templates.
|
||||||
|
|
||||||
|
|languageSpecificPrimitives
|
||||||
|
|List(String)
|
||||||
|
|None
|
||||||
|
|Specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double.
|
||||||
|
|
||||||
|
|importMappings
|
||||||
|
|Map(String,String)
|
||||||
|
|None
|
||||||
|
|Specifies mappings between a given class and the import that should be used for that class.
|
||||||
|
|
||||||
|
|invokerPackage
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Root package for generated code.
|
||||||
|
|
||||||
|
|groupId
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|GroupId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
|
||||||
|
|id
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|ArtifactId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
|
||||||
|
|version
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Artifact version in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
|
||||||
|
|library
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Reference the library template (sub-template) of a generator.
|
||||||
|
|
||||||
|
|gitUserId
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Git user ID, e.g. openapitools.
|
||||||
|
|
||||||
|
|gitRepoId
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Git repo ID, e.g. openapi-generator.
|
||||||
|
|
||||||
|
|releaseNote
|
||||||
|
|String
|
||||||
|
|'Minor update'
|
||||||
|
|Release note.
|
||||||
|
|
||||||
|
|httpUserAgent
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|HTTP user agent, e.g. codegen_csharp_api_client. Generator default is 'OpenAPI-Generator/{packageVersion}}/{language}', but may be generator-specific.
|
||||||
|
|
||||||
|
|reservedWordsMappings
|
||||||
|
|Map(String,String)
|
||||||
|
|None
|
||||||
|
|Specifies how a reserved name should be escaped to. Otherwise, the default _<name> is used.
|
||||||
|
|
||||||
|
|ignoreFileOverride
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|Specifies an override location for the .openapi-generator-ignore file. Most useful on initial generation.
|
||||||
|
|
||||||
|
|removeOperationIdPrefix
|
||||||
|
|Boolean
|
||||||
|
|false
|
||||||
|
|Remove prefix of operationId, e.g. config_getId => getId.
|
||||||
|
|
||||||
|
|apiFilesConstrainedTo
|
||||||
|
|List(String)
|
||||||
|
|None
|
||||||
|
|Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all). See Note Below.
|
||||||
|
|
||||||
|
|modelFilesConstrainedTo
|
||||||
|
|List(String)
|
||||||
|
|None
|
||||||
|
|Defines which model-related files should be generated. This allows you to create a subset of generated files (or none at all). See Note Below.
|
||||||
|
|
||||||
|
|supportingFilesConstrainedTo
|
||||||
|
|List(String)
|
||||||
|
|None
|
||||||
|
|Defines which supporting files should be generated. This allows you to create a subset of generated files (or none at all). See Note Below.
|
||||||
|
|
||||||
|
|generateModelTests
|
||||||
|
|Boolean
|
||||||
|
|true
|
||||||
|
|Defines whether or not model-related _test_ files should be generated.
|
||||||
|
|
||||||
|
|generateModelDocumentation
|
||||||
|
|Boolean
|
||||||
|
|true
|
||||||
|
|Defines whether or not model-related _documentation_ files should be generated.
|
||||||
|
|
||||||
|
|generateApiTests
|
||||||
|
|Boolean
|
||||||
|
|true
|
||||||
|
|Defines whether or not api-related _test_ files should be generated.
|
||||||
|
|
||||||
|
|generateApiDocumentation
|
||||||
|
|Boolean
|
||||||
|
|true
|
||||||
|
|Defines whether or not api-related _documentation_ files should be generated.
|
||||||
|
|
||||||
|
|withXml
|
||||||
|
|Boolean
|
||||||
|
|false
|
||||||
|
|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.
|
||||||
|
|
||||||
|
|configOptions
|
||||||
|
|Map(String,String)
|
||||||
|
|None
|
||||||
|
|A map of options specific to a generator.
|
||||||
|
|
||||||
|
|===
|
||||||
|
|
||||||
|
[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`.
|
||||||
|
====
|
||||||
|
|
||||||
|
=== openApiValidate
|
||||||
|
|
||||||
|
.Options
|
||||||
|
|===
|
||||||
|
|Key |Data Type |Default |Description
|
||||||
|
|
||||||
|
|inputSpec
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|The input specification to validate. Supports all formats supported by the Parser.
|
||||||
|
|
||||||
|
|===
|
||||||
|
|
||||||
|
=== openApiMeta
|
||||||
|
|
||||||
|
.Options
|
||||||
|
|===
|
||||||
|
|Key |Data Type |Default |Description
|
||||||
|
|
||||||
|
|generatorName
|
||||||
|
|String
|
||||||
|
|None
|
||||||
|
|The human-readable generator name of the newly created template generator.
|
||||||
|
|
||||||
|
|packageName
|
||||||
|
|String
|
||||||
|
|org.openapitools.codegen
|
||||||
|
|The packageName generatorName to put the main class into.
|
||||||
|
|
||||||
|
|outputFolder
|
||||||
|
|String
|
||||||
|
|Current Directory
|
||||||
|
|Where to write the generated files
|
||||||
|
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
== Examples
|
||||||
|
|
||||||
|
=== openApiGenerate
|
||||||
|
|
||||||
|
This task exposes all options available via OpenAPI Generator CLI and the OpenAPI Generator Maven Plugin.
|
||||||
|
|
||||||
|
.in build.gradle
|
||||||
|
[source,groovy]
|
||||||
|
----
|
||||||
|
openApiGenerate {
|
||||||
|
generatorName = "kotlin"
|
||||||
|
inputSpec = "$rootDir/specs/petstore-v3.0.yaml".toString()
|
||||||
|
outputDir = "$buildDir/generated".toString()
|
||||||
|
apiPackage = "org.openapi.example.api"
|
||||||
|
invokerPackage = "org.openapi.example.invoker"
|
||||||
|
modelPackage = "org.openapi.example.model"
|
||||||
|
modelFilesConstrainedTo = [
|
||||||
|
"Error"
|
||||||
|
]
|
||||||
|
configOptions = [
|
||||||
|
dateLibrary: "java8"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
The above code demonstrates configuration of global options as well as generator-specific config options.
|
||||||
|
|
||||||
|
=== openApiGenerators
|
||||||
|
|
||||||
|
This is an output-only listing task. There's no need to add configuration to build.gradle.
|
||||||
|
|
||||||
|
.Example output of openApiGenerators task
|
||||||
|
[source,terminal]
|
||||||
|
----
|
||||||
|
$ ./gradlew openApiGenerators
|
||||||
|
|
||||||
|
> Task :openApiGenerators
|
||||||
|
The following generators are available:
|
||||||
|
|
||||||
|
CLIENT generators:
|
||||||
|
- ada
|
||||||
|
…
|
||||||
|
|
||||||
|
SERVER generators:
|
||||||
|
- ada-server
|
||||||
|
…
|
||||||
|
|
||||||
|
DOCUMENTATION generators:
|
||||||
|
- cwiki
|
||||||
|
…
|
||||||
|
|
||||||
|
CONFIG generators:
|
||||||
|
- apache2
|
||||||
|
|
||||||
|
OTHER generators:
|
||||||
|
…
|
||||||
|
|
||||||
|
BUILD SUCCESSFUL in 0s
|
||||||
|
1 actionable task: 1 executed
|
||||||
|
----
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
Generator type listings in the above example have been truncated to avoid potential confusion with changing generator support.
|
||||||
|
|
||||||
|
Please run the above task to list all available generators.
|
||||||
|
====
|
||||||
|
|
||||||
|
=== openApiMeta
|
||||||
|
|
||||||
|
.in build.gradle
|
||||||
|
[source,groovy]
|
||||||
|
----
|
||||||
|
openApiMeta {
|
||||||
|
generatorName = "Jim"
|
||||||
|
packageName = "us.jimschubert.example"
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
.Example output of openApiMeta task
|
||||||
|
[source,terminal]
|
||||||
|
----
|
||||||
|
$ ./gradlew openApiMeta
|
||||||
|
|
||||||
|
> Task :openApiMeta
|
||||||
|
Wrote file to /Users/jim/my_project/pom.xml
|
||||||
|
Wrote file to /Users/jim/my_project/src/main/java/us/jimschubert/example/JimGenerator.java
|
||||||
|
Wrote file to /Users/jim/my_project/README.md
|
||||||
|
Wrote file to /Users/jim/my_project/src/main/resources/jim/api.mustache
|
||||||
|
Wrote file to /Users/jim/my_project/src/main/resources/jim/model.mustache
|
||||||
|
Wrote file to /Users/jim/my_project/src/main/resources/jim/myFile.mustache
|
||||||
|
Wrote file to /Users/jim/my_project/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
|
||||||
|
Created generator JimGenerator
|
||||||
|
|
||||||
|
BUILD SUCCESSFUL in 0s
|
||||||
|
1 actionable task: 1 executed
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
=== openApiValidate
|
||||||
|
|
||||||
|
.in buid.gradle
|
||||||
|
[source,groovy]
|
||||||
|
----
|
||||||
|
openApiValidate {
|
||||||
|
inputSpec = "/src/openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml"
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
.Example output of openApiValidate task (success)
|
||||||
|
[source,terminal]
|
||||||
|
----
|
||||||
|
$ ./gradlew openApiValidate --input=/Users/jim/projects/openapi-generator/modules/openapi-generator/src/test/resources/3_0/ping.yaml
|
||||||
|
|
||||||
|
> Task :openApiValidate
|
||||||
|
Validating spec /Users/jim/projects/openapi-generator/modules/openapi-generator/src/test/resources/3_0/ping.yaml
|
||||||
|
Spec is valid.
|
||||||
|
|
||||||
|
BUILD SUCCESSFUL in 0s
|
||||||
|
1 actionable task: 1 executed
|
||||||
|
----
|
||||||
|
|
||||||
|
.Example output of openApiValidate task (failure)
|
||||||
|
[source,terminal]
|
||||||
|
----
|
||||||
|
$ ./gradlew openApiValidate
|
||||||
|
|
||||||
|
> Task :openApiValidate FAILED
|
||||||
|
Validating spec /Users/jim/projects/openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml
|
||||||
|
|
||||||
|
Spec is invalid.
|
||||||
|
Issues:
|
||||||
|
|
||||||
|
attribute info is missing
|
||||||
|
|
||||||
|
|
||||||
|
FAILURE: Build failed with an exception.
|
||||||
|
|
||||||
|
* What went wrong:
|
||||||
|
Execution failed for task ':openApiValidate'.
|
||||||
|
> Validation failed.
|
||||||
|
|
||||||
|
* Try:
|
||||||
|
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
|
||||||
|
|
||||||
|
* Get more help at https://help.gradle.org
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
.in terminal (alternate)
|
||||||
|
[source,terminal]
|
||||||
|
----
|
||||||
|
$ ./gradlew openApiValidate --input=/Users/jim/projects/openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml
|
||||||
|
----
|
89
modules/openapi-generator-gradle-plugin/build.gradle
Normal file
89
modules/openapi-generator-gradle-plugin/build.gradle
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
buildscript {
|
||||||
|
ext.kotlin_version = '1.2.41'
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
url "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
classpath "gradle.plugin.org.gradle.kotlin:gradle-kotlin-dsl-plugins:0.17.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'org.openapitools'
|
||||||
|
// Shared OpenAPI Generator version be passed via command line arg as -PopenApiGeneratorVersion=VERSION
|
||||||
|
version "$openApiGeneratorVersion"
|
||||||
|
description = """
|
||||||
|
This plugin supports common functionality found in Open API Generator CLI as a gradle 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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
apply plugin: 'java-gradle-plugin'
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
apply plugin: "org.gradle.kotlin.kotlin-dsl"
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
targetCompatibility = 1.8
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile gradleApi()
|
||||||
|
// Shared OpenAPI Generator version be passed via command line arg as -PopenApiGeneratorVersion=VERSION
|
||||||
|
compile "org.openapitools:openapi-generator:$openApiGeneratorVersion"
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
|
testCompile 'org.testng:testng:6.9.6',
|
||||||
|
"org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
|
testCompile "org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlin_version"
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useTestNG()
|
||||||
|
testClassesDirs = files(project.tasks.compileTestKotlin.destinationDir)
|
||||||
|
testLogging.showStandardStreams = false
|
||||||
|
|
||||||
|
beforeTest { descriptor ->
|
||||||
|
logger.lifecycle("Running test: " + descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
failFast = true
|
||||||
|
|
||||||
|
onOutput { descriptor, event ->
|
||||||
|
// SLF4J may complain about multiple bindings dependign on how this is run.
|
||||||
|
// This is just a warning, but can make test output less readable. So we ignore it specifically.
|
||||||
|
if (!event.message.contains("SLF4J:")) {
|
||||||
|
logger.lifecycle("Test: " + descriptor + " produced standard out/err: " + event.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gradlePlugin {
|
||||||
|
plugins {
|
||||||
|
openApiGenerator {
|
||||||
|
id = 'org.openapi.generator'
|
||||||
|
implementationClass = 'org.openapitools.generator.gradle.plugin.OpenApiGeneratorPlugin'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileKotlin {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileTestKotlin {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
openApiGeneratorVersion=3.0.0-SNAPSHOT
|
BIN
modules/openapi-generator-gradle-plugin/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
modules/openapi-generator-gradle-plugin/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
modules/openapi-generator-gradle-plugin/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
modules/openapi-generator-gradle-plugin/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
172
modules/openapi-generator-gradle-plugin/gradlew
vendored
Executable file
172
modules/openapi-generator-gradle-plugin/gradlew
vendored
Executable file
@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
84
modules/openapi-generator-gradle-plugin/gradlew.bat
vendored
Normal file
84
modules/openapi-generator-gradle-plugin/gradlew.bat
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
59
modules/openapi-generator-gradle-plugin/pom.xml
Normal file
59
modules/openapi-generator-gradle-plugin/pom.xml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.openapitools</groupId>
|
||||||
|
<artifactId>openapi-generator-project</artifactId>
|
||||||
|
<version>3.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../..</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>openapi-generator-gradle-plugin</artifactId>
|
||||||
|
|
||||||
|
<name>openapi-generator-gradle-plugin (gradle-plugin)</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openapitools</groupId>
|
||||||
|
<artifactId>openapi-generator</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<!-- NOTE: Consider this temporary, as a way to cleanly hook into our pipeline.
|
||||||
|
We've discussed moving the entire project to gradle, which would avoid this fitting. -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.fortasoft</groupId>
|
||||||
|
<artifactId>gradle-maven-plugin</artifactId>
|
||||||
|
<version>1.0.8</version>
|
||||||
|
<configuration>
|
||||||
|
<gradleVersion>4.7</gradleVersion>
|
||||||
|
<args>
|
||||||
|
<arg>-P openApiGeneratorVersion=${project.version}</arg>
|
||||||
|
</args>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<!-- goal must be "invoke" -->
|
||||||
|
<goal>invoke</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<tasks>
|
||||||
|
<!-- calls "clean build publishToMavenLocal" -->
|
||||||
|
<task>clean</task>
|
||||||
|
<task>build</task>
|
||||||
|
<task>publishToMavenLocal</task>
|
||||||
|
</tasks>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
3
modules/openapi-generator-gradle-plugin/samples/local-spec/.gitignore
vendored
Normal file
3
modules/openapi-generator-gradle-plugin/samples/local-spec/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.gradle/
|
||||||
|
src/
|
||||||
|
build/
|
@ -0,0 +1,14 @@
|
|||||||
|
# Local Spec Sample
|
||||||
|
|
||||||
|
This example assumes you have Gradle 4.7+ installed. No gradle wrapper is provided in samples.
|
||||||
|
|
||||||
|
First, publish the openapi-generator-gradle-plugin locally via `sh gradlew build publishToMavenLocal` in the module directory.
|
||||||
|
|
||||||
|
Then, run the following tasks in this example directory.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gradle openApiGenerate
|
||||||
|
gradle openApiMeta
|
||||||
|
gradle openApiValidate
|
||||||
|
gradle buildGoSdk
|
||||||
|
```
|
@ -0,0 +1,49 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
url "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "org.openapitools:openapi-generator-gradle-plugin:3.0.0-SNAPSHOT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'org.openapi.generator'
|
||||||
|
|
||||||
|
openApiMeta {
|
||||||
|
generatorName = "Sample"
|
||||||
|
packageName = "org.openapitools.example"
|
||||||
|
outputFolder = "$buildDir/meta".toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
openApiValidate {
|
||||||
|
inputSpec = "$rootDir/petstore-v3.0-invalid.yaml".toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builds a Kotlin client by default.
|
||||||
|
openApiGenerate {
|
||||||
|
generatorName = "kotlin"
|
||||||
|
inputSpec = "$rootDir/petstore-v3.0.yaml".toString()
|
||||||
|
outputDir = "$buildDir/kotlin".toString()
|
||||||
|
apiPackage = "org.openapitools.example.api"
|
||||||
|
invokerPackage = "org.openapitools.example.invoker"
|
||||||
|
modelPackage = "org.openapitools.example.model"
|
||||||
|
configOptions = [
|
||||||
|
dateLibrary: "java8"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
task buildGoSdk(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask){
|
||||||
|
generatorName = "go"
|
||||||
|
inputSpec = "$rootDir/petstore-v3.0.yaml".toString()
|
||||||
|
additionalProperties = [
|
||||||
|
packageName: "petstore"
|
||||||
|
]
|
||||||
|
outputDir = "$buildDir/go".toString()
|
||||||
|
configOptions = [
|
||||||
|
dateLibrary: "threetenp"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
openapi: "3.0.0"
|
||||||
|
servers:
|
||||||
|
- url: http://petstore.swagger.io/v1
|
||||||
|
paths:
|
||||||
|
/pets:
|
||||||
|
get:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
post:
|
||||||
|
summary: Create a pet
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Null response
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/pets/{petId}:
|
||||||
|
get:
|
||||||
|
summary: Info for a specific pet
|
||||||
|
operationId: showPetById
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: petId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The id of the pet to retrieve
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Expected response to a valid request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Pet:
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
Pets:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Pet"
|
||||||
|
Error:
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
- message
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
message:
|
||||||
|
type: string
|
@ -0,0 +1,109 @@
|
|||||||
|
openapi: "3.0.0"
|
||||||
|
info:
|
||||||
|
version: 1.0.0
|
||||||
|
title: Swagger Petstore
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
servers:
|
||||||
|
- url: http://petstore.swagger.io/v1
|
||||||
|
paths:
|
||||||
|
/pets:
|
||||||
|
get:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
post:
|
||||||
|
summary: Create a pet
|
||||||
|
operationId: createPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Null response
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/pets/{petId}:
|
||||||
|
get:
|
||||||
|
summary: Info for a specific pet
|
||||||
|
operationId: showPetById
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: petId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The id of the pet to retrieve
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Expected response to a valid request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Pet:
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
Pets:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Pet"
|
||||||
|
Error:
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
- message
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
message:
|
||||||
|
type: string
|
2
modules/openapi-generator-gradle-plugin/settings.gradle
Normal file
2
modules/openapi-generator-gradle-plugin/settings.gradle
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
rootProject.name = 'openapi-generator-gradle-plugin'
|
||||||
|
|
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.generator.gradle.plugin
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.invoke
|
||||||
|
import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorGenerateExtension
|
||||||
|
import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorMetaExtension
|
||||||
|
import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorValidateExtension
|
||||||
|
import org.openapitools.generator.gradle.plugin.tasks.GenerateTask
|
||||||
|
import org.openapitools.generator.gradle.plugin.tasks.GeneratorsTask
|
||||||
|
import org.openapitools.generator.gradle.plugin.tasks.MetaTask
|
||||||
|
import org.openapitools.generator.gradle.plugin.tasks.ValidateTask
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A plugin providing common Open API Generator use cases.
|
||||||
|
*
|
||||||
|
* @author Jim Schubert
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
class OpenApiGeneratorPlugin : Plugin<Project> {
|
||||||
|
override fun apply(project: Project) {
|
||||||
|
project.run {
|
||||||
|
val meta = extensions.create(
|
||||||
|
"openApiMeta",
|
||||||
|
OpenApiGeneratorMetaExtension::class.java,
|
||||||
|
project
|
||||||
|
)
|
||||||
|
|
||||||
|
val validate = extensions.create(
|
||||||
|
"openApiValidate",
|
||||||
|
OpenApiGeneratorValidateExtension::class.java,
|
||||||
|
project
|
||||||
|
)
|
||||||
|
|
||||||
|
val generate = extensions.create(
|
||||||
|
"openApiGenerate",
|
||||||
|
OpenApiGeneratorGenerateExtension::class.java,
|
||||||
|
project
|
||||||
|
)
|
||||||
|
|
||||||
|
generate.outputDir.set("$buildDir/generate-resources/main")
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
"openApiGenerators"(GeneratorsTask::class) {
|
||||||
|
group = pluginGroup
|
||||||
|
description = "Lists generators available via Open API Generators."
|
||||||
|
}
|
||||||
|
"openApiMeta"(MetaTask::class) {
|
||||||
|
group = pluginGroup
|
||||||
|
description = "Generates a new generator to be consumed via Open API Generator."
|
||||||
|
|
||||||
|
generatorName.set(meta.generatorName)
|
||||||
|
packageName.set(meta.packageName)
|
||||||
|
outputFolder.set(meta.outputFolder)
|
||||||
|
}
|
||||||
|
"openApiValidate"(ValidateTask::class) {
|
||||||
|
group = pluginGroup
|
||||||
|
description = "Validates an Open API 2.0 or 3.x specification document."
|
||||||
|
|
||||||
|
inputSpec.set(validate.inputSpec)
|
||||||
|
}
|
||||||
|
"openApiGenerate"(GenerateTask::class) {
|
||||||
|
group = pluginGroup
|
||||||
|
description = "Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents."
|
||||||
|
|
||||||
|
verbose.set(generate.verbose)
|
||||||
|
generatorName.set(generate.generatorName)
|
||||||
|
outputDir.set(generate.outputDir)
|
||||||
|
inputSpec.set(generate.inputSpec)
|
||||||
|
templateDir.set(generate.templateDir)
|
||||||
|
auth.set(generate.auth)
|
||||||
|
systemProperties.set(generate.systemProperties)
|
||||||
|
configFile.set(generate.configFile)
|
||||||
|
skipOverwrite.set(generate.skipOverwrite)
|
||||||
|
apiPackage.set(generate.apiPackage)
|
||||||
|
modelPackage.set(generate.modelPackage)
|
||||||
|
modelNamePrefix.set(generate.modelNamePrefix)
|
||||||
|
modelNameSuffix.set(generate.modelNameSuffix)
|
||||||
|
instantiationTypes.set(generate.instantiationTypes)
|
||||||
|
typeMappings.set(generate.typeMappings)
|
||||||
|
additionalProperties.set(generate.additionalProperties)
|
||||||
|
languageSpecificPrimitives.set(generate.languageSpecificPrimitives)
|
||||||
|
importMappings.set(generate.importMappings)
|
||||||
|
invokerPackage.set(generate.invokerPackage)
|
||||||
|
groupId.set(generate.groupId)
|
||||||
|
id.set(generate.id)
|
||||||
|
version.set(generate.version)
|
||||||
|
library.set(generate.library)
|
||||||
|
gitUserId.set(generate.gitUserId)
|
||||||
|
gitRepoId.set(generate.gitRepoId)
|
||||||
|
releaseNote.set(generate.releaseNote)
|
||||||
|
httpUserAgent.set(generate.httpUserAgent)
|
||||||
|
reservedWordsMappings.set(generate.reservedWordsMappings)
|
||||||
|
ignoreFileOverride.set(generate.ignoreFileOverride)
|
||||||
|
removeOperationIdPrefix.set(generate.removeOperationIdPrefix)
|
||||||
|
apiFilesConstrainedTo.set(generate.apiFilesConstrainedTo)
|
||||||
|
modelFilesConstrainedTo.set(generate.modelFilesConstrainedTo)
|
||||||
|
supportingFilesConstrainedTo.set(generate.supportingFilesConstrainedTo)
|
||||||
|
generateModelTests.set(generate.generateModelTests)
|
||||||
|
generateModelDocumentation.set(generate.generateModelDocumentation)
|
||||||
|
generateApiTests.set(generate.generateApiTests)
|
||||||
|
generateApiDocumentation.set(generate.generateApiDocumentation)
|
||||||
|
withXml.set(generate.withXml)
|
||||||
|
configOptions.set(generate.configOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val pluginGroup = "OpenAPI Tools"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.generator.gradle.plugin.extensions
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.listProperty
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradle project level extension object definition for the generate task
|
||||||
|
*
|
||||||
|
* @author Jim Schubert
|
||||||
|
*/
|
||||||
|
open class OpenApiGeneratorGenerateExtension(project: Project) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The verbosity of generation
|
||||||
|
*/
|
||||||
|
val verbose = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the generator which will handle codegen. (see "openApiGenerators" task)
|
||||||
|
*/
|
||||||
|
val generatorName = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output target directory into which code will be generated.
|
||||||
|
*/
|
||||||
|
val outputDir = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Open API 2.0/3.x specification location.
|
||||||
|
*/
|
||||||
|
val inputSpec = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The template directory holding a custom template.
|
||||||
|
*/
|
||||||
|
val templateDir = project.objects.property<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
|
||||||
|
*/
|
||||||
|
val auth = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets specified system properties.
|
||||||
|
*/
|
||||||
|
val systemProperties = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to json configuration file.
|
||||||
|
* File content should be in a json format { "optionKey":"optionValue", "optionKey1":"optionValue1"...}
|
||||||
|
* Supported options can be different for each language. Run config-help -g {generator name} command for language specific config options.
|
||||||
|
*/
|
||||||
|
val configFile = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies if the existing files should be overwritten during the generation.
|
||||||
|
*/
|
||||||
|
val skipOverwrite = project.objects.property<Boolean?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package for generated api classes
|
||||||
|
*/
|
||||||
|
val apiPackage = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package for generated models
|
||||||
|
*/
|
||||||
|
val modelPackage = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix that will be prepended to all model names. Default is the empty string.
|
||||||
|
*/
|
||||||
|
val modelNamePrefix = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suffix that will be appended to all model names. Default is the empty string.
|
||||||
|
*/
|
||||||
|
val modelNameSuffix = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets instantiation type mappings.
|
||||||
|
*/
|
||||||
|
val instantiationTypes = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets mappings between OpenAPI spec types and generated code types.
|
||||||
|
*/
|
||||||
|
val typeMappings = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets additional properties that can be referenced by the mustache templates.
|
||||||
|
*/
|
||||||
|
val additionalProperties = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double.
|
||||||
|
*/
|
||||||
|
val languageSpecificPrimitives = project.objects.listProperty<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies mappings between a given class and the import that should be used for that class.
|
||||||
|
*/
|
||||||
|
val importMappings = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Root package for generated code.
|
||||||
|
*/
|
||||||
|
val invokerPackage = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GroupId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
*/
|
||||||
|
val groupId = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArtifactId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
*/
|
||||||
|
val id = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Artifact version in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
*/
|
||||||
|
val version = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference the library template (sub-template) of a generator.
|
||||||
|
*/
|
||||||
|
val library = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Git user ID, e.g. openapitools.
|
||||||
|
*/
|
||||||
|
val gitUserId = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Git repo ID, e.g. openapi-generator.
|
||||||
|
*/
|
||||||
|
val gitRepoId = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release note, default to 'Minor update'.
|
||||||
|
*/
|
||||||
|
val releaseNote = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP user agent, e.g. codegen_csharp_api_client, default to 'OpenAPI-Generator/{packageVersion}}/{language}'
|
||||||
|
*/
|
||||||
|
val httpUserAgent = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies how a reserved name should be escaped to. Otherwise, the default _<name> is used.
|
||||||
|
*/
|
||||||
|
val reservedWordsMappings = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an override location for the .openapi-generator-ignore file. Most useful on initial generation.
|
||||||
|
*/
|
||||||
|
val ignoreFileOverride = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove prefix of operationId, e.g. config_getId => getId
|
||||||
|
*/
|
||||||
|
val removeOperationIdPrefix = project.objects.property<Boolean?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines which API-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].
|
||||||
|
*/
|
||||||
|
val apiFilesConstrainedTo = project.objects.listProperty<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
val modelFilesConstrainedTo = project.objects.listProperty<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
val supportingFilesConstrainedTo = project.objects.listProperty<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
val generateModelTests = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
val generateModelDocumentation = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
val generateApiTests = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
val generateApiDocumentation = project.objects.property<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.
|
||||||
|
*/
|
||||||
|
val withXml = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of options specific to a generator.
|
||||||
|
*/
|
||||||
|
val configOptions = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
releaseNote.set("Minor update")
|
||||||
|
modelNamePrefix.set("")
|
||||||
|
modelNameSuffix.set("")
|
||||||
|
generateModelTests.set(true)
|
||||||
|
generateModelDocumentation.set(true)
|
||||||
|
generateApiTests.set(true)
|
||||||
|
generateApiDocumentation.set(true)
|
||||||
|
withXml.set(false)
|
||||||
|
configOptions.set(mapOf())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.generator.gradle.plugin.extensions
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradle project level extension object definition for the meta-generator task
|
||||||
|
*
|
||||||
|
* @author Jim Schubert
|
||||||
|
*/
|
||||||
|
open class OpenApiGeneratorMetaExtension(project: Project) {
|
||||||
|
/**
|
||||||
|
* The human-readable generator name of the newly created template generator.
|
||||||
|
*/
|
||||||
|
val generatorName = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The packageName generatorName to put the main class into (defaults to org.openapitools.codegen)
|
||||||
|
*/
|
||||||
|
val packageName = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to write the generated files (current dir by default).
|
||||||
|
*/
|
||||||
|
val outputFolder = project.objects.property<String>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
generatorName.set("default")
|
||||||
|
packageName.set("org.openapitools.codegen")
|
||||||
|
outputFolder.set("")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.generator.gradle.plugin.extensions
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradle project level extension object definition for the generators task
|
||||||
|
*
|
||||||
|
* @author Jim Schubert
|
||||||
|
*/
|
||||||
|
open class OpenApiGeneratorValidateExtension(project: Project) {
|
||||||
|
/**
|
||||||
|
* The input specification to validate. Supports all formats supported by the Parser.
|
||||||
|
*/
|
||||||
|
val inputSpec = project.objects.property<String>()
|
||||||
|
}
|
@ -0,0 +1,541 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.generator.gradle.plugin.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.internal.logging.text.StyledTextOutput
|
||||||
|
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||||
|
import org.gradle.kotlin.dsl.listProperty
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
import org.openapitools.codegen.CodegenConstants
|
||||||
|
import org.openapitools.codegen.DefaultGenerator
|
||||||
|
import org.openapitools.codegen.config.CodegenConfigurator
|
||||||
|
import org.openapitools.codegen.config.CodegenConfiguratorUtils.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task which generates the desired code.
|
||||||
|
*
|
||||||
|
* Example (CLI):
|
||||||
|
*
|
||||||
|
* ./gradlew -q openApiGenerate
|
||||||
|
*
|
||||||
|
* @author Jim Schubert
|
||||||
|
*/
|
||||||
|
open class GenerateTask : DefaultTask() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The verbosity of generation
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val verbose = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the generator which will handle codegen. (see "openApiGenerators" task)
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val generatorName = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output target directory into which code will be generated.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val outputDir = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Open API 2.0/3.x specification location.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val inputSpec = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The template directory holding a custom template.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val templateDir = project.objects.property<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
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val auth = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets specified system properties.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val systemProperties = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to json configuration file.
|
||||||
|
* File content should be in a json format { "optionKey":"optionValue", "optionKey1":"optionValue1"...}
|
||||||
|
* Supported options can be different for each language. Run config-help -g {generator name} command for language specific config options.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val configFile = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies if the existing files should be overwritten during the generation.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val skipOverwrite = project.objects.property<Boolean?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package for generated api classes
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val apiPackage = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package for generated models
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val modelPackage = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix that will be prepended to all model names. Default is the empty string.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val modelNamePrefix = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suffix that will be appended to all model names. Default is the empty string.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val modelNameSuffix = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets instantiation type mappings.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val instantiationTypes = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets mappings between OpenAPI spec types and generated code types.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val typeMappings = project.objects.property<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.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val additionalProperties = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val languageSpecificPrimitives = project.objects.listProperty<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies mappings between a given class and the import that should be used for that class.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val importMappings = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Root package for generated code.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val invokerPackage = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GroupId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val groupId = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArtifactId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val id = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Artifact version in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val version = project.objects.property<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference the library template (sub-template) of a generator.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val library = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Git user ID, e.g. openapitools.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val gitUserId = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Git repo ID, e.g. openapi-generator.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val gitRepoId = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release note, default to 'Minor update'.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val releaseNote = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP user agent, e.g. codegen_csharp_api_client, default to 'OpenAPI-Generator/{packageVersion}}/{language}'
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val httpUserAgent = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies how a reserved name should be escaped to.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val reservedWordsMappings = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an override location for the .openapi-generator-ignore file. Most useful on initial generation.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val ignoreFileOverride = project.objects.property<String?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove prefix of operationId, e.g. config_getId => getId
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val removeOperationIdPrefix = project.objects.property<Boolean?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val apiFilesConstrainedTo = project.objects.listProperty<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val modelFilesConstrainedTo = project.objects.listProperty<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val supportingFilesConstrainedTo = project.objects.listProperty<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val generateModelTests = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val generateModelDocumentation = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val generateApiTests = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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].
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val generateApiDocumentation = project.objects.property<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.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val withXml = project.objects.property<Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dynamic map of options specific to a generator.
|
||||||
|
*/
|
||||||
|
@get:Internal
|
||||||
|
val configOptions = project.objects.property<Map<String, String>>()
|
||||||
|
|
||||||
|
private val originalEnvironmentVariables = mutableMapOf<String, String>()
|
||||||
|
|
||||||
|
private fun <T : Any?> Property<T>.ifNotEmpty(block: Property<T>.(T) -> Unit) {
|
||||||
|
if (isPresent) {
|
||||||
|
val item: T? = get()
|
||||||
|
if (item != null) {
|
||||||
|
when (get()) {
|
||||||
|
is String -> if ((get() as String).isNotEmpty()) {
|
||||||
|
block(get())
|
||||||
|
}
|
||||||
|
is String? -> if (true == (get() as String?)?.isNotEmpty()) {
|
||||||
|
block(get())
|
||||||
|
}
|
||||||
|
else -> block(get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@TaskAction
|
||||||
|
fun doWork() {
|
||||||
|
val configurator: CodegenConfigurator = if (configFile.isPresent) {
|
||||||
|
CodegenConfigurator.fromFile(configFile.get())
|
||||||
|
} else CodegenConfigurator()
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (systemProperties.isPresent) {
|
||||||
|
systemProperties.get().forEach { (key, value) ->
|
||||||
|
originalEnvironmentVariables[key] = System.getProperty(key)
|
||||||
|
System.setProperty(key, value)
|
||||||
|
configurator.addSystemProperty(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportingFilesConstrainedTo.isPresent && supportingFilesConstrainedTo.get().isNotEmpty()) {
|
||||||
|
System.setProperty(CodegenConstants.SUPPORTING_FILES, supportingFilesConstrainedTo.get().joinToString(","))
|
||||||
|
} else {
|
||||||
|
System.clearProperty(CodegenConstants.SUPPORTING_FILES)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelFilesConstrainedTo.isPresent && modelFilesConstrainedTo.get().isNotEmpty()) {
|
||||||
|
System.setProperty(CodegenConstants.MODELS, modelFilesConstrainedTo.get().joinToString(","))
|
||||||
|
} else {
|
||||||
|
System.clearProperty(CodegenConstants.MODELS)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apiFilesConstrainedTo.isPresent && apiFilesConstrainedTo.get().isNotEmpty()) {
|
||||||
|
System.setProperty(CodegenConstants.APIS, apiFilesConstrainedTo.get().joinToString(","))
|
||||||
|
} else {
|
||||||
|
System.clearProperty(CodegenConstants.APIS)
|
||||||
|
}
|
||||||
|
|
||||||
|
System.setProperty(CodegenConstants.API_DOCS, generateApiDocumentation.get().toString())
|
||||||
|
System.setProperty(CodegenConstants.MODEL_DOCS, generateModelDocumentation.get().toString())
|
||||||
|
System.setProperty(CodegenConstants.MODEL_TESTS, generateModelTests.get().toString())
|
||||||
|
System.setProperty(CodegenConstants.API_TESTS, generateApiTests.get().toString())
|
||||||
|
System.setProperty(CodegenConstants.WITH_XML, withXml.get().toString())
|
||||||
|
|
||||||
|
// now override with any specified parameters
|
||||||
|
verbose.ifNotEmpty { value ->
|
||||||
|
configurator.isVerbose = value
|
||||||
|
}
|
||||||
|
|
||||||
|
skipOverwrite.ifNotEmpty { value ->
|
||||||
|
configurator.isSkipOverwrite = value ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
inputSpec.ifNotEmpty { value ->
|
||||||
|
configurator.inputSpec = value
|
||||||
|
}
|
||||||
|
|
||||||
|
generatorName.ifNotEmpty { value ->
|
||||||
|
configurator.generatorName = value
|
||||||
|
}
|
||||||
|
|
||||||
|
outputDir.ifNotEmpty { value ->
|
||||||
|
configurator.outputDir = value
|
||||||
|
}
|
||||||
|
|
||||||
|
auth.ifNotEmpty { value ->
|
||||||
|
configurator.auth = value
|
||||||
|
}
|
||||||
|
|
||||||
|
templateDir.ifNotEmpty { value ->
|
||||||
|
configurator.templateDir = value
|
||||||
|
}
|
||||||
|
|
||||||
|
apiPackage.ifNotEmpty { value ->
|
||||||
|
configurator.apiPackage = value
|
||||||
|
}
|
||||||
|
|
||||||
|
modelPackage.ifNotEmpty { value ->
|
||||||
|
configurator.modelPackage = value
|
||||||
|
}
|
||||||
|
|
||||||
|
modelNamePrefix.ifNotEmpty { value ->
|
||||||
|
configurator.modelNamePrefix = value
|
||||||
|
}
|
||||||
|
|
||||||
|
modelNameSuffix.ifNotEmpty { value ->
|
||||||
|
configurator.modelNameSuffix = value
|
||||||
|
}
|
||||||
|
|
||||||
|
invokerPackage.ifNotEmpty { value ->
|
||||||
|
configurator.invokerPackage = value
|
||||||
|
}
|
||||||
|
|
||||||
|
groupId.ifNotEmpty { value ->
|
||||||
|
configurator.groupId = value
|
||||||
|
}
|
||||||
|
|
||||||
|
id.ifNotEmpty { value ->
|
||||||
|
configurator.artifactId = value
|
||||||
|
}
|
||||||
|
|
||||||
|
version.ifNotEmpty { value ->
|
||||||
|
configurator.artifactVersion = value
|
||||||
|
}
|
||||||
|
|
||||||
|
library.ifNotEmpty { value ->
|
||||||
|
configurator.library = value
|
||||||
|
}
|
||||||
|
|
||||||
|
gitUserId.ifNotEmpty { value ->
|
||||||
|
configurator.gitUserId = value
|
||||||
|
}
|
||||||
|
|
||||||
|
gitRepoId.ifNotEmpty { value ->
|
||||||
|
configurator.gitRepoId = value
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseNote.ifNotEmpty { value ->
|
||||||
|
configurator.releaseNote = value
|
||||||
|
}
|
||||||
|
|
||||||
|
httpUserAgent.ifNotEmpty { value ->
|
||||||
|
configurator.httpUserAgent = value
|
||||||
|
}
|
||||||
|
|
||||||
|
ignoreFileOverride.ifNotEmpty { value ->
|
||||||
|
configurator.ignoreFileOverride = value
|
||||||
|
}
|
||||||
|
|
||||||
|
removeOperationIdPrefix.ifNotEmpty { value ->
|
||||||
|
configurator.removeOperationIdPrefix = value!!
|
||||||
|
}
|
||||||
|
|
||||||
|
if (systemProperties.isPresent) {
|
||||||
|
systemProperties.get().forEach { entry ->
|
||||||
|
configurator.addSystemProperty(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instantiationTypes.isPresent) {
|
||||||
|
instantiationTypes.get().forEach { entry ->
|
||||||
|
configurator.addInstantiationType(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importMappings.isPresent) {
|
||||||
|
importMappings.get().forEach { entry ->
|
||||||
|
configurator.addImportMapping(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeMappings.isPresent) {
|
||||||
|
typeMappings.get().forEach { entry ->
|
||||||
|
configurator.addTypeMapping(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (additionalProperties.isPresent) {
|
||||||
|
additionalProperties.get().forEach { entry ->
|
||||||
|
configurator.addAdditionalProperty(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (languageSpecificPrimitives.isPresent) {
|
||||||
|
languageSpecificPrimitives.get().forEach {
|
||||||
|
configurator.addLanguageSpecificPrimitive(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reservedWordsMappings.isPresent) {
|
||||||
|
reservedWordsMappings.get().forEach { entry ->
|
||||||
|
configurator.addAdditionalReservedWordMapping(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val clientOptInput = configurator.toClientOptInput()
|
||||||
|
val codgenConfig = clientOptInput.config
|
||||||
|
|
||||||
|
if (configOptions.isPresent) {
|
||||||
|
val userSpecifiedConfigOptions = configOptions.get()
|
||||||
|
codgenConfig.cliOptions().forEach {
|
||||||
|
if (userSpecifiedConfigOptions.containsKey(it.opt)) {
|
||||||
|
clientOptInput.config.additionalProperties()[it.opt] = userSpecifiedConfigOptions[it.opt]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
|
||||||
|
out.withStyle(StyledTextOutput.Style.Success)
|
||||||
|
|
||||||
|
DefaultGenerator().opts(clientOptInput).generate()
|
||||||
|
|
||||||
|
out.println("Successfully generated code to ${configurator.outputDir}")
|
||||||
|
} catch (e: RuntimeException) {
|
||||||
|
logger.error(e.message)
|
||||||
|
throw GradleException("Code generation failed.")
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
originalEnvironmentVariables.forEach { entry ->
|
||||||
|
System.setProperty(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
originalEnvironmentVariables.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.generator.gradle.plugin.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.internal.logging.text.StyledTextOutput
|
||||||
|
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||||
|
import org.openapitools.codegen.CodegenConfigLoader
|
||||||
|
import org.openapitools.codegen.CodegenType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task which lists out the generators available in OpenAPI Generator
|
||||||
|
*
|
||||||
|
* Example (CLI):
|
||||||
|
*
|
||||||
|
* ./gradlew -q openApiGenerators
|
||||||
|
*
|
||||||
|
* @author Jim Schubert
|
||||||
|
*/
|
||||||
|
open class GeneratorsTask : DefaultTask() {
|
||||||
|
@Suppress("unused")
|
||||||
|
@TaskAction
|
||||||
|
fun doWork() {
|
||||||
|
val generators = CodegenConfigLoader.getAll()
|
||||||
|
|
||||||
|
val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
|
||||||
|
|
||||||
|
StringBuilder().apply {
|
||||||
|
val types = CodegenType.values()
|
||||||
|
|
||||||
|
append("The following generators are available:")
|
||||||
|
|
||||||
|
append(System.lineSeparator())
|
||||||
|
append(System.lineSeparator())
|
||||||
|
|
||||||
|
for (type in types) {
|
||||||
|
append(type.name).append(" generators:")
|
||||||
|
append(System.lineSeparator())
|
||||||
|
|
||||||
|
generators.filter { it.tag == type }
|
||||||
|
.sortedBy { it.name }
|
||||||
|
.forEach({ generator ->
|
||||||
|
append(" - ")
|
||||||
|
append(generator.name)
|
||||||
|
append(System.lineSeparator())
|
||||||
|
})
|
||||||
|
|
||||||
|
append(System.lineSeparator())
|
||||||
|
append(System.lineSeparator())
|
||||||
|
}
|
||||||
|
|
||||||
|
out.withStyle(StyledTextOutput.Style.Success)
|
||||||
|
out.formatln("%s%n", toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.generator.gradle.plugin.tasks
|
||||||
|
|
||||||
|
import com.samskivert.mustache.Mustache
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.internal.logging.text.StyledTextOutput
|
||||||
|
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
import org.openapitools.codegen.CodegenConfig
|
||||||
|
import org.openapitools.codegen.CodegenConstants
|
||||||
|
import org.openapitools.codegen.DefaultGenerator
|
||||||
|
import org.openapitools.codegen.SupportingFile
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task which generates a new generator (meta). Useful for redistributable generator packages.
|
||||||
|
*
|
||||||
|
* @author Jim Schubert
|
||||||
|
*/
|
||||||
|
open class MetaTask : DefaultTask() {
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
val generatorName = project.objects.property<String>()
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
val packageName = project.objects.property<String>()
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
val outputFolder = project.objects.property<String>()
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@TaskAction
|
||||||
|
fun doWork() {
|
||||||
|
|
||||||
|
val packageToPath = packageName.get().replace(".", File.separator)
|
||||||
|
val dir = File(outputFolder.get())
|
||||||
|
val klass = "${generatorName.get().titleCasedTextOnly()}Generator"
|
||||||
|
|
||||||
|
val templateResourceDir = generatorName.get().hyphenatedTextOnly()
|
||||||
|
|
||||||
|
val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
|
||||||
|
|
||||||
|
out.withStyle(StyledTextOutput.Style.Info)
|
||||||
|
|
||||||
|
logger.debug("package: {}", packageName.get())
|
||||||
|
logger.debug("dir: {}", dir.absolutePath)
|
||||||
|
logger.debug("generator class: {}", klass)
|
||||||
|
|
||||||
|
val supportingFiles = listOf(
|
||||||
|
SupportingFile("pom.mustache", "", "pom.xml"),
|
||||||
|
SupportingFile("generatorClass.mustache", dir("src", "main", "java", packageToPath), "$klass.java"),
|
||||||
|
SupportingFile("README.mustache", "", "README.md"),
|
||||||
|
SupportingFile("api.template", dir("src", "main", "resources", templateResourceDir), "api.mustache"),
|
||||||
|
SupportingFile("model.template", dir("src", "main", "resources", templateResourceDir), "model.mustache"),
|
||||||
|
SupportingFile("myFile.template", dir("src", "main", "resources", templateResourceDir), "myFile.mustache"),
|
||||||
|
SupportingFile("services.mustache", dir("src", "main", "resources", "META-INF", "services"), CodegenConfig::class.java.canonicalName))
|
||||||
|
|
||||||
|
val currentVersion = CodegenConstants::class.java.`package`.implementationVersion
|
||||||
|
|
||||||
|
val data = mapOf("generatorPackage" to packageToPath,
|
||||||
|
"generatorClass" to klass,
|
||||||
|
"name" to templateResourceDir,
|
||||||
|
"fullyQualifiedGeneratorClass" to "${packageName.get()}.$klass",
|
||||||
|
"openapiGeneratorVersion" to currentVersion)
|
||||||
|
|
||||||
|
val generator = DefaultGenerator()
|
||||||
|
supportingFiles.map {
|
||||||
|
try {
|
||||||
|
val destinationFolder = File(File(dir.absolutePath), it.folder)
|
||||||
|
destinationFolder.mkdirs()
|
||||||
|
val outputFile = File(destinationFolder, it.destinationFilename)
|
||||||
|
|
||||||
|
val template = generator.readTemplate(File("codegen", it.templateFile).path)
|
||||||
|
var formatted = template
|
||||||
|
|
||||||
|
if (it.templateFile.endsWith(".mustache")) {
|
||||||
|
formatted = Mustache.compiler()
|
||||||
|
.withLoader(loader(generator))
|
||||||
|
.defaultValue("")
|
||||||
|
.compile(template).execute(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFile.writeText(formatted, Charset.forName("UTF8"))
|
||||||
|
|
||||||
|
out.formatln("Wrote file to %s", outputFile.absolutePath)
|
||||||
|
|
||||||
|
// TODO: register outputs
|
||||||
|
// return outputFile
|
||||||
|
} catch (e: IOException) {
|
||||||
|
logger.error(e.message)
|
||||||
|
throw GradleException("Can't generate project", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.withStyle(StyledTextOutput.Style.Success)
|
||||||
|
out.formatln("Created generator %s", klass)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loader(generator: DefaultGenerator): Mustache.TemplateLoader {
|
||||||
|
return Mustache.TemplateLoader { name ->
|
||||||
|
generator.getTemplateReader("codegen${File.separator}$name.mustache")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.titleCasedTextOnly(): String =
|
||||||
|
this.split(Regex("[^a-zA-Z0-9]")).joinToString(separator = "", transform = String::capitalize)
|
||||||
|
|
||||||
|
private fun String.hyphenatedTextOnly(): String =
|
||||||
|
this.split(Regex("[^a-zA-Z0-9]")).joinToString(separator = "-", transform = String::toLowerCase)
|
||||||
|
|
||||||
|
private fun dir(vararg parts: String): String =
|
||||||
|
parts.joinToString(separator = File.separator)
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.generator.gradle.plugin.tasks
|
||||||
|
|
||||||
|
import io.swagger.parser.OpenAPIParser
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.api.tasks.options.Option
|
||||||
|
import org.gradle.internal.logging.text.StyledTextOutput
|
||||||
|
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generator which validates an Open API spec. This task outputs a list of validation issues and errors.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* cli:
|
||||||
|
*
|
||||||
|
* ./gradlew openApiValidate --input=/path/to/file
|
||||||
|
*
|
||||||
|
* build.gradle:
|
||||||
|
*
|
||||||
|
* openApiMeta {
|
||||||
|
* inputSpec = "path/to/spec.yaml"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @author Jim Schubert
|
||||||
|
*/
|
||||||
|
open class ValidateTask : DefaultTask() {
|
||||||
|
@get:Internal
|
||||||
|
var inputSpec = project.objects.property<String>()
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@get:Internal
|
||||||
|
@set:Option(option = "input", description = "The input specification.")
|
||||||
|
var input: String? = null
|
||||||
|
set(value) {
|
||||||
|
inputSpec.set(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@TaskAction
|
||||||
|
fun doWork() {
|
||||||
|
val spec = inputSpec.get()
|
||||||
|
logger.quiet("Validating spec $spec")
|
||||||
|
val result = OpenAPIParser().readLocation(spec, null, null)
|
||||||
|
val messages = result.messages.toSet()
|
||||||
|
val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
|
||||||
|
|
||||||
|
if (messages.isNotEmpty()) {
|
||||||
|
|
||||||
|
out.withStyle(StyledTextOutput.Style.Error)
|
||||||
|
out.println("\nSpec is invalid.\nIssues:\n")
|
||||||
|
|
||||||
|
messages.forEach {
|
||||||
|
out.withStyle(StyledTextOutput.Style.Error)
|
||||||
|
out.println("\t$it\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
throw GradleException("Validation failed.")
|
||||||
|
} else {
|
||||||
|
out.withStyle(StyledTextOutput.Style.Success)
|
||||||
|
out.println("Spec is valid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package org.openapitools.generator.gradle.plugin
|
||||||
|
|
||||||
|
import org.gradle.testkit.runner.GradleRunner
|
||||||
|
import org.gradle.testkit.runner.TaskOutcome
|
||||||
|
import org.testng.annotations.Test
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class GenerateTaskDslTest : TestBase() {
|
||||||
|
override var temp: File = createTempDir(javaClass.simpleName)
|
||||||
|
|
||||||
|
private val defaultBuildGradle = """
|
||||||
|
plugins {
|
||||||
|
id 'org.openapi.generator'
|
||||||
|
}
|
||||||
|
openApiGenerate {
|
||||||
|
generatorName = "kotlin"
|
||||||
|
inputSpec = file("spec.yaml").absolutePath
|
||||||
|
outputDir = file("build/kotlin").absolutePath
|
||||||
|
apiPackage = "org.openapitools.example.api"
|
||||||
|
invokerPackage = "org.openapitools.example.invoker"
|
||||||
|
modelPackage = "org.openapitools.example.model"
|
||||||
|
configOptions = [
|
||||||
|
dateLibrary: "java8"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `openApiGenerate should create an expected file structure from DSL config`() {
|
||||||
|
// Arrange
|
||||||
|
val projectFiles = mapOf(
|
||||||
|
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0-invalid.yaml")
|
||||||
|
)
|
||||||
|
withProject(defaultBuildGradle, projectFiles)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = GradleRunner.create()
|
||||||
|
.withProjectDir(temp)
|
||||||
|
.withArguments("openApiGenerate")
|
||||||
|
.withPluginClasspath()
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result.output.contains("Successfully generated code to"), "User friendly generate notice is missing.")
|
||||||
|
|
||||||
|
listOf(
|
||||||
|
"build/kotlin/.openapi-generator-ignore",
|
||||||
|
"build/kotlin/docs/PetsApi.md",
|
||||||
|
"build/kotlin/docs/Pets.md",
|
||||||
|
"build/kotlin/docs/Error.md",
|
||||||
|
"build/kotlin/docs/Pet.md",
|
||||||
|
"build/kotlin/README.md",
|
||||||
|
"build/kotlin/build.gradle",
|
||||||
|
"build/kotlin/.openapi-generator/VERSION",
|
||||||
|
"build/kotlin/settings.gradle",
|
||||||
|
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Pets.kt",
|
||||||
|
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Pet.kt",
|
||||||
|
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Error.kt",
|
||||||
|
"build/kotlin/src/main/kotlin/org/openapitools/example/api/PetsApi.kt",
|
||||||
|
"build/kotlin/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt"
|
||||||
|
).map {
|
||||||
|
val f = File(temp, it)
|
||||||
|
assertTrue(f.exists() && f.isFile, "An expected file was not generated when invoking the generation.")
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(TaskOutcome.SUCCESS, result.task(":openApiGenerate")?.outcome,
|
||||||
|
"Expected a successful run, but found ${result.task(":openApiGenerate")?.outcome}")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package org.openapitools.generator.gradle.plugin
|
||||||
|
|
||||||
|
import org.gradle.testkit.runner.GradleRunner
|
||||||
|
import org.gradle.testkit.runner.TaskOutcome
|
||||||
|
import org.testng.annotations.Test
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class GeneratorsTaskDslTest : TestBase() {
|
||||||
|
override var temp: File = createTempDir(javaClass.simpleName)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `openApiGenerators should list generators available to the user`() {
|
||||||
|
// Arrange
|
||||||
|
withProject("""
|
||||||
|
| plugins {
|
||||||
|
| id 'org.openapi.generator'
|
||||||
|
| }
|
||||||
|
""".trimMargin())
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = GradleRunner.create()
|
||||||
|
.withProjectDir(temp)
|
||||||
|
.withArguments("openApiGenerators")
|
||||||
|
.withPluginClasspath()
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result.output.contains("The following generators are available:"), "User friendly generator notice is missing.")
|
||||||
|
assertTrue(result.output.contains("CLIENT generators:"), "Expected client generator header is missing.")
|
||||||
|
assertTrue(result.output.contains("android"), "Spot-checking listed client generators is missing a client generator.")
|
||||||
|
assertTrue(result.output.contains("SERVER generators:"), "Expected server generator header is missing.")
|
||||||
|
assertTrue(result.output.contains("kotlin-server"), "Spot-checking listed server generators is missing a server generator.")
|
||||||
|
assertEquals(TaskOutcome.SUCCESS, result.task(":openApiGenerators")?.outcome,
|
||||||
|
"Expected a successful run, but found ${result.task(":openApiGenerators")?.outcome}")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package org.openapitools.generator.gradle.plugin
|
||||||
|
|
||||||
|
import org.gradle.testkit.runner.GradleRunner
|
||||||
|
import org.gradle.testkit.runner.TaskOutcome
|
||||||
|
import org.testng.annotations.Test
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class MetaTaskDslTest : TestBase() {
|
||||||
|
override var temp: File = createTempDir(javaClass.simpleName)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `openApiMeta should generate desired project contents`() {
|
||||||
|
// Arrange
|
||||||
|
val buildDirReplacement = "\$buildDir/meta"
|
||||||
|
withProject("""
|
||||||
|
| plugins {
|
||||||
|
| id 'org.openapi.generator'
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| openApiMeta {
|
||||||
|
| generatorName = "Sample"
|
||||||
|
| packageName = "org.openapitools.example"
|
||||||
|
| outputFolder = "$buildDirReplacement".toString()
|
||||||
|
| }
|
||||||
|
""".trimMargin())
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = GradleRunner.create()
|
||||||
|
.withProjectDir(temp)
|
||||||
|
.withArguments("openApiMeta")
|
||||||
|
.withPluginClasspath()
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result.output.contains("Wrote file to"), "User friendly write notice is missing.")
|
||||||
|
|
||||||
|
// To avoid any OS-specific output causing issues with our stdout comparisons, only compare on expected filenames.
|
||||||
|
listOf(
|
||||||
|
"SampleGenerator.java",
|
||||||
|
"README.md",
|
||||||
|
"api.mustache",
|
||||||
|
"model.mustache",
|
||||||
|
"myFile.mustache",
|
||||||
|
"org.openapitools.codegen.CodegenConfig",
|
||||||
|
"pom.xml"
|
||||||
|
).map {
|
||||||
|
assertTrue(result.output.contains(it), "Expected $it to be listed in gradle stdout.")
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
TaskOutcome.SUCCESS,
|
||||||
|
result.task(":openApiMeta")?.outcome,
|
||||||
|
"Expected a successful run, but found ${result.task(":openApiMeta")?.outcome}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.openapitools.generator.gradle.plugin
|
||||||
|
|
||||||
|
import org.testng.annotations.AfterMethod
|
||||||
|
import org.testng.annotations.BeforeMethod
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
abstract class TestBase {
|
||||||
|
protected open lateinit var temp: File
|
||||||
|
|
||||||
|
@BeforeMethod
|
||||||
|
protected fun before() {
|
||||||
|
temp = createTempDir(javaClass.simpleName)
|
||||||
|
temp.deleteOnExit()
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterMethod
|
||||||
|
protected fun after(){
|
||||||
|
temp.deleteRecursively()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun withProject(
|
||||||
|
buildContents: String,
|
||||||
|
projectFiles: Map<String, InputStream> = mapOf()
|
||||||
|
) {
|
||||||
|
val buildFile = File(temp,"build.gradle")
|
||||||
|
buildFile.writeText(buildContents)
|
||||||
|
|
||||||
|
projectFiles.forEach { entry ->
|
||||||
|
val target = File(temp, entry.key)
|
||||||
|
entry.value.copyTo(target.outputStream())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package org.openapitools.generator.gradle.plugin
|
||||||
|
|
||||||
|
import org.gradle.testkit.runner.GradleRunner
|
||||||
|
import org.gradle.testkit.runner.TaskOutcome.FAILED
|
||||||
|
import org.gradle.testkit.runner.TaskOutcome.SUCCESS
|
||||||
|
import org.testng.annotations.Test
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class ValidateTaskDslTest : TestBase() {
|
||||||
|
override var temp: File = createTempDir(javaClass.simpleName)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `openApiValidate should fail on non-file spec`() {
|
||||||
|
// Arrange
|
||||||
|
withProject("""
|
||||||
|
| plugins {
|
||||||
|
| id 'org.openapi.generator'
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| openApiValidate {
|
||||||
|
| inputSpec = "some_location"
|
||||||
|
| }
|
||||||
|
""".trimMargin())
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = GradleRunner.create()
|
||||||
|
.withProjectDir(temp)
|
||||||
|
.withArguments("openApiValidate")
|
||||||
|
.withPluginClasspath()
|
||||||
|
.buildAndFail()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result.output.contains("unable to read location `some_location`"), "Unexpected/no message presented to the user for a spec pointing to an invalid URI.")
|
||||||
|
assertEquals(FAILED, result.task(":openApiValidate")?.outcome,
|
||||||
|
"Expected a failed run, but found ${result.task(":openApiValidate")?.outcome}")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `openApiValidate should succeed on valid spec`() {
|
||||||
|
// Arrange
|
||||||
|
val projectFiles = mapOf(
|
||||||
|
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0.yaml")
|
||||||
|
)
|
||||||
|
|
||||||
|
withProject("""
|
||||||
|
| plugins {
|
||||||
|
| id 'org.openapi.generator'
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| openApiValidate {
|
||||||
|
| inputSpec = file("spec.yaml").absolutePath
|
||||||
|
| }
|
||||||
|
""".trimMargin(), projectFiles)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = GradleRunner.create()
|
||||||
|
.withProjectDir(temp)
|
||||||
|
.withArguments("openApiValidate")
|
||||||
|
.withPluginClasspath()
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result.output.contains("Spec is valid."), "Unexpected/no message presented to the user for a valid spec.")
|
||||||
|
assertEquals(SUCCESS, result.task(":openApiValidate")?.outcome,
|
||||||
|
"Expected a successful run, but found ${result.task(":openApiValidate")?.outcome}")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `openApiValidate should fail on invalid spec`() {
|
||||||
|
// Arrange
|
||||||
|
val projectFiles = mapOf(
|
||||||
|
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0-invalid.yaml")
|
||||||
|
)
|
||||||
|
withProject("""
|
||||||
|
| plugins {
|
||||||
|
| id 'org.openapi.generator'
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| openApiValidate {
|
||||||
|
| inputSpec = file('spec.yaml').absolutePath
|
||||||
|
| }
|
||||||
|
""".trimMargin(), projectFiles)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = GradleRunner.create()
|
||||||
|
.withProjectDir(temp)
|
||||||
|
.withArguments("openApiValidate")
|
||||||
|
.withPluginClasspath()
|
||||||
|
.buildAndFail()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result.output.contains("Spec is invalid."), "Unexpected/no message presented to the user for an invalid spec.")
|
||||||
|
assertEquals(FAILED, result.task(":openApiValidate")?.outcome,
|
||||||
|
"Expected a failed run, but found ${result.task(":openApiValidate")?.outcome}")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
openapi: "3.0.0"
|
||||||
|
servers:
|
||||||
|
- url: http://petstore.swagger.io/v1
|
||||||
|
paths:
|
||||||
|
/pets:
|
||||||
|
get:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
post:
|
||||||
|
summary: Create a pet
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Null response
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/pets/{petId}:
|
||||||
|
get:
|
||||||
|
summary: Info for a specific pet
|
||||||
|
operationId: showPetById
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: petId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The id of the pet to retrieve
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Expected response to a valid request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Pet:
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
Pets:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Pet"
|
||||||
|
Error:
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
- message
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
message:
|
||||||
|
type: string
|
@ -0,0 +1,109 @@
|
|||||||
|
openapi: "3.0.0"
|
||||||
|
info:
|
||||||
|
version: 1.0.0
|
||||||
|
title: Swagger Petstore
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
servers:
|
||||||
|
- url: http://petstore.swagger.io/v1
|
||||||
|
paths:
|
||||||
|
/pets:
|
||||||
|
get:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
post:
|
||||||
|
summary: Create a pet
|
||||||
|
operationId: createPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Null response
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/pets/{petId}:
|
||||||
|
get:
|
||||||
|
summary: Info for a specific pet
|
||||||
|
operationId: showPetById
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: petId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The id of the pet to retrieve
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Expected response to a valid request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Pet:
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
Pets:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Pet"
|
||||||
|
Error:
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
- message
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
message:
|
||||||
|
type: string
|
1
pom.xml
1
pom.xml
@ -883,6 +883,7 @@
|
|||||||
<module>modules/openapi-generator</module>
|
<module>modules/openapi-generator</module>
|
||||||
<module>modules/openapi-generator-cli</module>
|
<module>modules/openapi-generator-cli</module>
|
||||||
<module>modules/openapi-generator-maven-plugin</module>
|
<module>modules/openapi-generator-maven-plugin</module>
|
||||||
|
<module>modules/openapi-generator-gradle-plugin</module>
|
||||||
<module>modules/openapi-generator-online</module>
|
<module>modules/openapi-generator-online</module>
|
||||||
</modules>
|
</modules>
|
||||||
<reporting>
|
<reporting>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user