mirror of
https://github.com/whyour/qinglong.git
synced 2026-11-06 17:34:34 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad29b7aa73 |
@@ -28,7 +28,7 @@ const backend = read(path.resolve(__dirname, '../app.js'));
|
|||||||
const root = process.env.QL_DIR || path.resolve(__dirname, '../../..');
|
const root = process.env.QL_DIR || path.resolve(__dirname, '../../..');
|
||||||
const version = read(path.join(root, 'version.yaml'))
|
const version = read(path.join(root, 'version.yaml'))
|
||||||
?.toString()
|
?.toString()
|
||||||
.match(/^\uFEFF?version:\s*["']?(\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?)/m)?.[1];
|
.match(/^\uFEFF?version:\s*["']?(\d+\.\d+\.\d+)/m)?.[1];
|
||||||
|
|
||||||
export const runtimeBuild = Object.freeze({
|
export const runtimeBuild = Object.freeze({
|
||||||
instanceId: randomUUID(),
|
instanceId: randomUUID(),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ CI 从同次构建的不可变镜像摘要导出完整 tar.gz,包含源码中
|
|||||||
gh workflow run build-docker-image.yml --ref develop
|
gh workflow run build-docker-image.yml --ref develop
|
||||||
```
|
```
|
||||||
|
|
||||||
开发包更新共用的 `upgrade-develop/latest.json`。`develop` 和 `debian-dev` 镜像都使用该索引,按实际 Node 架构和 musl/glibc 选择包,无需设置测试专用下载源。开发批次位于 `upgrade-build-develop-<run-id>-<run-attempt>`,tag 不带版本号;索引中仍保留开发版本供客户端判断更新。开发批次不会改写正式版本或 `upgrade-master`。同一开发渠道的镜像构建和包发布串行执行,与 master 独立。
|
开发包更新共用的 `upgrade-develop/latest.json`。`develop` 和 `debian-dev` 镜像都使用该索引,按实际 Node 架构和 musl/glibc 选择包,无需设置测试专用下载源。开发批次位于 `upgrade-build-develop-v<version>-<run-id>-<run-attempt>`,不会改写正式版本或 `upgrade-master`。同一开发渠道的镜像构建和包发布串行执行,与 master 独立。
|
||||||
|
|
||||||
开发包只保留最新一个已验证批次:所有平台资产和渠道索引的大小、SHA256 校验成功后,删除其他名称匹配的开发构建 prerelease;不删除正式包、渠道索引或无法分类的旧 release。构建或上传失败不会删除上一套可用包。旧批次被删除后,已选中旧索引但尚未下载完的客户端可能需要重新发起下载;准备失败仍保留旧服务和数据。
|
开发包只保留最新一个已验证批次:所有平台资产和渠道索引的大小、SHA256 校验成功后,删除其他名称匹配的开发构建 prerelease;不删除正式包、渠道索引或无法分类的旧 release。构建或上传失败不会删除上一套可用包。旧批次被删除后,已选中旧索引但尚未下载完的客户端可能需要重新发起下载;准备失败仍保留旧服务和数据。
|
||||||
|
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ function publishBundles({
|
|||||||
// unchanged. Only the version/channel pointer is overwritten, never bytes
|
// unchanged. Only the version/channel pointer is overwritten, never bytes
|
||||||
// that an in-flight download has already selected by hash.
|
// that an in-flight download has already selected by hash.
|
||||||
const development = branch === 'develop';
|
const development = branch === 'develop';
|
||||||
const tag = development
|
const tag = `upgrade-build-${
|
||||||
? `upgrade-build-develop-${buildId}`
|
development ? 'develop-' : ''
|
||||||
: `upgrade-build-v${version}-${buildId}`;
|
}v${version}-${buildId}`;
|
||||||
const index = {
|
const index = {
|
||||||
...releaseIndex(directory, commit, repository, {
|
...releaseIndex(directory, commit, repository, {
|
||||||
version,
|
version,
|
||||||
@@ -149,9 +149,7 @@ function publishBundles({
|
|||||||
}
|
}
|
||||||
ensureRelease(
|
ensureRelease(
|
||||||
tag,
|
tag,
|
||||||
development
|
`${development ? 'Development platform upgrade' : 'Platform upgrade'} v${version} (${buildId})`,
|
||||||
? `Development platform upgrade (${buildId})`
|
|
||||||
: `Platform upgrade v${version} (${buildId})`,
|
|
||||||
);
|
);
|
||||||
const assets = platforms
|
const assets = platforms
|
||||||
.flatMap((target) => {
|
.flatMap((target) => {
|
||||||
@@ -245,7 +243,7 @@ function publishBundles({
|
|||||||
for (const release of pages.flat()) {
|
for (const release of pages.flat()) {
|
||||||
if (
|
if (
|
||||||
release.tag_name !== tag &&
|
release.tag_name !== tag &&
|
||||||
/^upgrade-build-develop-(?:v\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?-)?\d+-\d+$/.test(
|
/^upgrade-build-develop-v\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?-\d+-\d+$/.test(
|
||||||
release.tag_name,
|
release.tag_name,
|
||||||
) &&
|
) &&
|
||||||
release.prerelease === true &&
|
release.prerelease === true &&
|
||||||
|
|||||||
@@ -366,22 +366,22 @@ test('automatic development publication keeps its prerelease version separate fr
|
|||||||
...Object.values(development.packages),
|
...Object.values(development.packages),
|
||||||
development.installer,
|
development.installer,
|
||||||
])
|
])
|
||||||
assert.ok(entry.url.includes('/upgrade-build-develop-100-1/'));
|
assert.ok(entry.url.includes('/upgrade-build-develop-v2.24.0-dev.0-100-1/'));
|
||||||
assert.ok(
|
assert.ok(
|
||||||
f.state.calls.some(
|
f.state.calls.some(
|
||||||
(args) =>
|
(args) =>
|
||||||
args[0] === 'release' &&
|
args[0] === 'release' &&
|
||||||
args[1] === 'create' &&
|
args[1] === 'create' &&
|
||||||
args[2] === 'upgrade-build-develop-100-1' &&
|
args[2] === 'upgrade-build-develop-v2.24.0-dev.0-100-1' &&
|
||||||
args[args.indexOf('--title') + 1] ===
|
args[args.indexOf('--title') + 1] ===
|
||||||
'Development platform upgrade (100-1)',
|
'Development platform upgrade v2.24.0-dev.0 (100-1)',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
assert.deepEqual(f.index(), production);
|
assert.deepEqual(f.index(), production);
|
||||||
assert.deepEqual(f.index('upgrade-v2.24.0'), production);
|
assert.deepEqual(f.index('upgrade-v2.24.0'), production);
|
||||||
assert.equal(f.state.releases.get('upgrade-build-v2.24.0-100-1').size, 24);
|
assert.equal(f.state.releases.get('upgrade-build-v2.24.0-100-1').size, 24);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
f.state.releases.get('upgrade-build-develop-100-1').size,
|
f.state.releases.get('upgrade-build-develop-v2.24.0-dev.0-100-1').size,
|
||||||
24,
|
24,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -433,16 +433,14 @@ for (const fault of [
|
|||||||
const options = { branch: 'develop', commit: f.state.developHead };
|
const options = { branch: 'develop', commit: f.state.developHead };
|
||||||
f.write(options.commit, 'development');
|
f.write(options.commit, 'development');
|
||||||
f.publish(options);
|
f.publish(options);
|
||||||
const oldTag = 'upgrade-build-develop-100-1';
|
const oldTag = 'upgrade-build-develop-v2.24.0-100-1';
|
||||||
const legacyTag = 'upgrade-build-develop-v2.24.0-99-1';
|
|
||||||
f.state.releases.set(legacyTag, new Map());
|
|
||||||
// Never prune production, channel aliases, legacy/unclassified releases,
|
// Never prune production, channel aliases, legacy/unclassified releases,
|
||||||
// drafts or a non-prerelease even when its name resembles a dev build.
|
// drafts or a non-prerelease even when its name resembles a dev build.
|
||||||
const protectedTags = [
|
const protectedTags = [
|
||||||
'upgrade-86c37f426a5ba9945d6af1910a7885a26f77e4bc',
|
'upgrade-86c37f426a5ba9945d6af1910a7885a26f77e4bc',
|
||||||
'v2.24.0',
|
'v2.24.0',
|
||||||
'upgrade-build-develop-10-1',
|
'upgrade-build-develop-v2.24.0-10-1',
|
||||||
'upgrade-build-develop-11-1',
|
'upgrade-build-develop-v2.24.0-11-1',
|
||||||
];
|
];
|
||||||
for (const tag of protectedTags) f.state.releases.set(tag, new Map());
|
for (const tag of protectedTags) f.state.releases.set(tag, new Map());
|
||||||
f.state.releaseMetadata = {
|
f.state.releaseMetadata = {
|
||||||
@@ -474,10 +472,9 @@ for (const fault of [
|
|||||||
a[0] === 'api' && a[1].includes('/releases/tags/upgrade-develop'),
|
a[0] === 'api' && a[1].includes('/releases/tags/upgrade-develop'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
assert.ok(f.state.releases.has('upgrade-build-develop-101-1'));
|
assert.ok(f.state.releases.has('upgrade-build-develop-v2.24.0-101-1'));
|
||||||
}
|
}
|
||||||
assert.equal(f.state.releases.has(oldTag), Boolean(fault));
|
assert.equal(f.state.releases.has(oldTag), Boolean(fault));
|
||||||
assert.equal(f.state.releases.has(legacyTag), Boolean(fault));
|
|
||||||
for (const tag of protectedTags) assert.ok(f.state.releases.has(tag));
|
for (const tag of protectedTags) assert.ok(f.state.releases.has(tag));
|
||||||
assert.deepEqual(f.index(), production);
|
assert.deepEqual(f.index(), production);
|
||||||
assert.deepEqual(f.index('upgrade-v2.24.0'), production);
|
assert.deepEqual(f.index('upgrade-v2.24.0'), production);
|
||||||
@@ -494,11 +491,11 @@ test('failed development cleanup is retryable without overwriting immutable asse
|
|||||||
/Delete unavailable/,
|
/Delete unavailable/,
|
||||||
);
|
);
|
||||||
assert.equal(f.index('upgrade-develop').buildId, '101-1');
|
assert.equal(f.index('upgrade-develop').buildId, '101-1');
|
||||||
assert.ok(f.state.releases.has('upgrade-build-develop-100-1'));
|
assert.ok(f.state.releases.has('upgrade-build-develop-v2.24.0-100-1'));
|
||||||
f.state.failDelete = false;
|
f.state.failDelete = false;
|
||||||
f.publish({ ...options, buildId: '101-1' });
|
f.publish({ ...options, buildId: '101-1' });
|
||||||
assert.ok(!f.state.releases.has('upgrade-build-develop-100-1'));
|
assert.ok(!f.state.releases.has('upgrade-build-develop-v2.24.0-100-1'));
|
||||||
assert.ok(f.state.releases.has('upgrade-build-develop-101-1'));
|
assert.ok(f.state.releases.has('upgrade-build-develop-v2.24.0-101-1'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('a newer development commit during upload preserves the published channel and its old package', (t) => {
|
test('a newer development commit during upload preserves the published channel and its old package', (t) => {
|
||||||
@@ -510,7 +507,7 @@ test('a newer development commit during upload preserves the published channel a
|
|||||||
f.state.changeDevelopHeadAfterUpload = true;
|
f.state.changeDevelopHeadAfterUpload = true;
|
||||||
assert.equal(f.publish({ ...options, buildId: '101-1' }), false);
|
assert.equal(f.publish({ ...options, buildId: '101-1' }), false);
|
||||||
assert.deepEqual(f.index('upgrade-develop'), before);
|
assert.deepEqual(f.index('upgrade-develop'), before);
|
||||||
assert.ok(f.state.releases.has('upgrade-build-develop-100-1'));
|
assert.ok(f.state.releases.has('upgrade-build-develop-v2.24.0-100-1'));
|
||||||
assert.ok(
|
assert.ok(
|
||||||
!f.state.calls.some((a) => a[0] === 'release' && a[1] === 'delete'),
|
!f.state.calls.some((a) => a[0] === 'release' && a[1] === 'delete'),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ test('a running process retains its own build identity when installed files chan
|
|||||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ql-runtime-build-'));
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ql-runtime-build-'));
|
||||||
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
||||||
fs.mkdirSync(path.join(root, 'static/build'), { recursive: true });
|
fs.mkdirSync(path.join(root, 'static/build'), { recursive: true });
|
||||||
fs.writeFileSync(path.join(root, 'version.yaml'), 'version: 2.24.0-dev.0');
|
fs.writeFileSync(path.join(root, 'version.yaml'), 'version: 2.24.0');
|
||||||
fs.writeFileSync(path.join(root, 'static/build/app.js'), 'old backend');
|
fs.writeFileSync(path.join(root, 'static/build/app.js'), 'old backend');
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(root, 'static/build-info.json'),
|
path.join(root, 'static/build-info.json'),
|
||||||
@@ -45,7 +45,7 @@ test('a running process retains its own build identity when installed files chan
|
|||||||
JSON.stringify({ sourceCommit: 'b'.repeat(40) }),
|
JSON.stringify({ sourceCommit: 'b'.repeat(40) }),
|
||||||
);
|
);
|
||||||
fs.writeFileSync(path.join(root, 'version.yaml'), 'version: 2.25.0');
|
fs.writeFileSync(path.join(root, 'version.yaml'), 'version: 2.25.0');
|
||||||
assert.equal(running.version, '2.24.0-dev.0');
|
assert.equal(running.version, '2.24.0');
|
||||||
assert.equal(running.sourceCommit, 'a'.repeat(40));
|
assert.equal(running.sourceCommit, 'a'.repeat(40));
|
||||||
assert.equal(
|
assert.equal(
|
||||||
running.backendSha256,
|
running.backendSha256,
|
||||||
|
|||||||
Reference in New Issue
Block a user