ci(ql3): wait for managed postgres resources

This commit is contained in:
whyour
2026-08-25 23:38:21 +08:00
parent d2ebce85fa
commit c2df0c7215
2 changed files with 64 additions and 14 deletions
@@ -390,10 +390,20 @@ function migrationFailureEvidence(snapshot) {
exitCode: terminated?.exitCode ?? null, exitCode: terminated?.exitCode ?? null,
reason: terminated?.reason ?? status?.state?.waiting?.reason ?? null, reason: terminated?.reason ?? status?.state?.waiting?.reason ?? null,
}; };
const message = (terminated?.message || '').trim(); const lines = (terminated?.message || '')
if (!message) return evidence; .split('\n')
.map((line) => line.trim())
.filter(Boolean)
.reverse();
if (lines.length === 0) return evidence;
let rejected = false;
for (const line of lines) {
let parsed;
try { try {
const parsed = JSON.parse(message); parsed = JSON.parse(line);
} catch {
continue;
}
const allowedKeys = ['schemaVersion', 'component', 'event', 'name', 'code']; const allowedKeys = ['schemaVersion', 'component', 'event', 'name', 'code'];
if ( if (
!parsed || !parsed ||
@@ -401,12 +411,15 @@ function migrationFailureEvidence(snapshot) {
Array.isArray(parsed) || Array.isArray(parsed) ||
Object.keys(parsed).some((key) => !allowedKeys.includes(key)) Object.keys(parsed).some((key) => !allowedKeys.includes(key))
) { ) {
return { ...evidence, failureMessage: 'rejected' }; rejected = true;
continue;
} }
return { ...evidence, failureMessage: parsed }; return { ...evidence, failureMessage: parsed };
} catch {
return { ...evidence, failureMessage: 'unparseable' };
} }
return {
...evidence,
failureMessage: rejected ? 'rejected' : 'unparseable',
};
} }
async function terminalJobSnapshot(fixture, name, timeoutMs = 180_000) { async function terminalJobSnapshot(fixture, name, timeoutMs = 180_000) {
@@ -974,6 +987,35 @@ async function main(argv = process.argv.slice(2)) {
: { ready: false, fact: `${pods.length}/3 Ready database Pods` }; : { ready: false, fact: `${pods.length}/3 Ready database Pods` };
}) })
).value; ).value;
await waitFor('CloudNativePG managed resources', 5 * 60_000, () => {
const roles = fixture.kubectlJson([
'-n',
NAMESPACE,
'get',
'databaseroles.postgresql.cnpg.io',
]).items;
const readyRoles = roles.filter(
(role) =>
role.status?.applied === true &&
role.status?.observedGeneration === role.metadata.generation,
);
const database = fixture.kubectlJson([
'-n',
NAMESPACE,
'get',
'database.postgresql.cnpg.io/ql3-postgres-qinglong',
]);
const databaseReady =
database.status?.applied === true &&
database.status?.observedGeneration === database.metadata.generation;
return readyRoles.length === ROLE_NAMES.length && databaseReady
? { ready: true, value: true }
: {
ready: false,
fact: `${readyRoles.length}/${ROLE_NAMES.length} roles applied; ` +
`databaseApplied=${String(databaseReady)}`,
};
});
const migrationManifest = localManifest( const migrationManifest = localManifest(
fixture.kubectl( fixture.kubectl(
@@ -128,13 +128,21 @@ test('keeps migration failure evidence content-free', () => {
terminated: { terminated: {
exitCode: 1, exitCode: 1,
reason: 'Error', reason: 'Error',
message: JSON.stringify({ message: [
JSON.stringify({
schemaVersion: 1,
component: 'qinglong3-cluster-migration',
event: 'migration_started',
migrationCount: 0,
}),
JSON.stringify({
schemaVersion: 1, schemaVersion: 1,
component: 'qinglong3-cluster-migration', component: 'qinglong3-cluster-migration',
event: 'migration_failed', event: 'migration_failed',
name: 'Error', name: 'Error',
code: 'EAI_AGAIN', code: 'EAI_AGAIN',
}), }),
].join('\n'),
}, },
}, },
}, },