Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Refactor [Sonar] #3189

Merged
merged 36 commits into from
Apr 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1cfd606
refactor(sonar)
calebcartwright Mar 2, 2019
1a7e0a7
refactor(sonarqube): creating separate services for SQ badges
calebcartwright Mar 3, 2019
2d1df76
refactor(sonar): more sonar refactorings
calebcartwright Mar 11, 2019
61e9fa2
refactor(sonar): fixed duplicate service names from c/p
calebcartwright Mar 11, 2019
216f79e
refactor(sonar): finished violations service impl
calebcartwright Mar 12, 2019
45f1a2c
refactor(sonar): finished unit tests for violations service
calebcartwright Mar 12, 2019
579a612
feat(sonar): violation badge updates
calebcartwright Mar 20, 2019
ce5ed1f
refactor(sonar): finished doc. api density service
calebcartwright Mar 29, 2019
54f721d
feat(sonar): added quality gate service
calebcartwright Mar 29, 2019
cdfc56d
chore: sonar doc tweaks
calebcartwright Mar 29, 2019
d578ddb
refactor(sonar): added redirector service
calebcartwright Mar 31, 2019
1a4eac4
Merge branch 'master' into sonarqube-refactor
calebcartwright Mar 31, 2019
cdb959d
refactor(sonar): added examples
calebcartwright Mar 31, 2019
6e94272
refactor(sonar): minor example updates
calebcartwright Mar 31, 2019
f434469
refactor(sonar): added final tests
calebcartwright Mar 31, 2019
4743ab0
chore(sonar): removed unneeded test spec file for base class
calebcartwright Mar 31, 2019
fdc88b8
Merge branch 'master' into sonarqube-refactor
calebcartwright Apr 5, 2019
e01c8f6
Merge branch 'master' into sonarqube-refactor
calebcartwright Apr 8, 2019
256c0d0
Merge branch 'master' into sonarqube-refactor
calebcartwright Apr 9, 2019
fe7cb37
refactor(sonar): updates based on PR feedback
calebcartwright Apr 13, 2019
b4cad8c
refactor(sonar): change query param to sonarVersion
calebcartwright Apr 13, 2019
64ec70e
Merge branch 'master' into sonarqube-refactor
calebcartwright Apr 13, 2019
3d4971f
refactor(sonar): fixing query param issue
calebcartwright Apr 13, 2019
9fa94fd
refactor(sonar): fix test color for generic metric
calebcartwright Apr 13, 2019
40920bb
chore: fix lint/prettier issue
calebcartwright Apr 13, 2019
4ef8c90
Merge branch 'master' into sonarqube-refactor
calebcartwright Apr 14, 2019
c5bfe3d
chore(sonar): update query param name in examples
calebcartwright Apr 14, 2019
da0415c
Merge branch 'sonarqube-refactor' of https://github.com/badges/shield…
calebcartwright Apr 14, 2019
bc61f0a
refactor(sonar): make schema metric key required
calebcartwright Apr 14, 2019
44ac1ea
reactor(sonar): fix tests
calebcartwright Apr 14, 2019
e4d4e46
Merge branch 'master' into sonarqube-refactor
calebcartwright Apr 14, 2019
a2f3c0b
refactor(sonar): added more example listings
calebcartwright Apr 14, 2019
5478bee
refactor(sonar): minor style updates
calebcartwright Apr 14, 2019
5059863
refactor(sonar): update examples
calebcartwright Apr 14, 2019
e006670
refactor(Sonar): minor example tweaks
calebcartwright Apr 14, 2019
3ddd046
Merge branch 'master' into sonarqube-refactor
calebcartwright Apr 15, 2019
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
91 changes: 91 additions & 0 deletions services/sonar/sonar-base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
'use strict'

const Joi = require('joi')
const serverSecrets = require('../../lib/server-secrets')
const { BaseJsonService } = require('..')
const { isLegacyVersion } = require('./sonar-helpers')

const schema = Joi.object({
component: Joi.object({
measures: Joi.array()
.items(
Joi.object({
metric: Joi.string().required(),
value: Joi.alternatives(
Joi.number().min(0),
Joi.allow('OK', 'ERROR')
).required(),
}).required()
)
.required(),
}).required(),
}).required()

