release.mjs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import fetch from "node-fetch";
  2. import { getOctokit, context } from "@actions/github";
  3. const UPDATE_TAG_NAME = "updater";
  4. const UPDATE_JSON_FILE = "update.json";
  5. const UPDATE_JSON_PROXY = "update-proxy.json";
  6. /// generate update.json
  7. /// upload to update tag's release asset
  8. async function resolveRelease() {
  9. if (process.env.GITHUB_TOKEN === undefined) {
  10. throw new Error("GITHUB_TOKEN is required");
  11. }
  12. const options = { owner: context.repo.owner, repo: context.repo.repo };
  13. const github = getOctokit(process.env.GITHUB_TOKEN);
  14. const { data: tags } = await github.rest.repos.listTags({
  15. ...options,
  16. per_page: 10,
  17. page: 1,
  18. });
  19. // get the latest publish tag
  20. const tag = tags.find((t) => t.name.startsWith("v"));
  21. console.log(tag);
  22. console.log();
  23. const { data: latestRelease } = await github.rest.repos.getReleaseByTag({
  24. ...options,
  25. tag: tag.name,
  26. });
  27. const updateData = {
  28. name: tag.name,
  29. notes: latestRelease.body, // use the release body directly
  30. pub_date: new Date().toISOString(),
  31. platforms: {
  32. win64: { signature: "", url: "" },
  33. linux: { signature: "", url: "" },
  34. darwin: { signature: "", url: "" },
  35. },
  36. };
  37. const promises = latestRelease.assets.map(async (asset) => {
  38. const { name, browser_download_url } = asset;
  39. // win64 url
  40. if (/\.msi\.zip$/.test(name)) {
  41. updateData.platforms.win64.url = browser_download_url;
  42. }
  43. // win64 signature
  44. if (/\.msi\.zip\.sig$/.test(name)) {
  45. updateData.platforms.win64.signature = await getSignature(
  46. browser_download_url
  47. );
  48. }
  49. // darwin url
  50. if (/\.app\.tar\.gz$/.test(name)) {
  51. updateData.platforms.darwin.url = browser_download_url;
  52. }
  53. // darwin signature
  54. if (/\.app\.tar\.gz\.sig$/.test(name)) {
  55. updateData.platforms.darwin.signature = await getSignature(
  56. browser_download_url
  57. );
  58. }
  59. // linux url
  60. if (/\.AppImage\.tar\.gz$/.test(name)) {
  61. updateData.platforms.linux.url = browser_download_url;
  62. }
  63. // linux signature
  64. if (/\.AppImage\.tar\.gz\.sig$/.test(name)) {
  65. updateData.platforms.linux.signature = await getSignature(
  66. browser_download_url
  67. );
  68. }
  69. });
  70. await Promise.allSettled(promises);
  71. console.log(updateData);
  72. // maybe should test the signature as well
  73. const { darwin, win64, linux } = updateData.platforms;
  74. if (!darwin.url) {
  75. console.log(`[Error]: failed to parse release for darwin`);
  76. delete updateData.platforms.darwin;
  77. }
  78. if (!win64.url) {
  79. console.log(`[Error]: failed to parse release for win64`);
  80. delete updateData.platforms.win64;
  81. }
  82. if (!linux.url) {
  83. console.log(`[Error]: failed to parse release for linux`);
  84. delete updateData.platforms.linux;
  85. }
  86. // 生成一个代理github的更新文件
  87. // 使用 https://hub.fastgit.xyz/ 做github资源的加速
  88. const updateDataNew = JSON.parse(JSON.stringify(updateData));
  89. Object.keys(updateDataNew.platforms).forEach((key) => {
  90. if (updateDataNew.platforms[key]) {
  91. updateDataNew.platforms[key].url = updateDataNew.platforms[
  92. key
  93. ].url.replace("https://github.com/", "https://hub.fastgit.xyz/");
  94. } else {
  95. console.log(`[Error]: updateDataNew.platforms.${key} is null`);
  96. }
  97. });
  98. // update the update.json
  99. const { data: updateRelease } = await github.rest.repos.getReleaseByTag({
  100. ...options,
  101. tag: UPDATE_TAG_NAME,
  102. });
  103. // delete the old assets
  104. for (let asset of updateRelease.assets) {
  105. if (asset.name === UPDATE_JSON_FILE) {
  106. await github.rest.repos.deleteReleaseAsset({
  107. ...options,
  108. asset_id: asset.id,
  109. });
  110. }
  111. if (asset.name === UPDATE_JSON_PROXY) {
  112. await github.rest.repos
  113. .deleteReleaseAsset({ ...options, asset_id: asset.id })
  114. .catch(console.error); // do not break the pipeline
  115. }
  116. }
  117. // upload assets
  118. await github.rest.repos.uploadReleaseAsset({
  119. ...options,
  120. release_id: updateRelease.id,
  121. name: UPDATE_JSON_FILE,
  122. data: JSON.stringify(updateData, null, 2),
  123. });
  124. await github.rest.repos.uploadReleaseAsset({
  125. ...options,
  126. release_id: updateRelease.id,
  127. name: UPDATE_JSON_PROXY,
  128. data: JSON.stringify(updateDataNew, null, 2),
  129. });
  130. }
  131. // get the signature file content
  132. async function getSignature(url) {
  133. const response = await fetch(url, {
  134. method: "GET",
  135. headers: { "Content-Type": "application/octet-stream" },
  136. });
  137. return response.text();
  138. }
  139. resolveRelease().catch(console.error);