diff --git a/.github/scripts/validate-pr-description.js b/.github/scripts/validate-pr-description.js index 5c05522..ae0fdfa 100644 --- a/.github/scripts/validate-pr-description.js +++ b/.github/scripts/validate-pr-description.js @@ -2,14 +2,35 @@ * Validate that a PR description has a filled Overview section. * Intended for use with actions/github-script. * + * Bot- and revert-authored PRs are exempt; detection lives here rather than in a + * caller/workflow `if` condition so the job still completes successfully instead of + * showing as skipped, which can block merges when this check is required. + * + * Bots in BOTS_REQUIRED_TO_VALIDATE are not exempt and must still fill Overview. + * * @param {{ core: import('@actions/core'), context: import('@actions/github').Context }} params * @param {{ minOverviewLength?: number }} options */ -/** - * Revert PRs are exempt from description validation. Detection lives here rather than - * in a workflow `if` condition so the job still completes successfully instead of - * showing as skipped, which can block merges when this check is required. - */ + +/** Bot logins that must still pass description validation (case-insensitive; `[bot]` suffix optional). */ +const BOTS_REQUIRED_TO_VALIDATE = [ + 'jarvis-alloy', + 'release-orchestrator', + 'release-orchestrator-ai', + 'argocd-alloy', +]; + +function normalizeBotLogin(login) { + return (login ?? '').toLowerCase().replace(/\[bot\]$/, ''); +} + +function isExemptBotPr(pr) { + if (pr?.user?.type !== 'Bot') { + return false; + } + return !BOTS_REQUIRED_TO_VALIDATE.includes(normalizeBotLogin(pr?.user?.login)); +} + function isRevertPr(pr) { const title = pr?.title ?? ''; const headRef = pr?.head?.ref ?? ''; @@ -20,6 +41,11 @@ module.exports = async function validatePrDescription({ core, context }, options const minOverviewLength = Number(options.minOverviewLength) || 40; const pr = context.payload.pull_request; + if (isExemptBotPr(pr)) { + core.info(`Skipping PR description check for bot-authored PR (${pr?.user?.login}).`); + return; + } + if (isRevertPr(pr)) { core.info('Skipping PR description check for revert PR.'); return; diff --git a/.github/workflows/callable.pr-description-check.yaml b/.github/workflows/callable.pr-description-check.yaml index c443e37..5dd8350 100644 --- a/.github/workflows/callable.pr-description-check.yaml +++ b/.github/workflows/callable.pr-description-check.yaml @@ -11,6 +11,16 @@ on: GH_TOKEN: required: true +# The actual use of the workflow should have the following: +#on: +# pull_request: +# types: [opened, edited, reopened] +# +# Bot and revert PRs are handled in validate-pr-description.js so this job still +# passes (except allowlisted bots that must still fill Overview). Callers must +# always invoke this workflow — do not add a job-level if on the caller, or the +# required check stays pending for bot-authored PRs. + jobs: pr-description-check: name: PR description check @@ -37,7 +47,8 @@ jobs: const script = require('${{ github.workspace }}/.github/scripts/validate-pr-description.js'); // github, context, and core are injected by github-script from this // job's runtime context (the caller's workflow run / PR payload). - // Revert PRs (title "Revert ..." or revert-* branch) are exempt — see validate-pr-description.js. + // Most bot- and revert-authored PRs are exempt; allowlisted bots still + // validate — see validate-pr-description.js. await script( { github, context, core }, { minOverviewLength: Number(process.env.MIN_OVERVIEW_LENGTH) }