const legacyApiSchema = Joi.array()
.items(
Joi.object({
msr: Joi.array()
.items(
Joi.object({
key: Joi.string().required(),
val: Joi.alternatives(
Joi.number().min(0),
Joi.allow('OK', 'ERROR')
).required(),
}).required()
)
.required(),
}).required()
)
.required()

module.exports = class SonarBase extends BaseJsonService {
transform({ json, sonarVersion }) {
const useLegacyApi = isLegacyVersion({ sonarVersion })
const rawValue = useLegacyApi
? json[0].msr[0].val
: json.component.measures[0].value
const value = parseInt(rawValue)

// Most values are numeric, but not all of them.
return { metricValue: value || rawValue }
}

async fetch({ sonarVersion, protocol, host, component, metricName }) {
let qs, url
const useLegacyApi = isLegacyVersion({ sonarVersion })

if (useLegacyApi) {
url = `${protocol}://${host}/api/resources`
qs = {
resource: component,
depth: 0,
metrics: metricName,
includeTrends: true,
}
} else {
url = `${protocol}://${host}/api/measures/component`
qs = {
componentKey: component,
metricKeys: metricName,
}
}

const options = { qs }

if (serverSecrets.sonarqube_token) {
options.auth = {
user: serverSecrets.sonarqube_token,
}
}

return this._requestJson({
schema: useLegacyApi ? legacyApiSchema : schema,
url,
options,
errorMessages: {
404: 'component or metric not found, or legacy API not supported',
chris48s marked this conversation as resolved.
Show resolved Hide resolved
},
})
}
}
69 changes: 69 additions & 0 deletions services/sonar/sonar-coverage.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use strict'

const { coveragePercentage } = require('../color-formatters')
const SonarBase = require('./sonar-base')
const {
documentation,
keywords,
patternBase,
queryParamSchema,
} = require('./sonar-helpers')

module.exports = class SonarCoverage extends SonarBase {
static get category() {
return 'coverage'
}

static get defaultBadgeData() {
return { label: 'coverage' }
}

static render({ coverage }) {
return {
message: `${coverage.toFixed(0)}%`,
color: coveragePercentage(coverage),
}
}

static get route() {
return {
base: 'sonar',
pattern: `${patternBase}/coverage`,
queryParamSchema,
}
}

static get examples() {
return [
{
title: 'Sonar Coverage',
namedParams: {
protocol: 'http',
host: 'sonar.petalslink.com',
component: 'org.ow2.petals:petals-se-ase',
},
queryParams: {
sonarVersion: '4.2',
},
staticPreview: this.render({ coverage: 63 }),
keywords,
documentation,
},
]
}

async handle({ protocol, host, component }, { sonarVersion }) {
const json = await this.fetch({
sonarVersion,
protocol,
host,
component,
metricName: 'coverage',
})
const { metricValue: coverage } = this.transform({
json,
sonarVersion,
})
return this.constructor.render({ coverage })
}
}
22 changes: 22 additions & 0 deletions services/sonar/sonar-coverage.tester.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

const t = (module.exports = require('../tester').createServiceTester())
const { isIntegerPercentage } = require('../test-validators')

t.create('Coverage')
.get(
'/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/coverage.json'
)
.expectBadge({
label: 'coverage',
message: isIntegerPercentage,
})

t.create('Coverage (legacy API supported)')
.get(
'/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/coverage.json?sonarVersion=4.2'
)
.expectBadge({
label: 'coverage',
message: isIntegerPercentage,
})
chris48s marked this conversation as resolved.
Show resolved Hide resolved
69 changes: 69 additions & 0 deletions services/sonar/sonar-documented-api-density.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use strict'

const SonarBase = require('./sonar-base')
const {
patternBase,
queryParamSchema,
getLabel,
positiveMetricColorScale,
keywords,
documentation,
} = require('./sonar-helpers')

const metric = 'public_documented_api_density'

