mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
fix(ci): close clean runner gaps
This commit is contained in:
@@ -45,7 +45,9 @@ jobs:
|
||||
- name: Install dependencies without lifecycle scripts
|
||||
run: pnpm install --frozen-lockfile --ignore-scripts
|
||||
- name: Initialize the public test environment
|
||||
run: cp .env.example .env
|
||||
run: |
|
||||
cp .env.example .env
|
||||
mkdir -p data/db
|
||||
- name: Rebuild the reviewed native SQLite binding
|
||||
run: pnpm rebuild @whyour/sqlite3
|
||||
- name: Build backend and QL3 workspace from source
|
||||
@@ -951,6 +953,8 @@ jobs:
|
||||
docker exec ${{ job.services.postgres.id }} psql -U postgres -d ql3_contract -v ON_ERROR_STOP=1 -c "CREATE ROLE ql3_runtime LOGIN PASSWORD 'ql3_runtime_test'"
|
||||
docker exec ${{ job.services.postgres.id }} psql -U postgres -d ql3_contract -v ON_ERROR_STOP=1 -c "CREATE ROLE ql3_admin LOGIN PASSWORD 'ql3_admin_test'"
|
||||
docker exec ${{ job.services.postgres.id }} psql -U postgres -d ql3_contract -v ON_ERROR_STOP=1 -c "CREATE ROLE ql3_automation_manager LOGIN PASSWORD 'ql3_automation_manager_test'"
|
||||
docker exec ${{ job.services.postgres.id }} psql -U postgres -d ql3_contract -v ON_ERROR_STOP=1 -c "CREATE ROLE ql3_approval_manager LOGIN PASSWORD 'ql3_approval_manager_test'"
|
||||
docker exec ${{ job.services.postgres.id }} psql -U postgres -d ql3_contract -v ON_ERROR_STOP=1 -c "CREATE ROLE ql3_run_manager LOGIN PASSWORD 'ql3_run_manager_test'"
|
||||
docker exec ${{ job.services.postgres.id }} psql -U postgres -d ql3_contract -v ON_ERROR_STOP=1 -c "CREATE ROLE ql3_package_manager LOGIN PASSWORD 'ql3_package_manager_test'"
|
||||
docker exec ${{ job.services.postgres.id }} psql -U postgres -d ql3_contract -v ON_ERROR_STOP=1 -c "CREATE ROLE ql3_package_executor LOGIN PASSWORD 'ql3_package_executor_test'"
|
||||
docker exec ${{ job.services.postgres.id }} psql -U postgres -d ql3_contract -v ON_ERROR_STOP=1 -c "CREATE ROLE ql3_worker_credential_manager LOGIN PASSWORD 'ql3_worker_credential_manager_test'"
|
||||
|
||||
@@ -54,11 +54,21 @@ function docker(args, options = {}) {
|
||||
}
|
||||
|
||||
function runCertificateTool(directory, args) {
|
||||
const uid = process.getuid?.();
|
||||
const gid = process.getgid?.();
|
||||
if (
|
||||
!Number.isSafeInteger(uid) ||
|
||||
uid < 0 ||
|
||||
!Number.isSafeInteger(gid) ||
|
||||
gid < 0
|
||||
) {
|
||||
throw new Error('cannot resolve the host certificate owner');
|
||||
}
|
||||
docker([
|
||||
'run',
|
||||
'--rm',
|
||||
'--user',
|
||||
'0:0',
|
||||
`${uid}:${gid}`,
|
||||
'--volume',
|
||||
`${directory}:/work`,
|
||||
'--workdir',
|
||||
@@ -187,6 +197,7 @@ function preparePostgresFileOwnership(directory) {
|
||||
'chown',
|
||||
`${identity[0]}:${identity[1]}`,
|
||||
'/work/server.key',
|
||||
'/work/active.crt',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -221,6 +232,7 @@ async function waitFor(operation, description, timeoutMs = WAIT_TIMEOUT_MS) {
|
||||
}
|
||||
|
||||
async function waitForPostgres(containerName) {
|
||||
try {
|
||||
await waitFor(
|
||||
() =>
|
||||
docker(
|
||||
@@ -239,6 +251,15 @@ async function waitForPostgres(containerName) {
|
||||
).status === 0,
|
||||
'TLS PostgreSQL readiness',
|
||||
);
|
||||
} catch (error) {
|
||||
const logs = docker(['logs', containerName], { allowFailure: true });
|
||||
const detail = [logs.stderr, logs.stdout].filter(Boolean).join('\n');
|
||||
throw new Error(
|
||||
`${error instanceof Error ? error.message : String(error)}${
|
||||
detail ? `\nPostgreSQL container logs:\n${detail}` : ''
|
||||
}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function databaseUrl(port) {
|
||||
@@ -340,6 +361,7 @@ async function expectTlsRejection(
|
||||
|
||||
async function reloadCertificate(containerName, directory, generation) {
|
||||
activateServerCertificate(directory, generation);
|
||||
preparePostgresFileOwnership(directory);
|
||||
docker(['kill', '--signal', 'HUP', containerName]);
|
||||
await delay(500);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ test('pins backend CI to the released Node line and bootstraps a clean checkout'
|
||||
assertOrdered(backend, [
|
||||
'pnpm install --frozen-lockfile --ignore-scripts',
|
||||
'cp .env.example .env',
|
||||
'mkdir -p data/db',
|
||||
'pnpm rebuild @whyour/sqlite3',
|
||||
'pnpm build:back',
|
||||
'pnpm run build:packages:ql3',
|
||||
@@ -47,6 +48,18 @@ test('pins backend CI to the released Node line and bootstraps a clean checkout'
|
||||
assert.doesNotMatch(backend, /if: matrix\.node == '24'/);
|
||||
});
|
||||
|
||||
test('provisions every role required by the PostgreSQL migration stream', () => {
|
||||
const postgres = jobSource('cluster-postgres', 'cluster-postgres-ha');
|
||||
for (const role of [
|
||||
'ql3_automation_manager',
|
||||
'ql3_approval_manager',
|
||||
'ql3_run_manager',
|
||||
'ql3_package_manager',
|
||||
]) {
|
||||
assert.match(postgres, new RegExp(`CREATE ROLE ${role} LOGIN PASSWORD`));
|
||||
}
|
||||
});
|
||||
|
||||
test('bootstraps jobs that previously depended on local modules or artifacts', () => {
|
||||
const serviceManager = jobSource(
|
||||
'service-manager-bridge',
|
||||
@@ -99,9 +112,7 @@ test('rebuilds the only native legacy binding used by resource evidence', () =>
|
||||
});
|
||||
|
||||
test('does not forward a literal separator into recovery evidence CLIs', () => {
|
||||
const recovery = jobSource(
|
||||
'cluster-plugin-package-recovery-e2e',
|
||||
);
|
||||
const recovery = jobSource('cluster-plugin-package-recovery-e2e');
|
||||
assert.doesNotMatch(
|
||||
recovery,
|
||||
/pnpm (?:test|audit):plugin-package-recovery-e2e:ql3 -- \\/,
|
||||
|
||||
@@ -60,7 +60,21 @@ test('builds cluster-postgres before the standalone TLS rotation contract', () =
|
||||
'pg_stat_ssl',
|
||||
'pg_is_in_recovery()',
|
||||
"current_setting('transaction_read_only')",
|
||||
'PostgreSQL container logs:',
|
||||
]) {
|
||||
assert.ok(source.includes(required), `missing TLS evidence: ${required}`);
|
||||
}
|
||||
assert.match(source, /const uid = process\.getuid\?\.\(\)/);
|
||||
assert.match(source, /const gid = process\.getgid\?\.\(\)/);
|
||||
const certificateTool = source.match(
|
||||
/function runCertificateTool[\s\S]*?\n}\n/,
|
||||
)?.[0];
|
||||
assert.ok(certificateTool);
|
||||
assert.match(certificateTool, /'--user',\s*`\$\{uid}:\$\{gid}`/);
|
||||
assert.doesNotMatch(certificateTool, /'0:0'/);
|
||||
assert.match(source, /'\/work\/server\.key',\s*'\/work\/active\.crt'/);
|
||||
assert.match(
|
||||
source,
|
||||
/activateServerCertificate\(directory, generation\);\s*preparePostgresFileOwnership\(directory\);\s*docker\(\['kill'/,
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user