release-helper.mjs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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 `${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. const { PRERELEASE } = process.env;
  43. return PRERELEASE ? `\
  44. **This is a beta release of Violentmonkey (also in [WebStore](\
  45. https://chrome.google.com/webstore/detail/violentmonkey-beta/opokoaglpekkimldnlggpoagmjegichg\
  46. )), use it at your own risk.**<br>\
  47. If you already use Violentmonkey, click \`Export to zip\` in settings before installing the beta.
  48. Notable changes:
  49. ${listCommits()}
  50. ` : `\
  51. See <https://violentmonkey.github.io/> for more details.
  52. `;
  53. }
  54. export async function createRelease() {
  55. console.info('Create release:', tag);
  56. const result = await getOctokit().rest.repos.createRelease({
  57. ...github.context.repo,
  58. tag_name: tag,
  59. name: process.env.RELEASE_NAME,
  60. body: getReleaseNote(),
  61. prerelease: process.env.PRERELEASE == 'true',
  62. });
  63. return result.data;
  64. }
  65. export async function ensureRelease() {
  66. const release = await getRelease() || await createRelease();
  67. return release;
  68. }
  69. export async function hasAsset(fileName) {
  70. const release = await getRelease();
  71. return release?.assets.some(asset => asset.name === fileName);
  72. }
  73. export async function uploadAssets() {
  74. const release = await ensureRelease();
  75. let assets = await readdir(ASSETS_DIR);
  76. assets = assets.filter(asset => release.assets.every(({ name }) => name !== asset));
  77. for (const asset of assets) {
  78. console.info(`> Upload asset: ${asset}`);
  79. await getOctokit().rest.repos.uploadReleaseAsset({
  80. ...github.context.repo,
  81. release_id: release.id,
  82. name: asset,
  83. data: await readFile(join(ASSETS_DIR, asset)),
  84. });
  85. }
  86. if (assets.length) console.info('Done');
  87. else console.info('No asset to upload');
  88. }
  89. export async function notifyReleaseStatus({ title, description, success = true }) {
  90. const { DISCORD_WEBHOOK_RELEASE } = process.env;
  91. if (!DISCORD_WEBHOOK_RELEASE) {
  92. console.warn('DISCORD_WEBHOOK_RELEASE is not available!');
  93. return;
  94. }
  95. const res = await fetch(DISCORD_WEBHOOK_RELEASE, {
  96. method: 'POST',
  97. headers: {
  98. 'Content-Type': 'application/json',
  99. },
  100. body: JSON.stringify({
  101. embeds: [
  102. {
  103. title,
  104. description,
  105. color: success ? 0x00ff00 : 0xff0000,
  106. },
  107. ],
  108. }),
  109. });
  110. if (!res.ok) console.error(res);
  111. }