release-helper.mjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { readdir, readFile } from 'fs/promises';
  2. import { join } from 'path';
  3. import github from '@actions/github';
  4. import { exec } from './common.js';
  5. const { VERSION, ASSETS_DIR, GITHUB_TOKEN } = process.env;
  6. const tag = `v${VERSION}`;
  7. let octokit;
  8. function getOctokit() {
  9. octokit ||= github.getOctokit(GITHUB_TOKEN);
  10. return octokit;
  11. }
  12. export async function getRelease() {
  13. try {
  14. const result = await getOctokit().rest.repos.getReleaseByTag({
  15. ...github.context.repo,
  16. tag,
  17. });
  18. console.info('Found release:', tag);
  19. return result.data;
  20. } catch (err) {
  21. if (err.status !== 404) throw err;
  22. }
  23. }
  24. function listCommits() {
  25. const thisTag = exec('git describe --abbrev=0 --tags');
  26. const prevTag = exec(`git describe --abbrev=0 --tags "${thisTag}^"`);
  27. const tagRange = `${prevTag}...${thisTag}`;
  28. const list = exec(`git log --oneline --skip=1 --reverse "${tagRange}"`)
  29. .replace(/</g, '\\<')
  30. .split('\n')
  31. .map((str, i) => `${str.split(/\s/, 2)[1]}${10000 + i}\n* ${str}`)
  32. .sort()
  33. .map(str => str.split('\n')[1])
  34. .join('\n');
  35. return `${prevTag}:\n${list}\n\nCommit log: ${
  36. process.env.GITHUB_SERVER_URL || 'https://github.com'
  37. }/${
  38. process.env.GITHUB_REPOSITORY || 'violentmonkey/violentmonkey'
  39. }/compare/${tagRange}`;
  40. }
  41. function getReleaseNote() {
  42. return `${process.env.PRERELEASE === 'true' ? `\
  43. **This is a beta release of Violentmonkey (also in [WebStore](\
  44. https://chrome.google.com/webstore/detail/violentmonkey-beta/opokoaglpekkimldnlggpoagmjegichg\
  45. )), use it at your own risk.**<br>\
  46. If you already use Violentmonkey, click \`Export to zip\` in settings before installing the beta.
  47. ` : ''}Notable changes since ${listCommits()}`;
  48. }
  49. export async function createRelease() {
  50. console.info('Create release:', tag);
  51. const result = await getOctokit().rest.repos.createRelease({
  52. ...github.context.repo,
  53. tag_name: tag,
  54. name: process.env.RELEASE_NAME,
  55. body: getReleaseNote(),
  56. prerelease: process.env.PRERELEASE == 'true',
  57. });
  58. return result.data;
  59. }
  60. export async function ensureRelease() {
  61. const release = await getRelease() || await createRelease();
  62. return release;
  63. }
  64. export async function hasAsset(fileName) {
  65. const release = await getRelease();
  66. return release?.assets.some(asset => asset.name === fileName);
  67. }
  68. export async function uploadAssets() {
  69. const release = await ensureRelease();
  70. let assets = await readdir(ASSETS_DIR);
  71. assets = assets.filter(asset => release.assets.every(({ name }) => name !== asset));
  72. for (const asset of assets) {
  73. console.info(`> Upload asset: ${asset}`);
  74. await getOctokit().rest.repos.uploadReleaseAsset({
  75. ...github.context.repo,
  76. release_id: release.id,
  77. name: asset,
  78. data: await readFile(join(ASSETS_DIR, asset)),
  79. });
  80. }
  81. if (assets.length) console.info('Done');
  82. else console.info('No asset to upload');
  83. }
  84. export async function notifyReleaseStatus({ title, description, success = true }) {
  85. const { DISCORD_WEBHOOK_RELEASE } = process.env;
  86. if (!DISCORD_WEBHOOK_RELEASE) {
  87. console.warn('DISCORD_WEBHOOK_RELEASE is not available!');
  88. return;
  89. }
  90. const res = await fetch(DISCORD_WEBHOOK_RELEASE, {
  91. method: 'POST',
  92. headers: {
  93. 'Content-Type': 'application/json',
  94. },
  95. body: JSON.stringify({
  96. embeds: [
  97. {
  98. title,
  99. description,
  100. color: success ? 0x00ff00 : 0xff0000,
  101. },
  102. ],
  103. }),
  104. });
  105. if (!res.ok) console.error(res);
  106. }