fix(ci): align kubernetes live evidence

This commit is contained in:
whyour
2026-08-22 14:34:39 +08:00
parent 5efaca3d5a
commit c0cd94f50d
8 changed files with 49 additions and 11 deletions
+9 -3
View File
@@ -9,6 +9,10 @@ const os = require('node:os');
const path = require('node:path'); const path = require('node:path');
const { spawnSync } = require('node:child_process'); const { spawnSync } = require('node:child_process');
const { readReleaseIdentity } = require('./lib/ql3-release-identity.cjs'); const { readReleaseIdentity } = require('./lib/ql3-release-identity.cjs');
const {
postgresqlControlSchemaContract,
postgresqlMainMigrationStream,
} = require('../packages/ql3-cluster-postgres/dist/migration/migration.js');
const ROOT = path.resolve(__dirname, '..'); const ROOT = path.resolve(__dirname, '..');
const QL3_VERSION = readReleaseIdentity(ROOT).version; const QL3_VERSION = readReleaseIdentity(ROOT).version;
@@ -59,6 +63,8 @@ const ROLE_NAMES = Object.freeze([
'ql3_worker_credential_manager', 'ql3_worker_credential_manager',
'ql3_worker_ingress', 'ql3_worker_ingress',
]); ]);
const MIGRATION_COUNT = postgresqlMainMigrationStream.migrations.length;
const CONTRACT_VERSION = postgresqlControlSchemaContract.contractVersion;
function fail(message) { function fail(message) {
throw new Error(message); throw new Error(message);
@@ -385,13 +391,13 @@ function roleEvidence(podName) {
FROM ql3.schema_capabilities FROM ql3.schema_capabilities
WHERE contract_name = 'control-core')`, WHERE contract_name = 'control-core')`,
).split('\t'); ).split('\t');
assert.deepEqual(schema, ['53', '52']); assert.deepEqual(schema, [String(MIGRATION_COUNT), String(CONTRACT_VERSION)]);
return { return {
roles: rows.map((row) => row[0]), roles: rows.map((row) => row[0]),
login: true, login: true,
elevatedAttributes: false, elevatedAttributes: false,
migrationCount: 54, migrationCount: MIGRATION_COUNT,
contractVersion: 53, contractVersion: CONTRACT_VERSION,
}; };
} }
@@ -33,6 +33,8 @@ const POSTGRES_INDEX_DIGEST =
'sha256:1961f96e6029a02c3812d7cb329a3b03a3ac2bb067058dec17b0f5596aca9296'; 'sha256:1961f96e6029a02c3812d7cb329a3b03a3ac2bb067058dec17b0f5596aca9296';
const POSTGRES_IMAGE_REFERENCE = `${POSTGRES_IMAGE}@${POSTGRES_INDEX_DIGEST}`; const POSTGRES_IMAGE_REFERENCE = `${POSTGRES_IMAGE}@${POSTGRES_INDEX_DIGEST}`;
const POSTGRES_REPOSITORY_DIGEST = `postgres@${POSTGRES_INDEX_DIGEST}`; const POSTGRES_REPOSITORY_DIGEST = `postgres@${POSTGRES_INDEX_DIGEST}`;
const POSTGRES_RUNTIME_IMAGE =
'postgres:18.4-bookworm-ql3-plugin-recovery-e2e';
const DEFAULT_ADMIN_IMAGE = 'qinglong3-cluster-admin:ql3-plugin-recovery-e2e'; const DEFAULT_ADMIN_IMAGE = 'qinglong3-cluster-admin:ql3-plugin-recovery-e2e';
const DEFAULT_CONTROL_IMAGE = const DEFAULT_CONTROL_IMAGE =
'qinglong3-cluster-control:ql3-plugin-recovery-e2e'; 'qinglong3-cluster-control:ql3-plugin-recovery-e2e';
@@ -293,6 +295,10 @@ function ensurePostgresImage() {
inspection.RepoDigests.includes(POSTGRES_REPOSITORY_DIGEST), inspection.RepoDigests.includes(POSTGRES_REPOSITORY_DIGEST),
`${POSTGRES_IMAGE} does not match ${POSTGRES_REPOSITORY_DIGEST}`, `${POSTGRES_IMAGE} does not match ${POSTGRES_REPOSITORY_DIGEST}`,
); );
run(DOCKER, ['image', 'tag', POSTGRES_IMAGE_REFERENCE, POSTGRES_RUNTIME_IMAGE], {
label: 'bind verified PostgreSQL fixture digest to its Kind-local tag',
});
assert.equal(imageId(POSTGRES_RUNTIME_IMAGE), inspection.Id);
} }
function imageId(image) { function imageId(image) {
@@ -486,7 +492,7 @@ createdb --username "$POSTGRES_USER" --owner ql3_migration qinglong
containers: [ containers: [
{ {
name: 'postgres', name: 'postgres',
image: POSTGRES_IMAGE_REFERENCE, image: POSTGRES_RUNTIME_IMAGE,
imagePullPolicy: 'Never', imagePullPolicy: 'Never',
env: [ env: [
{ name: 'POSTGRES_USER', value: 'postgres' }, { name: 'POSTGRES_USER', value: 'postgres' },
@@ -1730,7 +1736,7 @@ async function main(argv = process.argv.slice(2)) {
for (const image of [ for (const image of [
ADMIN_IMAGE, ADMIN_IMAGE,
CONTROL_IMAGE, CONTROL_IMAGE,
POSTGRES_IMAGE_REFERENCE, POSTGRES_RUNTIME_IMAGE,
]) { ]) {
kind( kind(
[ [
@@ -6,6 +6,7 @@ const fs = require('node:fs');
const path = require('node:path'); const path = require('node:path');
const FIXTURE = 'qinglong/provider-credential-test-kubernetes-live-contract@v1'; const FIXTURE = 'qinglong/provider-credential-test-kubernetes-live-contract@v1';
const AI_MIGRATION_COUNT = 21;
const LIMITATIONS = Object.freeze([ const LIMITATIONS = Object.freeze([
'three privileged K3s Docker nodes with fixture-only prebound hostPath volumes are not production infrastructure, dynamic storage or control-plane HA evidence', 'three privileged K3s Docker nodes with fixture-only prebound hostPath volumes are not production infrastructure, dynamic storage or control-plane HA evidence',
'the private HTTPS provider is a deterministic in-cluster fixture rather than an external SaaS provider', 'the private HTTPS provider is a deterministic in-cluster fixture rather than an external SaaS provider',
@@ -186,7 +187,7 @@ function validateProviderCredentialTestKubernetesLiveReport(report) {
database?.managerRole !== 'ql3_ai_credential_manager' || database?.managerRole !== 'ql3_ai_credential_manager' ||
database?.testerRole !== 'ql3_ai_credential_tester' || database?.testerRole !== 'ql3_ai_credential_tester' ||
database?.migrationCount < 50 || database?.migrationCount < 50 ||
database?.aiMigrationCount !== 15 || database?.aiMigrationCount !== AI_MIGRATION_COUNT ||
database?.tlsVerified !== true || database?.tlsVerified !== true ||
database?.primaryChangedDuringFailover !== true database?.primaryChangedDuringFailover !== true
) { ) {
@@ -438,6 +439,7 @@ if (require.main === module) {
} }
module.exports = { module.exports = {
AI_MIGRATION_COUNT,
FIXTURE, FIXTURE,
LIMITATIONS, LIMITATIONS,
validateProviderCredentialTestKubernetesLiveReport, validateProviderCredentialTestKubernetesLiveReport,
@@ -29,6 +29,7 @@ const {
reviewedOperatorManifest, reviewedOperatorManifest,
} = require('./ql3-cloudnativepg-live-contract.cjs'); } = require('./ql3-cloudnativepg-live-contract.cjs');
const { const {
AI_MIGRATION_COUNT,
FIXTURE, FIXTURE,
LIMITATIONS, LIMITATIONS,
validateProviderCredentialTestKubernetesLiveReport, validateProviderCredentialTestKubernetesLiveReport,
@@ -1453,7 +1454,7 @@ async function main() {
), ),
); );
assert.equal(databaseFacts.postgresVersionNumber, 180004); assert.equal(databaseFacts.postgresVersionNumber, 180004);
assert.equal(databaseFacts.aiMigrationCount, 15); assert.equal(databaseFacts.aiMigrationCount, AI_MIGRATION_COUNT);
psql( psql(
fixture, fixture,
@@ -132,9 +132,12 @@ test('provisions the fail-closed worker ingress identity and derives all role ev
); );
assert.match(source, /const roleList = ROLE_NAMES\.map/); assert.match(source, /const roleList = ROLE_NAMES\.map/);
assert.match(source, /WHERE rolname IN \(\$\{roleList\}\)/); assert.match(source, /WHERE rolname IN \(\$\{roleList\}\)/);
assert.match(source, /assert\.deepEqual\(schema, \['53', '52'\]\)/); assert.match(
assert.match(source, /migrationCount: 54/); source,
assert.match(source, /contractVersion: 53/); /assert\.deepEqual\(schema, \[String\(MIGRATION_COUNT\), String\(CONTRACT_VERSION\)\]\)/,
);
assert.match(source, /migrationCount: MIGRATION_COUNT/);
assert.match(source, /contractVersion: CONTRACT_VERSION/);
assert.match(source, /createWorkerIngressTls\(tempDirectory\)/); assert.match(source, /createWorkerIngressTls\(tempDirectory\)/);
for (const key of [ for (const key of [
'worker-credential-pepper', 'worker-credential-pepper',
@@ -29,6 +29,12 @@ test('E2E live gate is opt-in and owns only one exact disposable Kind cluster',
assert.match(live, /kind\(\['delete', 'cluster', '--name', clusterName\]/); assert.match(live, /kind\(\['delete', 'cluster', '--name', clusterName\]/);
assert.match(live, /QL3_KEEP_KIND_CLUSTER/); assert.match(live, /QL3_KEEP_KIND_CLUSTER/);
assert.match(live, /kindest\/node:v1\.32\.8@sha256:/); assert.match(live, /kindest\/node:v1\.32\.8@sha256:/);
assert.match(
live,
/image', 'tag', POSTGRES_IMAGE_REFERENCE, POSTGRES_RUNTIME_IMAGE/,
);
assert.match(live, /image: POSTGRES_RUNTIME_IMAGE/);
assert.match(live, /imagePullPolicy: 'Never'/);
assert.match( assert.match(
live, live,
/condition\.type === 'Failed' && condition\.status === 'True'/, /condition\.type === 'Failed' && condition\.status === 'True'/,
@@ -2,6 +2,7 @@ const assert = require('node:assert/strict');
const test = require('node:test'); const test = require('node:test');
const { const {
AI_MIGRATION_COUNT,
FIXTURE, FIXTURE,
LIMITATIONS, LIMITATIONS,
validateProviderCredentialTestKubernetesLiveReport, validateProviderCredentialTestKubernetesLiveReport,
@@ -36,7 +37,7 @@ function report() {
managerRole: 'ql3_ai_credential_manager', managerRole: 'ql3_ai_credential_manager',
testerRole: 'ql3_ai_credential_tester', testerRole: 'ql3_ai_credential_tester',
migrationCount: 54, migrationCount: 54,
aiMigrationCount: 15, aiMigrationCount: AI_MIGRATION_COUNT,
tlsVerified: true, tlsVerified: true,
primaryChangedDuringFailover: true, primaryChangedDuringFailover: true,
}, },
@@ -15,6 +15,19 @@ const {
providerServerSource, providerServerSource,
terminalJobSnapshot, terminalJobSnapshot,
} = require('../../scripts/ql3-provider-credential-test-kubernetes-live-contract.cjs'); } = require('../../scripts/ql3-provider-credential-test-kubernetes-live-contract.cjs');
const {
AI_MIGRATION_COUNT,
} = require('../../scripts/ql3-provider-credential-test-kubernetes-live-audit.cjs');
const {
postgresModelInvocationMigrationDefinition,
} = require('../../packages/ql3-ai/dist/migration/modelInvocationMigration.js');
test('binds live evidence to the complete reviewed AI migration stream', () => {
assert.equal(
AI_MIGRATION_COUNT,
postgresModelInvocationMigrationDefinition.migrations.length,
);
});
function template() { function template() {
return { return {