diff --git a/services/github/github-api-provider.js b/services/github/github-api-provider.js index ba3075a8f4d6d..cae672ae31e4b 100644 --- a/services/github/github-api-provider.js +++ b/services/github/github-api-provider.js @@ -188,6 +188,7 @@ class GithubApiProvider { 'User-Agent': userAgent, Accept: 'application/vnd.github.v3+json', Authorization: `token ${tokenString}`, + ...options.headers, }, }, } diff --git a/services/github/github-discussions-total.service.js b/services/github/github-discussions-total.service.js new file mode 100644 index 0000000000000..760f11a1367e7 --- /dev/null +++ b/services/github/github-discussions-total.service.js @@ -0,0 +1,74 @@ +'use strict' + +const { default: gql } = require('graphql-tag') +const Joi = require('joi') +const { nonNegativeInteger } = require('../validators') +const { GithubAuthV4Service } = require('./github-auth-service') +const { transformErrors } = require('./github-helpers') + +const schema = Joi.object({ + data: Joi.object({ + repository: Joi.object({ + discussions: Joi.object({ + totalCount: nonNegativeInteger, + }).required(), + }).required(), + }).required(), +}).required() + +module.exports = class GithubTotalDiscussions extends GithubAuthV4Service { + static category = 'other' + static route = { + base: 'github/discussions', + pattern: ':user/:repo', + } + + static examples = [ + { + title: 'GitHub Discussions', + namedParams: { + user: 'vercel', + repo: 'next.js', + }, + staticPreview: this.render({ + discussions: '6000 total', + }), + }, + ] + + static defaultBadgeData = { label: 'discussions', color: 'blue' } + + static render({ discussions }) { + return { message: discussions } + } + + async fetch({ user, repo }) { + return this._requestGraphql({ + query: gql` + query($user: String!, $repo: String!) { + repository(name: $repo, owner: $user) { + discussions { + totalCount + } + } + } + `, + variables: { user, repo }, + schema, + options: { headers: { 'GraphQL-Features': 'discussions_api' } }, + transformErrors, + }) + } + + async handle({ user, repo }) { + const json = await this.fetch({ user, repo }) + const { + data: { + repository: { + discussions: { totalCount }, + }, + }, + } = json + return this.constructor.render({ discussions: `${totalCount} total` }) + } +} diff --git a/services/github/github-discussions-total.tester.js b/services/github/github-discussions-total.tester.js new file mode 100644 index 0000000000000..737419d485378 --- /dev/null +++ b/services/github/github-discussions-total.tester.js @@ -0,0 +1,15 @@ +'use strict' + +const { withRegex } = require('../test-validators') +const t = (module.exports = require('../tester').createServiceTester()) + +t.create('GitHub Total Discussions (repo not found)') + .get('/not-a-user/not-a-repo.json') + .expectBadge({ label: 'discussions', message: 'repo not found' }) + +// example: 6000 total +const numberSpaceTotal = withRegex(/^\d+ total$/) + +t.create('GitHub Total Discussions (repo having discussions)') + .get('/vercel/next.js.json') + .expectBadge({ label: 'discussions', message: numberSpaceTotal })