updateChangelog.js 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. const fs = require("fs");
  2. const util = require("util");
  3. const exec = util.promisify(require("child_process").exec);
  4. const excalidrawDir = `${__dirname}/../src/packages/excalidraw`;
  5. const excalidrawPackage = `${excalidrawDir}/package.json`;
  6. const pkg = require(excalidrawPackage);
  7. const lastVersion = pkg.version;
  8. const existingChangeLog = fs.readFileSync(
  9. `${excalidrawDir}/CHANGELOG.md`,
  10. "utf8",
  11. );
  12. const supportedTypes = ["feat", "fix", "style", "refactor", "perf", "build"];
  13. const headerForType = {
  14. feat: "Features",
  15. fix: "Fixes",
  16. style: "Styles",
  17. refactor: " Refactor",
  18. perf: "Performance",
  19. build: "Build",
  20. };
  21. const getCommitHashForLastVersion = async () => {
  22. try {
  23. const commitMessage = `"release @excalidraw/excalidraw@${lastVersion}"`;
  24. const { stdout } = await exec(
  25. `git log --format=format:"%H" --grep=${commitMessage}`,
  26. );
  27. return stdout;
  28. } catch (error) {
  29. console.error(error);
  30. }
  31. };
  32. const getLibraryCommitsSinceLastRelease = async () => {
  33. const commitHash = await getCommitHashForLastVersion();
  34. const { stdout } = await exec(
  35. `git log --pretty=format:%s ${commitHash}...master`,
  36. );
  37. const commitsSinceLastRelease = stdout.split("\n");
  38. const commitList = {};
  39. supportedTypes.forEach((type) => {
  40. commitList[type] = [];
  41. });
  42. commitsSinceLastRelease.forEach((commit) => {
  43. const indexOfColon = commit.indexOf(":");
  44. const type = commit.slice(0, indexOfColon);
  45. if (!supportedTypes.includes(type)) {
  46. return;
  47. }
  48. const messageWithoutType = commit.slice(indexOfColon + 1).trim();
  49. const messageWithCapitalizeFirst =
  50. messageWithoutType.charAt(0).toUpperCase() + messageWithoutType.slice(1);
  51. const prNumber = commit.match(/\(#([0-9]*)\)/)[1];
  52. // return if the changelog already contains the pr number which would happen for package updates
  53. if (existingChangeLog.includes(prNumber)) {
  54. return;
  55. }
  56. const prMarkdown = `[#${prNumber}](https://github.com/excalidraw/excalidraw/pull/${prNumber})`;
  57. const messageWithPRLink = messageWithCapitalizeFirst.replace(
  58. /\(#[0-9]*\)/,
  59. prMarkdown,
  60. );
  61. commitList[type].push(messageWithPRLink);
  62. });
  63. return commitList;
  64. };
  65. const updateChangelog = async (nextVersion) => {
  66. const commitList = await getLibraryCommitsSinceLastRelease();
  67. let changelogForLibrary =
  68. "## Excalidraw Library\n\n**_This section lists the updates made to the excalidraw library and will not affect the integration._**\n\n";
  69. supportedTypes.forEach((type) => {
  70. if (commitList[type].length) {
  71. changelogForLibrary += `### ${headerForType[type]}\n\n`;
  72. const commits = commitList[type];
  73. commits.forEach((commit) => {
  74. changelogForLibrary += `- ${commit}\n\n`;
  75. });
  76. }
  77. });
  78. changelogForLibrary += "---\n";
  79. const lastVersionIndex = existingChangeLog.indexOf(`## ${lastVersion}`);
  80. let updatedContent =
  81. existingChangeLog.slice(0, lastVersionIndex) +
  82. changelogForLibrary +
  83. existingChangeLog.slice(lastVersionIndex);
  84. const currentDate = new Date().toISOString().slice(0, 10);
  85. const newVersion = `## ${nextVersion} (${currentDate})`;
  86. updatedContent = updatedContent.replace(`## Unreleased`, newVersion);
  87. fs.writeFileSync(`${excalidrawDir}/CHANGELOG.md`, updatedContent, "utf8");
  88. };
  89. module.exports = updateChangelog;