diff --git a/.github/scripts/validate-pr-description.js b/.github/scripts/validate-pr-description.js index 5c05522..48edfdd 100644 --- a/.github/scripts/validate-pr-description.js +++ b/.github/scripts/validate-pr-description.js @@ -2,14 +2,33 @@ * Validate that a PR description has a filled Overview section. * Intended for use with actions/github-script. * + * Only bots in BOTS_EXEMPT_FROM_VALIDATION and revert 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. + * * @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 exempt from description validation (case-insensitive; `[bot]` suffix optional). */ +const BOTS_EXEMPT_FROM_VALIDATION = [ + 'alloy-cli', + 'alloy-release-orchestrator', + 'argocd-alloy', + 'jarvis-alloy', + 'release-orchestrator-ai', +]; + +function normalizeBotLogin(login) { + return (login ?? '').toLowerCase().replace(/\[bot\]$/, ''); +} + +function isExemptBotPr(pr) { + const login = normalizeBotLogin(pr?.user?.login); + return BOTS_EXEMPT_FROM_VALIDATION.includes(login); +} + function isRevertPr(pr) { const title = pr?.title ?? ''; const headRef = pr?.head?.ref ?? ''; @@ -20,6 +39,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 allowlisted bot (${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..43e0f6a 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] +# +# Allowlisted bot and revert PRs are handled in validate-pr-description.js so this +# job still passes. Other bot PRs must 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,7 @@ 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. + // Only allowlisted Alloy bots and revert PRs are exempt — see validate-pr-description.js. await script( { github, context, core }, { minOverviewLength: Number(process.env.MIN_OVERVIEW_LENGTH) }