Files
wehub-resource-sync 4ce4204b6c
CI / Lint (push) Failing after 2s
CI / Build (push) Has been skipped
SDK CI / PHP SDK (push) Failing after 1s
Split PHP SDK / PHP SDK tests (push) Failing after 1s
CI / Test (push) Failing after 1s
CI / Dashboard (push) Failing after 0s
SDK CI / JavaScript SDK (push) Failing after 0s
SDK CI / Python SDK (push) Failing after 2s
SDK CI / Java SDK (push) Failing after 1s
Split PHP SDK / Mirror sdk/php -> rmyndharis/openwa-php (push) Has been skipped
CI / Test (PostgreSQL migrations) (push) Failing after 7m47s
CI / Docker Build (push) Has been skipped
chore: import upstream snapshot with attribution
2026-07-13 12:24:08 +08:00

75 lines
3.6 KiB
JavaScript

/* eslint-disable */
// PostgreSQL migration + uuid-default smoke. CI runs this against a throwaway postgres:16 service:
// it applies the FULL data-migration chain from scratch (previously never exercised on Postgres in CI)
// and asserts every generated-uuid primary key has a DB-side DEFAULT. Without one, a
// `@PrimaryGeneratedColumn('uuid')` insert fails on Postgres with a NOT NULL violation (23502) — the
// exact failure SQLite hides, because its driver mints the uuid client-side.
//
// Runs against the compiled migrations in dist/ (so it matches `migration:run:prod`); `npm run build`
// first. Configured from DATABASE_* env vars.
require('reflect-metadata');
const path = require('path');
const { DataSource } = require('typeorm');
// @PrimaryColumn tables: their `id` is supplied by the application, so it legitimately has NO DB default.
// Everything else with an `id` column is expected to be a generated-uuid PK that MUST carry a default.
const APP_GENERATED_ID_TABLES = ['ingress_events', 'plugin_instances'];
async function main() {
// Mirror the migration CLI (data-source.ts): a non-public POSTGRES_SCHEMA sets the session
// search_path so the raw, unqualified migration DDL + the typeorm_migrations ledger land in it.
const schema = process.env.POSTGRES_SCHEMA || 'public';
const useCustomSearchPath = schema !== 'public';
const ds = new DataSource({
type: 'postgres',
schema,
host: process.env.DATABASE_HOST || 'localhost',
port: Number(process.env.DATABASE_PORT || 5432),
username: process.env.DATABASE_USERNAME || 'openwa',
password: process.env.DATABASE_PASSWORD || 'openwa',
database: process.env.DATABASE_NAME || 'openwa',
migrations: [path.join(__dirname, '..', 'dist', 'database', 'migrations', '*.js')],
...(useCustomSearchPath ? { extra: { options: `-c search_path=${schema},public` } } : {}),
});
await ds.initialize();
const ran = await ds.runMigrations();
console.log(`Applied ${ran.length} data migrations to PostgreSQL from scratch.`);
// Auto-coverage: any `id` column with no DEFAULT that isn't an app-generated PK is a uuid-PK table
// missing gen_random_uuid(). This catches current AND future tables without a maintained list.
const noDefaultRows = await ds.query(
`SELECT table_name FROM information_schema.columns
WHERE table_schema = $1 AND column_name = 'id' AND column_default IS NULL`,
[schema],
);
const offenders = noDefaultRows
.map((r) => r.table_name)
.filter((t) => t !== 'migrations' && !APP_GENERATED_ID_TABLES.includes(t));
// Belt-and-suspenders: positively assert the two tables this migration set fixes carry a default.
for (const t of ['conversation_mappings', 'integration_delivery_failures']) {
const rows = await ds.query(
`SELECT column_default FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 AND column_name = 'id'`,
[schema, t],
);
if (!rows.length || rows[0].column_default == null) offenders.push(`${t} (expected a default, found none)`);
}
await ds.destroy();
const unique = [...new Set(offenders)];
if (unique.length) {
console.error('\n❌ Generated-uuid PK column(s) missing a Postgres DEFAULT — inserts will fail (23502):');
for (const t of unique) console.error(' - ' + t);
console.error('\nFix: add `ALTER COLUMN "id" SET DEFAULT gen_random_uuid()::varchar` in a Postgres-only migration.');
process.exit(1);
}
console.log('✅ Migration chain applied cleanly and every generated-uuid PK has a Postgres DEFAULT.');
}
main().catch((err) => {
console.error(err);
process.exit(1);
});