mirror of
https://github.com/facebook/react-native.git
synced 2026-03-31 09:02:15 +00:00
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/55382 This adds a `validatePRBody.js` script that checks pull request descriptions for required sections as part of a new `analyze-pr.yml` workflow that will replace part of the Danger-pr workflow. The validation includes: - **Description length check**: Fails if the PR body is missing or less than 50 characters - **Summary section check**: Warns if the PR lacks a "## Summary" section - **Test plan check**: Warns if the PR lacks a "## Test Plan" section - **Changelog validation**: failing if missing or invalid Key behaviors: - Phabricator-sourced PRs (detected via "Differential Revision:" in body) skip summary, test plan, and changelog validation since these are enforced differently - Validation messages use GitHub's `[!WARNING]` and `[!CAUTION]` callout syntax for clear visual feedback - The workflow fails (via `core.setFailed`) when any required check fails - Messages are passed to `postPRComment` alongside API changes for consolidated PR comments This aims to mimic relevant parts of dangerfile.js Changelog: [Internal] Reviewed By: huntie Differential Revision: D91158803 fbshipit-source-id: 2304251d18f9fc8bf9a29e536fff2d979573bd86
103 lines
2.7 KiB
JavaScript
103 lines
2.7 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const changelogRegex =
|
|
/\[\s?(ANDROID|GENERAL|IOS|INTERNAL)\s?\]\s?\[\s?(BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY)\s?\]\s*?-?\s*?(.*)/i;
|
|
|
|
const internalChangelogRegex = /\[\s?(INTERNAL)\s?\].*/gi;
|
|
|
|
function validateChangelog(commitMsg) {
|
|
if (!commitMsg.toLowerCase().includes('changelog:')) {
|
|
return 'missing';
|
|
}
|
|
const hasValidChangelog = changelogRegex.test(commitMsg);
|
|
const hasValidInternalChangelog = internalChangelogRegex.test(commitMsg);
|
|
|
|
if (hasValidChangelog || hasValidInternalChangelog) {
|
|
return 'valid';
|
|
}
|
|
|
|
return 'invalid';
|
|
}
|
|
|
|
function validatePRBody(prBody) {
|
|
const body = prBody ?? '';
|
|
const bodyLower = body.toLowerCase();
|
|
const isFromPhabricator = bodyLower.includes('differential revision:');
|
|
|
|
const messages = [];
|
|
let hasFail = false;
|
|
|
|
function addWarning(title, text) {
|
|
messages.push(`> [!WARNING]
|
|
> **${title}**
|
|
>
|
|
> ${text}`);
|
|
}
|
|
|
|
function addFail(title, text) {
|
|
hasFail = true;
|
|
messages.push(`> [!CAUTION]
|
|
> **${title}**
|
|
>
|
|
> ${text}`);
|
|
}
|
|
|
|
if (!body || body.length < 50) {
|
|
addFail('Missing Description', 'This pull request needs a description.');
|
|
} else {
|
|
const hasSummary =
|
|
bodyLower.includes('## summary') || bodyLower.includes('summary:');
|
|
if (!hasSummary && body.split('\n').length <= 2 && !isFromPhabricator) {
|
|
addWarning(
|
|
'Missing Summary',
|
|
'Please add a "## Summary" section to your PR description. This is a good place to explain the motivation for making this change.',
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!isFromPhabricator) {
|
|
const hasTestPlan = ['## test plan', 'test plan:', 'tests:', 'test:'].some(
|
|
t => bodyLower.includes(t),
|
|
);
|
|
if (!hasTestPlan) {
|
|
addWarning(
|
|
'Missing Test Plan',
|
|
'Please add a "## Test Plan" section to your PR description. A Test Plan lets us know how these changes were tested.',
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!isFromPhabricator) {
|
|
const status = validateChangelog(body);
|
|
const link =
|
|
'https://reactnative.dev/contributing/changelogs-in-pull-requests';
|
|
if (status === 'missing') {
|
|
addFail(
|
|
'Missing Changelog',
|
|
`Please add a Changelog to your PR description. See [Changelog format](${link})`,
|
|
);
|
|
} else if (status === 'invalid') {
|
|
addFail(
|
|
'Invalid Changelog Format',
|
|
`Please verify your Changelog format. See [Changelog format](${link})`,
|
|
);
|
|
}
|
|
}
|
|
|
|
return {
|
|
message: messages.join('\n\n'),
|
|
status: hasFail ? 'FAIL' : 'PASS',
|
|
};
|
|
}
|
|
|
|
module.exports = validatePRBody;
|