diff --git a/services/gitlab/gitlab-pipeline-status.service.js b/services/gitlab/gitlab-pipeline-status.service.js index 70494b1a6c21c..7c0b355576d09 100644 --- a/services/gitlab/gitlab-pipeline-status.service.js +++ b/services/gitlab/gitlab-pipeline-status.service.js @@ -11,11 +11,12 @@ const badgeSchema = Joi.object({ const queryParamSchema = Joi.object({ gitlab_url: optionalUrl, + branch: Joi.string(), }).required() const documentation = `
- Important: If your project is publicly visible, but the badge is like this: + Important: You must use the Project Path, not the Project Id. Additionally, if your project is publicly visible, but the badge is like this:
@@ -39,26 +40,23 @@ class GitlabPipelineStatus extends BaseSvgScrapingService { static category = 'build' static route = { - base: 'gitlab/pipeline', - pattern: ':user/:repo/:branch+', + base: 'gitlab/pipeline-status', + pattern: ':project+', queryParamSchema, } static examples = [ { title: 'Gitlab pipeline status', - namedParams: { - user: 'gitlab-org', - repo: 'gitlab', - branch: 'master', - }, + namedParams: { project: 'gitlab-org/gitlab' }, + queryParams: { branch: 'master' }, staticPreview: this.render({ status: 'passed' }), documentation, }, { title: 'Gitlab pipeline status (self-hosted)', - namedParams: { user: 'GNOME', repo: 'pango', branch: 'master' }, - queryParams: { gitlab_url: 'https://gitlab.gnome.org' }, + namedParams: { project: 'GNOME/pango' }, + queryParams: { gitlab_url: 'https://gitlab.gnome.org', branch: 'master' }, staticPreview: this.render({ status: 'passed' }), documentation, }, @@ -68,33 +66,67 @@ class GitlabPipelineStatus extends BaseSvgScrapingService { return renderBuildStatusBadge({ status }) } - async handle( - { user, repo, branch }, - { gitlab_url: baseUrl = 'https://gitlab.com' } - ) { - const { message: status } = await this._requestSvg({ + async fetch({ project, branch, baseUrl }) { + return this._requestSvg({ schema: badgeSchema, - url: `${baseUrl}/${user}/${repo}/badges/${branch}/pipeline.svg`, + url: `${baseUrl}/${decodeURIComponent( + project + )}/badges/${branch}/pipeline.svg`, errorMessages: { 401: 'repo not found', 404: 'repo not found', }, }) + } + + static transform(data) { + const { message: status } = data if (status === 'unknown') { throw new NotFound({ prettyMessage: 'branch not found' }) } + return { status } + } + + async handle( + { project }, + { gitlab_url: baseUrl = 'https://gitlab.com', branch = 'main' } + ) { + const data = await this.fetch({ + project, + branch, + baseUrl, + }) + const { status } = this.constructor.transform(data) return this.constructor.render({ status }) } } const GitlabPipelineStatusRedirector = redirector({ category: 'build', + name: 'GitlabPipelineStatusRedirector', route: { base: 'gitlab/pipeline', pattern: ':user/:repo', }, - transformPath: ({ user, repo }) => `/gitlab/pipeline/${user}/${repo}/master`, + transformPath: ({ user, repo }) => `/gitlab/pipeline-status/${user}/${repo}`, + transformQueryParams: ({ _b }) => ({ branch: 'master' }), dateAdded: new Date('2020-07-12'), }) -export { GitlabPipelineStatus, GitlabPipelineStatusRedirector } +const GitlabPipelineStatusBranchRouteParamRedirector = redirector({ + category: 'build', + name: 'GitlabPipelineStatusBranchRouteParamRedirector', + route: { + base: 'gitlab/pipeline', + pattern: ':user/:repo/:branch+', + }, + transformPath: ({ user, repo }) => `/gitlab/pipeline-status/${user}/${repo}`, + transformQueryParams: ({ branch }) => ({ branch }), + dateAdded: new Date('2021-10-20'), +}) + +export { + GitlabPipelineStatus, + GitlabPipelineStatusRedirector, + GitlabPipelineStatusBranchRouteParamRedirector, +} diff --git a/services/gitlab/gitlab-pipeline-status.tester.js b/services/gitlab/gitlab-pipeline-status.tester.js index 2edadbb000e15..41166ddd41d78 100644 --- a/services/gitlab/gitlab-pipeline-status.tester.js +++ b/services/gitlab/gitlab-pipeline-status.tester.js @@ -3,16 +3,27 @@ import { ServiceTester } from '../tester.js' export const t = new ServiceTester({ id: 'GitlabPipeline', title: 'Gitlab Pipeline', - pathPrefix: '/gitlab/pipeline', + pathPrefix: '/gitlab', }) -t.create('Pipeline status').get('/gitlab-org/gitlab/v10.7.6.json').expectBadge({ - label: 'build', - message: isBuildStatus, -}) +t.create('Pipeline status') + .get('/pipeline-status/gitlab-org/gitlab.json?branch=v10.7.6') + .expectBadge({ + label: 'build', + message: isBuildStatus, + }) + +t.create('Pipeline status (nested groups)') + .get( + '/pipeline-status/megabyte-labs/dockerfile/ci-pipeline/ansible-lint.json?branch=master' + ) + .expectBadge({ + label: 'build', + message: isBuildStatus, + }) t.create('Pipeline status (nonexistent branch)') - .get('/gitlab-org/gitlab/nope-not-a-branch.json') + .get('/pipeline-status/gitlab-org/gitlab.json?branch=nope-not-a-branch') .expectBadge({ label: 'build', message: 'branch not found', @@ -26,19 +37,25 @@ t.create('Pipeline status (nonexistent branch)') // error message, we will simply display inaccessible // https://github.com/badges/shields/pull/5538 t.create('Pipeline status (nonexistent repo)') - .get('/this-repo/does-not-exist/master.json') + .get('/pipeline-status/this-repo/does-not-exist.json?branch=master') .expectBadge({ label: 'build', message: 'inaccessible', }) t.create('Pipeline status (custom gitlab URL)') - .get('/GNOME/pango/main.json?gitlab_url=https://gitlab.gnome.org') + .get('/pipeline-status/GNOME/pango.json?gitlab_url=https://gitlab.gnome.org') .expectBadge({ label: 'build', message: isBuildStatus, }) t.create('Pipeline no branch redirect') - .get('/gitlab-org/gitlab.svg') - .expectRedirect('/gitlab/pipeline/gitlab-org/gitlab/master.svg') + .get('/pipeline/gitlab-org/gitlab.svg') + .expectRedirect('/gitlab/pipeline-status/gitlab-org/gitlab.svg?branch=master') + +t.create('Pipeline legacy route with branch redirect') + .get('/pipeline/gitlab-org/gitlab/v10.7.6?style=flat') + .expectRedirect( + '/gitlab/pipeline-status/gitlab-org/gitlab.svg?branch=v10.7.6&style=flat' + )