From c121889bddd595b1ce97835b02a05e3b05ff141a Mon Sep 17 00:00:00 2001 From: chris48s Date: Tue, 13 Feb 2024 19:33:28 +0000 Subject: [PATCH] migrate some services from examples to openApi part 46; affects [codeclimate librariesio nexus] and securityheaders (#9933) * fix codeclimate tests * migrate some services from examples to openApi * fix nexus service tests * update codeclimate tests again --- .../codeclimate-analysis.service.js | 70 ++++----- .../codeclimate-analysis.tester.js | 2 +- services/codeclimate/codeclimate-common.js | 4 +- .../codeclimate-coverage.service.js | 32 ++-- .../codeclimate-coverage.tester.js | 2 +- .../librariesio-dependencies.service.js | 70 +++------ services/nexus/nexus.service.js | 147 +++++++++--------- services/nexus/nexus.tester.js | 24 ++- .../security-headers.service.js | 38 ++--- 9 files changed, 170 insertions(+), 219 deletions(-) diff --git a/services/codeclimate/codeclimate-analysis.service.js b/services/codeclimate/codeclimate-analysis.service.js index b8df15625f198..e3e064b0054a9 100644 --- a/services/codeclimate/codeclimate-analysis.service.js +++ b/services/codeclimate/codeclimate-analysis.service.js @@ -1,8 +1,8 @@ import Joi from 'joi' import { colorScale, letterScore } from '../color-formatters.js' import { nonNegativeInteger } from '../validators.js' -import { BaseJsonService, NotFound } from '../index.js' -import { keywords, isLetterGrade, fetchRepo } from './codeclimate-common.js' +import { BaseJsonService, NotFound, pathParams } from '../index.js' +import { isLetterGrade, fetchRepo } from './codeclimate-common.js' const schema = Joi.object({ data: Joi.object({ @@ -93,43 +93,43 @@ export default class CodeclimateAnalysis extends BaseJsonService { ':variant(maintainability|maintainability-percentage|tech-debt|issues)/:user/:repo', } - static examples = [ - { - title: 'Code Climate maintainability', - pattern: - ':format(maintainability|maintainability-percentage)/:user/:repo', - namedParams: { - format: 'maintainability', - user: 'tensorflow', - repo: 'models', + static openApi = { + '/codeclimate/{variant}/{user}/{repo}': { + get: { + summary: 'Code Climate maintainability', + parameters: pathParams( + { + name: 'variant', + example: 'maintainability', + schema: { + type: 'string', + enum: ['maintainability', 'maintainability-percentage'], + }, + }, + { name: 'user', example: 'tensorflow' }, + { name: 'repo', example: 'models' }, + ), }, - staticPreview: this.render({ - variant: 'maintainability', - maintainabilityLetter: 'F', - }), - keywords, }, - { - title: 'Code Climate issues', - pattern: 'issues/:user/:repo', - namedParams: { user: 'twbs', repo: 'bootstrap' }, - staticPreview: this.render({ - variant: 'issues', - issueCount: '89', - }), - keywords, + '/codeclimate/tech-debt/{user}/{repo}': { + get: { + summary: 'Code Climate issues', + parameters: pathParams( + { name: 'user', example: 'tensorflow' }, + { name: 'repo', example: 'models' }, + ), + }, }, - { - title: 'Code Climate technical debt', - pattern: 'tech-debt/:user/:repo', - namedParams: { user: 'tensorflow', repo: 'models' }, - staticPreview: this.render({ - variant: 'tech-debt', - techDebtPercentage: 3.0, - }), - keywords, + '/codeclimate/issues/{user}/{repo}': { + get: { + summary: 'Code Climate technical debt', + parameters: pathParams( + { name: 'user', example: 'tensorflow' }, + { name: 'repo', example: 'models' }, + ), + }, }, - ] + } static render({ variant, ...props }) { const { render } = variantMap[variant] diff --git a/services/codeclimate/codeclimate-analysis.tester.js b/services/codeclimate/codeclimate-analysis.tester.js index f5143d0607525..73544fbeb6cde 100644 --- a/services/codeclimate/codeclimate-analysis.tester.js +++ b/services/codeclimate/codeclimate-analysis.tester.js @@ -55,7 +55,7 @@ t.create('issues when outer user repos query returns multiple items') relationships: { latest_default_branch_snapshot: { data: { - id: '64786eee4fedea000101580d', + id: '65ae115f34117d0001055101', type: 'snapshots', }, }, diff --git a/services/codeclimate/codeclimate-common.js b/services/codeclimate/codeclimate-common.js index 83146074f7e73..589e9563c6058 100644 --- a/services/codeclimate/codeclimate-common.js +++ b/services/codeclimate/codeclimate-common.js @@ -1,8 +1,6 @@ import Joi from 'joi' import { NotFound } from '../index.js' -const keywords = ['codeclimate'] - const isLetterGrade = Joi.equal('A', 'B', 'C', 'D', 'E', 'F').required() const repoSchema = Joi.object({ @@ -39,4 +37,4 @@ async function fetchRepo(serviceInstance, { user, repo }) { return repoInfos } -export { keywords, isLetterGrade, fetchRepo } +export { isLetterGrade, fetchRepo } diff --git a/services/codeclimate/codeclimate-coverage.service.js b/services/codeclimate/codeclimate-coverage.service.js index b9c654bfa4130..9a5dc883ee886 100644 --- a/services/codeclimate/codeclimate-coverage.service.js +++ b/services/codeclimate/codeclimate-coverage.service.js @@ -1,7 +1,7 @@ import Joi from 'joi' import { coveragePercentage, letterScore } from '../color-formatters.js' -import { BaseJsonService, NotFound } from '../index.js' -import { keywords, isLetterGrade, fetchRepo } from './codeclimate-common.js' +import { BaseJsonService, NotFound, pathParams } from '../index.js' +import { isLetterGrade, fetchRepo } from './codeclimate-common.js' const schema = Joi.object({ data: Joi.object({ @@ -21,22 +21,22 @@ export default class CodeclimateCoverage extends BaseJsonService { pattern: ':format(coverage|coverage-letter)/:user/:repo', } - static examples = [ - { - title: 'Code Climate coverage', - namedParams: { - format: 'coverage', - user: 'codeclimate', - repo: 'codeclimate', + static openApi = { + '/codeclimate/{format}/{user}/{repo}': { + get: { + summary: 'Code Climate coverage', + parameters: pathParams( + { + name: 'format', + example: 'coverage', + schema: { type: 'string', enum: this.getEnum('format') }, + }, + { name: 'user', example: 'codeclimate' }, + { name: 'repo', example: 'codeclimate' }, + ), }, - staticPreview: this.render({ - format: 'coverage', - percentage: 95.123, - letter: 'A', - }), - keywords, }, - ] + } static render({ wantLetter, percentage, letter }) { if (wantLetter) { diff --git a/services/codeclimate/codeclimate-coverage.tester.js b/services/codeclimate/codeclimate-coverage.tester.js index f9123d94e184a..baa4dd03c1615 100644 --- a/services/codeclimate/codeclimate-coverage.tester.js +++ b/services/codeclimate/codeclimate-coverage.tester.js @@ -46,7 +46,7 @@ t.create('test coverage when outer user repos query returns multiple items') }, latest_default_branch_test_report: { data: { - id: '6463c8a3e3bc340001004bce', + id: '65a1662cb0077b00013cb4de', type: 'test_reports', }, }, diff --git a/services/librariesio/librariesio-dependencies.service.js b/services/librariesio/librariesio-dependencies.service.js index 10ed50202b6cc..25b27318c86f6 100644 --- a/services/librariesio/librariesio-dependencies.service.js +++ b/services/librariesio/librariesio-dependencies.service.js @@ -1,4 +1,5 @@ import Joi from 'joi' +import { pathParams } from '../index.js' import LibrariesIoBase from './librariesio-base.js' import { transform, @@ -24,62 +25,27 @@ class LibrariesIoProjectDependencies extends LibrariesIoBase { pattern: ':platform/:scope(@[^/]+)?/:packageName/:version?', } - static examples = [ - { - title: 'Libraries.io dependency status for latest release', - pattern: ':platform/:packageName', - namedParams: { - platform: 'hex', - packageName: 'phoenix', + static openApi = { + '/librariesio/release/{platform}/{packageName}': { + get: { + summary: 'Libraries.io dependency status for latest release', + parameters: pathParams( + { name: 'platform', example: 'npm' }, + { name: 'packageName', example: '@babel/core' }, + ), }, - staticPreview: renderDependenciesBadge({ - deprecatedCount: 0, - outdatedCount: 1, - }), }, - { - title: 'Libraries.io dependency status for specific release', - pattern: ':platform/:packageName/:version', - namedParams: { - platform: 'hex', - packageName: 'phoenix', - version: '1.0.3', + '/librariesio/release/{platform}/{packageName}/{version}': { + get: { + summary: 'Libraries.io dependency status for specific release', + parameters: pathParams( + { name: 'platform', example: 'npm' }, + { name: 'packageName', example: '@babel/core' }, + { name: 'version', example: '7.0.0' }, + ), }, - staticPreview: renderDependenciesBadge({ - deprecatedCount: 0, - outdatedCount: 3, - }), }, - { - title: - 'Libraries.io dependency status for latest release, scoped npm package', - pattern: ':platform/:scope/:packageName', - namedParams: { - platform: 'npm', - scope: '@babel', - packageName: 'core', - }, - staticPreview: renderDependenciesBadge({ - deprecatedCount: 8, - outdatedCount: 0, - }), - }, - { - title: - 'Libraries.io dependency status for specific release, scoped npm package', - pattern: ':platform/:scope/:packageName/:version', - namedParams: { - platform: 'npm', - scope: '@babel', - packageName: 'core', - version: '7.0.0', - }, - staticPreview: renderDependenciesBadge({ - deprecatedCount: 12, - outdatedCount: 0, - }), - }, - ] + } static _cacheLength = 900 diff --git a/services/nexus/nexus.service.js b/services/nexus/nexus.service.js index fe03670dbc488..e6641725bb839 100644 --- a/services/nexus/nexus.service.js +++ b/services/nexus/nexus.service.js @@ -5,7 +5,13 @@ import { optionalUrl, optionalDottedVersionNClausesWithOptionalSuffix, } from '../validators.js' -import { BaseJsonService, InvalidResponse, NotFound } from '../index.js' +import { + BaseJsonService, + InvalidResponse, + NotFound, + pathParams, + queryParams, +} from '../index.js' import { isSnapshotVersion } from './nexus-version.js' const nexus2SearchApiSchema = Joi.object({ @@ -51,6 +57,36 @@ const queryParamSchema = Joi.object({ nexusVersion: Joi.equal('2', '3'), }).required() +const openApiQueryParams = queryParams( + { name: 'server', example: 'https://oss.sonatype.org', required: true }, + { + name: 'nexusVersion', + example: '2', + schema: { type: 'string', enum: ['2', '3'] }, + description: + 'Specifying `nexusVersion=3` when targeting Nexus 3 servers will speed up the badge rendering.', + }, + { + name: 'queryOpt', + example: ':c=agent-apple-osx:p=tar.gz', + description: `

+ Note that you can use query options with any Nexus badge type (Releases, Snapshots, or Repository). +

+

+ Query options should be provided as key=value pairs separated by a colon. +

+

+ Possible values: +

+

+`, + }, +) + export default class Nexus extends BaseJsonService { static category = 'version' @@ -66,88 +102,45 @@ export default class Nexus extends BaseJsonService { serviceKey: 'nexus', } - static examples = [ - { - title: 'Sonatype Nexus (Releases)', - pattern: 'r/:groupId/:artifactId', - namedParams: { - groupId: 'org.apache.commons', - artifactId: 'commons-lang3', + static openApi = { + '/nexus/r/{groupId}/{artifactId}': { + get: { + summary: 'Sonatype Nexus (Releases)', + parameters: [ + ...pathParams( + { name: 'groupId', example: 'com.google.guava' }, + { name: 'artifactId', example: 'guava' }, + ), + ...openApiQueryParams, + ], }, - queryParams: { - server: 'https://nexus.pentaho.org', - nexusVersion: '3', - }, - staticPreview: this.render({ - version: '3.9', - }), - documentation: `

- Specifying 'nexusVersion=3' when targeting Nexus 3 servers will speed up the badge rendering. - Note that you can use this query parameter with any Nexus badge type (Releases, Snapshots, or Repository). -

- `, }, - { - title: 'Sonatype Nexus (Snapshots)', - pattern: 's/:groupId/:artifactId', - namedParams: { - groupId: 'com.google.guava', - artifactId: 'guava', + '/nexus/s/{groupId}/{artifactId}': { + get: { + summary: 'Sonatype Nexus (Snapshots)', + parameters: [ + ...pathParams( + { name: 'groupId', example: 'com.google.guava' }, + { name: 'artifactId', example: 'guava' }, + ), + ...openApiQueryParams, + ], }, - queryParams: { - server: 'https://oss.sonatype.org', - }, - staticPreview: this.render({ - version: 'v24.0-SNAPSHOT', - }), }, - { - title: 'Sonatype Nexus (Repository)', - pattern: ':repo/:groupId/:artifactId', - namedParams: { - repo: 'developer', - groupId: 'ai.h2o', - artifactId: 'h2o-automl', - }, - queryParams: { - server: 'https://repository.jboss.org/nexus', + '/nexus/{repo}/{groupId}/{artifactId}': { + get: { + summary: 'Sonatype Nexus (Repository)', + parameters: [ + ...pathParams( + { name: 'repo', example: 'snapshots' }, + { name: 'groupId', example: 'com.google.guava' }, + { name: 'artifactId', example: 'guava' }, + ), + ...openApiQueryParams, + ], }, - staticPreview: this.render({ - version: '3.22.0.2', - }), - }, - { - title: 'Sonatype Nexus (Query Options)', - pattern: ':repo/:groupId/:artifactId', - namedParams: { - repo: 'fs-public-snapshots', - groupId: 'com.progress.fuse', - artifactId: 'fusehq', - }, - queryParams: { - server: 'https://repository.jboss.org/nexus', - queryOpt: ':c=agent-apple-osx:p=tar.gz', - }, - staticPreview: this.render({ - version: '7.0.1-SNAPSHOT', - }), - documentation: `

- Note that you can use query options with any Nexus badge type (Releases, Snapshots, or Repository). -

-

- Query options should be provided as key=value pairs separated by a colon. -

-

- Possible values: -

-

- `, }, - ] + } static defaultBadgeData = { label: 'nexus', diff --git a/services/nexus/nexus.tester.js b/services/nexus/nexus.tester.js index a5f6e7f1e17b8..0c3f9d925b67d 100644 --- a/services/nexus/nexus.tester.js +++ b/services/nexus/nexus.tester.js @@ -230,7 +230,7 @@ t.create('Nexus 2 - user query params') t.create('Nexus 3 - search release version valid artifact') .get( - '/r/org.apache.commons/commons-lang3.json?server=https://nexus.pentaho.org&nexusVersion=3', + '/r/me.neznamy/tab-api.json?server=https://repo.tomkeuper.com&nexusVersion=3', ) .expectBadge({ label: 'nexus', @@ -241,9 +241,7 @@ t.create( 'Nexus 3 - search release version valid artifact without explicit nexusVersion parameter', ) .timeout(15000) - .get( - '/r/org.apache.commons/commons-lang3.json?server=https://nexus.pentaho.org', - ) + .get('/r/me.neznamy/tab-api.json?server=https://repo.tomkeuper.com') .expectBadge({ label: 'nexus', message: isVersion, @@ -251,7 +249,7 @@ t.create( t.create('Nexus 3 - search release version of an nonexistent artifact') .get( - '/r/org.apache.commons/nonexistent-artifact-id.json?server=https://nexus.pentaho.org&nexusVersion=3', + '/r/me.neznamy/nonexistent-artifact-id.json?server=https://repo.tomkeuper.com&nexusVersion=3', ) .expectBadge({ label: 'nexus', @@ -260,7 +258,7 @@ t.create('Nexus 3 - search release version of an nonexistent artifact') t.create('Nexus 3 - search snapshot version valid snapshot artifact') .get( - '/s/org.pentaho/pentaho-registry.json?server=https://nexus.pentaho.org&nexusVersion=3', + '/s/com.tomkeuper.bedwars/bedwars-api.json?server=https://repo.tomkeuper.com&nexusVersion=3', ) .expectBadge({ label: 'nexus', @@ -269,7 +267,7 @@ t.create('Nexus 3 - search snapshot version valid snapshot artifact') t.create('Nexus 3 - search snapshot version for artifact without snapshots') .get( - '/s/javax.inject/javax.inject.json?server=https://nexus.pentaho.org&nexusVersion=3', + '/s/com.tomkeuper/spigot.json?server=https://repo.tomkeuper.com&nexusVersion=3', ) .expectBadge({ label: 'nexus', @@ -279,7 +277,7 @@ t.create('Nexus 3 - search snapshot version for artifact without snapshots') t.create('Nexus 3 - repository version') .get( - '/proxy-public-3rd-party-release/com.h2database/h2.json?server=https://nexus.pentaho.org&nexusVersion=3', + '/bedwars-releases/me.neznamy/tab-api.json?server=https://repo.tomkeuper.com&nexusVersion=3', ) .expectBadge({ label: 'nexus', @@ -291,7 +289,7 @@ t.create( ) .timeout(15000) .get( - '/proxy-public-3rd-party-release/com.h2database/h2.json?server=https://nexus.pentaho.org', + '/bedwars-releases/me.neznamy/tab-api.json?server=https://repo.tomkeuper.com&nexusVersion=3', ) .expectBadge({ label: 'nexus', @@ -300,7 +298,7 @@ t.create( t.create('Nexus 3 - repository version with query') .get( - `/proxy-public-3rd-party-release/org.junit.jupiter/junit-jupiter.json?server=https://nexus.pentaho.org&nexusVersion=3&queryOpt=${encodeURIComponent( + `/bedwars-releases/me.neznamy/tab-api.json?server=https://repo.tomkeuper.com&nexusVersion=3&queryOpt=${encodeURIComponent( ':maven.extension=jar:direction=asc', )}`, ) @@ -312,11 +310,11 @@ t.create('Nexus 3 - repository version with query') t.create('Nexus 3 - search release version without snapshots') .get( // Limit the version from above, so that any later artifacts don't break this test. - `/r/org.pentaho.adaptive/pdi-engines.json?server=https://nexus.pentaho.org&nexusVersion=3&queryOpt=${encodeURIComponent( - ':maven.baseVersion=<8.0.0.1', + `/r/me.neznamy/tab-api.json?server=https://repo.tomkeuper.com&nexusVersion=3&queryOpt=${encodeURIComponent( + ':maven.baseVersion=<4.0.0.0', )}`, ) .expectBadge({ label: 'nexus', - message: 'v8.0.0.0-28', + message: 'v4.0.0', }) diff --git a/services/security-headers/security-headers.service.js b/services/security-headers/security-headers.service.js index a108a4abcba31..e9356f41dbee9 100644 --- a/services/security-headers/security-headers.service.js +++ b/services/security-headers/security-headers.service.js @@ -1,13 +1,13 @@ import Joi from 'joi' import { optionalUrl } from '../validators.js' -import { BaseService, NotFound } from '../index.js' +import { BaseService, NotFound, queryParams } from '../index.js' const queryParamSchema = Joi.object({ url: optionalUrl.required(), ignoreRedirects: Joi.equal(''), }).required() -const documentation = ` +const description = ` The [Security Headers](https://securityheaders.com/) provide an easy mechanism to analyze HTTP response headers and give information on how to deploy missing headers. @@ -24,26 +24,22 @@ export default class SecurityHeaders extends BaseService { queryParamSchema, } - static examples = [ - { - title: 'Security Headers', - namedParams: {}, - queryParams: { url: 'https://shields.io' }, - staticPreview: this.render({ - grade: 'A+', - }), - documentation, - }, - { - title: "Security Headers (Don't follow redirects)", - namedParams: {}, - queryParams: { url: 'https://www.shields.io', ignoreRedirects: null }, - staticPreview: this.render({ - grade: 'R', - }), - documentation, + static openApi = { + '/security-headers': { + get: { + summary: 'Security Headers', + description, + parameters: queryParams( + { name: 'url', example: 'https://shields.io', required: true }, + { + name: 'ignoreRedirects', + schema: { type: 'boolean' }, + example: null, + }, + ), + }, }, - ] + } static defaultBadgeData = { label: 'security headers',