diff --git a/tools/wpdev/src/commands/bundle.ts b/tools/wpdev/src/commands/bundle.ts index dbfcfb29..d3a41686 100644 --- a/tools/wpdev/src/commands/bundle.ts +++ b/tools/wpdev/src/commands/bundle.ts @@ -234,11 +234,12 @@ export default class Bundle extends WithProjects { return task.skip(); } - const { readmeTxtFile } = bundle.tasks.updateChangelog; + const { readmeTxtFile, ...config } = bundle.tasks.updateChangelog; return updateChangelog({ changesetJsonFile: this.flags['changeset-json'], readmeTxtFile: path.join(project.dir, readmeTxtFile), + ...config, packageName: project.packageJson.name, version, }); diff --git a/tools/wpdev/src/utils/changelog.ts b/tools/wpdev/src/utils/changelog.ts index 6a0cee59..cd819bde 100644 --- a/tools/wpdev/src/utils/changelog.ts +++ b/tools/wpdev/src/utils/changelog.ts @@ -35,10 +35,35 @@ type UpdateChangelogConfig = UpdateChangelogOptions & { export function updateChangelog({ changesetJsonFile, + defaultChange, readmeTxtFile, + prevChangesPattern, packageName, version, }: UpdateChangelogConfig) { + let readmeTxt = fs.readFileSync(readmeTxtFile, 'utf8'); + + const versionStr = `= ${version} =`; + + const prevChangesRegex = + prevChangesPattern.pattern instanceof RegExp + ? prevChangesPattern.pattern + : new RegExp( + prevChangesPattern.pattern, + 'flags' in prevChangesPattern ? prevChangesPattern.flags : 's', + ); + + const prevChanges = readmeTxt.match(prevChangesRegex); + + /** + * The pattern must have a capturing group for actual changes. + * + * If the version is already in the changelog, skip. + */ + if (!prevChanges?.[1] || prevChanges[0].includes(versionStr)) { + return; + } + const data = readChangesetJson(changesetJsonFile); const changesetsMap = new Map( @@ -65,20 +90,19 @@ export function updateChangelog({ } } - let readmeTxt = fs.readFileSync(readmeTxtFile, 'utf8'); - - const versionStr = `= ${version} =`; - if (!changes.length) { - changes.push('- Maintenance release.'); + changes.push(`- ${defaultChange}`); } const changesStr = changes.join('\n'); - readmeTxt = readmeTxt.replace( - /== Changelog ==\n.*?\[See full changelog\]/s, - `== Changelog ==\n\n${versionStr}\n${changesStr}\n\n[See full changelog]`, + // Replace the captured group with the new changes + const updatedChanges = prevChanges[0].replace( + prevChanges[1], + `${versionStr}\n${changesStr}`, ); + readmeTxt = readmeTxt.replace(prevChangesRegex, updatedChanges); + fs.writeFileSync(readmeTxtFile, readmeTxt); } diff --git a/tools/wpdev/src/utils/schema.ts b/tools/wpdev/src/utils/schema.ts index 23a553e8..01c42f18 100644 --- a/tools/wpdev/src/utils/schema.ts +++ b/tools/wpdev/src/utils/schema.ts @@ -109,8 +109,29 @@ const updateRequirementsData = z.object({ target: targetFilesSchema.describe('The target files.'), }); +const pattern = z.union([ + z.object({ + pattern: z.string().describe('The text pattern to match.'), + flags: z.string().optional().describe('The regex flags.'), + }), + z.object({ + pattern: z.instanceof(RegExp).describe('The regex pattern to match.'), + }), +]); + const updateChangelogData = z.object({ readmeTxtFile: z.string().optional().default('src/readme.txt'), + defaultChange: z.string().optional().default('Maintenance release.'), + prevChangesPattern: pattern + .optional() + .default({ + pattern: + '== Changelog ==[\\n]{1,2}(.*?)[\\n]{1,2}\\[See full changelog\\]', + flags: 's', + }) + .describe( + 'The regex to match the previous changelog. The pattern must have a capturing group for actual changes.', + ), }); const updateVersionData = z.array( @@ -140,17 +161,7 @@ const updateVersionData = z.array( .object({ type: z.literal('general'), textPatterns: z - .array( - z.union([ - z.object({ - pattern: z.string(), - flags: z.string().optional(), - }), - z.object({ - pattern: z.instanceof(RegExp), - }), - ]), - ) + .array(pattern) .describe('The text patterns to match. Regex can also be used.'), }) .merge(targetFilesSchema),