diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aeb66e1..588a3be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: CI +name: Release CI on: [push] @@ -53,7 +53,7 @@ jobs: yarn run check - name: Tauri build - uses: tauri-apps/tauri-action@v0 + uses: tauri-apps/tauri-action@b9ce5d7dc68082d21d30a60103b0ab8c5ddae3a1 # enable cache even though failed continue-on-error: true env: @@ -95,6 +95,5 @@ jobs: - name: Release update.json run: yarn run release - continue-on-error: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/scripts/release.mjs b/scripts/release.mjs index 6760260..1752043 100644 --- a/scripts/release.mjs +++ b/scripts/release.mjs @@ -1,7 +1,8 @@ -import { createRequire } from "module"; +import fetch from "node-fetch"; import { getOctokit, context } from "@actions/github"; -const require = createRequire(import.meta.url); +const UPDATE_TAG_NAME = "updater"; +const UPDATE_JSON_FILE = "update.json"; /// generate update.json /// upload to update tag's release asset @@ -10,46 +11,85 @@ async function resolveRelease() { throw new Error("GITHUB_TOKEN is required"); } - const packageJson = require("../package.json"); + const options = { owner: context.repo.owner, repo: context.repo.repo }; + const github = getOctokit(process.env.GITHUB_TOKEN); + + const { data: tags } = await github.rest.repos.listTags({ + ...options, + per_page: 10, + page: 1, + }); + + // get the latest publish tag + const tag = tags.find((t) => t.name.startsWith("v")); + + console.log(tag); + console.log(); + + const { data: latestRelease } = await github.rest.repos.getReleaseByTag({ + ...options, + tag: tag.name, + }); - const { version } = packageJson; - const urlPrefix = "https://github.com/zzzgydi/clash-verge/releases/download"; const updateData = { - name: `v${version}`, - notes: `Version ${version} is available now!!!`, + name: tag.name, + notes: latestRelease.body, // use the release body directly pub_date: new Date().toISOString(), platforms: { - win64: { - signature: "", - url: `${urlPrefix}/v${version}/clash-verge_${version}_x64.msi.zip`, - }, - darwin: { - signature: "", - url: `${urlPrefix}/v${version}/clash-verge.app.tar.gz`, - }, + win64: { signature: "", url: "" }, + darwin: { signature: "", url: "" }, }, }; - console.log(`Generating Version "${version}" update.json`); + const promises = latestRelease.assets.map(async (asset) => { + const { name, browser_download_url } = asset; - const github = getOctokit(process.env.GITHUB_TOKEN); - - const { data: release } = await github.rest.repos.getReleaseByTag({ - owner: context.repo.owner, - repo: context.repo.repo, - tag: "updater", - }); - const { data: assets } = await github.rest.repos.listReleaseAssets({ - owner: context.repo.owner, - repo: context.repo.repo, - release_id: release.id, + // win64 url + if (/\.msi\.zip$/.test(name)) { + updateData.platforms.win64.url = browser_download_url; + } + // darwin url + if (/\.app\.tar\.gz$/.test(name)) { + updateData.platforms.darwin.url = browser_download_url; + } + // win64 signature + if (/\.msi\.zip\.sig$/.test(name)) { + updateData.platforms.win64.signature = await getSignature( + browser_download_url + ); + } + // darwin signature + if (/\.app\.tar\.gz\.sig$/.test(name)) { + updateData.platforms.darwin.signature = await getSignature( + browser_download_url + ); + } }); - for (let asset of assets) { - if (asset.name === "update.json") { + await Promise.allSettled(promises); + console.log(updateData); + + // maybe should test the signature as well + const { darwin, win64 } = updateData.platforms; + if (!darwin.url) { + console.log(`[Error]: failed to parse release for darwin`); + delete updateData.platforms.darwin; + } + if (!win64.url) { + console.log(`[Error]: failed to parse release for win64`); + delete updateData.platforms.win64; + } + + // update the update.json + const { data: updateRelease } = await github.rest.repos.getReleaseByTag({ + ...options, + tag: UPDATE_TAG_NAME, + }); + + for (let asset of updateRelease.assets) { + if (asset.name === UPDATE_JSON_FILE) { await github.rest.repos.deleteReleaseAsset({ - owner: context.repo.owner, - repo: context.repo.repo, + ...options, asset_id: asset.id, }); break; @@ -57,12 +97,21 @@ async function resolveRelease() { } await github.rest.repos.uploadReleaseAsset({ - owner: context.repo.owner, - repo: context.repo.repo, - release_id: release.id, - name: "update.json", + ...options, + release_id: updateRelease.id, + name: UPDATE_JSON_FILE, data: JSON.stringify(updateData, null, 2), }); } -resolveRelease(); +// get the signature file content +async function getSignature(url) { + const response = await fetch(url, { + method: "GET", + headers: { "Content-Type": "application/octet-stream" }, + }); + + return response.text(); +} + +resolveRelease().catch(console.error);