mirror of
https://github.com/esphome/esphome.git
synced 2026-05-21 02:01:57 +08:00
1dfeef0265
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
97 lines
3.4 KiB
YAML
97 lines
3.4 KiB
YAML
name: PR Title Check
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, edited, synchronize, reopened]
|
|
branches-ignore:
|
|
- release
|
|
- beta
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
|
|
jobs:
|
|
check:
|
|
name: Validate PR title
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
with:
|
|
script: |
|
|
const {
|
|
detectComponents,
|
|
hasCoreChanges,
|
|
hasDashboardChanges,
|
|
hasGitHubActionsChanges,
|
|
} = require('./.github/scripts/detect-tags.js');
|
|
|
|
const title = context.payload.pull_request.title;
|
|
const author = context.payload.pull_request.user.login;
|
|
|
|
// Skip bot PRs (e.g. dependabot) - they have their own title format
|
|
if (author === 'dependabot[bot]') {
|
|
return;
|
|
}
|
|
|
|
// Block titles starting with "word:" or "word(scope):" patterns
|
|
const commitStylePattern = /^\w+(\(.*?\))?[!]?\s*:/;
|
|
if (commitStylePattern.test(title)) {
|
|
core.setFailed(
|
|
`PR title should not start with a "prefix:" style format.\n` +
|
|
`Please use the format: [component] Brief description\n`
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Get changed files to detect tags
|
|
const files = await github.paginate(github.rest.pulls.listFiles, {
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: context.issue.number,
|
|
});
|
|
const filenames = files.map(f => f.filename);
|
|
|
|
// Detect tags from changed files using shared logic
|
|
const tags = new Set();
|
|
|
|
for (const comp of detectComponents(filenames)) {
|
|
tags.add(comp);
|
|
}
|
|
if (hasCoreChanges(filenames)) tags.add('core');
|
|
if (hasDashboardChanges(filenames)) tags.add('dashboard');
|
|
if (hasGitHubActionsChanges(filenames)) tags.add('ci');
|
|
|
|
if (tags.size === 0) {
|
|
return;
|
|
}
|
|
|
|
// Check for angle brackets not wrapped in backticks.
|
|
// Astro docs MDX treats bare < as JSX component opening tags.
|
|
const stripped = title.replace(/`[^`]*`/g, '');
|
|
if (/[<>]/.test(stripped)) {
|
|
core.setFailed(
|
|
'PR title contains `<` or `>` not wrapped in backticks.\n' +
|
|
'Astro docs MDX interprets bare `<` as JSX components.\n' +
|
|
'Please wrap angle brackets with backticks, e.g.: [component] Add `<feature>` support'
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Check title starts with [tag] prefix
|
|
const bracketPattern = /^\[\w+\]/;
|
|
if (!bracketPattern.test(title)) {
|
|
const suggestion = [...tags].map(c => `[${c}]`).join('');
|
|
// Skip if the suggested prefix would be too long for a readable title
|
|
if (suggestion.length > 40) {
|
|
return;
|
|
}
|
|
core.setFailed(
|
|
`PR modifies: ${[...tags].join(', ')}\n` +
|
|
`Title must start with a [tag] prefix.\n` +
|
|
`Suggested: ${suggestion} <description>`
|
|
);
|
|
}
|