updateChangelog.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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 badCommits = [];
  22. const getCommitHashForLastVersion = async () => {
  23. try {
  24. const commitMessage = `"release @excalidraw/excalidraw@${lastVersion}"`;
  25. const { stdout } = await exec(
  26. `git log --format=format:"%H" --grep=${commitMessage}`,
  27. );
  28. return stdout;
  29. } catch (error) {
  30. console.error(error);
  31. }
  32. };
  33. const getLibraryCommitsSinceLastRelease = async () => {
  34. const commitHash = await getCommitHashForLastVersion();
  35. const { stdout } = await exec(
  36. `git log --pretty=format:%s ${commitHash}...master`,
  37. );
  38. const commitsSinceLastRelease = stdout.split("\n");
  39. const commitList = {};
  40. supportedTypes.forEach((type) => {
  41. commitList[type] = [];
  42. });
  43. commitsSinceLastRelease.forEach((commit) => {
  44. const indexOfColon = commit.indexOf(":");
  45. const type = commit.slice(0, indexOfColon);
  46. if (!supportedTypes.includes(type)) {
  47. return;
  48. }
  49. const messageWithoutType = commit.slice(indexOfColon + 1).trim();
  50. const messageWithCapitalizeFirst =
  51. messageWithoutType.charAt(0).toUpperCase() + messageWithoutType.slice(1);
  52. const prMatch = commit.match(/\(#([0-9]*)\)/);
  53. if (prMatch) {
  54. const prNumber = prMatch[1];
  55. // return if the changelog already contains the pr number which would happen for package updates
  56. if (existingChangeLog.includes(prNumber)) {
  57. return;
  58. }
  59. const prMarkdown = `[#${prNumber}](https://github.com/excalidraw/excalidraw/pull/${prNumber})`;
  60. const messageWithPRLink = messageWithCapitalizeFirst.replace(
  61. /\(#[0-9]*\)/,
  62. prMarkdown,
  63. );
  64. commitList[type].push(messageWithPRLink);
  65. } else {
  66. badCommits.push(commit);
  67. commitList[type].push(messageWithCapitalizeFirst);
  68. }
  69. });
  70. console.info("Bad commits:", badCommits);
  71. return commitList;
  72. };
  73. const updateChangelog = async (nextVersion) => {
  74. const commitList = await getLibraryCommitsSinceLastRelease();
  75. let changelogForLibrary =
  76. "## Excalidraw Library\n\n**_This section lists the updates made to the excalidraw library and will not affect the integration._**\n\n";
  77. supportedTypes.forEach((type) => {
  78. if (commitList[type].length) {
  79. changelogForLibrary += `### ${headerForType[type]}\n\n`;
  80. const commits = commitList[type];
  81. commits.forEach((commit) => {
  82. changelogForLibrary += `- ${commit}\n\n`;
  83. });
  84. }
  85. });
  86. changelogForLibrary += "---\n";
  87. const lastVersionIndex = existingChangeLog.indexOf(`## ${lastVersion}`);
  88. let updatedContent =
  89. existingChangeLog.slice(0, lastVersionIndex) +
  90. changelogForLibrary +
  91. existingChangeLog.slice(lastVersionIndex);
  92. const currentDate = new Date().toISOString().slice(0, 10);
  93. const newVersion = `## ${nextVersion} (${currentDate})`;
  94. updatedContent = updatedContent.replace(`## Unreleased`, newVersion);
  95. fs.writeFileSync(`${excalidrawDir}/CHANGELOG.md`, updatedContent, "utf8");
  96. };
  97. module.exports = updateChangelog;