|
| 1 | +/** |
| 2 | + * Checks if a PR should be excluded from the changelog |
| 3 | + * Used by the changelog-ci workflow to determine early if processing should continue |
| 4 | + */ |
| 5 | + |
| 6 | +import { INCLUDED_TYPES } from "./update-changelog.mjs"; |
| 7 | + |
| 8 | +/** |
| 9 | + * Labels that should exclude PRs from the changelog |
| 10 | + */ |
| 11 | +const EXCLUDED_LABELS = [ |
| 12 | + "skip-changelog", |
| 13 | + "no-changelog", |
| 14 | + "dependencies", |
| 15 | + "dependabot", |
| 16 | + "auto version bump", |
| 17 | + "release", |
| 18 | +]; |
| 19 | + |
| 20 | +/** |
| 21 | + * Commit types that should exclude PRs from the changelog |
| 22 | + */ |
| 23 | +const EXCLUDED_TYPES = [ |
| 24 | + "build", |
| 25 | + "chore", |
| 26 | + "ci", |
| 27 | + "docs", |
| 28 | + "image", |
| 29 | + "style", |
| 30 | + "test", |
| 31 | +]; |
| 32 | + |
| 33 | +/** |
| 34 | + * All valid commit types (included + excluded) |
| 35 | + * Included types are derived from TYPE_TO_SECTION |
| 36 | + */ |
| 37 | +const ALL_COMMIT_TYPES = [...INCLUDED_TYPES, ...EXCLUDED_TYPES]; |
| 38 | + |
| 39 | +/** |
| 40 | + * Regex to match conventional commit type prefix in PR titles, |
| 41 | + * including both included and excluded types. |
| 42 | + */ |
| 43 | +const typeRegex = new RegExp( |
| 44 | + `^(${ALL_COMMIT_TYPES.join("|")})(\\(.+?\\))?!?:`, |
| 45 | + "i", |
| 46 | +); |
| 47 | + |
| 48 | +/** |
| 49 | + * Checks if the PR has any labels that are in the EXCLUDED_LABELS list. |
| 50 | + * The PR should be excluded from the changelog update process if any excluded label is found. |
| 51 | + * |
| 52 | + * @param {string[]} labels - Array of PR labels |
| 53 | + * @returns {boolean} - True if any label is excluded |
| 54 | + */ |
| 55 | +function hasExcludedLabel(labels) { |
| 56 | + return labels.some((label) => |
| 57 | + EXCLUDED_LABELS.includes(label.name.toLowerCase()), |
| 58 | + ); |
| 59 | +} |
| 60 | + |
| 61 | +/** |
| 62 | + * Gets the name of the excluded label, if any. |
| 63 | + * @param {string[]} labels - Array of PR labels |
| 64 | + * @returns {string|undefined} - The name of the excluded label, if any |
| 65 | + */ |
| 66 | +function getExcludedLabel(labels) { |
| 67 | + return labels.find((label) => |
| 68 | + EXCLUDED_LABELS.includes(label.name.toLowerCase()), |
| 69 | + )?.name; |
| 70 | +} |
| 71 | + |
| 72 | +/** |
| 73 | + * Checks if a PR should be excluded from the changelog |
| 74 | + */ |
| 75 | +export default async function checkExclusions({ pr, core }) { |
| 76 | + try { |
| 77 | + const prTitle = pr.title; |
| 78 | + |
| 79 | + console.log(`🔍 Checking exclusions for PR #${pr.number}: ${prTitle}`); |
| 80 | + |
| 81 | + let shouldSkip = false; |
| 82 | + let skipReason = ""; |
| 83 | + |
| 84 | + // Check for excluded labels |
| 85 | + if (hasExcludedLabel(pr.labels)) { |
| 86 | + const excludedLabel = getExcludedLabel(pr.labels); |
| 87 | + console.log(`⏭️ PR has excluded label "${excludedLabel}". Should skip.`); |
| 88 | + shouldSkip = true; |
| 89 | + skipReason = `excluded label: ${excludedLabel}`; |
| 90 | + } |
| 91 | + // Check for conventional commit type |
| 92 | + else { |
| 93 | + // Match the PR title against the regex to extract the commit type. |
| 94 | + const match = prTitle.match(typeRegex); |
| 95 | + |
| 96 | + // If no conventional commit type is found, skip the PR. |
| 97 | + if (!match) { |
| 98 | + console.log( |
| 99 | + "⚠️ No conventional commit type found in PR title. Should skip.", |
| 100 | + ); |
| 101 | + shouldSkip = true; |
| 102 | + skipReason = "no conventional commit type"; |
| 103 | + } |
| 104 | + // If a commit type is found, check if it's in the excluded types list. |
| 105 | + else { |
| 106 | + // Extract the commit type from the matched regex and |
| 107 | + // convert it to lowercase for comparison. |
| 108 | + const type = match[1].toLowerCase(); |
| 109 | + |
| 110 | + // If the commit type is in the EXCLUDED_TYPES list, skip the PR. |
| 111 | + if (EXCLUDED_TYPES.includes(type)) { |
| 112 | + console.log( |
| 113 | + `⚠️ Conventional commit type "${type}" is excluded. Should skip.`, |
| 114 | + ); |
| 115 | + shouldSkip = true; |
| 116 | + skipReason = `excluded type: ${type}`; |
| 117 | + } |
| 118 | + // If the commit type is NOT in the EXCLUDED_TYPES list, include the PR. |
| 119 | + else { |
| 120 | + console.log(`✅ PR will be included in changelog (type: ${type})`); |
| 121 | + } |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + // Set outputs |
| 126 | + core.setOutput("should-skip", shouldSkip.toString()); |
| 127 | + // If skipping, provide the reason. |
| 128 | + if (shouldSkip) { |
| 129 | + core.setOutput("skip-reason", skipReason); |
| 130 | + } |
| 131 | + } catch (error) { |
| 132 | + console.error("❌ Error checking exclusions:", error); |
| 133 | + core.setFailed(`Failed to check exclusions: ${error.message}`); |
| 134 | + } |
| 135 | +} |
0 commit comments