Add [github] Milestone service (#4747)
* Add isMetricOverMetric test validator * Add Github Milestone and Milestone-Detail Co-authored-by: Pierre-Yves B <PyvesDev@gmail.com>
This commit is contained in:
110
services/github/github-milestone-detail.service.js
Normal file
110
services/github/github-milestone-detail.service.js
Normal file
@@ -0,0 +1,110 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { metric } = require('../text-formatters')
|
||||
const { nonNegativeInteger } = require('../validators')
|
||||
const { GithubAuthV3Service } = require('./github-auth-service')
|
||||
const { documentation, errorMessagesFor } = require('./github-helpers')
|
||||
|
||||
const schema = Joi.object({
|
||||
open_issues: nonNegativeInteger,
|
||||
closed_issues: nonNegativeInteger,
|
||||
title: Joi.string().required(),
|
||||
}).required()
|
||||
|
||||
module.exports = class GithubMilestoneDetail extends GithubAuthV3Service {
|
||||
static get category() {
|
||||
return 'issue-tracking'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'github/milestones',
|
||||
pattern:
|
||||
':variant(issues-closed|issues-open|issues-total|progress|progress-percent)/:user/:repo/:number([0-9]+)',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'GitHub milestone',
|
||||
namedParams: {
|
||||
variant: 'issues-open',
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
number: '1',
|
||||
},
|
||||
staticPreview: {
|
||||
label: 'milestone issues',
|
||||
message: '17/22',
|
||||
color: 'blue',
|
||||
},
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'milestones',
|
||||
color: 'informational',
|
||||
}
|
||||
}
|
||||
|
||||
static render({ user, repo, variant, number, milestone }) {
|
||||
let milestoneMetric
|
||||
let color
|
||||
let label = ''
|
||||
|
||||
switch (variant) {
|
||||
case 'issues-open':
|
||||
milestoneMetric = milestone.open_issues
|
||||
color = 'red'
|
||||
label = 'open issues'
|
||||
break
|
||||
case 'issues-closed':
|
||||
milestoneMetric = milestone.closed_issues
|
||||
color = 'green'
|
||||
label = 'closed issues'
|
||||
break
|
||||
case 'issues-total':
|
||||
milestoneMetric = milestone.open_issues + milestone.closed_issues
|
||||
color = 'blue'
|
||||
label = 'issues'
|
||||
break
|
||||
case 'progress':
|
||||
milestoneMetric = `${milestone.closed_issues}/${milestone.open_issues +
|
||||
milestone.closed_issues}`
|
||||
color = 'blue'
|
||||
break
|
||||
case 'progress-percent':
|
||||
milestoneMetric = `${Math.floor(
|
||||
(milestone.closed_issues /
|
||||
(milestone.open_issues + milestone.closed_issues)) *
|
||||
100
|
||||
)}%`
|
||||
color = 'blue'
|
||||
}
|
||||
|
||||
return {
|
||||
label: `${milestone.title} ${label}`,
|
||||
message: metric(milestoneMetric),
|
||||
color,
|
||||
link: [`https://github.com/${user}/${repo}/milestone/${number}`],
|
||||
}
|
||||
}
|
||||
|
||||
async fetch({ user, repo, number }) {
|
||||
return this._requestJson({
|
||||
url: `/repos/${user}/${repo}/milestones/${number}`,
|
||||
schema,
|
||||
errorMessages: errorMessagesFor(`repo or milestone not found`),
|
||||
})
|
||||
}
|
||||
|
||||
async handle({ user, repo, variant, number }) {
|
||||
const milestone = await this.fetch({ user, repo, number })
|
||||
return this.constructor.render({ user, repo, variant, number, milestone })
|
||||
}
|
||||
}
|
||||
55
services/github/github-milestone-detail.tester.js
Normal file
55
services/github/github-milestone-detail.tester.js
Normal file
@@ -0,0 +1,55 @@
|
||||
'use strict'
|
||||
|
||||
const {
|
||||
isMetric,
|
||||
isMetricOverMetric,
|
||||
isIntegerPercentage,
|
||||
} = require('../test-validators')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
t.create('Milestone Open Issues')
|
||||
.get('/issues-open/MacroPower/milestone-test/1.json')
|
||||
.expectBadge({
|
||||
label: 'openWithOneOpenIssue open issues',
|
||||
message: isMetric,
|
||||
link: [`https://github.com/MacroPower/milestone-test/milestone/1`],
|
||||
})
|
||||
|
||||
t.create('Milestone Closed Issues')
|
||||
.get('/issues-closed/MacroPower/milestone-test/3.json')
|
||||
.expectBadge({
|
||||
label: 'closedWithOneClosedIssue closed issues',
|
||||
message: isMetric,
|
||||
link: [`https://github.com/MacroPower/milestone-test/milestone/3`],
|
||||
})
|
||||
|
||||
t.create('Milestone Total Issues')
|
||||
.get('/issues-total/MacroPower/milestone-test/2.json')
|
||||
.expectBadge({
|
||||
label: 'openWithOneOpenOneClosedIssue issues',
|
||||
message: isMetric,
|
||||
link: [`https://github.com/MacroPower/milestone-test/milestone/2`],
|
||||
})
|
||||
|
||||
t.create('Milestone Progress')
|
||||
.get('/progress/MacroPower/milestone-test/2.json')
|
||||
.expectBadge({
|
||||
label: 'openWithOneOpenOneClosedIssue',
|
||||
message: isMetricOverMetric,
|
||||
link: [`https://github.com/MacroPower/milestone-test/milestone/2`],
|
||||
})
|
||||
|
||||
t.create('Milestone Progress (Percent)')
|
||||
.get('/progress-percent/MacroPower/milestone-test/2.json')
|
||||
.expectBadge({
|
||||
label: 'openWithOneOpenOneClosedIssue',
|
||||
message: isIntegerPercentage,
|
||||
link: [`https://github.com/MacroPower/milestone-test/milestone/2`],
|
||||
})
|
||||
|
||||
t.create('Milestones (repo or milestone not found)')
|
||||
.get('/progress/badges/helmets/1.json')
|
||||
.expectBadge({
|
||||
label: 'milestones',
|
||||
message: 'repo or milestone not found',
|
||||
})
|
||||
93
services/github/github-milestone.service.js
Normal file
93
services/github/github-milestone.service.js
Normal file
@@ -0,0 +1,93 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { metric } = require('../text-formatters')
|
||||
const { GithubAuthV3Service } = require('./github-auth-service')
|
||||
const { documentation, errorMessagesFor } = require('./github-helpers')
|
||||
|
||||
const schema = Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
state: Joi.string().required(),
|
||||
})
|
||||
)
|
||||
.required()
|
||||
|
||||
module.exports = class GithubMilestone extends GithubAuthV3Service {
|
||||
static get category() {
|
||||
return 'issue-tracking'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'github/milestones',
|
||||
pattern: ':variant(open|closed|all)/:user/:repo',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'GitHub milestones',
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
variant: 'open',
|
||||
},
|
||||
staticPreview: {
|
||||
label: 'milestones',
|
||||
message: '2',
|
||||
color: 'red',
|
||||
},
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'milestones',
|
||||
color: 'informational',
|
||||
}
|
||||
}
|
||||
|
||||
static render({ user, repo, variant, milestones }) {
|
||||
const milestoneLength = milestones.length
|
||||
let color
|
||||
let label = ''
|
||||
|
||||
switch (variant) {
|
||||
case 'all':
|
||||
color = 'blue'
|
||||
break
|
||||
case 'open':
|
||||
color = 'red'
|
||||
label = 'active'
|
||||
break
|
||||
case 'closed':
|
||||
color = 'green'
|
||||
label = 'completed'
|
||||
break
|
||||
}
|
||||
|
||||
return {
|
||||
label: `${label} milestones`,
|
||||
message: metric(milestoneLength),
|
||||
color,
|
||||
link: [`https://github.com/${user}/${repo}/milestones`],
|
||||
}
|
||||
}
|
||||
|
||||
async fetch({ user, repo, variant }) {
|
||||
return this._requestJson({
|
||||
url: `/repos/${user}/${repo}/milestones?state=${variant}`,
|
||||
schema,
|
||||
errorMessages: errorMessagesFor(`repo not found`),
|
||||
})
|
||||
}
|
||||
|
||||
async handle({ user, repo, variant }) {
|
||||
const milestones = await this.fetch({ user, repo, variant })
|
||||
return this.constructor.render({ user, repo, variant, milestones })
|
||||
}
|
||||
}
|
||||
35
services/github/github-milestone.tester.js
Normal file
35
services/github/github-milestone.tester.js
Normal file
@@ -0,0 +1,35 @@
|
||||
'use strict'
|
||||
|
||||
const { isMetric } = require('../test-validators')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
t.create('All Milestones')
|
||||
.get('/all/MacroPower/milestone-test.json')
|
||||
.expectBadge({
|
||||
label: 'milestones',
|
||||
message: isMetric,
|
||||
link: [`https://github.com/MacroPower/milestone-test/milestones`],
|
||||
})
|
||||
|
||||
t.create('Open Milestones')
|
||||
.get('/open/MacroPower/milestone-test.json')
|
||||
.expectBadge({
|
||||
label: 'active milestones',
|
||||
message: isMetric,
|
||||
link: [`https://github.com/MacroPower/milestone-test/milestones`],
|
||||
})
|
||||
|
||||
t.create('Closed Milestones')
|
||||
.get('/closed/MacroPower/milestone-test.json')
|
||||
.expectBadge({
|
||||
label: 'completed milestones',
|
||||
message: isMetric,
|
||||
link: [`https://github.com/MacroPower/milestone-test/milestones`],
|
||||
})
|
||||
|
||||
t.create('Milestones (repo not found)')
|
||||
.get('/all/badges/helmets.json')
|
||||
.expectBadge({
|
||||
label: 'milestones',
|
||||
message: 'repo not found',
|
||||
})
|
||||
@@ -68,6 +68,10 @@ const isMetricOpenIssues = withRegex(
|
||||
/^([1-9][0-9]*[kMGTPEZY]?|[1-9]\.[1-9][kMGTPEZY]) open$/
|
||||
)
|
||||
|
||||
const isMetricOverMetric = withRegex(
|
||||
/^([1-9][0-9]*[kMGTPEZY]?|[1-9]\.[1-9][kMGTPEZY])\/([1-9][0-9]*[kMGTPEZY]?|[1-9]\.[1-9][kMGTPEZY])$/
|
||||
)
|
||||
|
||||
const isMetricOverTimePeriod = withRegex(
|
||||
/^([1-9][0-9]*[kMGTPEZY]?|[1-9]\.[1-9][kMGTPEZY])\/(year|month|four weeks|week|day)$/
|
||||
)
|
||||
@@ -144,6 +148,7 @@ module.exports = {
|
||||
isStarRating,
|
||||
isMetric,
|
||||
isMetricOpenIssues,
|
||||
isMetricOverMetric,
|
||||
isMetricOverTimePeriod,
|
||||
isPercentage,
|
||||
isIntegerPercentage,
|
||||
|
||||
Reference in New Issue
Block a user