chore: updater autobuild (#5295)
* chore(updater): configure autobuild channel and refresh suffixes * feat(updater): add channel-aware updater and UI integration * feat(updater): support channel-specific updater command * feat(updater): enable downgrade-aware updates for autobuild channel * fix(updater): tighten prerelease downgrade gating and forward target * style: prettier
This commit is contained in:
committed by
Slinetrac
Unverified
parent
48a19f99e2
commit
5ae74ae439
@@ -1,5 +1,8 @@
|
||||
import fetch from "node-fetch";
|
||||
import process from "node:process";
|
||||
|
||||
import { getOctokit, context } from "@actions/github";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
import { resolveUpdateLog, resolveUpdateLogDefault } from "./updatelog.mjs";
|
||||
|
||||
// Add stable update JSON filenames
|
||||
@@ -10,6 +13,11 @@ const UPDATE_JSON_PROXY = "update-proxy.json";
|
||||
const ALPHA_TAG_NAME = "updater-alpha";
|
||||
const ALPHA_UPDATE_JSON_FILE = "update.json";
|
||||
const ALPHA_UPDATE_JSON_PROXY = "update-proxy.json";
|
||||
// Add autobuild update JSON filenames
|
||||
const AUTOBUILD_SOURCE_TAG_NAME = "autobuild";
|
||||
const AUTOBUILD_TAG_NAME = "updater-autobuild";
|
||||
const AUTOBUILD_UPDATE_JSON_FILE = "update.json";
|
||||
const AUTOBUILD_UPDATE_JSON_PROXY = "update-proxy.json";
|
||||
|
||||
/// generate update.json
|
||||
/// upload to update tag's release asset
|
||||
@@ -48,12 +56,12 @@ async function resolveUpdater() {
|
||||
|
||||
// More flexible tag detection with regex patterns
|
||||
const stableTagRegex = /^v\d+\.\d+\.\d+$/; // Matches vX.Y.Z format
|
||||
// const preReleaseRegex = /^v\d+\.\d+\.\d+-(alpha|beta|rc|pre)/i; // Matches vX.Y.Z-alpha/beta/rc format
|
||||
const preReleaseRegex = /^(alpha|beta|rc|pre)$/i; // Matches exact alpha/beta/rc/pre tags
|
||||
|
||||
// Get the latest stable tag and pre-release tag
|
||||
// Get tags for known channels
|
||||
const stableTag = tags.find((t) => stableTagRegex.test(t.name));
|
||||
const preReleaseTag = tags.find((t) => preReleaseRegex.test(t.name));
|
||||
const autobuildTag = tags.find((t) => t.name === AUTOBUILD_SOURCE_TAG_NAME);
|
||||
|
||||
console.log("All tags:", tags.map((t) => t.name).join(", "));
|
||||
console.log("Stable tag:", stableTag ? stableTag.name : "None found");
|
||||
@@ -61,32 +69,79 @@ async function resolveUpdater() {
|
||||
"Pre-release tag:",
|
||||
preReleaseTag ? preReleaseTag.name : "None found",
|
||||
);
|
||||
console.log(
|
||||
"Autobuild tag:",
|
||||
autobuildTag ? autobuildTag.name : "None found",
|
||||
);
|
||||
console.log();
|
||||
|
||||
// Process stable release
|
||||
if (stableTag) {
|
||||
await processRelease(github, options, stableTag, false);
|
||||
}
|
||||
const channels = [
|
||||
{
|
||||
name: "stable",
|
||||
tagName: stableTag?.name,
|
||||
updateReleaseTag: UPDATE_TAG_NAME,
|
||||
jsonFile: UPDATE_JSON_FILE,
|
||||
proxyFile: UPDATE_JSON_PROXY,
|
||||
prerelease: false,
|
||||
},
|
||||
{
|
||||
name: "alpha",
|
||||
tagName: preReleaseTag?.name,
|
||||
updateReleaseTag: ALPHA_TAG_NAME,
|
||||
jsonFile: ALPHA_UPDATE_JSON_FILE,
|
||||
proxyFile: ALPHA_UPDATE_JSON_PROXY,
|
||||
prerelease: true,
|
||||
},
|
||||
{
|
||||
name: "autobuild",
|
||||
tagName: autobuildTag?.name ?? AUTOBUILD_SOURCE_TAG_NAME,
|
||||
updateReleaseTag: AUTOBUILD_TAG_NAME,
|
||||
jsonFile: AUTOBUILD_UPDATE_JSON_FILE,
|
||||
proxyFile: AUTOBUILD_UPDATE_JSON_PROXY,
|
||||
prerelease: true,
|
||||
},
|
||||
];
|
||||
|
||||
// Process pre-release if found
|
||||
if (preReleaseTag) {
|
||||
await processRelease(github, options, preReleaseTag, true);
|
||||
for (const channel of channels) {
|
||||
if (!channel.tagName) {
|
||||
console.log(`[${channel.name}] tag not found, skipping...`);
|
||||
continue;
|
||||
}
|
||||
await processRelease(github, options, channel);
|
||||
}
|
||||
}
|
||||
|
||||
// Process a release (stable or alpha) and generate update files
|
||||
async function processRelease(github, options, tag, isAlpha) {
|
||||
if (!tag) return;
|
||||
// Process a release and generate update files for the specified channel
|
||||
async function processRelease(github, options, channelConfig) {
|
||||
if (!channelConfig) return;
|
||||
|
||||
const {
|
||||
tagName,
|
||||
name: channelName,
|
||||
updateReleaseTag,
|
||||
jsonFile,
|
||||
proxyFile,
|
||||
prerelease,
|
||||
} = channelConfig;
|
||||
|
||||
const channelLabel =
|
||||
channelName.charAt(0).toUpperCase() + channelName.slice(1);
|
||||
|
||||
try {
|
||||
const { data: release } = await github.rest.repos.getReleaseByTag({
|
||||
...options,
|
||||
tag: tag.name,
|
||||
tag: tagName,
|
||||
});
|
||||
|
||||
const releaseTagName = release.tag_name ?? tagName;
|
||||
|
||||
console.log(
|
||||
`[${channelName}] Preparing update metadata from release "${releaseTagName}"`,
|
||||
);
|
||||
|
||||
const updateData = {
|
||||
name: tag.name,
|
||||
notes: await resolveUpdateLog(tag.name).catch(() =>
|
||||
name: releaseTagName,
|
||||
notes: await resolveUpdateLog(releaseTagName).catch(() =>
|
||||
resolveUpdateLogDefault().catch(() => "No changelog available"),
|
||||
),
|
||||
pub_date: new Date().toISOString(),
|
||||
@@ -186,13 +241,15 @@ async function processRelease(github, options, tag, isAlpha) {
|
||||
});
|
||||
|
||||
await Promise.allSettled(promises);
|
||||
console.log(updateData);
|
||||
console.log(`[${channelName}] Update data snapshot:`, updateData);
|
||||
|
||||
// maybe should test the signature as well
|
||||
// delete the null field
|
||||
Object.entries(updateData.platforms).forEach(([key, value]) => {
|
||||
if (!value.url) {
|
||||
console.log(`[Error]: failed to parse release for "${key}"`);
|
||||
console.log(
|
||||
`[${channelName}] [Error]: failed to parse release for "${key}"`,
|
||||
);
|
||||
delete updateData.platforms[key];
|
||||
}
|
||||
});
|
||||
@@ -205,15 +262,14 @@ async function processRelease(github, options, tag, isAlpha) {
|
||||
updateDataNew.platforms[key].url =
|
||||
"https://download.clashverge.dev/" + value.url;
|
||||
} else {
|
||||
console.log(`[Error]: updateDataNew.platforms.${key} is null`);
|
||||
console.log(
|
||||
`[${channelName}] [Error]: updateDataNew.platforms.${key} is null`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Get the appropriate updater release based on isAlpha flag
|
||||
const releaseTag = isAlpha ? ALPHA_TAG_NAME : UPDATE_TAG_NAME;
|
||||
console.log(
|
||||
`Processing ${isAlpha ? "alpha" : "stable"} release:`,
|
||||
releaseTag,
|
||||
`[${channelName}] Processing update release target "${updateReleaseTag}"`,
|
||||
);
|
||||
|
||||
try {
|
||||
@@ -223,30 +279,28 @@ async function processRelease(github, options, tag, isAlpha) {
|
||||
// Try to get the existing release
|
||||
const response = await github.rest.repos.getReleaseByTag({
|
||||
...options,
|
||||
tag: releaseTag,
|
||||
tag: updateReleaseTag,
|
||||
});
|
||||
updateRelease = response.data;
|
||||
console.log(
|
||||
`Found existing ${releaseTag} release with ID: ${updateRelease.id}`,
|
||||
`[${channelName}] Found existing ${updateReleaseTag} release with ID: ${updateRelease.id}`,
|
||||
);
|
||||
} catch (error) {
|
||||
// If release doesn't exist, create it
|
||||
if (error.status === 404) {
|
||||
console.log(
|
||||
`Release with tag ${releaseTag} not found, creating new release...`,
|
||||
`[${channelName}] Release with tag ${updateReleaseTag} not found, creating new release...`,
|
||||
);
|
||||
const createResponse = await github.rest.repos.createRelease({
|
||||
...options,
|
||||
tag_name: releaseTag,
|
||||
name: isAlpha
|
||||
? "Auto-update Alpha Channel"
|
||||
: "Auto-update Stable Channel",
|
||||
body: `This release contains the update information for ${isAlpha ? "alpha" : "stable"} channel.`,
|
||||
prerelease: isAlpha,
|
||||
tag_name: updateReleaseTag,
|
||||
name: `Auto-update ${channelLabel} Channel`,
|
||||
body: `This release contains the update information for the ${channelName} channel.`,
|
||||
prerelease,
|
||||
});
|
||||
updateRelease = createResponse.data;
|
||||
console.log(
|
||||
`Created new ${releaseTag} release with ID: ${updateRelease.id}`,
|
||||
`[${channelName}] Created new ${updateReleaseTag} release with ID: ${updateRelease.id}`,
|
||||
);
|
||||
} else {
|
||||
// If it's another error, throw it
|
||||
@@ -255,11 +309,8 @@ async function processRelease(github, options, tag, isAlpha) {
|
||||
}
|
||||
|
||||
// File names based on release type
|
||||
const jsonFile = isAlpha ? ALPHA_UPDATE_JSON_FILE : UPDATE_JSON_FILE;
|
||||
const proxyFile = isAlpha ? ALPHA_UPDATE_JSON_PROXY : UPDATE_JSON_PROXY;
|
||||
|
||||
// Delete existing assets with these names
|
||||
for (let asset of updateRelease.assets) {
|
||||
for (const asset of updateRelease.assets) {
|
||||
if (asset.name === jsonFile) {
|
||||
await github.rest.repos.deleteReleaseAsset({
|
||||
...options,
|
||||
@@ -270,7 +321,12 @@ async function processRelease(github, options, tag, isAlpha) {
|
||||
if (asset.name === proxyFile) {
|
||||
await github.rest.repos
|
||||
.deleteReleaseAsset({ ...options, asset_id: asset.id })
|
||||
.catch(console.error); // do not break the pipeline
|
||||
.catch((deleteError) =>
|
||||
console.error(
|
||||
`[${channelName}] Failed to delete existing proxy asset:`,
|
||||
deleteError.message,
|
||||
),
|
||||
); // do not break the pipeline
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,20 +346,22 @@ async function processRelease(github, options, tag, isAlpha) {
|
||||
});
|
||||
|
||||
console.log(
|
||||
`Successfully uploaded ${isAlpha ? "alpha" : "stable"} update files to ${releaseTag}`,
|
||||
`[${channelName}] Successfully uploaded update files to ${updateReleaseTag}`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Failed to process ${isAlpha ? "alpha" : "stable"} release:`,
|
||||
`[${channelName}] Failed to process update release:`,
|
||||
error.message,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.status === 404) {
|
||||
console.log(`Release not found for tag: ${tag.name}, skipping...`);
|
||||
console.log(
|
||||
`[${channelName}] Release not found for tag: ${tagName}, skipping...`,
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
`Failed to get release for tag: ${tag.name}`,
|
||||
`[${channelName}] Failed to get release for tag: ${tagName}`,
|
||||
error.message,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user