mirror of
https://github.com/whyour/qinglong.git
synced 2026-11-02 15:56:59 +08:00
Package production dependencies per architecture for online and offline upgrades. Validate dependencies and isolated backend startup before readiness, repair once when permitted, and preserve service/data through failed preparation or rollback. Publish release bundles with master images and expose an opt-in develop build sharing the development index across Alpine and Debian images.
110 lines
3.6 KiB
JavaScript
110 lines
3.6 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const vm = require('node:vm');
|
|
const yaml = require('js-yaml');
|
|
|
|
const workflow = yaml.load(
|
|
fs.readFileSync('.github/workflows/build-docker-image.yml', 'utf8'),
|
|
);
|
|
// These conditions use GitHub's boolean operators and format(), which have the
|
|
// same semantics for the boolean/string contexts exercised here.
|
|
const evaluate = (expression, github, inputs = {}) => {
|
|
const run = (code) =>
|
|
vm.runInNewContext(code, {
|
|
github: { run_id: '100', run_attempt: '1', ...github },
|
|
inputs,
|
|
format: (template, ...values) =>
|
|
template.replace(/\{(\d+)\}/g, (_, i) => values[i]),
|
|
});
|
|
const exact = expression.match(/^\$\{\{([\s\S]*?)\}\}$/);
|
|
return exact
|
|
? run(exact[1])
|
|
: expression.replace(/\$\{\{([\s\S]*?)\}\}/g, (_, code) =>
|
|
String(run(code)),
|
|
);
|
|
};
|
|
|
|
test('both bundle jobs require master or an explicit development dispatch', () => {
|
|
assert.equal(
|
|
workflow.on.workflow_dispatch.inputs.build_development_bundles.default,
|
|
false,
|
|
);
|
|
const cases = [
|
|
['push', 'refs/heads/develop', {}, false],
|
|
['push', 'refs/heads/develop', { build_development_bundles: true }, false],
|
|
['workflow_dispatch', 'refs/heads/develop', {}, false],
|
|
[
|
|
'workflow_dispatch',
|
|
'refs/heads/develop',
|
|
{ build_development_bundles: true },
|
|
true,
|
|
],
|
|
[
|
|
'workflow_dispatch',
|
|
'refs/heads/develop',
|
|
{ build_development_bundles: true, static_sync_only: true },
|
|
false,
|
|
],
|
|
['push', 'refs/heads/master', {}, true],
|
|
['workflow_dispatch', 'refs/heads/master', {}, true],
|
|
[
|
|
'workflow_dispatch',
|
|
'refs/heads/master',
|
|
{ static_sync_only: true },
|
|
false,
|
|
],
|
|
['push', 'refs/tags/v2.24.0', {}, false],
|
|
[
|
|
'workflow_dispatch',
|
|
'refs/tags/v2.24.0',
|
|
{ build_development_bundles: true },
|
|
false,
|
|
],
|
|
];
|
|
for (const name of ['build-upgrade-bundles', 'publish-upgrade-bundles'])
|
|
for (const [event_name, ref, inputs, expected] of cases)
|
|
assert.equal(
|
|
Boolean(evaluate(workflow.jobs[name].if, { event_name, ref }, inputs)),
|
|
expected,
|
|
`${name}: ${event_name} ${ref} ${JSON.stringify(inputs)}`,
|
|
);
|
|
assert.deepEqual(workflow.jobs['build-upgrade-bundles'].needs, [
|
|
'build-alpine',
|
|
'build-debian',
|
|
]);
|
|
assert.ok(
|
|
workflow.jobs['build-upgrade-bundles'].steps.some(
|
|
(step) =>
|
|
step.env?.ALPINE_DIGEST ===
|
|
'${{ needs.build-alpine.outputs.image-digest }}' &&
|
|
step.env?.DEBIAN_DIGEST ===
|
|
'${{ needs.build-debian.outputs.image-digest }}',
|
|
),
|
|
);
|
|
});
|
|
|
|
test('manual development releases serialize separately while normal develop CI remains independent', () => {
|
|
const group = (event_name, ref, inputs = {}, run_id = '100') =>
|
|
evaluate(workflow.concurrency.group, { event_name, ref, run_id }, inputs);
|
|
const master = group('push', 'refs/heads/master');
|
|
const development = group('workflow_dispatch', 'refs/heads/develop', {
|
|
build_development_bundles: true,
|
|
});
|
|
assert.equal(
|
|
development,
|
|
group(
|
|
'workflow_dispatch',
|
|
'refs/heads/develop',
|
|
{ build_development_bundles: true },
|
|
'101',
|
|
),
|
|
);
|
|
assert.equal(master, group('push', 'refs/heads/master', {}, '101'));
|
|
assert.notEqual(master, development);
|
|
const push = group('push', 'refs/heads/develop');
|
|
assert.notEqual(push, development);
|
|
assert.notEqual(push, group('push', 'refs/heads/develop', {}, '101'));
|
|
assert.equal(workflow.concurrency['cancel-in-progress'], false);
|
|
});
|