From 16a7aebaddc9dfc48179049260c71348e5e2c59d Mon Sep 17 00:00:00 2001 From: yonastewabe Date: Fri, 24 Jul 2026 14:01:21 +0300 Subject: [PATCH] update migration to before deployment in freight api --- .github/workflows/deploy.yml | 7 +++--- apps/edr-freight-api/Dockerfile | 4 ++++ apps/edr-freight-api/package.json | 1 + .../src/config/database.config.ts | 15 +++++++----- apps/edr-freight-api/src/data-source.ts | 24 ++++++------------- apps/edr-freight-api/src/scripts/migrate.ts | 24 +++++++++++++++++++ 6 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 apps/edr-freight-api/src/scripts/migrate.ts diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f0beccd20..c648fec09 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -144,15 +144,16 @@ jobs: run: ./scripts/deploy/create-npmrc.sh - name: Resolve env file path for ${{ matrix.service }} - if: contains(fromJson('["passenger-api", "payment-api"]'), matrix.service) + if: contains(fromJson('["freight-api", "passenger-api", "payment-api"]'), matrix.service) run: | case "${{ matrix.service }}" in + freight-api) echo "SERVICE_ENV_FILE=apps/edr-freight-api/.env" >> "$GITHUB_ENV" ;; passenger-api) echo "SERVICE_ENV_FILE=apps/edr-passenger-api/.env" >> "$GITHUB_ENV" ;; payment-api) echo "SERVICE_ENV_FILE=apps/edr-payment-api/.env" >> "$GITHUB_ENV" ;; esac - name: Build migration image for ${{ matrix.service }} - if: contains(fromJson('["passenger-api", "payment-api"]'), matrix.service) + if: contains(fromJson('["freight-api", "passenger-api", "payment-api"]'), matrix.service) run: | set -euo pipefail docker build \ @@ -163,7 +164,7 @@ jobs: . - name: Run migrations for ${{ matrix.service }} - if: contains(fromJson('["passenger-api", "payment-api"]'), matrix.service) + if: contains(fromJson('["freight-api", "passenger-api", "payment-api"]'), matrix.service) run: | set -euo pipefail docker run --rm --env-file "${SERVICE_ENV_FILE}" "${COMPOSE_PROJECT_NAME}-${{ matrix.service }}-migration" diff --git a/apps/edr-freight-api/Dockerfile b/apps/edr-freight-api/Dockerfile index 984e622db..e2c4137cc 100644 --- a/apps/edr-freight-api/Dockerfile +++ b/apps/edr-freight-api/Dockerfile @@ -31,6 +31,10 @@ COPY --from=builder /app/ . RUN --mount=type=cache,id=pnpm,target=/pnpm/store \ pnpm deploy --filter="@edr/freight-api" --prod --legacy /deploy +FROM deployer AS migration +WORKDIR /deploy +CMD ["node", "dist/scripts/migrate.js"] + FROM node:24.15.0-alpine AS runner RUN apk add --no-cache libc6-compat ENV NODE_ENV=production diff --git a/apps/edr-freight-api/package.json b/apps/edr-freight-api/package.json index bca74475e..8ecd815ed 100644 --- a/apps/edr-freight-api/package.json +++ b/apps/edr-freight-api/package.json @@ -36,6 +36,7 @@ "iam:migration:show": "pnpm run iam:typeorm:cli migration:show", "iam:seed:run": "cross-env APP_MODULE_PATH=./dist/app.module dotenv -- node ./node_modules/@tria-plc/iamapi-common/dist/db/seed.cli.js", "migrate": "ts-node -r tsconfig-paths/register src/scripts/run-migrations.ts", + "migration:run": "node dist/scripts/migrate.js", "script": "ts-node -r tsconfig-paths/register src/scripts/main.ts" }, "dependencies": { diff --git a/apps/edr-freight-api/src/config/database.config.ts b/apps/edr-freight-api/src/config/database.config.ts index dcf09fbd9..65029819d 100644 --- a/apps/edr-freight-api/src/config/database.config.ts +++ b/apps/edr-freight-api/src/config/database.config.ts @@ -1,5 +1,6 @@ import { registerAs } from "@nestjs/config"; import { TypeOrmModuleOptions } from "@nestjs/typeorm"; +import { DataSourceOptions } from "typeorm"; import { join, dirname } from "path"; import { DefaultPosition, @@ -95,7 +96,7 @@ const iamMigrationsGlob = join( ); const freightMigrationsGlob = join(__dirname, "../migrations/*.js"); -export default registerAs("database", (): TypeOrmModuleOptions => { +export function buildDataSourceOptions(): DataSourceOptions { return { type: "postgres", host: process.env.DB_HOST ?? "localhost", @@ -111,17 +112,19 @@ export default registerAs("database", (): TypeOrmModuleOptions => { // The search_path is instead applied per-connection via a pool `connect` // handler in app.module.ts (see setPoolSearchPath). entities: [__dirname + "/../**/*.entity.{ts,js}", ...iamEntities], - autoLoadEntities: true, migrations: [ - // IAM schema + tables must be created before freight migrations iamMigrationsGlob, freightMigrationsGlob, ], - migrationsRun: true, migrationsTransactionMode: "each", - // Schema changes via migrations only (synchronize breaks ITMLS backfill on existing rows). synchronize: false, logging: process.env.TYPEORM_LOGGING === "true" ? true : ["error", "warn"], }; -}); +} + +export default registerAs("database", (): TypeOrmModuleOptions => ({ + ...buildDataSourceOptions(), + autoLoadEntities: true, + migrationsRun: false, +})); diff --git a/apps/edr-freight-api/src/data-source.ts b/apps/edr-freight-api/src/data-source.ts index 2ae202ebd..03baa31e2 100644 --- a/apps/edr-freight-api/src/data-source.ts +++ b/apps/edr-freight-api/src/data-source.ts @@ -1,21 +1,11 @@ // apps/edr-freight-api/src/data-source.ts -import 'dotenv/config'; -import { DataSource } from 'typeorm'; -//import { ensurePostgresSchemas } from './utils/ensure-postgres-schemas'; // adjust path if needed +import "dotenv/config"; +import { DataSource, DataSourceOptions } from "typeorm"; +import { buildDataSourceOptions } from "./config/database.config"; export const AppDataSource = new DataSource({ - type: 'postgres', - host: process.env.DB_HOST ?? 'localhost', - port: Number(process.env.DB_PORT ?? 5433), - username: process.env.DB_USER ?? 'postgres', - password: process.env.DB_PASSWORD ?? '', - database: process.env.DB_NAME ?? 'edr_freight', - schema: 'freight', // default schema for entities without an explicit schema - entities: [__dirname + '/**/*.entity{.ts,.js}'], - migrations: [__dirname + '/migrations/*{.ts,.js}'], - synchronize: false, - logging: process.env.TYPEORM_LOGGING === 'true', -}); + ...buildDataSourceOptions(), + schema: "freight", +} as DataSourceOptions); -// Optional: call ensurePostgresSchemas before initializing -// But you can also run it separately. +export default AppDataSource; diff --git a/apps/edr-freight-api/src/scripts/migrate.ts b/apps/edr-freight-api/src/scripts/migrate.ts new file mode 100644 index 000000000..7f331e1d3 --- /dev/null +++ b/apps/edr-freight-api/src/scripts/migrate.ts @@ -0,0 +1,24 @@ +import "dotenv/config"; +import { AppDataSource } from "../data-source"; +import { ensurePostgresSchemas } from "../config/ensure-postgres-schemas"; +import { buildDataSourceOptions } from "../config/database.config"; + +async function main(): Promise { + await ensurePostgresSchemas(buildDataSourceOptions()); + + await AppDataSource.initialize(); + try { + const applied = await AppDataSource.runMigrations(); + for (const migration of applied) { + console.log(`applied: ${migration.name}`); + } + if (applied.length === 0) console.log("no pending migrations"); + } finally { + await AppDataSource.destroy(); + } +} + +main().catch((err) => { + console.error(err); + process.exit(1); +});