module.exports = class SonarDocumentedApiDensity extends SonarBase {
calebcartwright marked this conversation as resolved.
Show resolved Hide resolved
static get category() {
return 'analysis'
}

static get defaultBadgeData() {
return { label: getLabel({ metric }) }
}

static render({ density }) {
return {
message: `${density}%`,
color: positiveMetricColorScale(density),
}
}

static get route() {
return {
base: 'sonar',
pattern: `${patternBase}/${metric}`,
queryParamSchema,
}
}

static get examples() {
return [
{
title: 'Sonar Documented API Density',
namedParams: {
protocol: 'http',
host: 'sonar.petalslink.com',
component: 'org.ow2.petals:petals-se-ase',
},
queryParams: {
sonarVersion: '4.2',
},
staticPreview: this.render({ density: 82 }),
keywords,
documentation,
},
]
}

async handle({ protocol, host, component }, { sonarVersion }) {
const json = await this.fetch({
sonarVersion,
protocol,
host,
component,
metricName: metric,
})
const { metricValue: density } = this.transform({ json, sonarVersion })
return this.constructor.render({ density })
}
}
29 changes: 29 additions & 0 deletions services/sonar/sonar-documented-api-density.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict'

const { test, given } = require('sazerac')
const SonarDocumentedApiDensity = require('./sonar-documented-api-density.service')

describe('SonarDocumentedApiDensity', function() {
test(SonarDocumentedApiDensity.render, () => {
given({ density: 0 }).expect({
message: '0%',
color: 'red',
})
given({ density: 10 }).expect({
message: '10%',
color: 'orange',
})
given({ density: 20 }).expect({
message: '20%',
color: 'yellow',
})
given({ density: 50 }).expect({
message: '50%',
color: 'yellowgreen',
})
given({ density: 100 }).expect({
message: '100%',
color: 'brightgreen',
})
})
})
22 changes: 22 additions & 0 deletions services/sonar/sonar-documented-api-density.tester.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

const { isIntegerPercentage } = require('../test-validators')
const t = (module.exports = require('../tester').createServiceTester())

t.create('Documented API Density')
.get(
'/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/public_documented_api_density.json'
)
.expectBadge({
label: 'public documented api density',
message: isIntegerPercentage,
})

t.create('Documented API Density (legacy API supported)')
.get(
'/http/sonar.petalslink.com/org.ow2.petals%3Apetals-se-ase/public_documented_api_density.json?sonarVersion=4.2'
)
.expectBadge({
label: 'public documented api density',
message: isIntegerPercentage,
})
81 changes: 81 additions & 0 deletions services/sonar/sonar-fortify-rating.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use strict'

const SonarBase = require('./sonar-base')
const {
patternBase,
queryParamSchema,
keywords,
documentation,
} = require('./sonar-helpers')

const colorMap = {
0: 'red',
1: 'orange',
2: 'yellow',
3: 'yellowgreen',
4: 'green',
5: 'brightgreen',
}

module.exports = class SonarFortifyRating extends SonarBase {
calebcartwright marked this conversation as resolved.
Show resolved Hide resolved
static get category() {
return 'analysis'
}

static get defaultBadgeData() {
return { label: 'fortify-security-rating' }
}

static render({ rating }) {
return {
message: `${rating}/5`,
color: colorMap[rating],
}
}

static get route() {
return {
base: 'sonar',
pattern: `${patternBase}/fortify-security-rating`,
queryParamSchema,
}
}

static get examples() {
return [
{
title: 'Sonar Fortify Security Rating',
namedParams: {
protocol: 'http',
host: 'sonar.petalslink.com',
component: 'org.ow2.petals:petals-se-ase',
chris48s marked this conversation as resolved.
Show resolved Hide resolved
},
queryParams: {
sonarVersion: '4.2',
},
staticPreview: this.render({ rating: 4 }),
keywords,
documentation: `
<p>
Note that the Fortify Security Rating badge will only work on Sonar instances that have the <a href='https://marketplace.microfocus.com/fortify/content/fortify-sonarqube-plugin'>Fortify SonarQube Plugin</a> installed.
The badge is not available for projects analyzed on SonarCloud.io
</p>
${documentation}
`,
},
]
}

async handle({ protocol, host, component }, { sonarVersion }) {
const json = await this.fetch({
sonarVersion,
protocol,
host,
component,
metricName: 'fortify-security-rating',
})

const { metricValue: rating } = this.transform({ json, sonarVersion })
return this.constructor.render({ rating })
}
}
Loading