Added [VisualStudioAppCenter] badges 🎉 (#4108)
* VisualStudioAppCenterBuilds * [vsacb] Add schema, documentation and use buildStatus for rendering * Add VSACReleasesVersion badge and test * Make tests green again, add another nock test and fix category * Add VSAC Releases Size badge and test * Add VSAC Base class * [vsacb] use base fetch function * Add VSACR OSVersion service and tests * Finishing touches * Change slug from VSAC to Visual-Studio-App-Center * Use prettyBytes for rendering * CQ * Use bytes response directly * Remove superfluous required statement * Improve os version badge format * Switch to nock for build test Co-authored-by: Pierre-Yves B. <PyvesDev@gmail.com> Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
'use strict'
|
||||
|
||||
const { BaseJsonService } = require('..')
|
||||
|
||||
const keywords = [
|
||||
'visual-studio',
|
||||
'vsac',
|
||||
'visual-studio-app-center',
|
||||
'app-center',
|
||||
]
|
||||
|
||||
const documentation =
|
||||
"You will need to create a <b>read-only</b> API token <a target='_blank' href='https://appcenter.ms/settings/apitokens'>here</a>."
|
||||
|
||||
class BaseVisualStudioAppCenterService extends BaseJsonService {
|
||||
async fetch({
|
||||
owner,
|
||||
app,
|
||||
token,
|
||||
schema,
|
||||
url = `https://api.appcenter.ms/v0.1/apps/${owner}/${app}/releases/latest`,
|
||||
}) {
|
||||
return this._requestJson({
|
||||
schema,
|
||||
options: {
|
||||
headers: {
|
||||
'X-API-Token': token,
|
||||
},
|
||||
},
|
||||
errorMessages: {
|
||||
401: 'invalid token',
|
||||
403: 'project not found',
|
||||
404: 'project not found',
|
||||
},
|
||||
url,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { keywords, documentation, BaseVisualStudioAppCenterService }
|
||||
@@ -0,0 +1,62 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
|
||||
const {
|
||||
BaseVisualStudioAppCenterService,
|
||||
keywords,
|
||||
documentation,
|
||||
} = require('./visual-studio-app-center-base')
|
||||
const { NotFound } = require('..')
|
||||
|
||||
const schema = Joi.array().items({
|
||||
result: isBuildStatus.required(),
|
||||
})
|
||||
|
||||
module.exports = class VisualStudioAppCenterBuilds extends BaseVisualStudioAppCenterService {
|
||||
static get category() {
|
||||
return 'build'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'visual-studio-app-center/builds',
|
||||
pattern: ':owner/:app/:branch/:token',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'Visual Studio App Center Builds',
|
||||
namedParams: {
|
||||
owner: 'jct',
|
||||
app: 'my-amazing-app',
|
||||
branch: 'master',
|
||||
token: 'ac70cv...',
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({ status: 'succeeded' }),
|
||||
keywords,
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'build',
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ owner, app, branch, token }) {
|
||||
const json = await this.fetch({
|
||||
token,
|
||||
schema,
|
||||
url: `https://api.appcenter.ms/v0.1/apps/${owner}/${app}/branches/${branch}/builds`,
|
||||
})
|
||||
if (json[0] == undefined)
|
||||
// Fetch will return a 200 with no data if no builds were found.
|
||||
throw new NotFound({ prettyMessage: 'no builds found' })
|
||||
return renderBuildStatusBadge({ status: json[0].result })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
'use strict'
|
||||
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
// Mocked response rather than real data as old builds are deleted after some time.
|
||||
t.create('Valid Build')
|
||||
.get('/nock/nock/master/token.json')
|
||||
.intercept(nock =>
|
||||
nock('https://api.appcenter.ms/v0.1/apps/')
|
||||
.get('/nock/nock/branches/master/builds')
|
||||
.reply(200, [
|
||||
{
|
||||
result: 'succeeded',
|
||||
},
|
||||
])
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'build',
|
||||
message: 'passing',
|
||||
})
|
||||
|
||||
t.create('Invalid Branch')
|
||||
.get('/jct/test-1/invalid/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json')
|
||||
.expectBadge({
|
||||
label: 'build',
|
||||
message: 'no builds found',
|
||||
})
|
||||
|
||||
t.create('Invalid API Token')
|
||||
.get('/jct/test-1/master/invalid.json')
|
||||
.expectBadge({
|
||||
label: 'build',
|
||||
message: 'invalid token',
|
||||
})
|
||||
@@ -0,0 +1,61 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const {
|
||||
BaseVisualStudioAppCenterService,
|
||||
keywords,
|
||||
documentation,
|
||||
} = require('./visual-studio-app-center-base')
|
||||
|
||||
const schema = Joi.object({
|
||||
app_os: Joi.string().required(),
|
||||
min_os: Joi.string().required(),
|
||||
}).required()
|
||||
|
||||
module.exports = class VisualStudioAppCenterReleasesOSVersion extends BaseVisualStudioAppCenterService {
|
||||
static get category() {
|
||||
return 'version'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'visual-studio-app-center/releases/osver',
|
||||
pattern: ':owner/:app/:token',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'Visual Studio App Center (Minimum) OS Version',
|
||||
namedParams: {
|
||||
owner: 'jct',
|
||||
app: 'my-amazing-app',
|
||||
token: 'ac70cv...',
|
||||
},
|
||||
staticPreview: this.render({ min_os: '4.1', app_os: 'Android' }),
|
||||
keywords,
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'min version',
|
||||
color: 'blue',
|
||||
}
|
||||
}
|
||||
|
||||
static render({ app_os, min_os }) {
|
||||
return {
|
||||
label: `${app_os.toLowerCase()}`,
|
||||
message: `${min_os}+`,
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ owner, app, token }) {
|
||||
const { app_os, min_os } = await this.fetch({ owner, app, token, schema })
|
||||
return this.constructor.render({ app_os, min_os })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
'use strict'
|
||||
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
// Note:
|
||||
// Unfortunately an Invalid user, invalid project, valid API token test is not possible due to the way Microsoft cache their responses.
|
||||
// For this reason 404 and 403 will instead both display 'project not found'
|
||||
|
||||
t.create('[fixed] Example Release')
|
||||
// This application will never have a new release created.
|
||||
.get(
|
||||
'/jct/test-fixed-android-react/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json'
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'android',
|
||||
message: '4.1+',
|
||||
})
|
||||
|
||||
t.create('Valid user, invalid project, valid API token')
|
||||
.get('/jcx/invalid/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json')
|
||||
.expectBadge({
|
||||
label: 'min version',
|
||||
message: 'project not found',
|
||||
})
|
||||
|
||||
t.create('Invalid user, invalid project, valid API token')
|
||||
.get('/invalid/invalid/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json')
|
||||
.expectBadge({
|
||||
label: 'min version',
|
||||
message: 'project not found',
|
||||
})
|
||||
|
||||
t.create('Invalid API Token')
|
||||
.get('/invalid/invalid/invalid.json')
|
||||
.expectBadge({
|
||||
label: 'min version',
|
||||
message: 'invalid token',
|
||||
})
|
||||
@@ -0,0 +1,61 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const prettyBytes = require('pretty-bytes')
|
||||
const { nonNegativeInteger } = require('../validators')
|
||||
const {
|
||||
BaseVisualStudioAppCenterService,
|
||||
keywords,
|
||||
documentation,
|
||||
} = require('./visual-studio-app-center-base')
|
||||
|
||||
const schema = Joi.object({
|
||||
size: nonNegativeInteger,
|
||||
}).required()
|
||||
|
||||
module.exports = class VisualStudioAppCenterReleasesSize extends BaseVisualStudioAppCenterService {
|
||||
static get category() {
|
||||
return 'size'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'visual-studio-app-center/releases/size',
|
||||
pattern: ':owner/:app/:token',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'Visual Studio App Center Size',
|
||||
namedParams: {
|
||||
owner: 'jct',
|
||||
app: 'my-amazing-app',
|
||||
token: 'ac70cv...',
|
||||
},
|
||||
staticPreview: this.render({ size: 8368844 }),
|
||||
keywords,
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'size',
|
||||
color: 'blue',
|
||||
}
|
||||
}
|
||||
|
||||
static render({ size }) {
|
||||
return {
|
||||
message: prettyBytes(size),
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ owner, app, token }) {
|
||||
const { size } = await this.fetch({ owner, app, token, schema })
|
||||
return this.constructor.render({ size })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
'use strict'
|
||||
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { isFileSize } = require('../test-validators')
|
||||
|
||||
t.create('8368844 bytes to 8.37 megabytes')
|
||||
.get('/nock/nock/nock.json')
|
||||
.intercept(nock =>
|
||||
nock('https://api.appcenter.ms/v0.1/apps/')
|
||||
.get('/nock/nock/releases/latest')
|
||||
.reply(200, {
|
||||
size: 8368844,
|
||||
})
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'size',
|
||||
message: '8.37 MB',
|
||||
})
|
||||
|
||||
t.create('Valid Release')
|
||||
.get(
|
||||
'/jct/test-fixed-android-react/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json'
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'size',
|
||||
message: isFileSize,
|
||||
})
|
||||
|
||||
t.create('Valid user, invalid project, valid API token')
|
||||
.get('/jcx/invalid/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json')
|
||||
.expectBadge({
|
||||
label: 'size',
|
||||
message: 'project not found',
|
||||
})
|
||||
|
||||
t.create('Invalid user, invalid project, valid API token')
|
||||
.get('/invalid/invalid/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json')
|
||||
.expectBadge({
|
||||
label: 'size',
|
||||
message: 'project not found',
|
||||
})
|
||||
|
||||
t.create('Invalid API Token')
|
||||
.get('/invalid/invalid/invalid.json')
|
||||
.expectBadge({
|
||||
label: 'size',
|
||||
message: 'invalid token',
|
||||
})
|
||||
@@ -0,0 +1,61 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { renderVersionBadge } = require('../version')
|
||||
const {
|
||||
BaseVisualStudioAppCenterService,
|
||||
keywords,
|
||||
documentation,
|
||||
} = require('./visual-studio-app-center-base')
|
||||
|
||||
const schema = Joi.object({
|
||||
version: Joi.string().required(),
|
||||
short_version: Joi.string().required(),
|
||||
}).required()
|
||||
|
||||
module.exports = class VisualStudioAppCenterReleasesVersion extends BaseVisualStudioAppCenterService {
|
||||
static get category() {
|
||||
return 'version'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'visual-studio-app-center/releases/version',
|
||||
pattern: ':owner/:app/:token',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'Visual Studio App Center Releases',
|
||||
namedParams: {
|
||||
owner: 'jct',
|
||||
app: 'my-amazing-app',
|
||||
token: 'ac70cv...',
|
||||
},
|
||||
staticPreview: renderVersionBadge({ version: '1.0 (4)' }),
|
||||
keywords,
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'release',
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ owner, app, token }) {
|
||||
const { version, short_version } = await this.fetch({
|
||||
owner,
|
||||
app,
|
||||
token,
|
||||
schema,
|
||||
})
|
||||
return renderVersionBadge({
|
||||
version: `${short_version} (${version})`,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
'use strict'
|
||||
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
// Note:
|
||||
// Unfortunately an Invalid user, invalid project, valid API token test is not possible due to the way Microsoft cache their responses.
|
||||
// For this reason 404 and 403 will instead both display 'project not found'
|
||||
|
||||
t.create('[fixed] Example Release')
|
||||
// This application will never have a new release created.
|
||||
.get(
|
||||
'/jct/test-fixed-android-react/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json'
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'release',
|
||||
message: 'v1.0 (1)',
|
||||
})
|
||||
|
||||
t.create('Valid user, invalid project, valid API token')
|
||||
.get('/jcx/invalid/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json')
|
||||
.expectBadge({
|
||||
label: 'release',
|
||||
message: 'project not found',
|
||||
})
|
||||
|
||||
t.create('Invalid user, invalid project, valid API token')
|
||||
.get('/invalid/invalid/8c9b519a0750095b9fea3d40b2645d8a0c24a2f3.json')
|
||||
.expectBadge({
|
||||
label: 'release',
|
||||
message: 'project not found',
|
||||
})
|
||||
|
||||
t.create('Invalid API Token')
|
||||
.get('/invalid/invalid/invalid.json')
|
||||
.expectBadge({
|
||||
label: 'release',
|
||||
message: 'invalid token',
|
||||
})
|
||||
Reference in New Issue
Block a user