mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-10-30 16:10:36 +00:00
ci/github-script/reminders: don't remind on cherry-picks (#572900)
This commit is contained in:
4
.github/workflows/check.yml
vendored
4
.github/workflows/check.yml
vendored
@@ -154,6 +154,10 @@ jobs:
|
||||
sparse-checkout: |
|
||||
ci/github-script
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --package-lock-only=false --no-audit bottleneck
|
||||
working-directory: trusted/ci/github-script
|
||||
|
||||
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
||||
if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_CLIENT_ID
|
||||
id: app-token
|
||||
|
||||
@@ -60,6 +60,49 @@ function isIgnoredBranchError(error: unknown) {
|
||||
)
|
||||
}
|
||||
|
||||
export function cherryPickedFromSha(message: string): string | undefined {
|
||||
// Using the last line with "cherry" + hash, because a chained backport
|
||||
// can result in multiple of those lines. Only the last one counts.
|
||||
return Array.from(message.matchAll(/cherry.*([0-9a-f]{40})/g))
|
||||
.at(-1)
|
||||
?.at(1)
|
||||
}
|
||||
|
||||
interface ShaIsInDevelopmentBranchProps {
|
||||
github: InstanceType<typeof GitHub>
|
||||
context: typeof actionsContext
|
||||
sha: string
|
||||
}
|
||||
export async function shaIsInDevelopmentBranch({
|
||||
github,
|
||||
context,
|
||||
sha,
|
||||
}: ShaIsInDevelopmentBranchProps): Promise<boolean> {
|
||||
let branches: string[] | undefined
|
||||
try {
|
||||
branches = (
|
||||
await github.request<CommitBranches>({
|
||||
// This is an undocumented endpoint to fetch the branches a commit is part of.
|
||||
// There is no equivalent in neither the REST nor the GraphQL API.
|
||||
// The endpoint itself is unlikely to go away, because GitHub uses it to display
|
||||
// the list of branches on the detail page of a commit.
|
||||
url: `https://github.com/${context.repo.owner}/${context.repo.repo}/branch_commits/${sha}`,
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
},
|
||||
})
|
||||
).data.branches
|
||||
.map(({ branch }) => branch)
|
||||
.filter((branch) => classify(branch).type.includes('development'))
|
||||
} catch (e) {
|
||||
// For some unknown reason a 404 error comes back as 500 without any more details in a GitHub Actions runner.
|
||||
// Ignore these to return a regular error message below.
|
||||
if (!isIgnoredBranchError(e)) throw e
|
||||
}
|
||||
|
||||
return branches !== undefined && branches.length > 0
|
||||
}
|
||||
|
||||
export default async ({
|
||||
github,
|
||||
context,
|
||||
@@ -103,13 +146,9 @@ export default async ({
|
||||
type: 'no-cherry-pick',
|
||||
}
|
||||
|
||||
// Using the last line with "cherry" + hash, because a chained backport
|
||||
// can result in multiple of those lines. Only the last one counts.
|
||||
const cherry = Array.from(
|
||||
commit.message.matchAll(/cherry.*([0-9a-f]{40})/g),
|
||||
).at(-1)
|
||||
const original_sha = cherryPickedFromSha(commit.message)
|
||||
|
||||
if (!cherry)
|
||||
if (!original_sha)
|
||||
return {
|
||||
sha,
|
||||
commit,
|
||||
@@ -118,30 +157,13 @@ export default async ({
|
||||
type: 'no-commit-hash',
|
||||
}
|
||||
|
||||
const original_sha = cherry[1]
|
||||
|
||||
let branches: string[] | undefined
|
||||
try {
|
||||
branches = (
|
||||
await github.request<CommitBranches>({
|
||||
// This is an undocumented endpoint to fetch the branches a commit is part of.
|
||||
// There is no equivalent in neither the REST nor the GraphQL API.
|
||||
// The endpoint itself is unlikely to go away, because GitHub uses it to display
|
||||
// the list of branches on the detail page of a commit.
|
||||
url: `https://github.com/${context.repo.owner}/${context.repo.repo}/branch_commits/${original_sha}`,
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
},
|
||||
})
|
||||
).data.branches
|
||||
.map(({ branch }) => branch)
|
||||
.filter((branch) => classify(branch).type.includes('development'))
|
||||
} catch (e) {
|
||||
// For some unknown reason a 404 error comes back as 500 without any more details in a GitHub Actions runner.
|
||||
// Ignore these to return a regular error message below.
|
||||
if (!isIgnoredBranchError(e)) throw e
|
||||
}
|
||||
if (!branches?.length)
|
||||
if (
|
||||
!(await shaIsInDevelopmentBranch({
|
||||
github,
|
||||
context,
|
||||
sha: original_sha,
|
||||
}))
|
||||
)
|
||||
return {
|
||||
sha,
|
||||
commit,
|
||||
|
||||
@@ -3,6 +3,7 @@ import path from 'node:path'
|
||||
import type * as actionsCore from '@actions/core'
|
||||
import type { context as actionsContext } from '@actions/github'
|
||||
import type { GitHub } from '@actions/github/lib/utils'
|
||||
import { cherryPickedFromSha, shaIsInDevelopmentBranch } from './commits.ts'
|
||||
import { getCommitDetailsForPR } from './get-pr-commit-details.ts'
|
||||
import { dismissReviews, postReview } from './reviews.ts'
|
||||
import { classify } from './supportedBranches.ts'
|
||||
@@ -63,12 +64,12 @@ export default async function postReminders({
|
||||
return
|
||||
}
|
||||
|
||||
const baseBranchType = classify(
|
||||
const { type: baseBranchType, stable } = classify(
|
||||
pr.base.ref.replace(/^refs\/heads\//, ''),
|
||||
).type
|
||||
const headBranchType = classify(
|
||||
)
|
||||
const { type: headBranchType } = classify(
|
||||
pr.head.ref.replace(/^refs\/heads\//, ''),
|
||||
).type
|
||||
)
|
||||
|
||||
if (
|
||||
baseBranchType.includes('development') &&
|
||||
@@ -85,7 +86,36 @@ export default async function postReminders({
|
||||
}
|
||||
|
||||
const details = await getCommitDetailsForPR({ core, pr, repoPath })
|
||||
const changedPaths = details.flatMap(({ changedPaths }) => changedPaths)
|
||||
let changedPaths: string[]
|
||||
if (stable && details.length < 250) {
|
||||
const prCommits = await github.paginate(github.rest.pulls.listCommits, {
|
||||
...context.repo,
|
||||
pull_number,
|
||||
})
|
||||
changedPaths = (
|
||||
await Promise.all(
|
||||
prCommits.map(async ({ files, commit }) => {
|
||||
// Ignore cherry-picks from development branches to stable branches
|
||||
const original_sha = cherryPickedFromSha(commit.message)
|
||||
if (
|
||||
!files ||
|
||||
(original_sha &&
|
||||
(await shaIsInDevelopmentBranch({
|
||||
github,
|
||||
context,
|
||||
sha: original_sha,
|
||||
})))
|
||||
) {
|
||||
return []
|
||||
} else {
|
||||
return files?.map(({ filename }) => filename)
|
||||
}
|
||||
}),
|
||||
)
|
||||
).flat(1)
|
||||
} else {
|
||||
changedPaths = details.flatMap(({ changedPaths }) => changedPaths)
|
||||
}
|
||||
|
||||
for (const { key, paths } of reminders) {
|
||||
if (matchesAny(changedPaths, paths)) {
|
||||
|
||||
Reference in New Issue
Block a user