diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 771af931..6b40cab4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,12 +39,6 @@ on: required: false default: false type: boolean - keep_old: - description: 'Keep superseded R2 version objects while publishing' - required: false - default: false - type: boolean - concurrency: group: windows-release-${{ inputs.tag }}-${{ inputs.mode }} cancel-in-progress: false @@ -174,7 +168,6 @@ jobs: env: RELEASE_TAG: ${{ inputs.tag }} CANDIDATE_RUN_ID: ${{ inputs.candidate_run_id }} - KEEP_OLD: ${{ inputs.keep_old }} NCURATOR_RELEASE_CANDIDATE_ROOT: ${{ github.workspace }}/release-candidates AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} @@ -210,10 +203,7 @@ jobs: - name: Publish retained candidate without rebuilding shell: bash - run: | - args=(--tag "$RELEASE_TAG" --publish-only --local-only) - if [ "$KEEP_OLD" = "true" ]; then args+=(--keep-old); fi - node scripts/release/windows.mjs "${args[@]}" + run: node scripts/release/windows.mjs --tag "$RELEASE_TAG" --publish-only --local-only - name: Release summary shell: bash diff --git a/doc/release.md b/doc/release.md index 9b70c741..f3789ec2 100644 --- a/doc/release.md +++ b/doc/release.md @@ -224,7 +224,7 @@ RELEASE_REPOSITORY=owner/repo publish 会上传候选产物和 fragment,更新对应平台的自动更新 metadata、官网 manifest 与固定下载地址,然后验证公开文件大小、sha512、文件名和 manifest。公开验证成功后才把候选状态标记为 `published`。 -默认会清理该平台的旧 artifacts 与 release-status;发布时使用 `--keep-old` 可以暂时保留旧对象。 +公开验证成功后会清理该平台更早版本的 artifacts 与 release-status,R2 只保留当前最新版本。 ### 本地保留与清理 diff --git a/scripts/release/macos.mjs b/scripts/release/macos.mjs index de7b4623..53f03358 100644 --- a/scripts/release/macos.mjs +++ b/scripts/release/macos.mjs @@ -26,7 +26,6 @@ const valueAfter = (name) => { return index >= 0 ? args[index + 1] : undefined } const releaseTag = valueAfter('--tag') || '' -const keepOld = args.includes('--keep-old') const regression = readRegressionSelection(args) const modes = [ ['prepare', args.includes('--prepare-only')], @@ -45,16 +44,13 @@ try { } if (!releaseVersion || modes.length !== 1) { throw new Error( - 'usage: node scripts/release/macos.mjs --tag (--prepare-only|--test-only|--publish-only) [--keep-old] [--domain ] [--suite ] [--group ] [--case ] [--fresh-knowledge-cache]' + 'usage: node scripts/release/macos.mjs --tag (--prepare-only|--test-only|--publish-only) [--domain ] [--suite ] [--group ] [--case ] [--fresh-knowledge-cache]' ) } const mode = modes[0][0] if (mode !== 'test' && hasRegressionSelectionArgs(args)) { throw new Error('regression selection options are only valid with --test-only') } -if (mode !== 'publish' && keepOld) { - throw new Error('--keep-old can only be combined with --publish-only') -} const run = (command, commandArgs, options = {}) => new Promise((resolve, reject) => { @@ -361,13 +357,11 @@ for (const candidate of candidates) { candidate.verified.fragmentPath ]) } -const finalizeArgs = [ +await run(process.execPath, [ path.join(ROOT, 'scripts', 'release', 'r2', 'finalize-macos.mjs'), '--tag', releaseTag -] -if (keepOld) finalizeArgs.push('--keep-old') -await run(process.execPath, finalizeArgs) +]) for (const platform of ['macos-arm64', 'macos-x64']) { await markCandidatePublished({ tag: releaseTag, platform }) } diff --git a/scripts/release/r2/finalize-macos.mjs b/scripts/release/r2/finalize-macos.mjs index aa879460..f0749121 100644 --- a/scripts/release/r2/finalize-macos.mjs +++ b/scripts/release/r2/finalize-macos.mjs @@ -15,14 +15,11 @@ const ROOT = process.cwd() const args = process.argv.slice(2) const tagIndex = args.indexOf('--tag') const releaseTag = tagIndex >= 0 ? args[tagIndex + 1] || '' : '' -const keepOld = args.includes('--keep-old') let releaseVersion = '' try { releaseVersion = parseReleaseTag(releaseTag, 'mac').version } catch { - throw new Error( - 'usage: node scripts/release/r2/finalize-macos.mjs --tag [--keep-old]' - ) + throw new Error('usage: node scripts/release/r2/finalize-macos.mjs --tag ') } const { aws, bucket, publicBaseUrl, listKeys, deleteKeys } = await createR2Client(ROOT) @@ -180,25 +177,23 @@ try { } } - if (!keepOld) { - const removable = (await listKeys('artifacts/macos/')).filter( - (key) => !key.startsWith(`artifacts/macos/${releaseTag}/`) + const removable = (await listKeys('artifacts/macos/')).filter( + (key) => !key.startsWith(`artifacts/macos/${releaseTag}/`) + ) + removable.push( + ...(await listKeys('release-status/macos/')).filter( + (key) => !key.startsWith(`release-status/macos/${releaseTag}/`) ) - removable.push( - ...(await listKeys('release-status/macos/')).filter( - (key) => !key.startsWith(`release-status/macos/${releaseTag}/`) - ) + ) + removable.push( + ...(await listKeys('artifacts/v')).filter((key) => /\/Ncurator-mac-[^/]+$/u.test(key)) + ) + removable.push( + ...(await listKeys('release-status/v')).filter((key) => + /\/macos-(?:arm64|x64)\.json$/u.test(key) ) - removable.push( - ...(await listKeys('artifacts/v')).filter((key) => /\/Ncurator-mac-[^/]+$/u.test(key)) - ) - removable.push( - ...(await listKeys('release-status/v')).filter((key) => - /\/macos-(?:arm64|x64)\.json$/u.test(key) - ) - ) - await deleteKeys(removable) - } + ) + await deleteKeys(removable) process.stdout.write( `[release] macOS ${releaseTag} is live on independent fixed download channels\n` ) diff --git a/scripts/release/r2/finalize-windows.mjs b/scripts/release/r2/finalize-windows.mjs index 349db1a4..edce202a 100644 --- a/scripts/release/r2/finalize-windows.mjs +++ b/scripts/release/r2/finalize-windows.mjs @@ -12,13 +12,10 @@ const ROOT = process.cwd() const args = process.argv.slice(2) const tagIndex = args.indexOf('--tag') const releaseTag = tagIndex >= 0 ? args[tagIndex + 1] || '' : '' -const keepOld = args.includes('--keep-old') try { parseReleaseTag(releaseTag, 'windows') } catch { - throw new Error( - 'usage: node scripts/release/r2/finalize-windows.mjs --tag [--keep-old]' - ) + throw new Error('usage: node scripts/release/r2/finalize-windows.mjs --tag ') } const { aws, bucket, publicBaseUrl, listKeys, deleteKeys } = await createR2Client(ROOT) @@ -165,23 +162,21 @@ try { throw new Error('public Windows release manifest verification failed') } - if (!keepOld) { - const removable = (await listKeys('artifacts/windows/')).filter( - (key) => !key.startsWith(`artifacts/windows/${releaseTag}/`) + const removable = (await listKeys('artifacts/windows/')).filter( + (key) => !key.startsWith(`artifacts/windows/${releaseTag}/`) + ) + removable.push( + ...(await listKeys('release-status/windows/')).filter( + (key) => key !== statusKey(releaseTag, 'windows-x64') ) - removable.push( - ...(await listKeys('release-status/windows/')).filter( - (key) => key !== statusKey(releaseTag, 'windows-x64') - ) - ) - removable.push( - ...(await listKeys('artifacts/v')).filter((key) => /\/Ncurator-windows-[^/]+$/u.test(key)) - ) - removable.push( - ...(await listKeys('release-status/v')).filter((key) => key.endsWith('/windows-x64.json')) - ) - await deleteKeys(removable) - } + ) + removable.push( + ...(await listKeys('artifacts/v')).filter((key) => /\/Ncurator-windows-[^/]+$/u.test(key)) + ) + removable.push( + ...(await listKeys('release-status/v')).filter((key) => key.endsWith('/windows-x64.json')) + ) + await deleteKeys(removable) process.stdout.write( `[release] Windows ${releaseTag} is live at ${publicBaseUrl}/${downloadKey}\n` ) diff --git a/scripts/release/r2/finalize.mjs b/scripts/release/r2/finalize.mjs index b7c447f7..cddb6035 100644 --- a/scripts/release/r2/finalize.mjs +++ b/scripts/release/r2/finalize.mjs @@ -10,9 +10,7 @@ let releaseFamily = '' try { releaseFamily = parseReleaseTag(releaseTag).family } catch { - throw new Error( - 'usage: node scripts/release/r2/finalize.mjs --tag [--keep-old]' - ) + throw new Error('usage: node scripts/release/r2/finalize.mjs --tag ') } const run = (script) => @@ -22,7 +20,6 @@ const run = (script) => '--tag', releaseTag ] - if (args.includes('--keep-old')) childArgs.push('--keep-old') const child = spawn(process.execPath, childArgs, { cwd: process.cwd(), env: process.env, diff --git a/scripts/release/shared/windows.mjs b/scripts/release/shared/windows.mjs index e73a5918..8cefc6c1 100644 --- a/scripts/release/shared/windows.mjs +++ b/scripts/release/shared/windows.mjs @@ -193,7 +193,7 @@ export const assertWindowsReleaseRouteAvailable = async ({ export const dispatchWindowsRelease = async ( root, releaseTag, - { mode, candidateRunId = '', regression = {}, keepOld = false } + { mode, candidateRunId = '', regression = {} } ) => { await loadReleaseEnvironment(root) const token = String(process.env.NCURATOR_ACTIONS_TOKEN || '').trim() @@ -219,8 +219,7 @@ export const dispatchWindowsRelease = async ( test_suite: String(regression.suite || ''), test_groups: Array.isArray(regression.groups) ? regression.groups.join(',') : '', test_case: String(regression.caseId || ''), - fresh_knowledge_cache: regression.freshKnowledgeCache ? 'true' : 'false', - keep_old: keepOld ? 'true' : 'false' + fresh_knowledge_cache: regression.freshKnowledgeCache ? 'true' : 'false' } }) } diff --git a/scripts/release/windows.mjs b/scripts/release/windows.mjs index 64044c76..e3c03896 100644 --- a/scripts/release/windows.mjs +++ b/scripts/release/windows.mjs @@ -35,7 +35,6 @@ const releaseTag = valueAfter('--tag') || '' const forceLocal = args.includes('--local-only') const forceActions = args.includes('--actions') const candidateRunId = valueAfter('--candidate-run-id') || '' -const keepOld = args.includes('--keep-old') const regression = readRegressionSelection(args) const modes = [ ['prepare', args.includes('--prepare-only')], @@ -51,7 +50,7 @@ try { } if (!releaseVersion || modes.length !== 1) { throw new Error( - 'usage: node scripts/release/windows.mjs --tag (--prepare-only|--test-only|--publish-only) [--local-only|--actions] [--candidate-run-id ] [--keep-old] [--domain ] [--suite ] [--group ] [--case ] [--fresh-knowledge-cache]' + 'usage: node scripts/release/windows.mjs --tag (--prepare-only|--test-only|--publish-only) [--local-only|--actions] [--candidate-run-id ] [--domain ] [--suite ] [--group ] [--case ] [--fresh-knowledge-cache]' ) } if (forceLocal && forceActions) throw new Error('--local-only and --actions cannot be combined') @@ -59,9 +58,6 @@ const mode = modes[0][0] if (mode !== 'test' && hasRegressionSelectionArgs(args)) { throw new Error('regression selection options are only valid with --test-only') } -if (mode !== 'publish' && keepOld) { - throw new Error('--keep-old can only be combined with --publish-only') -} if (candidateRunId && !['test', 'publish'].includes(mode)) { throw new Error('--candidate-run-id is only valid for Actions test-only or publish-only') } @@ -99,8 +95,7 @@ if (route === 'actions') { await dispatchWindowsRelease(ROOT, releaseTag, { mode, candidateRunId, - regression: regression.state, - keepOld + regression: regression.state }) process.exit(0) } @@ -319,13 +314,11 @@ await run( ], { cwd: ROOT, env: process.env } ) -const finalizeArgs = [ - path.join(ROOT, 'scripts', 'release', 'r2', 'finalize-windows.mjs'), - '--tag', - releaseTag -] -if (keepOld) finalizeArgs.push('--keep-old') -await run(process.execPath, finalizeArgs, { cwd: ROOT, env: process.env }) +await run( + process.execPath, + [path.join(ROOT, 'scripts', 'release', 'r2', 'finalize-windows.mjs'), '--tag', releaseTag], + { cwd: ROOT, env: process.env } +) await verifyPublicReleaseFragment(candidate.verified.fragment, publicBaseUrl) await verifyR2ReleaseFragment(candidate.verified.fragment, inspection.awsExecutable) await markCandidatePublished({ tag: releaseTag, platform: 'windows-x64' }) diff --git a/tests/case/settings/update/app-update-publish-config.test.ts b/tests/case/settings/update/app-update-publish-config.test.ts index 61c7c094..5ebb94b5 100644 --- a/tests/case/settings/update/app-update-publish-config.test.ts +++ b/tests/case/settings/update/app-update-publish-config.test.ts @@ -59,7 +59,7 @@ describe('app update publish config', () => { expect(workflow).toContain('- test') expect(workflow).toContain('candidate_run_id:') expect(workflow).toContain('test_domain:') - expect(workflow).toContain('keep_old:') + expect(workflow).not.toContain('keep_old:') expect(workflow).toContain('test-windows:') expect(workflow).toContain('actions/upload-artifact@v4') expect(workflow).toContain('actions/download-artifact@v4') @@ -69,7 +69,7 @@ describe('app update publish config', () => { expect(windowsRelease).toContain("route === 'actions'") expect(windowsRelease).not.toContain('--package-e2e') expect(windowsRelease).toContain('readRegressionSelection') - expect(windowsRelease).toContain("finalizeArgs.push('--keep-old')") + expect(windowsRelease).not.toContain('--keep-old') expect(windowsRelease).toContain('--prepare-only') expect(windowsRelease).toContain('--test-only') expect(windowsRelease).toContain('--publish-only') @@ -99,6 +99,8 @@ describe('app update publish config', () => { expect(windowsFinalize).not.toContain('releases/latest/macos.json') expect(macFinalize).toContain('releases/latest/macos.json') expect(macFinalize).not.toContain('releases/latest/windows.json') + expect(windowsFinalize).not.toContain('--keep-old') + expect(macFinalize).not.toContain('--keep-old') expect(tagContract).toContain('/^(mac|windows)-v') }) })