-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
switch from github workflows to github actions workflows; test [githubactionsworkflowstatus githubworkflowstatus] #8475
Changes from 2 commits
808dfec
7ea7cf5
de39617
e0b7dbd
7e7d006
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
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' | ||
|
||
const schema = Joi.object({ | ||
workflow_runs: Joi.array() | ||
.items( | ||
Joi.object({ | ||
conclusion: Joi.alternatives() | ||
.try(isBuildStatus, Joi.equal('no status')) | ||
.required(), | ||
}) | ||
) | ||
.required() | ||
.min(0) | ||
.max(1), | ||
}).required() | ||
|
||
const queryParamSchema = Joi.object({ | ||
event: Joi.string(), | ||
branch: Joi.string().required(), | ||
}).required() | ||
|
||
const keywords = ['action', 'actions'] | ||
|
||
export default class GithubActionsWorkflowStatus extends GithubAuthV3Service { | ||
static category = 'build' | ||
|
||
static route = { | ||
base: 'github/actions/workflow/status', | ||
pattern: ':user/:repo/:workflow+', | ||
chris48s marked this conversation as resolved.
Show resolved
Hide resolved
|
||
queryParamSchema, | ||
} | ||
|
||
static examples = [ | ||
{ | ||
title: 'GitHub Workflow Status', | ||
namedParams: { | ||
user: 'actions', | ||
repo: 'toolkit', | ||
workflow: 'unit-tests.yml', | ||
}, | ||
queryParams: { | ||
branch: 'main', | ||
}, | ||
staticPreview: renderBuildStatusBadge({ | ||
status: 'passing', | ||
}), | ||
documentation, | ||
keywords, | ||
}, | ||
{ | ||
title: 'GitHub Workflow Status (with event)', | ||
namedParams: { | ||
user: 'actions', | ||
repo: 'toolkit', | ||
workflow: 'unit-tests.yml', | ||
}, | ||
queryParams: { | ||
event: 'push', | ||
branch: 'main', | ||
}, | ||
staticPreview: renderBuildStatusBadge({ | ||
status: 'passing', | ||
}), | ||
documentation, | ||
keywords, | ||
}, | ||
] | ||
|
||
static defaultBadgeData = { | ||
label: 'build', | ||
} | ||
|
||
async fetch({ user, repo, workflow, branch, event }) { | ||
return await this._requestJson({ | ||
schema, | ||
url: `/repos/${user}/${repo}/actions/workflows/${workflow}/runs`, | ||
options: { | ||
searchParams: { | ||
branch, | ||
event, | ||
page: '1', | ||
per_page: '1', | ||
exclude_pull_requests: 'true', | ||
Comment on lines
+85
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These params are here for performance reasons. There's huge execution time difference between this query with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. Definitely understand the performance angle, but curious if there's any functional impacts? Am I correctly interpreting this as meaning that runs triggered by a pull request would be excluded? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope. Passing this means the |
||
}, | ||
}, | ||
errorMessages: errorMessagesFor('repo or workflow not found'), | ||
}) | ||
} | ||
|
||
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' }) | ||
} | ||
return renderBuildStatusBadge({ status: data.workflow_runs[0].conclusion }) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import Joi from 'joi' | ||
import { isBuildStatus } from '../build-status.js' | ||
import { createServiceTester } from '../tester.js' | ||
export const t = await createServiceTester() | ||
|
||
const isWorkflowStatus = Joi.alternatives() | ||
.try(isBuildStatus, Joi.equal('no status')) | ||
.required() | ||
|
||
t.create('nonexistent repo') | ||
.get('/badges/shields-fakeness/fake.yml.json?branch=main') | ||
.expectBadge({ | ||
label: 'build', | ||
message: 'repo or workflow not found', | ||
}) | ||
|
||
t.create('nonexistent workflow') | ||
.get('/actions/toolkit/not-a-real-workflow.yml.json?branch=main') | ||
.expectBadge({ | ||
label: 'build', | ||
message: 'repo or workflow not found', | ||
}) | ||
|
||
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', | ||
}) | ||
|
||
t.create('nonexistent event') | ||
.get( | ||
'/actions/toolkit/unit-tests.yml.json?branch=main&event=not-a-real-event' | ||
) | ||
.expectBadge({ | ||
label: 'build', | ||
message: 'branch or event not found', | ||
}) | ||
|
||
t.create('valid workflow') | ||
.get('/actions/toolkit/unit-tests.yml.json?branch=main') | ||
.expectBadge({ | ||
label: 'build', | ||
message: isWorkflowStatus, | ||
}) | ||
|
||
t.create('valid workflow (with event)') | ||
.get('/actions/toolkit/unit-tests.yml.json?branch=main&event=push') | ||
.expectBadge({ | ||
label: 'build', | ||
message: isWorkflowStatus, | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,100 +1,11 @@ | ||
import Joi from 'joi' | ||
import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js' | ||
import { BaseSvgScrapingService } from '../index.js' | ||
import { documentation } from './github-helpers.js' | ||
import { deprecatedService } from '../index.js' | ||
|
||
const schema = Joi.object({ | ||
message: Joi.alternatives() | ||
.try(isBuildStatus, Joi.equal('no status')) | ||
.required(), | ||
}).required() | ||
|
||
const queryParamSchema = Joi.object({ | ||
event: Joi.string(), | ||
}).required() | ||
|
||
const keywords = ['action', 'actions'] | ||
|
||
export default class GithubWorkflowStatus extends BaseSvgScrapingService { | ||
static category = 'build' | ||
|
||
static route = { | ||
export default deprecatedService({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Normally when we deprecate a badge we are just getting rid of it completely. Often the upstream service has been retired, or whatever. If we can provide a migration path from old to new, we use a redirect. In this case, we can't do either of those things because the Because we've never had this situation where we're asking people to switch and we can't provide a redirect, we've never done this before, but I wonder if instead of serving There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'd recommend going with your issue link suggestion. Completely agreed that 99% of those that see the badge won't be able to do anything about it, but having a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
category: 'build', | ||
route: { | ||
base: 'github/workflow/status', | ||
pattern: ':user/:repo/:workflow/:branch*', | ||
queryParamSchema, | ||
} | ||
|
||
static examples = [ | ||
{ | ||
title: 'GitHub Workflow Status', | ||
pattern: ':user/:repo/:workflow', | ||
namedParams: { | ||
user: 'actions', | ||
repo: 'toolkit', | ||
workflow: 'toolkit-unit-tests', | ||
}, | ||
staticPreview: renderBuildStatusBadge({ | ||
status: 'passing', | ||
}), | ||
documentation, | ||
keywords, | ||
}, | ||
{ | ||
title: 'GitHub Workflow Status (branch)', | ||
pattern: ':user/:repo/:workflow/:branch', | ||
namedParams: { | ||
user: 'actions', | ||
repo: 'toolkit', | ||
workflow: 'toolkit-unit-tests', | ||
branch: 'master', | ||
}, | ||
staticPreview: renderBuildStatusBadge({ | ||
status: 'passing', | ||
}), | ||
documentation, | ||
keywords, | ||
}, | ||
{ | ||
title: 'GitHub Workflow Status (event)', | ||
pattern: ':user/:repo/:workflow', | ||
namedParams: { | ||
user: 'actions', | ||
repo: 'toolkit', | ||
workflow: 'toolkit-unit-tests', | ||
}, | ||
queryParams: { | ||
event: 'push', | ||
}, | ||
staticPreview: renderBuildStatusBadge({ | ||
status: 'passing', | ||
}), | ||
documentation, | ||
keywords, | ||
}, | ||
] | ||
|
||
static defaultBadgeData = { | ||
label: 'build', | ||
} | ||
|
||
async fetch({ user, repo, workflow, branch, event }) { | ||
const { message: status } = await this._requestSvg({ | ||
schema, | ||
url: `https://github.com/${user}/${repo}/workflows/${encodeURIComponent( | ||
workflow | ||
)}/badge.svg`, | ||
options: { searchParams: { branch, event } }, | ||
valueMatcher: />([^<>]+)<\/tspan><\/text><\/g><path/, | ||
errorMessages: { | ||
404: 'repo, branch, or workflow not found', | ||
}, | ||
}) | ||
|
||
return { status } | ||
} | ||
|
||
async handle({ user, repo, workflow, branch }, { event }) { | ||
const { status } = await this.fetch({ user, repo, workflow, branch, event }) | ||
return renderBuildStatusBadge({ status }) | ||
} | ||
} | ||
pattern: ':various+', | ||
}, | ||
label: 'build', | ||
dateAdded: new Date('2022-10-03'), | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,42 @@ | ||
import Joi from 'joi' | ||
import { isBuildStatus } from '../build-status.js' | ||
import { createServiceTester } from '../tester.js' | ||
export const t = await createServiceTester() | ||
import { ServiceTester } from '../tester.js' | ||
|
||
const isWorkflowStatus = Joi.alternatives() | ||
.try(isBuildStatus, Joi.equal('no status')) | ||
.required() | ||
export const t = new ServiceTester({ | ||
id: 'GithubWorkflowStatus', | ||
title: 'Github Workflow Status', | ||
pathPrefix: '/github/workflow/status', | ||
}) | ||
|
||
t.create('nonexistent repo') | ||
t.create('no longer available (previously nonexistent repo)') | ||
.get('/badges/shields-fakeness/fake.json') | ||
.expectBadge({ | ||
label: 'build', | ||
message: 'repo, branch, or workflow not found', | ||
message: 'no longer available', | ||
}) | ||
|
||
t.create('nonexistent workflow') | ||
t.create('no longer available (previously nonexistent workflow)') | ||
.get('/actions/toolkit/not-a-real-workflow.json') | ||
.expectBadge({ | ||
label: 'build', | ||
message: 'repo, branch, or workflow not found', | ||
message: 'no longer available', | ||
}) | ||
|
||
t.create('valid workflow') | ||
t.create('no longer available (previously valid workflow)') | ||
.get('/actions/toolkit/toolkit-unit-tests.json') | ||
.expectBadge({ | ||
label: 'build', | ||
message: isWorkflowStatus, | ||
message: 'no longer available', | ||
}) | ||
|
||
t.create('valid workflow (branch)') | ||
t.create('no longer available (previously valid workflow - branch)') | ||
.get('/actions/toolkit/toolkit-unit-tests/master.json') | ||
.expectBadge({ | ||
label: 'build', | ||
message: isWorkflowStatus, | ||
message: 'no longer available', | ||
}) | ||
|
||
t.create('valid workflow (event)') | ||
t.create('no longer available (previously valid workflow - event)') | ||
.get('/actions/toolkit/toolkit-unit-tests.json?event=push') | ||
.expectBadge({ | ||
label: 'build', | ||
message: isWorkflowStatus, | ||
message: 'no longer available', | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made branch a required param for this badge. Not my favourite solution, but workflow can contain a
/
andbranch=HEAD
doesn't work so we can't make the default "whatever the default branch is" in one request, so required query param it is. Lets lay that marker down while we're making a breaking change.I don't think "latest workflow status across all branches" is a sensible default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know off hand if this has to explicitly be a branch or will the upstream endpoint accept any valid ref?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docs say
Anecdotally, I tried some calls with a tag and a commit hash (which I expected would return a valid result if this could accept any ref). They returned 0 results.