-
Notifications
You must be signed in to change notification settings - Fork 0
/
generator.js
223 lines (200 loc) · 7.91 KB
/
generator.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#!/usr/bin/env node
const latest = require('./get-version');
const semver = require('semver');
const argv = require('yargs');
// get 'annotated' list of node/image and nodegit versions
function get_versions(node_versions_count, nodegit_versions_count) {
return new Promise((resolve) => {
let p_node_versions = latest.node_versions();
let p_nodegit_versions = latest.npm_pkg_versions('nodegit', true);
Promise.all([p_node_versions, p_nodegit_versions])
.then(([node_versions_all, nodegit_versions_all]) => {
// filter node versions:
// - lts
// - latest (if not lts)
// - clamp at N items
let make_image_info = (versions) => {
return versions.map((v) => {
return Object.assign(v, {
image: `${v.release}-alpine`,
tag_suffixes: [
`${v.release}-alpine`,
...(v.lts ? [`${v.lts}-alpine`] : [])
]
})
});
};
node_versions = [
{ image: 'lts-alpine', tag_suffixes: ['lts-alpine'] },
...make_image_info(
((versions, latest) => {
return latest.lts ? versions : [latest, ...versions];
})(node_versions_all.filter(v => v.lts), node_versions_all[0])
.map(v => Object.assign(v, {lts: v.lts ? v.lts.toLowerCase() : v.lts}))
.slice(0, node_versions_count)
)
];
// filter nodegit versions:
// - with prerelease
// - clamp at N items
// - add 'tag'
// - add 'prefix'es
let make_prefixes = (versions) => {
// get index for latest to add 'latest' and <empty> prefix
latest_idx = versions.findIndex(v => !v.prerelease)
// get index for a prerelease version: should only ever get one (latest next)
next_idx = versions.findIndex(v => v.prerelease)
return versions.map((v, idx) => Object.assign(v, {
tag_prefixes: [
...(idx == latest_idx ? ['', 'latest'] : []),
...(idx == next_idx ? ['next'] : []),
v.tag
]
}));
};
nodegit_versions = make_prefixes(
latest.minor_latest(nodegit_versions_all.versions, true, nodegit_versions_count)
.map((v) => {
version = semver.parse(v['~']);
v['tag'] = [version.major, version.minor].join('.');
return v;
})
.reverse()
);
resolve(
{
node: node_versions,
nodegit: nodegit_versions
}
);
});
});
}
// build list of node/image and nodegit versions to build containers for
function make_build_info(node_versions, nodegit_versions) {
// compile combination of images, nodegit versions and tags
return [
// "static" latest/current alpine + latest nodegit (explicitly use latest [alpine, current-alpine] and not latest from node versions)
{
image: 'alpine',
variants: [
{
nodegit: nodegit_versions.find(v => !semver.prerelease(v.version)).version,
tags: ['alpine', 'current-alpine', 'latest-current-alpine']
}
]
},
...node_versions.map((n) => {
return {
image: `${n.image}`,
variants: [
...nodegit_versions.map(v => (
{
nodegit: v.version,
tags: v.tag_prefixes.map(
p => [
...n.tag_suffixes.map(
s => `${p}${p?'-':''}${s}`
)
]
)
.flat()
.flat()
.sort()
}
))
]
}
})
]
}
// generate docker buildx --tag options for access by matrix values
function make_buildx_tags(builds, image_name) {
return builds.reduce((acc, image) => {
acc[image.image] = image.variants.reduce((acc, version) => {
acc[version.nodegit] = version.tags.map(t => `--tag ${image_name}:${t}`).join(' ')
return acc;
}, {})
return acc;
}, {});
}
// generate docker tags for access by matrix values
function make_tags(builds) {
return builds.reduce((acc, image) => {
acc[image.image] = image.variants.reduce((acc, version) => {
acc[version.nodegit] = version.tags;
return acc;
}, {})
return acc;
}, {});
}
// generate testing image names for access by matrix values
function make_test_images(builds, image_name) {
return builds.reduce((acc, image) => {
acc[image.image] = image.variants.reduce((acc, version) => {
acc[version.nodegit] = `${image_name}:${version.tags[0]}`
return acc;
}, {})
return acc;
}, {});
}
// generate github actions matrix
function make_matrix(node_versions, nodegit_versions) {
return {
image: node_versions.map(v => v.image),
nodegit: nodegit_versions.map(v => v.version),
include: [{ image: 'alpine', nodegit: nodegit_versions.find(v => !semver.prerelease(v.version)).version }]
}
}
// generate list of used node and nodegit versions
// > to be used for new releases detection
function make_version_info(node_versions, nodegit_versions) {
return {
node: node_versions.map(v => v.version).filter(v => v),
nodegit: nodegit_versions.map(v => v.version)
}
}
// cli
if (require.main === module) {
// build node + nodegit version selection and docker tags
argv
.usage('Usage:\n $0 <imagename> [options]')
.command('$0 <imagename> [options]', 'generate container build data',
(yargs) => {
return yargs
.alias('n', 'node-versions')
.describe('n', 'number of node versions to build containers for')
.alias('g', 'nodegit-versions')
.describe('g', 'number of nodegit versions to build containers for')
.positional('imagename', {})
.demandOption(['n', 'g'])
},
(argv) => {
const node_versions_count = argv.n;
const nodegit_versions_count = argv.g;
const image_name = argv.imagename;
get_versions(node_versions_count, nodegit_versions_count)
.then((versions) => {
let builds = make_build_info(versions.node, versions.nodegit);
let buildx_tags = make_buildx_tags(builds, image_name);
let test_images = make_test_images(builds, image_name);
let tags = make_tags(builds);
let matrix = make_matrix(versions.node, versions.nodegit);
let version_info = make_version_info(versions.node, versions.nodegit);
console.log(
JSON.stringify(
{
matrix: matrix,
buildx: buildx_tags,
tags: tags,
'test-images': test_images,
'version-info': version_info
},
null, 2
)
);
});
}
)
.argv;
}