@kaitranntt/ccs 7.79.1-dev.35 → 7.79.1-dev.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const { execFileSync } = require('node:child_process');
|
|
6
|
+
|
|
7
|
+
function parseStableVersion(value) {
|
|
8
|
+
const match = String(value || '').match(/^v?([0-9]+)\.([0-9]+)\.([0-9]+)$/);
|
|
9
|
+
if (!match) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
major: Number(match[1]),
|
|
14
|
+
minor: Number(match[2]),
|
|
15
|
+
patch: Number(match[3]),
|
|
16
|
+
raw: `v${Number(match[1])}.${Number(match[2])}.${Number(match[3])}`,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function compareVersions(left, right) {
|
|
21
|
+
for (const key of ['major', 'minor', 'patch']) {
|
|
22
|
+
if (left[key] !== right[key]) {
|
|
23
|
+
return left[key] - right[key];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function stableVersionKey(version) {
|
|
30
|
+
return `${version.major}.${version.minor}.${version.patch}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function parseArgs(argv) {
|
|
34
|
+
const args = {};
|
|
35
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
36
|
+
const arg = argv[i];
|
|
37
|
+
if (!arg.startsWith('--')) {
|
|
38
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
39
|
+
}
|
|
40
|
+
const key = arg.slice(2);
|
|
41
|
+
if (key === 'tags-stdin') {
|
|
42
|
+
args.tagsStdin = true;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const value = argv[i + 1];
|
|
46
|
+
if (!value || value.startsWith('--')) {
|
|
47
|
+
throw new Error(`Missing value for --${key}`);
|
|
48
|
+
}
|
|
49
|
+
args[key] = value;
|
|
50
|
+
i += 1;
|
|
51
|
+
}
|
|
52
|
+
return args;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function readStableTagsFromGit() {
|
|
56
|
+
const output = execFileSync('git', ['tag', '--list', 'v*'], {
|
|
57
|
+
encoding: 'utf8',
|
|
58
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
59
|
+
});
|
|
60
|
+
return output.split(/\r?\n/).filter(Boolean);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function parseStableTags(tags) {
|
|
64
|
+
const byKey = new Map();
|
|
65
|
+
for (const tag of tags) {
|
|
66
|
+
const version = parseStableVersion(tag.trim());
|
|
67
|
+
if (version) {
|
|
68
|
+
byKey.set(stableVersionKey(version), version);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return Array.from(byKey.values()).sort(compareVersions);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function evaluateDashboardSunset({ targetTag, baselineVersion, releaseWindow, stableTags }) {
|
|
75
|
+
const target = parseStableVersion(targetTag);
|
|
76
|
+
if (!target) {
|
|
77
|
+
throw new Error(`Target tag must be stable semver like v1.2.3, got: ${targetTag}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const baseline = parseStableVersion(baselineVersion);
|
|
81
|
+
if (!baseline) {
|
|
82
|
+
throw new Error(`DEPRECATION_BASELINE_VERSION must be stable semver, got: ${baselineVersion}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!Number.isInteger(releaseWindow) || releaseWindow < 1) {
|
|
86
|
+
throw new Error(`STABLE_RELEASE_WINDOW must be a positive integer, got: ${releaseWindow}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (compareVersions(target, baseline) < 0) {
|
|
90
|
+
return {
|
|
91
|
+
publish: true,
|
|
92
|
+
elapsed: 0,
|
|
93
|
+
reason: `${target.raw} is before dashboard deprecation baseline ${baseline.raw}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const versions = parseStableTags(stableTags);
|
|
98
|
+
const hasBaseline = versions.some((version) => compareVersions(version, baseline) === 0);
|
|
99
|
+
if (compareVersions(target, baseline) > 0 && !hasBaseline) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Cannot count dashboard sunset releases: baseline tag ${baseline.raw} is missing from git tags`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!versions.some((version) => compareVersions(version, target) === 0)) {
|
|
106
|
+
versions.push(target);
|
|
107
|
+
versions.sort(compareVersions);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const elapsed = versions.filter(
|
|
111
|
+
(version) => compareVersions(version, baseline) > 0 && compareVersions(version, target) <= 0,
|
|
112
|
+
).length;
|
|
113
|
+
const publish = elapsed < releaseWindow;
|
|
114
|
+
const reason = publish
|
|
115
|
+
? `legacy dashboard publish is still inside sunset window (${elapsed}/${releaseWindow} stable releases elapsed since ${baseline.raw})`
|
|
116
|
+
: `legacy dashboard sunset reached (${elapsed}/${releaseWindow} stable releases elapsed since ${baseline.raw})`;
|
|
117
|
+
|
|
118
|
+
return { publish, elapsed, reason };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function appendGithubOutput(values) {
|
|
122
|
+
if (!process.env.GITHUB_OUTPUT) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const lines = Object.entries(values).map(([key, value]) => `${key}=${String(value)}`);
|
|
126
|
+
fs.appendFileSync(process.env.GITHUB_OUTPUT, `${lines.join('\n')}\n`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function main() {
|
|
130
|
+
const args = parseArgs(process.argv.slice(2));
|
|
131
|
+
const targetTag = args.target || process.env.TARGET_TAG;
|
|
132
|
+
const baselineVersion = args.baseline || process.env.DEPRECATION_BASELINE_VERSION;
|
|
133
|
+
const windowValue = args.window || process.env.STABLE_RELEASE_WINDOW || '2';
|
|
134
|
+
const releaseWindow = Number(windowValue);
|
|
135
|
+
const stableTags = args.tagsStdin
|
|
136
|
+
? fs.readFileSync(0, 'utf8').split(/\r?\n/).filter(Boolean)
|
|
137
|
+
: readStableTagsFromGit();
|
|
138
|
+
|
|
139
|
+
const result = evaluateDashboardSunset({
|
|
140
|
+
targetTag,
|
|
141
|
+
baselineVersion,
|
|
142
|
+
releaseWindow,
|
|
143
|
+
stableTags,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
appendGithubOutput({
|
|
147
|
+
publish: result.publish ? 'true' : 'false',
|
|
148
|
+
elapsed: result.elapsed,
|
|
149
|
+
reason: result.reason,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const status = result.publish ? '[OK]' : '[i]';
|
|
153
|
+
console.log(`${status} ${result.reason}`);
|
|
154
|
+
if (!result.publish) {
|
|
155
|
+
console.log('[i] Skipping ghcr.io/kaitranntt/ccs-dashboard publish; use ghcr.io/kaitranntt/ccs.');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (require.main === module) {
|
|
160
|
+
try {
|
|
161
|
+
main();
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error(`[X] ${error.message}`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = {
|
|
169
|
+
evaluateDashboardSunset,
|
|
170
|
+
parseStableVersion,
|
|
171
|
+
};
|