@@ -236,6 +236,8 @@ jobs:
236236 permissions:
237237 contents: write
238238 packages: write
239+ outputs:
240+ set_latest: ${{ steps.promote_oci.outputs.set_latest }}
239241 steps:
240242 - name: Validate release preconditions
241243 env:
@@ -316,6 +318,7 @@ jobs:
316318 password: ${{ secrets.GITHUB_TOKEN }}
317319
318320 - name: Promote OCI image tags
321+ id: promote_oci
319322 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
320323 env:
321324 RC_VERSION: ${{ needs.prepare.outputs.new_version }}
@@ -328,17 +331,21 @@ jobs:
328331
329332 if (!rc || !final) { core.setFailed('Missing RC_VERSION or FINAL_VERSION'); return; }
330333
331- // Get highest existing final version from GHCR
334+ // Get highest existing final version from GitHub releases (not OCI)
332335 let highest = '';
333336 try {
334- const { data } = await github.rest.packages.getAllPackageVersionsForPackageOwnedByOrg({
335- package_type: 'container', package_name: 'cli', org: context.repo.owner
337+ const releases = await github.rest.repos.listReleases({
338+ owner: context.repo.owner,
339+ repo: context.repo.repo,
340+ per_page: 100,
336341 });
337- highest = data.flatMap(v => v.metadata?.container?.tags || [])
342+ highest = releases.data
343+ .filter(r => !r.prerelease && r.tag_name.startsWith('cli/v'))
344+ .map(r => r.tag_name.replace('cli/', ''))
338345 .filter(t => /^v\d+\.\d+\.\d+$/.test(t))
339346 .sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))
340347 .pop() || '';
341- } catch (e) { core.warning(`Could not fetch existing tags : ${e.message}`); }
348+ } catch (e) { core.warning(`Could not fetch existing releases : ${e.message}`); }
342349
343350 // Set :latest only if this version is >= the current highest
344351 const setLatest = !highest || final.localeCompare(highest, undefined, { numeric: true }) >= 0;
@@ -347,10 +354,14 @@ jobs:
347354 execSync(`oras tag "${repo}:${rc}" ${tags}`, { stdio: 'inherit' });
348355 core.info(setLatest ? `✅ Tagged :${final} and :latest` : `⚠️ Tagged :${final} (${highest} is higher)`);
349356
357+ // Export setLatest for use in release_final job
358+ core.setOutput('set_latest', setLatest ? 'true' : 'false');
359+
350360 await core.summary.addHeading('OCI Image Promotion').addTable([
351361 [{data: 'Field', header: true}, {data: 'Value', header: true}],
352362 ['Source', `${repo}:${rc}`],
353363 ['Final', `${repo}:${final}`],
364+ ['Highest existing', highest || '(none)'],
354365 ['Latest', setLatest ? 'Yes' : `No (${highest} > ${final})`],
355366 ]).write();
356367
@@ -395,6 +406,7 @@ jobs:
395406 TARGET_REPO: ${{ env.REGISTRY }}/${{ github.repository_owner }}/cli
396407 BINARIES_DIR: ${{ runner.temp }}/binaries
397408 NOTES_FILE: ${{ runner.temp }}/CHANGELOG.md
409+ SET_LATEST: ${{ needs.promote_final.outputs.set_latest }}
398410 with:
399411 github-token: ${{ secrets.GITHUB_TOKEN }}
400412 script: |
@@ -407,6 +419,7 @@ jobs:
407419 const targetRepo = process.env.TARGET_REPO;
408420 const binariesDir = process.env.BINARIES_DIR;
409421 const notesFile = process.env.NOTES_FILE;
422+ const setLatest = process.env.SET_LATEST === 'true';
410423
411424 let notes = fs.existsSync(notesFile)
412425 ? fs.readFileSync(notesFile, 'utf8').trim()
@@ -421,15 +434,22 @@ jobs:
421434 `[${finalTag}] - promoted from [${rcTag}] on ${today}`
422435 );
423436
437+ // Use make_latest to control whether this release is marked as "Latest"
438+ // Only set as latest if this version >= highest existing final version
424439 const created = await github.rest.repos.createRelease({
425440 owner: context.repo.owner,
426441 repo: context.repo.repo,
427442 tag_name: finalTag,
428443 name: `CLI ${finalVersion}`,
429444 body: notes,
430445 prerelease: false,
446+ make_latest: setLatest ? 'true' : 'false',
431447 });
432448
449+ core.info(setLatest
450+ ? `✅ Release marked as Latest`
451+ : `⚠️ Release NOT marked as Latest (older patch release)`);
452+
433453 // Upload binaries from RC release (same binaries that were tested)
434454 const binaries = fs.readdirSync(binariesDir).filter(f => f.startsWith('ocm-'));
435455 for (const file of binaries) {
@@ -448,13 +468,18 @@ jobs:
448468 }
449469
450470 const releaseUrl = created.data.html_url;
471+ const ociTags = setLatest
472+ ? `${targetRepo}:${finalVersion}, ${targetRepo}:latest`
473+ : `${targetRepo}:${finalVersion}`;
474+
451475 await core.summary
452476 .addHeading('Final Release Published')
453477 .addTable([
454478 [{data: 'Field', header: true}, {data: 'Value', header: true}],
455479 ['Final Tag', finalTag],
456480 ['Promoted from RC', rcTag],
457- ['OCI Tags', `${targetRepo}:${finalVersion}, ${targetRepo}:latest`],
481+ ['OCI Tags', ociTags],
482+ ['GitHub Latest', setLatest ? 'Yes' : 'No (older version)'],
458483 ])
459484 .addEOL()
460485 .addLink(releaseUrl, releaseUrl)
0 commit comments