From 05ab8a0bd73f24386f41ede22eb8e3f9a1a35fe2 Mon Sep 17 00:00:00 2001 From: guoxudong Date: Sat, 8 Oct 2022 09:49:07 +0800 Subject: [PATCH] feat: add [GitlabLanguageCount] service (#8377) * feat: add gitlab language count service * fix testr * fix Signed-off-by: guoxudong Signed-off-by: guoxudong Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com> --- .../gitlab/gitlab-languages-count.service.js | 68 +++++++++++++++++++ .../gitlab/gitlab-languages-count.tester.js | 25 +++++++ 2 files changed, 93 insertions(+) create mode 100644 services/gitlab/gitlab-languages-count.service.js create mode 100644 services/gitlab/gitlab-languages-count.tester.js diff --git a/services/gitlab/gitlab-languages-count.service.js b/services/gitlab/gitlab-languages-count.service.js new file mode 100644 index 0000000000..60e6588e7a --- /dev/null +++ b/services/gitlab/gitlab-languages-count.service.js @@ -0,0 +1,68 @@ +import Joi from 'joi' +import { optionalUrl } from '../validators.js' +import { metric } from '../text-formatters.js' +import { documentation, errorMessagesFor } from './gitlab-helper.js' +import GitLabBase from './gitlab-base.js' + +/* +We're expecting a response like { "Ruby": 67.13, "JavaScript": 19.66 } +The keys could be anything and {} is a valid response (e.g: for an empty project) +*/ +const schema = Joi.object().pattern(/./, Joi.number().min(0).max(100)) + +const queryParamSchema = Joi.object({ + gitlab_url: optionalUrl, +}).required() + +export default class GitlabLanguageCount extends GitLabBase { + static category = 'analysis' + + static route = { + base: 'gitlab/languages/count', + pattern: ':project+', + queryParamSchema, + } + + static examples = [ + { + title: 'GitLab language count', + namedParams: { + project: 'gitlab-org/gitlab', + }, + queryParams: { gitlab_url: 'https://gitlab.com' }, + staticPreview: { + label: 'languages', + message: '5', + }, + documentation, + }, + ] + + static defaultBadgeData = { label: 'languages' } + + static render({ languagesCount }) { + return { + message: metric(languagesCount), + color: 'blue', + } + } + + async fetch({ project, baseUrl }) { + // https://docs.gitlab.com/ee/api/projects.html#languages + return super.fetch({ + schema, + url: `${baseUrl}/api/v4/projects/${encodeURIComponent( + project + )}/languages`, + errorMessages: errorMessagesFor('project not found'), + }) + } + + async handle({ project }, { gitlab_url: baseUrl = 'https://gitlab.com' }) { + const data = await this.fetch({ + project, + baseUrl, + }) + return this.constructor.render({ languagesCount: Object.keys(data).length }) + } +} diff --git a/services/gitlab/gitlab-languages-count.tester.js b/services/gitlab/gitlab-languages-count.tester.js new file mode 100644 index 0000000000..13a7b0ba05 --- /dev/null +++ b/services/gitlab/gitlab-languages-count.tester.js @@ -0,0 +1,25 @@ +import { isMetric } from '../test-validators.js' +import { createServiceTester } from '../tester.js' + +export const t = await createServiceTester() + +t.create('language count').get('/gitlab-org/gitlab.json').expectBadge({ + label: 'languages', + message: isMetric, + color: 'blue', +}) + +t.create('language count (self-managed)') + .get('/gitlab-cn/gitlab.json?gitlab_url=https://jihulab.com') + .expectBadge({ + label: 'languages', + message: isMetric, + color: 'blue', + }) + +t.create('language count (project not found)') + .get('/open/guoxudong.io/shields-test/do-not-exist.json') + .expectBadge({ + label: 'languages', + message: 'project not found', + })