diff --git a/services/gitlab/gitlab-last-commit.service.js b/services/gitlab/gitlab-last-commit.service.js new file mode 100644 index 0000000000000000000000000000000000000000..b2342d669b0fe20932142e5c5d819862fba61c26 --- /dev/null +++ b/services/gitlab/gitlab-last-commit.service.js @@ -0,0 +1,79 @@ +import Joi from 'joi' +import { optionalUrl } from '../validators.js' +import { formatDate } from '../text-formatters.js' +import { age as ageColor } from '../color-formatters.js' +import { documentation, errorMessagesFor } from './gitlab-helper.js' +import GitLabBase from './gitlab-base.js' + +const schema = Joi.array() + .items( + Joi.object({ + committed_date: Joi.string().required(), + }).required() + ) + .required() + .min(1) + +const queryParamSchema = Joi.object({ + ref: Joi.string(), + gitlab_url: optionalUrl, +}).required() + +const refText = ` +<p> + ref can be filled with the name of a branch, tag or revision range of the repository. +</p> +` + +const defaultDocumentation = documentation + refText + +export default class GitlabLastCommit extends GitLabBase { + static category = 'activity' + + static route = { + base: 'gitlab/last-commit', + pattern: ':project+', + queryParamSchema, + } + + static examples = [ + { + title: 'GitLab last commit', + namedParams: { + project: 'gitlab-org/gitlab', + }, + queryParams: { gitlab_url: 'https://gitlab.com' }, + staticPreview: this.render({ commitDate: '2013-07-31T20:01:41Z' }), + documentation: defaultDocumentation, + }, + ] + + static defaultBadgeData = { label: 'last commit' } + + static render({ commitDate }) { + return { + message: formatDate(commitDate), + color: ageColor(Date.parse(commitDate)), + } + } + + async fetch({ project, baseUrl, ref }) { + // https://docs.gitlab.com/ee/api/commits.html#list-repository-commits + return super.fetch({ + url: `${baseUrl}/api/v4/projects/${encodeURIComponent( + project + )}/repository/commits`, + options: { searchParams: { ref_name: ref } }, + schema, + errorMessages: errorMessagesFor('project not found'), + }) + } + + async handle( + { project }, + { gitlab_url: baseUrl = 'https://gitlab.com', ref } + ) { + const data = await this.fetch({ project, baseUrl, ref }) + return this.constructor.render({ commitDate: data[0].committed_date }) + } +} diff --git a/services/gitlab/gitlab-last-commit.tester.js b/services/gitlab/gitlab-last-commit.tester.js new file mode 100644 index 0000000000000000000000000000000000000000..ecc29fdbd720892491171146c8c24a5bb16bb490 --- /dev/null +++ b/services/gitlab/gitlab-last-commit.tester.js @@ -0,0 +1,30 @@ +import { isFormattedDate } from '../test-validators.js' +import { createServiceTester } from '../tester.js' + +export const t = await createServiceTester() + +t.create('last commit (recent)').get('/gitlab-org/gitlab.json').expectBadge({ + label: 'last commit', + message: isFormattedDate, +}) + +t.create('last commit (on ref and ancient)') + .get('/gitlab-org/gitlab.json?ref=v13.8.6-ee') + .expectBadge({ + label: 'last commit', + message: 'march 2021', + }) + +t.create('last commit (self-managed)') + .get('/gitlab-cn/gitlab.json?gitlab_url=https://jihulab.com') + .expectBadge({ + label: 'last commit', + message: isFormattedDate, + }) + +t.create('last commit (project not found)') + .get('/open/guoxudong.io/shields-test/do-not-exist.json') + .expectBadge({ + label: 'last commit', + message: 'project not found', + })