fix(release): never roll the latest updater feed back to an older tag

This commit is contained in:
Yun Chan 2026-09-28 00:53:45 +09:00
parent 524d390bc2
commit 5fef311575
3 changed files with 303 additions and 12 deletions

View file

@ -24,6 +24,7 @@ import { basename, join } from "node:path";
import process from "node:process";
import { fileURLToPath, URL } from "node:url";
import credentialHelpers from "../lib/credentials.cjs";
import { publishLatestAlias, readPublishedFeedVersion } from "./lib/latest-feed-guard.mjs";
const { forgejoAuthorization } = credentialHelpers;
@ -110,28 +111,40 @@ for (const file of sorted) {
});
}
// 2) latest feed 갱신 — 설치 자산 먼저, metadata 마지막
// 2) latest feed 갱신 — 설치 자산 먼저, metadata 마지막, 정책 파일 맨 마지막.
// 이미 더 새 버전이 latest에 게시돼 있으면(이전 태그 재실행·mirror 지연 완료)
// alias와 update-policy.json은 건드리지 않는다. 버전별 경로와 Release는 계속 게시한다.
const latestOrder = [...sorted].sort((a, b) => {
const order = Number(isUpdateMetadata(a.name)) - Number(isUpdateMetadata(b.name));
return order || a.name.localeCompare(b.name);
});
for (const file of latestOrder) {
await uploadToRegistry(file, `${packageLatestUrl}/${encodeURIComponent(safeAssetName(file.name))}`, {
replace: true,
});
const latestFeed = await publishLatestAlias({
publishingVersion: version,
files: [...latestOrder, { name: POLICY_FILENAME, path: policyPath }],
readPublishedVersion: () =>
readPublishedFeedVersion({ url: `${packageLatestUrl}/latest.yml`, fetchImpl: forgejoFetch }),
upload: (file) =>
uploadToRegistry(file, `${packageLatestUrl}/${encodeURIComponent(safeAssetName(file.name))}`, {
replace: true,
}),
});
if (!latestFeed.update) {
process.stdout.write(
`WARNING: latest feed already serves ${latestFeed.publishedVersion} (newer than ${version}) — ` +
"kept latest.yml and update-policy.json unchanged.\n",
);
}
await uploadToRegistry(
{ name: POLICY_FILENAME, path: policyPath },
`${packageLatestUrl}/${POLICY_FILENAME}`,
{ replace: true },
);
// 3) metadata 참조 검증 + 공개 URL 재검증
for (const file of latestOrder.filter((candidate) => isYamlUpdateMetadata(candidate.name))) {
validateUpdateMetadataReferences(file, latestOrder);
}
for (const name of ["latest.yml", POLICY_FILENAME]) {
await verifyPublicFile(`${packageLatestUrl}/${name}`);
if (latestFeed.update) {
for (const name of ["latest.yml", POLICY_FILENAME]) {
await verifyPublicFile(`${packageLatestUrl}/${name}`);
}
} else {
await verifyPublicFile(`${packageVersionedUrl}/latest.yml`);
}
// 4) Forgejo Release 생성/갱신 + 자산 첨부