diff --git a/services/github/github-actions-workflow-status.service.js b/services/github/github-actions-workflow-status.service.js index 466e90732aa25ff2c2a3abf1285f7e665b923e4b..7c92cd030d700ad80e77fa8466a73ff84c07459e 100644 --- a/services/github/github-actions-workflow-status.service.js +++ b/services/github/github-actions-workflow-status.service.js @@ -1,46 +1,22 @@ import Joi from 'joi' import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js' -import { NotFound } from '../index.js' -import { GithubAuthV3Service } from './github-auth-service.js' -import { documentation, errorMessagesFor } from './github-helpers.js' +import { BaseSvgScrapingService } from '../index.js' +import { documentation } from './github-helpers.js' const schema = Joi.object({ - workflow_runs: Joi.array() - .items( - Joi.object({ - status: Joi.equal( - 'completed', - 'action_required', - 'cancelled', - 'failure', - 'neutral', - 'skipped', - 'stale', - 'success', - 'timed_out', - 'in_progress', - 'queued', - 'requested', - 'waiting' - ).required(), - conclusion: Joi.alternatives() - .try(isBuildStatus, Joi.equal('no status'), null) - .required(), - }) - ) - .required() - .min(0) - .max(1), + message: Joi.alternatives() + .try(isBuildStatus, Joi.equal('no status')) + .required(), }).required() const queryParamSchema = Joi.object({ event: Joi.string(), - branch: Joi.string().required(), + branch: Joi.string(), }).required() const keywords = ['action', 'actions'] -export default class GithubActionsWorkflowStatus extends GithubAuthV3Service { +export default class GithubActionsWorkflowStatus extends BaseSvgScrapingService { static category = 'build' static route = { @@ -57,6 +33,19 @@ export default class GithubActionsWorkflowStatus extends GithubAuthV3Service { repo: 'toolkit', workflow: 'unit-tests.yml', }, + staticPreview: renderBuildStatusBadge({ + status: 'passing', + }), + documentation, + keywords, + }, + { + title: 'GitHub Workflow Status (with branch)', + namedParams: { + user: 'actions', + repo: 'toolkit', + workflow: 'unit-tests.yml', + }, queryParams: { branch: 'main', }, @@ -75,7 +64,6 @@ export default class GithubActionsWorkflowStatus extends GithubAuthV3Service { }, queryParams: { event: 'push', - branch: 'main', }, staticPreview: renderBuildStatusBadge({ status: 'passing', @@ -90,30 +78,23 @@ export default class GithubActionsWorkflowStatus extends GithubAuthV3Service { } async fetch({ user, repo, workflow, branch, event }) { - return await this._requestJson({ + const { message: status } = await this._requestSvg({ schema, - url: `/repos/${user}/${repo}/actions/workflows/${workflow}/runs`, - options: { - searchParams: { - branch, - event, - page: '1', - per_page: '1', - exclude_pull_requests: 'true', - }, + url: `https://github.com/${user}/${repo}/actions/workflows/${encodeURIComponent( + workflow + )}/badge.svg`, + options: { searchParams: { branch, event } }, + valueMatcher: />([^<>]+)<\/tspan><\/text><\/g><path/, + errorMessages: { + 404: 'repo or workflow not found', }, - errorMessages: errorMessagesFor('repo or workflow not found'), }) + + return { status } } async handle({ user, repo, workflow }, { branch, event }) { - const data = await this.fetch({ user, repo, workflow, branch, event }) - if (data.workflow_runs.length === 0) { - throw new NotFound({ prettyMessage: 'branch or event not found' }) - } - const status = data.workflow_runs[0].conclusion - ? data.workflow_runs[0].conclusion - : data.workflow_runs[0].status.replace('_', ' ') + const { status } = await this.fetch({ user, repo, workflow, branch, event }) return renderBuildStatusBadge({ status }) } } diff --git a/services/github/github-actions-workflow-status.tester.js b/services/github/github-actions-workflow-status.tester.js index 08386c25aeb3df63b37be4a94418cc4a0b7f65f2..2e76688aaa9e9f521e49cad707b8e44a8ed0d5f0 100644 --- a/services/github/github-actions-workflow-status.tester.js +++ b/services/github/github-actions-workflow-status.tester.js @@ -7,22 +7,15 @@ const isWorkflowStatus = Joi.alternatives() .try(isBuildStatus, Joi.equal('no status')) .required() -t.create('missing branch param') - .get('/actions/toolkit/unit-tests.yml.json') - .expectBadge({ - label: 'build', - message: 'invalid query parameter: branch', - }) - t.create('nonexistent repo') - .get('/badges/shields-fakeness/fake.yml.json?branch=main') + .get('/badges/shields-fakeness/fake.yml.json') .expectBadge({ label: 'build', message: 'repo or workflow not found', }) t.create('nonexistent workflow') - .get('/actions/toolkit/not-a-real-workflow.yml.json?branch=main') + .get('/actions/toolkit/not-a-real-workflow.yml.json') .expectBadge({ label: 'build', message: 'repo or workflow not found', @@ -32,54 +25,33 @@ t.create('nonexistent branch') .get('/actions/toolkit/unit-tests.yml.json?branch=not-a-real-branch') .expectBadge({ label: 'build', - message: 'branch or event not found', + message: 'no status', }) t.create('nonexistent event') - .get( - '/actions/toolkit/unit-tests.yml.json?branch=main&event=not-a-real-event' - ) + .get('/actions/toolkit/unit-tests.yml.json?event=not-a-real-event') .expectBadge({ label: 'build', - message: 'branch or event not found', + message: 'no status', }) t.create('valid workflow') - .get('/actions/toolkit/unit-tests.yml.json?branch=main') + .get('/actions/toolkit/unit-tests.yml.json') .expectBadge({ label: 'build', message: isWorkflowStatus, }) -t.create('valid workflow (with event)') - .get('/actions/toolkit/unit-tests.yml.json?branch=main&event=push') +t.create('valid workflow (with branch)') + .get('/actions/toolkit/unit-tests.yml.json?branch=main') .expectBadge({ label: 'build', message: isWorkflowStatus, }) -t.create('workflow in progress') - .get('/actions/toolkit/unit-tests.yml.json?branch=main') - .intercept(nock => - nock('https://api.github.com') - .get('/repos/actions/toolkit/actions/workflows/unit-tests.yml/runs') - .query({ - branch: 'main', - page: '1', - per_page: '1', - exclude_pull_requests: 'true', - }) - .reply(200, { - workflow_runs: [ - { - status: 'in_progress', - conclusion: null, - }, - ], - }) - ) +t.create('valid workflow (with event)') + .get('/actions/toolkit/unit-tests.yml.json?event=push') .expectBadge({ label: 'build', - message: 'in progress', - color: 'lightgrey', + message: isWorkflowStatus, })