diff --git a/.github/workflow-scripts/__tests__/validatePRBody-test.js b/.github/workflow-scripts/__tests__/validatePRBody-test.js new file mode 100644 index 000000000000..146ffa82a6c7 --- /dev/null +++ b/.github/workflow-scripts/__tests__/validatePRBody-test.js @@ -0,0 +1,62 @@ +/** + * 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 validatePRBody = require('../validatePRBody'); + +function prBody(changelog) { + return `## Summary + +Explain why the change is needed. + +${changelog} + +## Test Plan + +Run the unit tests.`; +} + +describe('validatePRBody changelog headings', () => { + it.each(['## Changelog', '## Changelog:'])( + 'accepts %s with a tagged entry', + heading => { + expect( + validatePRBody(prBody(`${heading}\n\n[GENERAL] [FIXED] - Fix a bug`)), + ).toEqual({message: '', status: 'PASS'}); + }, + ); + + it('accepts a heading without a colon with CRLF line endings', () => { + const body = prBody('## Changelog\n\n[INTERNAL] [FIXED] - Fix CI'); + expect(validatePRBody(body.replace(/\n/g, '\r\n'))).toEqual({ + message: '', + status: 'PASS', + }); + }); + + it('accepts consecutive internal changelogs consistently', () => { + const body = prBody('## Changelog\n\n[INTERNAL] [FIXED] - Fix CI'); + expect(validatePRBody(body).status).toBe('PASS'); + expect(validatePRBody(body).status).toBe('PASS'); + }); + + it('still requires a tagged entry', () => { + expect(validatePRBody(prBody('## Changelog\n\nNo tags')).message).toContain( + 'Invalid Changelog Format', + ); + }); + + it('does not treat an unmarked Changelog line as a heading', () => { + expect( + validatePRBody(prBody('Changelog\n\n[GENERAL] [FIXED] - Fix a bug')) + .message, + ).toContain('Missing Changelog'); + }); +}); diff --git a/.github/workflow-scripts/validatePRBody.js b/.github/workflow-scripts/validatePRBody.js index 5757b38137a4..e296bcb38788 100644 --- a/.github/workflow-scripts/validatePRBody.js +++ b/.github/workflow-scripts/validatePRBody.js @@ -12,14 +12,15 @@ 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; +const internalChangelogRegex = /\[\s?(INTERNAL)\s?\].*/i; -function validateChangelog(commitMsg) { - if (!commitMsg.toLowerCase().includes('changelog:')) { +function validateChangelog(prBody) { + const hasChangelogHeading = /^##[ \t]+changelog[ \t]*\r?$/im.test(prBody); + if (!prBody.toLowerCase().includes('changelog:') && !hasChangelogHeading) { return 'missing'; } - const hasValidChangelog = changelogRegex.test(commitMsg); - const hasValidInternalChangelog = internalChangelogRegex.test(commitMsg); + const hasValidChangelog = changelogRegex.test(prBody); + const hasValidInternalChangelog = internalChangelogRegex.test(prBody); if (hasValidChangelog || hasValidInternalChangelog) { return 'valid';