create-preview-links.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. const fs = require('fs');
  2. /*
  3. * This function creates a WordPress Playground blueprint JSON string for a theme.
  4. *
  5. * @param {string} themeSlug - The slug of the theme to create a blueprint for.
  6. * @param {string} branch - The branch where the theme changes are located.
  7. * @returns {string} - A JSON string representing the blueprint.
  8. */
  9. function createBlueprint(themeSlug, branch) {
  10. const template = {
  11. steps: [
  12. {
  13. step: 'login',
  14. username: 'admin',
  15. password: 'password',
  16. },
  17. {
  18. step: 'installTheme',
  19. themeZipFile: {
  20. resource: 'url',
  21. url: `https://github-proxy.com/proxy.php?action=partial&repo=Automattic/themes&directory=${themeSlug}&branch=${branch}`,
  22. },
  23. },
  24. {
  25. step: 'activateTheme',
  26. themeFolderName: themeSlug,
  27. },
  28. ],
  29. };
  30. return JSON.stringify(template);
  31. }
  32. /*
  33. * This function reads the `style.css` file of a theme and returns the theme name.
  34. *
  35. * @param {string} themeSlug - The slug of the theme to get the name of.
  36. * @returns {string} - The name of the theme as defined in the `style.css` file.
  37. */
  38. function getThemeName(themeSlug) {
  39. const styleCss = fs.readFileSync(`${themeSlug}/style.css`, 'utf8');
  40. const themeName = styleCss.match(/Theme Name:(.*)/i)[1].trim();
  41. return themeName;
  42. }
  43. /*
  44. * This function reads the `style.css` file of a theme and returns the name of the parent theme.
  45. * If the theme is not a child theme, it returns an empty string.
  46. *
  47. * @param {string} themeSlug - The slug of the theme to get the parent theme name of.
  48. * @returns {string} - The name of the parent theme as defined in the `style.css` file.
  49. */
  50. function getParentThemeName(themeSlug) {
  51. const styleCss = fs.readFileSync(`${themeSlug}/style.css`, 'utf8');
  52. const parentTheme = styleCss.match(/Template:(.*)/i);
  53. const isChildTheme = parentTheme && '' !== parentTheme[1].trim();
  54. if (!isChildTheme) {
  55. return '';
  56. }
  57. return parentTheme && '' !== parentTheme[1].trim()
  58. ? parentTheme[1].trim()
  59. : '';
  60. }
  61. /*
  62. * This function creates a comment on a PR with preview links for the changed themes.
  63. * It is used by `preview-theme` workflow.
  64. *
  65. * @param {object} github - An authenticated instance of the GitHub API.
  66. * @param {object} context - The context of the event that triggered the action.
  67. * @param {string} changedThemeSlugs - A space-separated string of theme slugs that have changed.
  68. */
  69. async function createPreviewLinksComment(github, context, changedThemeSlugs) {
  70. const changedThemes = changedThemeSlugs.split(' ');
  71. const previewLinks = changedThemes
  72. .map((themeSlug) => {
  73. const parentThemeName = getParentThemeName(themeSlug);
  74. const note = parentThemeName
  75. ? ` (child theme of **${parentThemeName}**)`
  76. : '';
  77. return `- [Preview changes for **${getThemeName(
  78. themeSlug
  79. )}**](https://playground.wordpress.net/#${createBlueprint(
  80. themeSlug,
  81. context.payload.pull_request.head.ref
  82. )})${note}`;
  83. })
  84. .join('\n');
  85. const includesChildThemes = changedThemes.some(
  86. (themeSlug) => '' !== getParentThemeName(themeSlug)
  87. );
  88. const comment = `
  89. I've detected changes to the following themes in this PR: ${changedThemes
  90. .map((themeSlug) => getThemeName(themeSlug))
  91. .join(', ')}.
  92. You can preview these changes by following the links below:
  93. ${previewLinks}
  94. I will update this comment with the latest preview links as you push more changes to this PR.
  95. **⚠️ Note:** The preview sites are created using [WordPress Playground](https://wordpress.org/playground/). You can add content, edit settings, and test the themes as you would on a real site, but please note that changes are not saved between sessions.
  96. ${
  97. includesChildThemes
  98. ? '\n**⚠️ Note:** Child themes are dependent on their parent themes. You will have to install the parent theme as well for the preview to work correctly.'
  99. : ''
  100. }
  101. `;
  102. const repoData = {
  103. owner: context.repo.owner,
  104. repo: context.repo.repo,
  105. };
  106. // Check if a comment already exists and update it if it does
  107. const { data: comments } = await github.rest.issues.listComments({
  108. issue_number: context.payload.pull_request.number,
  109. ...repoData,
  110. });
  111. const existingComment = comments.find(
  112. (comment) =>
  113. comment.user.login === 'github-actions[bot]' &&
  114. comment.body.startsWith('### Preview changes')
  115. );
  116. const commentObject = {
  117. body: `### Preview changes\n${comment}`,
  118. ...repoData,
  119. };
  120. if (existingComment) {
  121. await github.rest.issues.updateComment({
  122. comment_id: existingComment.id,
  123. ...commentObject,
  124. });
  125. return;
  126. }
  127. // Create a new comment if one doesn't exist
  128. github.rest.issues.createComment({
  129. issue_number: context.payload.pull_request.number,
  130. ...commentObject,
  131. });
  132. }
  133. module.exports = createPreviewLinksComment;