@@ -20,6 +20,7 @@ import { createInterface } from "readline";
2020import * as childProcess from "child_process" ;
2121import { REPORT_GENERATORS , CHECK_INFO , generateAllReports } from "../lib/checkup" ;
2222import { createCheckupReport , uploadCheckupReportJson , RpcError , formatRpcErrorForDisplay , withRetry } from "../lib/checkup-api" ;
23+ import { getRunningPostgresVersion , getTargetPostgresVersion , runPgUpgrade , needsPostgresUpgrade } from "../lib/pg-upgrade" ;
2324
2425// Singleton readline interface for stdin prompts
2526let rl : ReturnType < typeof createInterface > | null = null ;
@@ -1069,130 +1070,6 @@ function isDockerRunning(): boolean {
10691070 }
10701071}
10711072
1072- /**
1073- * Get PostgreSQL major version from a running container
1074- * @returns Major version number (e.g., 15, 17, 18) or null if container not running
1075- */
1076- function getRunningPostgresVersion ( containerName : string ) : number | null {
1077- try {
1078- const result = spawnSync (
1079- "docker" ,
1080- [ "exec" , containerName , "psql" , "-U" , "postgres" , "-t" , "-c" , "SHOW server_version_num" ] ,
1081- { stdio : "pipe" , encoding : "utf8" }
1082- ) ;
1083- if ( result . status === 0 && result . stdout ) {
1084- const versionNum = parseInt ( result . stdout . trim ( ) , 10 ) ;
1085- if ( ! isNaN ( versionNum ) ) {
1086- return Math . floor ( versionNum / 10000 ) ; // e.g., 150000 -> 15
1087- }
1088- }
1089- return null ;
1090- } catch {
1091- return null ;
1092- }
1093- }
1094-
1095- /**
1096- * Get target PostgreSQL major version from docker-compose.yml
1097- * @returns Major version number or null if not found
1098- */
1099- function getTargetPostgresVersion ( composeFilePath : string ) : number | null {
1100- try {
1101- const content = fs . readFileSync ( composeFilePath , "utf8" ) ;
1102- // Match postgres:XX image tag for sink-postgres service
1103- const match = content . match ( / s i n k - p o s t g r e s : [ \s \S ] * ?i m a g e : \s * p o s t g r e s : ( \d + ) / ) ;
1104- if ( match && match [ 1 ] ) {
1105- return parseInt ( match [ 1 ] , 10 ) ;
1106- }
1107- return null ;
1108- } catch {
1109- return null ;
1110- }
1111- }
1112-
1113- /**
1114- * Run pg_upgrade to migrate PostgreSQL data between major versions
1115- * Uses the new postgres image with old binaries installed
1116- */
1117- async function runPgUpgrade (
1118- oldVersion : number ,
1119- newVersion : number ,
1120- projectDir : string
1121- ) : Promise < boolean > {
1122- console . log ( `\nMigrating PostgreSQL data from version ${ oldVersion } to ${ newVersion } ...` ) ;
1123-
1124- const volumeName = "postgres_ai_sink_postgres_data" ;
1125- const containerName = "postgres-ai-pg-upgrade" ;
1126-
1127- // Build the upgrade script that runs inside the container
1128- const upgradeScript = `
1129- set -e
1130-
1131- echo "Installing PostgreSQL ${ oldVersion } binaries..."
1132- apt-get update -qq
1133- apt-get install -y -qq postgresql-${ oldVersion } >/dev/null 2>&1
1134-
1135- echo "Preparing data directories..."
1136- mkdir -p /var/lib/postgresql/${ newVersion } /data
1137- chown postgres:postgres /var/lib/postgresql/${ newVersion } /data
1138- chmod 700 /var/lib/postgresql/${ newVersion } /data
1139-
1140- # Initialize new data directory
1141- echo "Initializing new PostgreSQL ${ newVersion } cluster..."
1142- su postgres -c "/usr/lib/postgresql/${ newVersion } /bin/initdb -D /var/lib/postgresql/${ newVersion } /data"
1143-
1144- # Run pg_upgrade
1145- echo "Running pg_upgrade..."
1146- cd /var/lib/postgresql
1147- su postgres -c "/usr/lib/postgresql/${ newVersion } /bin/pg_upgrade \\
1148- --old-datadir=/var/lib/postgresql/data \\
1149- --new-datadir=/var/lib/postgresql/${ newVersion } /data \\
1150- --old-bindir=/usr/lib/postgresql/${ oldVersion } /bin \\
1151- --new-bindir=/usr/lib/postgresql/${ newVersion } /bin \\
1152- --link"
1153-
1154- # Replace old data with upgraded data
1155- echo "Finalizing upgrade..."
1156- rm -rf /var/lib/postgresql/data.old 2>/dev/null || true
1157- mv /var/lib/postgresql/data /var/lib/postgresql/data.old
1158- mv /var/lib/postgresql/${ newVersion } /data /var/lib/postgresql/data
1159-
1160- echo "PostgreSQL upgrade completed successfully!"
1161- ` ;
1162-
1163- try {
1164- // Remove any existing upgrade container
1165- spawnSync ( "docker" , [ "rm" , "-f" , containerName ] , { stdio : "ignore" } ) ;
1166-
1167- // Run upgrade in a temporary container
1168- console . log ( "Starting upgrade container..." ) ;
1169- const result = spawnSync (
1170- "docker" ,
1171- [
1172- "run" ,
1173- "--rm" ,
1174- "--name" , containerName ,
1175- "-v" , `${ volumeName } :/var/lib/postgresql/data` ,
1176- `postgres:${ newVersion } ` ,
1177- "bash" , "-c" , upgradeScript
1178- ] ,
1179- { stdio : "inherit" }
1180- ) ;
1181-
1182- if ( result . status === 0 ) {
1183- console . log ( "✓ PostgreSQL upgrade completed successfully\n" ) ;
1184- return true ;
1185- } else {
1186- console . error ( "✗ PostgreSQL upgrade failed" ) ;
1187- return false ;
1188- }
1189- } catch ( error ) {
1190- const message = error instanceof Error ? error . message : String ( error ) ;
1191- console . error ( `PostgreSQL upgrade failed: ${ message } ` ) ;
1192- return false ;
1193- }
1194- }
1195-
11961073/**
11971074 * Get docker compose command
11981075 */
@@ -1837,17 +1714,17 @@ mon
18371714 }
18381715
18391716 // Check if PostgreSQL major version upgrade is needed
1840- const needsPgUpgrade = currentPgVersion && targetPgVersion && currentPgVersion !== targetPgVersion ;
1717+ const pgUpgradeNeeded = needsPostgresUpgrade ( currentPgVersion , targetPgVersion ) ;
18411718
1842- if ( needsPgUpgrade ) {
1719+ if ( pgUpgradeNeeded && currentPgVersion && targetPgVersion ) {
18431720 console . log ( `\n⚠ PostgreSQL major version change detected: ${ currentPgVersion } → ${ targetPgVersion } ` ) ;
18441721
18451722 // Stop services before upgrade
18461723 console . log ( "\nStopping services for PostgreSQL upgrade..." ) ;
18471724 await runCompose ( [ "stop" ] ) ;
18481725
18491726 // Run pg_upgrade
1850- const upgradeSuccess = await runPgUpgrade ( currentPgVersion , targetPgVersion , projectDir ) ;
1727+ const upgradeSuccess = await runPgUpgrade ( currentPgVersion , targetPgVersion ) ;
18511728
18521729 if ( ! upgradeSuccess ) {
18531730 console . error ( "\n✗ PostgreSQL upgrade failed" ) ;
@@ -1876,7 +1753,7 @@ mon
18761753
18771754 if ( restartCode === 0 ) {
18781755 console . log ( "\n✓ Update completed successfully" ) ;
1879- if ( needsPgUpgrade ) {
1756+ if ( pgUpgradeNeeded ) {
18801757 console . log ( `✓ PostgreSQL upgraded from ${ currentPgVersion } to ${ targetPgVersion } ` ) ;
18811758 }
18821759 } else {
0 commit comments