ci/labels: run prettier
This is the result of: prettier --no-semi --single-quote
This commit is contained in:
parent
89ee8975ab
commit
9936e7d751
@ -1,4 +1,4 @@
|
|||||||
module.exports = async function({ github, context, core }) {
|
module.exports = async function ({ github, context, core }) {
|
||||||
const Bottleneck = require('bottleneck')
|
const Bottleneck = require('bottleneck')
|
||||||
const path = require('node:path')
|
const path = require('node:path')
|
||||||
const { DefaultArtifactClient } = require('@actions/artifact')
|
const { DefaultArtifactClient } = require('@actions/artifact')
|
||||||
@ -10,7 +10,7 @@ module.exports = async function({ github, context, core }) {
|
|||||||
issues: 0,
|
issues: 0,
|
||||||
prs: 0,
|
prs: 0,
|
||||||
requests: 0,
|
requests: 0,
|
||||||
artifacts: 0
|
artifacts: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rate-Limiting and Throttling, see for details:
|
// Rate-Limiting and Throttling, see for details:
|
||||||
@ -20,7 +20,7 @@ module.exports = async function({ github, context, core }) {
|
|||||||
// Avoid concurrent requests
|
// Avoid concurrent requests
|
||||||
maxConcurrent: 1,
|
maxConcurrent: 1,
|
||||||
// Will be updated with first `updateReservoir()` call below.
|
// Will be updated with first `updateReservoir()` call below.
|
||||||
reservoir: 0
|
reservoir: 0,
|
||||||
})
|
})
|
||||||
// Pause between mutative requests
|
// Pause between mutative requests
|
||||||
const writeLimits = new Bottleneck({ minTime: 1000 }).chain(allLimits)
|
const writeLimits = new Bottleneck({ minTime: 1000 }).chain(allLimits)
|
||||||
@ -33,8 +33,7 @@ module.exports = async function({ github, context, core }) {
|
|||||||
stats.requests++
|
stats.requests++
|
||||||
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(options.method))
|
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(options.method))
|
||||||
return writeLimits.schedule(request.bind(null, options))
|
return writeLimits.schedule(request.bind(null, options))
|
||||||
else
|
else return allLimits.schedule(request.bind(null, options))
|
||||||
return allLimits.schedule(request.bind(null, options))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
async function updateReservoir() {
|
async function updateReservoir() {
|
||||||
@ -57,26 +56,28 @@ module.exports = async function({ github, context, core }) {
|
|||||||
const reservoirUpdater = setInterval(updateReservoir, 60 * 1000)
|
const reservoirUpdater = setInterval(updateReservoir, 60 * 1000)
|
||||||
|
|
||||||
async function handlePullRequest(item) {
|
async function handlePullRequest(item) {
|
||||||
const log = (k,v) => core.info(`PR #${item.number} - ${k}: ${v}`)
|
const log = (k, v) => core.info(`PR #${item.number} - ${k}: ${v}`)
|
||||||
|
|
||||||
const pull_number = item.number
|
const pull_number = item.number
|
||||||
|
|
||||||
// This API request is important for the merge-conflict label, because it triggers the
|
// This API request is important for the merge-conflict label, because it triggers the
|
||||||
// creation of a new test merge commit. This is needed to actually determine the state of a PR.
|
// creation of a new test merge commit. This is needed to actually determine the state of a PR.
|
||||||
const pull_request = (await github.rest.pulls.get({
|
const pull_request = (
|
||||||
...context.repo,
|
await github.rest.pulls.get({
|
||||||
pull_number
|
...context.repo,
|
||||||
})).data
|
pull_number,
|
||||||
|
})
|
||||||
|
).data
|
||||||
|
|
||||||
const reviews = await github.paginate(github.rest.pulls.listReviews, {
|
const reviews = await github.paginate(github.rest.pulls.listReviews, {
|
||||||
...context.repo,
|
...context.repo,
|
||||||
pull_number
|
pull_number,
|
||||||
})
|
})
|
||||||
|
|
||||||
const approvals = new Set(
|
const approvals = new Set(
|
||||||
reviews
|
reviews
|
||||||
.filter(review => review.state == 'APPROVED')
|
.filter((review) => review.state == 'APPROVED')
|
||||||
.map(review => review.user?.id)
|
.map((review) => review.user?.id),
|
||||||
)
|
)
|
||||||
|
|
||||||
// After creation of a Pull Request, `merge_commit_sha` will be null initially:
|
// After creation of a Pull Request, `merge_commit_sha` will be null initially:
|
||||||
@ -84,7 +85,8 @@ module.exports = async function({ github, context, core }) {
|
|||||||
// To avoid labeling the PR as conflicted before that, we wait a few minutes.
|
// To avoid labeling the PR as conflicted before that, we wait a few minutes.
|
||||||
// This is intentionally less than the time that Eval takes, so that the label job
|
// This is intentionally less than the time that Eval takes, so that the label job
|
||||||
// running after Eval can indeed label the PR as conflicted if that is the case.
|
// running after Eval can indeed label the PR as conflicted if that is the case.
|
||||||
const merge_commit_sha_valid = new Date() - new Date(pull_request.created_at) > 3 * 60 * 1000
|
const merge_commit_sha_valid =
|
||||||
|
new Date() - new Date(pull_request.created_at) > 3 * 60 * 1000
|
||||||
|
|
||||||
const prLabels = {
|
const prLabels = {
|
||||||
// We intentionally don't use the mergeable or mergeable_state attributes.
|
// We intentionally don't use the mergeable or mergeable_state attributes.
|
||||||
@ -98,31 +100,41 @@ module.exports = async function({ github, context, core }) {
|
|||||||
// On the first pass of the day, we just fetch the pull request, which triggers
|
// On the first pass of the day, we just fetch the pull request, which triggers
|
||||||
// the creation. At this stage, the label is likely not updated, yet.
|
// the creation. At this stage, the label is likely not updated, yet.
|
||||||
// The second pass will then read the result from the first pass and set the label.
|
// The second pass will then read the result from the first pass and set the label.
|
||||||
'2.status: merge conflict': merge_commit_sha_valid && !pull_request.merge_commit_sha,
|
'2.status: merge conflict':
|
||||||
|
merge_commit_sha_valid && !pull_request.merge_commit_sha,
|
||||||
'12.approvals: 1': approvals.size == 1,
|
'12.approvals: 1': approvals.size == 1,
|
||||||
'12.approvals: 2': approvals.size == 2,
|
'12.approvals: 2': approvals.size == 2,
|
||||||
'12.approvals: 3+': approvals.size >= 3,
|
'12.approvals: 3+': approvals.size >= 3,
|
||||||
'12.first-time contribution':
|
'12.first-time contribution': [
|
||||||
[ 'NONE', 'FIRST_TIMER', 'FIRST_TIME_CONTRIBUTOR' ].includes(pull_request.author_association),
|
'NONE',
|
||||||
|
'FIRST_TIMER',
|
||||||
|
'FIRST_TIME_CONTRIBUTOR',
|
||||||
|
].includes(pull_request.author_association),
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id: run_id, conclusion } = (await github.rest.actions.listWorkflowRuns({
|
const { id: run_id, conclusion } =
|
||||||
...context.repo,
|
(
|
||||||
workflow_id: 'pr.yml',
|
await github.rest.actions.listWorkflowRuns({
|
||||||
event: 'pull_request_target',
|
...context.repo,
|
||||||
exclude_pull_requests: true,
|
workflow_id: 'pr.yml',
|
||||||
head_sha: pull_request.head.sha
|
event: 'pull_request_target',
|
||||||
})).data.workflow_runs[0] ??
|
exclude_pull_requests: true,
|
||||||
|
head_sha: pull_request.head.sha,
|
||||||
|
})
|
||||||
|
).data.workflow_runs[0] ??
|
||||||
// TODO: Remove this after 2025-09-17, at which point all eval.yml artifacts will have expired.
|
// TODO: Remove this after 2025-09-17, at which point all eval.yml artifacts will have expired.
|
||||||
(await github.rest.actions.listWorkflowRuns({
|
(
|
||||||
...context.repo,
|
await github.rest.actions.listWorkflowRuns({
|
||||||
// In older PRs, we need eval.yml instead of pr.yml.
|
...context.repo,
|
||||||
workflow_id: 'eval.yml',
|
// In older PRs, we need eval.yml instead of pr.yml.
|
||||||
event: 'pull_request_target',
|
workflow_id: 'eval.yml',
|
||||||
status: 'success',
|
event: 'pull_request_target',
|
||||||
exclude_pull_requests: true,
|
status: 'success',
|
||||||
head_sha: pull_request.head.sha
|
exclude_pull_requests: true,
|
||||||
})).data.workflow_runs[0] ?? {}
|
head_sha: pull_request.head.sha,
|
||||||
|
})
|
||||||
|
).data.workflow_runs[0] ??
|
||||||
|
{}
|
||||||
|
|
||||||
// Newer PRs might not have run Eval to completion, yet.
|
// Newer PRs might not have run Eval to completion, yet.
|
||||||
// Older PRs might not have an eval.yml workflow, yet.
|
// Older PRs might not have an eval.yml workflow, yet.
|
||||||
@ -146,17 +158,24 @@ module.exports = async function({ github, context, core }) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const artifact = run_id && (await github.rest.actions.listWorkflowRunArtifacts({
|
const artifact =
|
||||||
...context.repo,
|
run_id &&
|
||||||
run_id,
|
(
|
||||||
name: 'comparison'
|
await github.rest.actions.listWorkflowRunArtifacts({
|
||||||
})).data.artifacts[0]
|
...context.repo,
|
||||||
|
run_id,
|
||||||
|
name: 'comparison',
|
||||||
|
})
|
||||||
|
).data.artifacts[0]
|
||||||
|
|
||||||
// Instead of checking the boolean artifact.expired, we will give us a minute to
|
// Instead of checking the boolean artifact.expired, we will give us a minute to
|
||||||
// actually download the artifact in the next step and avoid that race condition.
|
// actually download the artifact in the next step and avoid that race condition.
|
||||||
// Older PRs, where the workflow run was already eval.yml, but the artifact was not
|
// Older PRs, where the workflow run was already eval.yml, but the artifact was not
|
||||||
// called "comparison", yet, will skip the download.
|
// called "comparison", yet, will skip the download.
|
||||||
const expired = !artifact || new Date(artifact?.expires_at ?? 0) < new Date(new Date().getTime() + 60 * 1000)
|
const expired =
|
||||||
|
!artifact ||
|
||||||
|
new Date(artifact?.expires_at ?? 0) <
|
||||||
|
new Date(new Date().getTime() + 60 * 1000)
|
||||||
log('Artifact expires at', artifact?.expires_at ?? '<n/a>')
|
log('Artifact expires at', artifact?.expires_at ?? '<n/a>')
|
||||||
if (!expired) {
|
if (!expired) {
|
||||||
stats.artifacts++
|
stats.artifacts++
|
||||||
@ -165,17 +184,23 @@ module.exports = async function({ github, context, core }) {
|
|||||||
findBy: {
|
findBy: {
|
||||||
repositoryName: context.repo.repo,
|
repositoryName: context.repo.repo,
|
||||||
repositoryOwner: context.repo.owner,
|
repositoryOwner: context.repo.owner,
|
||||||
token: core.getInput('github-token')
|
token: core.getInput('github-token'),
|
||||||
},
|
},
|
||||||
path: path.resolve(pull_number.toString()),
|
path: path.resolve(pull_number.toString()),
|
||||||
expectedHash: artifact.digest
|
expectedHash: artifact.digest,
|
||||||
})
|
})
|
||||||
|
|
||||||
const maintainers = new Set(Object.keys(
|
const maintainers = new Set(
|
||||||
JSON.parse(await readFile(`${pull_number}/maintainers.json`, 'utf-8'))
|
Object.keys(
|
||||||
).map(m => Number.parseInt(m, 10)))
|
JSON.parse(
|
||||||
|
await readFile(`${pull_number}/maintainers.json`, 'utf-8'),
|
||||||
|
),
|
||||||
|
).map((m) => Number.parseInt(m, 10)),
|
||||||
|
)
|
||||||
|
|
||||||
const evalLabels = JSON.parse(await readFile(`${pull_number}/changed-paths.json`, 'utf-8')).labels
|
const evalLabels = JSON.parse(
|
||||||
|
await readFile(`${pull_number}/changed-paths.json`, 'utf-8'),
|
||||||
|
).labels
|
||||||
|
|
||||||
Object.assign(
|
Object.assign(
|
||||||
prLabels,
|
prLabels,
|
||||||
@ -184,10 +209,12 @@ module.exports = async function({ github, context, core }) {
|
|||||||
// The old eval labels would have been set by the eval run,
|
// The old eval labels would have been set by the eval run,
|
||||||
// so now they'll be present in `before`.
|
// so now they'll be present in `before`.
|
||||||
// TODO: Simplify once old eval results have expired (~2025-10)
|
// TODO: Simplify once old eval results have expired (~2025-10)
|
||||||
(Array.isArray(evalLabels) ? undefined : evalLabels),
|
Array.isArray(evalLabels) ? undefined : evalLabels,
|
||||||
{
|
{
|
||||||
'12.approved-by: package-maintainer': Array.from(maintainers).some(m => approvals.has(m)),
|
'12.approved-by: package-maintainer': Array.from(maintainers).some(
|
||||||
}
|
(m) => approvals.has(m),
|
||||||
|
),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +223,7 @@ module.exports = async function({ github, context, core }) {
|
|||||||
|
|
||||||
async function handle(item) {
|
async function handle(item) {
|
||||||
try {
|
try {
|
||||||
const log = (k,v,skip) => {
|
const log = (k, v, skip) => {
|
||||||
core.info(`#${item.number} - ${k}: ${v}` + (skip ? ' (skipped)' : ''))
|
core.info(`#${item.number} - ${k}: ${v}` + (skip ? ' (skipped)' : ''))
|
||||||
return skip
|
return skip
|
||||||
}
|
}
|
||||||
@ -216,38 +243,44 @@ module.exports = async function({ github, context, core }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const latest_event_at = new Date(
|
const latest_event_at = new Date(
|
||||||
(await github.paginate(
|
(
|
||||||
github.rest.issues.listEventsForTimeline,
|
await github.paginate(github.rest.issues.listEventsForTimeline, {
|
||||||
{
|
|
||||||
...context.repo,
|
...context.repo,
|
||||||
issue_number,
|
issue_number,
|
||||||
per_page: 100
|
per_page: 100,
|
||||||
}
|
})
|
||||||
))
|
)
|
||||||
.filter(({ event }) => [
|
.filter(({ event }) =>
|
||||||
// These events are hand-picked from:
|
[
|
||||||
// https://docs.github.com/en/rest/using-the-rest-api/issue-event-types?apiVersion=2022-11-28
|
// These events are hand-picked from:
|
||||||
// Each of those causes a PR/issue to *not* be considered as stale anymore.
|
// https://docs.github.com/en/rest/using-the-rest-api/issue-event-types?apiVersion=2022-11-28
|
||||||
// Most of these use created_at.
|
// Each of those causes a PR/issue to *not* be considered as stale anymore.
|
||||||
'assigned',
|
// Most of these use created_at.
|
||||||
'commented', // uses updated_at, because that could be > created_at
|
'assigned',
|
||||||
'committed', // uses committer.date
|
'commented', // uses updated_at, because that could be > created_at
|
||||||
'head_ref_force_pushed',
|
'committed', // uses committer.date
|
||||||
'milestoned',
|
'head_ref_force_pushed',
|
||||||
'pinned',
|
'milestoned',
|
||||||
'ready_for_review',
|
'pinned',
|
||||||
'renamed',
|
'ready_for_review',
|
||||||
'reopened',
|
'renamed',
|
||||||
'review_dismissed',
|
'reopened',
|
||||||
'review_requested',
|
'review_dismissed',
|
||||||
'reviewed', // uses submitted_at
|
'review_requested',
|
||||||
'unlocked',
|
'reviewed', // uses submitted_at
|
||||||
'unmarked_as_duplicate',
|
'unlocked',
|
||||||
].includes(event))
|
'unmarked_as_duplicate',
|
||||||
.map(({ created_at, updated_at, committer, submitted_at }) => new Date(updated_at ?? created_at ?? submitted_at ?? committer.date))
|
].includes(event),
|
||||||
// Reverse sort by date value. The default sort() sorts by string representation, which is bad for dates.
|
)
|
||||||
.sort((a,b) => b-a)
|
.map(
|
||||||
.at(0) ?? item.created_at
|
({ created_at, updated_at, committer, submitted_at }) =>
|
||||||
|
new Date(
|
||||||
|
updated_at ?? created_at ?? submitted_at ?? committer.date,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// Reverse sort by date value. The default sort() sorts by string representation, which is bad for dates.
|
||||||
|
.sort((a, b) => b - a)
|
||||||
|
.at(0) ?? item.created_at,
|
||||||
)
|
)
|
||||||
log('latest_event_at', latest_event_at.toISOString())
|
log('latest_event_at', latest_event_at.toISOString())
|
||||||
|
|
||||||
@ -256,33 +289,37 @@ module.exports = async function({ github, context, core }) {
|
|||||||
// Create a map (Label -> Boolean) of all currently set labels.
|
// Create a map (Label -> Boolean) of all currently set labels.
|
||||||
// Each label is set to True and can be disabled later.
|
// Each label is set to True and can be disabled later.
|
||||||
const before = Object.fromEntries(
|
const before = Object.fromEntries(
|
||||||
(await github.paginate(github.rest.issues.listLabelsOnIssue, {
|
(
|
||||||
...context.repo,
|
await github.paginate(github.rest.issues.listLabelsOnIssue, {
|
||||||
issue_number
|
...context.repo,
|
||||||
}))
|
issue_number,
|
||||||
.map(({ name }) => [name, true])
|
})
|
||||||
|
).map(({ name }) => [name, true]),
|
||||||
)
|
)
|
||||||
|
|
||||||
Object.assign(itemLabels, {
|
Object.assign(itemLabels, {
|
||||||
'2.status: stale': !before['1.severity: security'] && latest_event_at < stale_at,
|
'2.status: stale':
|
||||||
|
!before['1.severity: security'] && latest_event_at < stale_at,
|
||||||
})
|
})
|
||||||
|
|
||||||
const after = Object.assign({}, before, itemLabels)
|
const after = Object.assign({}, before, itemLabels)
|
||||||
|
|
||||||
// No need for an API request, if all labels are the same.
|
// No need for an API request, if all labels are the same.
|
||||||
const hasChanges = Object.keys(after).some(name => (before[name] ?? false) != after[name])
|
const hasChanges = Object.keys(after).some(
|
||||||
if (log('Has changes', hasChanges, !hasChanges))
|
(name) => (before[name] ?? false) != after[name],
|
||||||
return;
|
)
|
||||||
|
if (log('Has changes', hasChanges, !hasChanges)) return
|
||||||
|
|
||||||
// Skipping labeling on a pull_request event, because we have no privileges.
|
// Skipping labeling on a pull_request event, because we have no privileges.
|
||||||
const labels = Object.entries(after).filter(([,value]) => value).map(([name]) => name)
|
const labels = Object.entries(after)
|
||||||
if (log('Set labels', labels, context.eventName == 'pull_request'))
|
.filter(([, value]) => value)
|
||||||
return;
|
.map(([name]) => name)
|
||||||
|
if (log('Set labels', labels, context.eventName == 'pull_request')) return
|
||||||
|
|
||||||
await github.rest.issues.setLabels({
|
await github.rest.issues.setLabels({
|
||||||
...context.repo,
|
...context.repo,
|
||||||
issue_number,
|
issue_number,
|
||||||
labels
|
labels,
|
||||||
})
|
})
|
||||||
} catch (cause) {
|
} catch (cause) {
|
||||||
throw new Error(`Labeling #${item.number} failed.`, { cause })
|
throw new Error(`Labeling #${item.number} failed.`, { cause })
|
||||||
@ -293,19 +330,23 @@ module.exports = async function({ github, context, core }) {
|
|||||||
if (context.payload.pull_request) {
|
if (context.payload.pull_request) {
|
||||||
await handle(context.payload.pull_request)
|
await handle(context.payload.pull_request)
|
||||||
} else {
|
} else {
|
||||||
const lastRun = (await github.rest.actions.listWorkflowRuns({
|
const lastRun = (
|
||||||
...context.repo,
|
await github.rest.actions.listWorkflowRuns({
|
||||||
workflow_id: 'labels.yml',
|
...context.repo,
|
||||||
event: 'schedule',
|
workflow_id: 'labels.yml',
|
||||||
status: 'success',
|
event: 'schedule',
|
||||||
exclude_pull_requests: true,
|
status: 'success',
|
||||||
per_page: 1
|
exclude_pull_requests: true,
|
||||||
})).data.workflow_runs[0]
|
per_page: 1,
|
||||||
|
})
|
||||||
|
).data.workflow_runs[0]
|
||||||
|
|
||||||
// Go back as far as the last successful run of this workflow to make sure
|
// Go back as far as the last successful run of this workflow to make sure
|
||||||
// we are not leaving anyone behind on GHA failures.
|
// we are not leaving anyone behind on GHA failures.
|
||||||
// Defaults to go back 1 hour on the first run.
|
// Defaults to go back 1 hour on the first run.
|
||||||
const cutoff = new Date(lastRun?.created_at ?? new Date().getTime() - 1 * 60 * 60 * 1000)
|
const cutoff = new Date(
|
||||||
|
lastRun?.created_at ?? new Date().getTime() - 1 * 60 * 60 * 1000,
|
||||||
|
)
|
||||||
core.info('cutoff timestamp: ' + cutoff.toISOString())
|
core.info('cutoff timestamp: ' + cutoff.toISOString())
|
||||||
|
|
||||||
const updatedItems = await github.paginate(
|
const updatedItems = await github.paginate(
|
||||||
@ -314,11 +355,11 @@ module.exports = async function({ github, context, core }) {
|
|||||||
q: [
|
q: [
|
||||||
`repo:"${context.repo.owner}/${context.repo.repo}"`,
|
`repo:"${context.repo.owner}/${context.repo.repo}"`,
|
||||||
'is:open',
|
'is:open',
|
||||||
`updated:>=${cutoff.toISOString()}`
|
`updated:>=${cutoff.toISOString()}`,
|
||||||
].join(' AND '),
|
].join(' AND '),
|
||||||
// TODO: Remove in 2025-10, when it becomes the default.
|
// TODO: Remove in 2025-10, when it becomes the default.
|
||||||
advanced_search: true
|
advanced_search: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
let cursor
|
let cursor
|
||||||
@ -327,24 +368,29 @@ module.exports = async function({ github, context, core }) {
|
|||||||
if (lastRun) {
|
if (lastRun) {
|
||||||
// The cursor to iterate through the full list of issues and pull requests
|
// The cursor to iterate through the full list of issues and pull requests
|
||||||
// is passed between jobs as an artifact.
|
// is passed between jobs as an artifact.
|
||||||
const artifact = (await github.rest.actions.listWorkflowRunArtifacts({
|
const artifact = (
|
||||||
...context.repo,
|
await github.rest.actions.listWorkflowRunArtifacts({
|
||||||
run_id: lastRun.id,
|
...context.repo,
|
||||||
name: 'pagination-cursor'
|
run_id: lastRun.id,
|
||||||
})).data.artifacts[0]
|
name: 'pagination-cursor',
|
||||||
|
})
|
||||||
|
).data.artifacts[0]
|
||||||
|
|
||||||
// If the artifact is not available, the next iteration starts at the beginning.
|
// If the artifact is not available, the next iteration starts at the beginning.
|
||||||
if (artifact) {
|
if (artifact) {
|
||||||
stats.artifacts++
|
stats.artifacts++
|
||||||
|
|
||||||
const { downloadPath } = await artifactClient.downloadArtifact(artifact.id, {
|
const { downloadPath } = await artifactClient.downloadArtifact(
|
||||||
findBy: {
|
artifact.id,
|
||||||
repositoryName: context.repo.repo,
|
{
|
||||||
repositoryOwner: context.repo.owner,
|
findBy: {
|
||||||
token: core.getInput('github-token')
|
repositoryName: context.repo.repo,
|
||||||
|
repositoryOwner: context.repo.owner,
|
||||||
|
token: core.getInput('github-token'),
|
||||||
|
},
|
||||||
|
expectedHash: artifact.digest,
|
||||||
},
|
},
|
||||||
expectedHash: artifact.digest
|
)
|
||||||
})
|
|
||||||
|
|
||||||
cursor = await readFile(path.resolve(downloadPath, 'cursor'), 'utf-8')
|
cursor = await readFile(path.resolve(downloadPath, 'cursor'), 'utf-8')
|
||||||
}
|
}
|
||||||
@ -360,7 +406,7 @@ module.exports = async function({ github, context, core }) {
|
|||||||
sort: 'created',
|
sort: 'created',
|
||||||
direction: 'asc',
|
direction: 'asc',
|
||||||
per_page: 100,
|
per_page: 100,
|
||||||
after: cursor
|
after: cursor,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Regex taken and comment adjusted from:
|
// Regex taken and comment adjusted from:
|
||||||
@ -369,7 +415,9 @@ module.exports = async function({ github, context, core }) {
|
|||||||
// <https://api.github.com/repositories/4542716/issues?page=3&per_page=100&after=Y3Vyc29yOnYyOpLPAAABl8qNnYDOvnSJxA%3D%3D>; rel="next",
|
// <https://api.github.com/repositories/4542716/issues?page=3&per_page=100&after=Y3Vyc29yOnYyOpLPAAABl8qNnYDOvnSJxA%3D%3D>; rel="next",
|
||||||
// <https://api.github.com/repositories/4542716/issues?page=1&per_page=100&before=Y3Vyc29yOnYyOpLPAAABl8xFV9DOvoouJg%3D%3D>; rel="prev"
|
// <https://api.github.com/repositories/4542716/issues?page=1&per_page=100&before=Y3Vyc29yOnYyOpLPAAABl8xFV9DOvoouJg%3D%3D>; rel="prev"
|
||||||
// Sets `next` to undefined if "next" URL is not present or `link` header is not set.
|
// Sets `next` to undefined if "next" URL is not present or `link` header is not set.
|
||||||
const next = ((allItems.headers.link ?? '').match(/<([^<>]+)>;\s*rel="next"/) ?? [])[1]
|
const next = ((allItems.headers.link ?? '').match(
|
||||||
|
/<([^<>]+)>;\s*rel="next"/,
|
||||||
|
) ?? [])[1]
|
||||||
if (next) {
|
if (next) {
|
||||||
cursor = new URL(next).searchParams.get('after')
|
cursor = new URL(next).searchParams.get('after')
|
||||||
const uploadPath = path.resolve('cursor')
|
const uploadPath = path.resolve('cursor')
|
||||||
@ -381,20 +429,29 @@ module.exports = async function({ github, context, core }) {
|
|||||||
[uploadPath],
|
[uploadPath],
|
||||||
path.resolve('.'),
|
path.resolve('.'),
|
||||||
{
|
{
|
||||||
retentionDays: 1
|
retentionDays: 1,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some items might be in both search results, so filtering out duplicates as well.
|
// Some items might be in both search results, so filtering out duplicates as well.
|
||||||
const items = [].concat(updatedItems, allItems.data)
|
const items = []
|
||||||
.filter((thisItem, idx, arr) => idx == arr.findIndex(firstItem => firstItem.number == thisItem.number))
|
.concat(updatedItems, allItems.data)
|
||||||
|
.filter(
|
||||||
|
(thisItem, idx, arr) =>
|
||||||
|
idx ==
|
||||||
|
arr.findIndex((firstItem) => firstItem.number == thisItem.number),
|
||||||
|
)
|
||||||
|
|
||||||
;(await Promise.allSettled(items.map(handle)))
|
;(await Promise.allSettled(items.map(handle)))
|
||||||
.filter(({ status }) => status == 'rejected')
|
.filter(({ status }) => status == 'rejected')
|
||||||
.map(({ reason }) => core.setFailed(`${reason.message}\n${reason.cause.stack}`))
|
.map(({ reason }) =>
|
||||||
|
core.setFailed(`${reason.message}\n${reason.cause.stack}`),
|
||||||
|
)
|
||||||
|
|
||||||
core.notice(`Processed ${stats.prs} PRs, ${stats.issues} Issues, made ${stats.requests + stats.artifacts} API requests and downloaded ${stats.artifacts} artifacts.`)
|
core.notice(
|
||||||
|
`Processed ${stats.prs} PRs, ${stats.issues} Issues, made ${stats.requests + stats.artifacts} API requests and downloaded ${stats.artifacts} artifacts.`,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
clearInterval(reservoirUpdater)
|
clearInterval(reservoirUpdater)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user