Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ It currently consists of

# Release Notes
BOAT is still under development and subject to change.
## 0.17.53
* Added 2 Lint rules `B007U` and `B009U` for Unified Backbase API specs:
* `B007U` checks whether paths do not contain `client-api`, `service-api` and `integration-api` prefixes. Any prefix is not allowed for Unified Backbase API.
* `B009U` checks whether paths do not contain any version number. Any version number is not allowed for Unified Backbase API.
* These rules are ignored by default, but if you redefine the list of ignored rules in your project, then you need to add these two rules to your list.
## 0.17.52
* Lint rule `B014` fix reference link to component examples
## 0.17.46
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public abstract class AbstractLintMojo extends InputMavenArtifactMojo {
@Parameter(name = "ignoreRules")
protected String[] ignoreRules = new String[]{"150","219","215","218","166","136","174","235","107","171","224","143",
"151","129","146","147","172","145","115","132","120", "134","183","154","105","104","130","118","110","153",
"101","176","116","M009","H002","M010","H001","M008","S005","S006","S007","M011"};
"101","176","116","M009","H002","M010","H001","M008","S005","S006","S007","M011","B007U","B009U"};

protected List<BoatLintReport> lint() throws MojoExecutionException, MojoFailureException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class LintMojoTests {
@Test
void testFailOnWarningNoWarnings() throws MojoFailureException, MojoExecutionException {
LintMojo lintMojo = new LintMojo();
lintMojo.setIgnoreRules(Arrays.array("219", "105", "104", "151", "134", "115","M0012", "224", "B013", "B014"));
lintMojo.setIgnoreRules(Arrays.array("219", "105", "104", "151", "134", "115","M0012", "224", "B013", "B014", "B007U", "B009U"));
lintMojo.setInput(getFile("/oas-examples/no-lint-warnings.yaml"));
lintMojo.setFailOnWarning(true);
lintMojo.execute();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.backbase.oss.boat.quay.ruleset

import com.typesafe.config.Config
import org.zalando.zally.rule.api.*
import kotlin.collections.map
import kotlin.collections.orEmpty

@Rule(
ruleSet = BoatRuleSet::class,
id = "B007U",
severity = Severity.MUST,
title = "Unified Backbase API specs do NOT expect any prefix in paths"
)
class NoPrefixPathRule(config: Config) {

private val validPathPrefixes = config
.getStringList("PrefixPathRule.validPathPrefixes")
.toSet()

@Check(Severity.MUST)
fun validate(context: Context): List<Violation> =

context.api.paths.orEmpty()
.map {
val extractParts = it.key.split("/")
val prefix = if (extractParts.size > 1) extractParts[1] else ""
Pair(prefix, it.value)
}
.filter {
validPathPrefixes.contains(it.first)
}
.map {
context.violation("Incorrect path prefix: ${it.first}", it.second)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.backbase.oss.boat.quay.ruleset

import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.PathItem
import org.zalando.zally.rule.api.*

@Rule(
ruleSet = BoatRuleSet::class,
id = "B009U",
severity = Severity.MUST,
title = "Unified Backbase API specs do NOT expect a version prefix in paths"
)
class NoVersionInUriRule {

private val description = "URL should not contain version number"
private val versionRegex = "(.*)v[0-9]+(.*)".toRegex()

@Check(severity = Severity.MUST)
fun validate(context: Context): List<Violation> =
(violatingPaths(context.api))
.map { context.violation(description, it) }


private fun violatingPaths(api: OpenAPI): Collection<PathItem> =
api.paths.orEmpty().entries
.filter { (path, _) -> path.matches(versionRegex) }
.map { (_, pathEntry) -> pathEntry }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package com.backbase.oss.boat.quay.ruleset

import com.backbase.oss.boat.quay.ruleset.test.ZallyAssertions
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.Test
import org.zalando.zally.core.DefaultContextFactory
import org.zalando.zally.core.rulesConfig

class NoPrefixPathRuleTest {

private val cut = NoPrefixPathRule(rulesConfig)

@Test
fun `correct path prefix`() {
@Language("YAML")
val context = DefaultContextFactory().getOpenApiContext(
"""
openapi: 3.0.3
info:
title: Thing API
version: 1.0.0
paths:
/foo:
get:
description: Lorem Ipsum
operationId: foo
responses:
202:
description: Lorem Ipsum
headers:
Location: # should not violate since not called `Link`
type: string
format: url
/bar:
get:
description: Lorem Ipsum
operationId: foo
responses:
202:
description: Lorem Ipsum
headers:
Location: # should not violate since not called `Link`
type: string
format: url
""".trimIndent()
)

val violations = cut.validate(context)

ZallyAssertions
.assertThat(violations)
.isEmpty()
}

@Test
fun `incorrect path prefix`() {
@Language("YAML")
val context = DefaultContextFactory().getOpenApiContext(
"""
openapi: 3.0.3
info:
title: Thing API
version: 1.0.0
paths:
/client-api/foo:
get:
description: Lorem Ipsum
operationId: foo
responses:
202:
description: Lorem Ipsum
headers:
Location: # should not violate since not called `Link`
type: string
format: url
/service-api/bar:
get:
description: Lorem Ipsum
operationId: bar
responses:
202:
description: Lorem Ipsum
headers:
Location: # should not violate since not called `Link`
type: string
format: url
/integration-api/bar2:
get:
description: Lorem Ipsum 2
operationId: bar2
responses:
202:
description: Lorem Ipsum 2
headers:
Location: # should not violate since not called `Link`
type: string
format: url
""".trimIndent()
)

val violations = cut.validate(context)

ZallyAssertions
.assertThat(violations)
.isNotEmpty
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.backbase.oss.boat.quay.ruleset

import com.backbase.oss.boat.quay.ruleset.test.ZallyAssertions
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.Test
import org.zalando.zally.core.DefaultContextFactory

class NoVersionInUriRuleTest {

private val cut = NoVersionInUriRule()

@Test
fun `correct path prefix without version`() {
@Language("YAML")
val context = DefaultContextFactory().getOpenApiContext(
"""
openapi: 3.0.3
info:
title: Thing API
version: 1.0.0
paths:
/api/foo:
get:
description: Lorem Ipsum
operationId: foo
responses:
202:
description: Lorem Ipsum
headers:
Location: # should not violate since not called `Link`
type: string
format: url
/api/bar:
get:
description: Lorem Ipsum
operationId: foo
responses:
202:
description: Lorem Ipsum
headers:
Location: # should not violate since not called `Link`
type: string
format: url
""".trimIndent()
)

val violations = cut.validate(context)

ZallyAssertions
.assertThat(violations)
.isEmpty()
}

@Test
fun `incorrect path prefix with version`() {
@Language("YAML")
val context = DefaultContextFactory().getOpenApiContext(
"""
openapi: 3.0.3
info:
title: Thing API
version: 1.0.0
paths:
/api/foo/v1true:
get:
description: Lorem Ipsum
operationId: foo
responses:
202:
description: Lorem Ipsum
headers:
Location: # should not violate since not called `Link`
type: string
format: url
/api/v1/bar:
get:
description: Lorem Ipsum
operationId: bar
responses:
202:
description: Lorem Ipsum
headers:
Location: # should not violate since not called `Link`
type: string
format: url
/v2/bar2:
get:
description: Lorem Ipsum 2
operationId: bar2
responses:
202:
description: Lorem Ipsum 2
headers:
Location: # should not violate since not called `Link`
type: string
format: url
""".trimIndent()
)

val violations = cut.validate(context)

ZallyAssertions
.assertThat(violations)
.isNotEmpty
}

}