114 lines
2.9 KiB
JavaScript
114 lines
2.9 KiB
JavaScript
'use strict'
|
|
|
|
const Joi = require('@hapi/joi')
|
|
const { optionalUrl } = require('../validators')
|
|
const { BaseJsonService } = require('..')
|
|
const { authConfig } = require('./jira-common')
|
|
|
|
const queryParamSchema = Joi.object({
|
|
baseUrl: optionalUrl.required(),
|
|
}).required()
|
|
|
|
const schema = Joi.object({
|
|
total: Joi.number(),
|
|
issues: Joi.array()
|
|
.items(
|
|
Joi.object({
|
|
fields: Joi.object({
|
|
resolution: Joi.object({
|
|
name: Joi.string(),
|
|
}).allow(null),
|
|
}).required(),
|
|
})
|
|
)
|
|
.required(),
|
|
}).required()
|
|
|
|
const documentation = `
|
|
<p>
|
|
To get the <code>Sprint ID</code>, go to your Backlog view in your project,
|
|
right click on your sprint name and get the value of
|
|
<code>data-sprint-id</code>.
|
|
</p>
|
|
`
|
|
|
|
module.exports = class JiraSprint extends BaseJsonService {
|
|
static category = 'issue-tracking'
|
|
|
|
static route = {
|
|
base: 'jira/sprint',
|
|
pattern: ':sprintId',
|
|
queryParamSchema,
|
|
}
|
|
|
|
static auth = authConfig
|
|
|
|
static examples = [
|
|
{
|
|
title: 'JIRA sprint completion',
|
|
namedParams: {
|
|
sprintId: '94',
|
|
},
|
|
queryParams: {
|
|
baseUrl: 'https://jira.spring.io',
|
|
},
|
|
staticPreview: this.render({
|
|
numCompletedIssues: 27,
|
|
numTotalIssues: 28,
|
|
}),
|
|
documentation,
|
|
},
|
|
]
|
|
|
|
static defaultBadgeData = { label: 'jira' }
|
|
|
|
static render({ numCompletedIssues, numTotalIssues }) {
|
|
const percentComplete = numTotalIssues
|
|
? (numCompletedIssues / numTotalIssues) * 100
|
|
: 0
|
|
let color = 'orange'
|
|
if (numCompletedIssues === 0) {
|
|
color = 'red'
|
|
} else if (numCompletedIssues === numTotalIssues) {
|
|
color = 'brightgreen'
|
|
}
|
|
return {
|
|
label: 'completion',
|
|
message: `${percentComplete.toFixed(0)}%`,
|
|
color,
|
|
}
|
|
}
|
|
|
|
async handle({ sprintId }, { baseUrl }) {
|
|
// Atlassian Documentation: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Search
|
|
// There are other sprint-specific APIs but those require authentication. The search API
|
|
// allows us to get the needed data without being forced to authenticate.
|
|
const json = await this._requestJson(
|
|
this.authHelper.withBasicAuth({
|
|
url: `${baseUrl}/rest/api/2/search`,
|
|
schema,
|
|
options: {
|
|
qs: {
|
|
jql: `sprint=${sprintId} AND type IN (Bug,Improvement,Story,"Technical task")`,
|
|
fields: 'resolution',
|
|
maxResults: 500,
|
|
},
|
|
},
|
|
errorMessages: {
|
|
400: 'sprint not found',
|
|
404: 'sprint not found',
|
|
},
|
|
})
|
|
)
|
|
|
|
const numTotalIssues = json.total
|
|
const numCompletedIssues = json.issues.filter(issue => {
|
|
if (issue.fields.resolution != null) {
|
|
return issue.fields.resolution.name !== 'Unresolved'
|
|
}
|
|
}).length
|
|
|
|
return this.constructor.render({ numTotalIssues, numCompletedIssues })
|
|
}
|
|
}
|