Something went wrong. Try again.
Nix Packages collection & NixOS github.com/NixOS/nixpkgs
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142import fs from 'node:fs'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'
/** * Reminders to post as a non-blocking review when a pull request touches * certain matching paths. */export const reminders: { key: string; paths: RegExp[] }[] = [ { key: 'docs-styleguide', paths: [/^doc\//, /^nixos\/doc\//, /^nixos\/modules\/.*\.md$/], },]
export function matchesAny(changedPaths: string[], patterns: RegExp[]) { return changedPaths.some((changedPath) => patterns.some((pattern) => pattern.test(changedPath)), )}
function reminderBody(key: string) { return fs .readFileSync(path.join(import.meta.dirname, 'reminders', `${key}.md`), { encoding: 'utf8', }) .trim()}
export default async function postReminders({ github, context, core, repoPath, dry,}: { github: InstanceType<typeof GitHub> context: typeof actionsContext core: typeof actionsCore repoPath?: string dry: boolean}) { const pull_number = context.payload.pull_request?.number if (!pull_number) { core.info('This is not a pull request. Skipping reminders.') return }
const pr = ( await github.rest.pulls.get({ ...context.repo, pull_number, }) ).data
if (pr.user.login.endsWith('[bot]')) { core.info('This is a bot, so reminders do not apply.') return }
const { type: baseBranchType, stable } = classify( pr.base.ref.replace(/^refs\/heads\//, ''), ) const { type: headBranchType } = classify( pr.head.ref.replace(/^refs\/heads\//, ''), )
if ( baseBranchType.includes('development') && headBranchType.includes('development') && pr.base.repo.id === pr.head.repo?.id ) { // This matches, for example, PRs from NixOS:staging-next to NixOS:master, or vice versa. // We ignore them, we should only care about PRs introducing new commits. // We still want to run on PRs from, e.g., Someone:master to NixOS:master though. core.info( 'This PR is from one development branch to another. Skipping reminders.', ) return }
const details = await getCommitDetailsForPR({ core, pr, repoPath }) 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)) { await postReview({ github, context, core, dry, event: 'COMMENT', body: reminderBody(key), reviewKey: key, }) } else { await dismissReviews({ github, context, core, dry, reviewKey: key, }) } }}