-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
91 lines (84 loc) · 2.9 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
const core = require('@actions/core');
const github = require('@actions/github');
async function run() {
const packageName = core.getInput('package');
const owner = github.context.repo.owner;
const filters = core
.getInput('filters')
.split('\n')
.map((f) => new RegExp(f.trim()));
const keepN = core.getInput('keep_n');
const olderThan = core.getInput('older_than');
const token = core.getInput('token');
// calculate older than time
const olderThanTime = new Date();
olderThanTime.setDate(olderThanTime.getDate() - olderThan);
// fetch all packages
const octokit = github.getOctokit(token);
const packages = await octokit.paginate(
octokit.rest.packages.getAllPackageVersionsForPackageOwnedByOrg,
{
package_type: 'container',
package_name: packageName,
org: owner,
per_page: 100,
}
);
// only handle container images
const containerImages = packages.filter(
(p) => p.metadata?.package_type === 'container'
);
// always keep images that have no tag or that do not match any filter
const globalKeep = containerImages.filter((p) => {
const tags = p.metadata?.container?.tags ?? [];
if (tags.length === 0) {
return true;
}
return tags.some((t) => !filters.some((f) => f.test(t)));
});
console.log(`Found ${containerImages.length} images of which ${globalKeep.length} do not match any filter or have no tags`);
// list images to keep per filter
const filterKeep = filters.flatMap((filter) => {
const keep = containerImages
.filter((p) => {
const tags = p.metadata?.container?.tags ?? [];
if (tags.length === 0) {
return false;
}
return tags.some((t) => filter.test(t));
})
// sort on date
.sort(
(a, b) =>
new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
)
// keep newest
.filter((p, index) => {
const isRecent =
olderThan > 0 ? new Date(p.created_at) > olderThanTime : false;
return isRecent || index < keepN;
});
const list = keep.map((p) => `${p.id}-(${p.metadata.container.tags.join('+')})`);
console.log(`Keeping [${list.join(', ')}] for filter ${filter}`);
return keep;
});
// list all images that do not have to be kept
const keepIds = [...globalKeep, ...filterKeep].map((p) => p.id);
const removeImages = containerImages.filter((p) => !keepIds.includes(p.id));
// remove the images
console.log(`Found ${removeImages.length} tagged images to remove`);
for (const r of removeImages) {
await octokit.rest.packages.deletePackageVersionForOrg({
package_type: 'container',
package_name: packageName,
org: owner,
package_version_id: r.id,
});
console.log(
`Deleted container image '${
r.name
}' (with tags: ${r.metadata.container.tags.join(', ')})`
);
}
}
run().catch((e) => core.setFailed(e.message));