release.mjs 4.5 KB

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