2424 DRY_RUN : ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || 'false' }}
2525
2626jobs :
27- cleanup-by-age :
27+ cleanup :
2828 runs-on : ubuntu-latest
2929 steps :
3030 - name : Delete old container versions but keep one
31+ id : cleanup_by_age
3132 uses : actions/github-script@v8
3233 env :
3334 PACKAGE_NAME : ${{ env.PACKAGE_NAME }}
3435 RETENTION_DAYS : ${{ env.RETENTION_DAYS }}
3536 DRY_RUN : ${{ env.DRY_RUN }}
3637 with :
38+ result-encoding : string
3739 script : |
3840 const owner = context.repo.owner;
3941 const packageType = 'container';
4042 const packageName = process.env.PACKAGE_NAME;
4143 const retentionDays = Number(process.env.RETENTION_DAYS);
4244 const dryRun = process.env.DRY_RUN === 'true';
4345 const cutoff = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);
46+ const deletedVersionIds = [];
4447
4548 const paginateVersions = async () => {
4649 try {
@@ -102,7 +105,7 @@ jobs:
102105
103106 if (sortedVersions.length <= 1) {
104107 core.info('Skipping age-based cleanup because only one package version exists.');
105- return;
108+ return JSON.stringify(deletedVersionIds) ;
106109 }
107110
108111 let retainedCount = sortedVersions.length;
@@ -129,18 +132,18 @@ jobs:
129132 if (!dryRun) {
130133 await deleteVersion(scope, version.id);
131134 }
135+ deletedVersionIds.push(version.id);
132136 retainedCount -= 1;
133137 }
134138
135- cleanup-sha-only :
136- needs : cleanup-by-age
137- runs-on : ubuntu-latest
138- steps :
139+ return JSON.stringify(deletedVersionIds);
140+
139141 - name : Delete container versions that only have SHA tags
140142 uses : actions/github-script@v8
141143 env :
142144 PACKAGE_NAME : ${{ env.PACKAGE_NAME }}
143145 DRY_RUN : ${{ env.DRY_RUN }}
146+ DELETED_VERSION_IDS : ${{ steps.cleanup_by_age.outputs.result }}
144147 with :
145148 script : |
146149 const owner = context.repo.owner;
@@ -207,14 +210,23 @@ jobs:
207210 (left, right) => new Date(right.updated_at) - new Date(left.updated_at),
208211 );
209212
210- if (sortedVersions.length <= 1) {
211- core.info('Skipping SHA-only cleanup because only one package version exists.');
213+ let remainingVersions = sortedVersions;
214+
215+ if (dryRun) {
216+ const deletedVersionIds = new Set(JSON.parse(process.env.DELETED_VERSION_IDS || '[]').map(String));
217+ core.info('Dry run enabled; excluding versions marked by the age-based cleanup step from SHA-only evaluation.');
218+
219+ remainingVersions = sortedVersions.filter((version) => !deletedVersionIds.has(String(version.id)));
220+ }
221+
222+ if (remainingVersions.length <= 1) {
223+ core.info('Skipping SHA-only cleanup because only one package version would remain after age-based cleanup.');
212224 return;
213225 }
214226
215- let retainedCount = sortedVersions .length;
227+ let retainedCount = remainingVersions .length;
216228
217- for (const [index, version] of sortedVersions .entries()) {
229+ for (const [index, version] of remainingVersions .entries()) {
218230 const tags = version.metadata?.container?.tags ?? [];
219231 const isShaOnly = tags.length > 0 && tags.every(isShaTag);
220232 const isNewest = index === 0;
0 commit comments