Fix entity-based migrations that crash on missing columns
MusicVideosUpdate and AddEpisodicGenres migrations used TypeORM entity classes which reference columns that don't exist at their migration timestamp (e.g. trailer_old, later entity fields). Rewrote both to use raw SQL INSERT/UPDATE statements. Also bumped CACHEBUST to v3 to force backend image rebuild. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,32 +1,17 @@
|
|||||||
/* eslint-disable unicorn/no-array-method-this-argument */
|
|
||||||
import { Project } from 'src/projects/entities/project.entity';
|
|
||||||
import { Category } from 'src/projects/enums/category.enum';
|
|
||||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
export class MusicVideosUpdate1729096262567 implements MigrationInterface {
|
export class MusicVideosUpdate1729096262567 implements MigrationInterface {
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
// update all projects that have category music-video to have the category narrative and type music-video
|
// Update all projects with category 'music-video' to category 'narrative' + type 'music-video'
|
||||||
const projects = await queryRunner.manager.find(Project, {
|
await queryRunner.query(
|
||||||
where: { category: 'music-video' as Category },
|
`UPDATE "projects" SET "category" = 'narrative', "type" = 'music-video' WHERE "category" = 'music-video' AND "deleted_at" IS NULL`,
|
||||||
});
|
);
|
||||||
const updatedProjects = projects.map((project) => {
|
|
||||||
project.category = 'narrative';
|
|
||||||
project.type = 'music-video';
|
|
||||||
return project;
|
|
||||||
});
|
|
||||||
await queryRunner.manager.save(updatedProjects);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
// update all projects that have category narrative and type music-video to have the category music-video
|
// Revert: projects with category 'narrative' and type 'music-video' back to category 'music-video', type 'film'
|
||||||
const projects = await queryRunner.manager.find(Project, {
|
await queryRunner.query(
|
||||||
where: { category: 'narrative' as Category, type: 'music-video' },
|
`UPDATE "projects" SET "category" = 'music-video', "type" = 'film' WHERE "category" = 'narrative' AND "type" = 'music-video' AND "deleted_at" IS NULL`,
|
||||||
});
|
);
|
||||||
const updatedProjects = projects.map((project) => {
|
|
||||||
project.category = 'music-video' as Category;
|
|
||||||
project.type = 'film';
|
|
||||||
return project;
|
|
||||||
});
|
|
||||||
await queryRunner.manager.save(updatedProjects);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,97 +1,33 @@
|
|||||||
import { Genre } from 'src/genres/entities/genre.entity';
|
|
||||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
export class AddEpisodicGenres1730338365708 implements MigrationInterface {
|
export class AddEpisodicGenres1730338365708 implements MigrationInterface {
|
||||||
episodicGenres = [
|
|
||||||
{
|
|
||||||
id: 'f49d5884-842b-4f8e-b64f-c3f9a4e335d2',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Drama',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3170f9cc-338a-4478-a14c-39bce63870d0',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Comedy',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '6f1785ef-b59b-4032-acc1-705f0aece2e6',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Action & Adventure',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '932a7b0e-b07b-4829-9e17-36b13805c516',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Science Fiction & Fantasy',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '88ea9593-12c0-4308-8157-c8ed5cf85568',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Mystery & Thriller',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '264f275e-87ec-4f91-9c64-28264d869375',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Horror',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'a0bf144a-9bb7-4152-b30f-6d52ad064cf4',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Reality TV',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '5b6ad647-d49b-4d4b-84c9-8b84bb5ebb86',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Documentary',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '57751942-f0ba-499a-b220-7985059bc194',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Animated Series',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'e90710dd-cac4-4997-923a-78b19d778876',
|
|
||||||
type: 'episodic',
|
|
||||||
name: "Children's Programming",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '62c3e54a-cf91-4a01-9eb3-f6e5ba70b74e',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Variety & Talk Shows',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '03e341d5-0338-406b-9672-64a06cf2b831',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'News & Current Affairs',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '094777d5-5926-43bf-a384-60f800fb6010',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Game Shows',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '7e32a2d4-9615-49c0-9238-d10f997c43d5',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Sports',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'b492be4d-0011-443a-9094-9b927e2650a5',
|
|
||||||
type: 'episodic',
|
|
||||||
name: 'Music Television',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.manager.save(
|
// Insert episodic genres using raw SQL to avoid entity column mismatches
|
||||||
queryRunner.manager.create<Genre, Record<string, unknown>>(
|
await queryRunner.query(`
|
||||||
Genre,
|
INSERT INTO "genres" ("id", "type", "name")
|
||||||
this.episodicGenres,
|
VALUES
|
||||||
),
|
('f49d5884-842b-4f8e-b64f-c3f9a4e335d2', 'episodic', 'Drama'),
|
||||||
);
|
('3170f9cc-338a-4478-a14c-39bce63870d0', 'episodic', 'Comedy'),
|
||||||
|
('6f1785ef-b59b-4032-acc1-705f0aece2e6', 'episodic', 'Action & Adventure'),
|
||||||
|
('932a7b0e-b07b-4829-9e17-36b13805c516', 'episodic', 'Science Fiction & Fantasy'),
|
||||||
|
('88ea9593-12c0-4308-8157-c8ed5cf85568', 'episodic', 'Mystery & Thriller'),
|
||||||
|
('264f275e-87ec-4f91-9c64-28264d869375', 'episodic', 'Horror'),
|
||||||
|
('a0bf144a-9bb7-4152-b30f-6d52ad064cf4', 'episodic', 'Reality TV'),
|
||||||
|
('5b6ad647-d49b-4d4b-84c9-8b84bb5ebb86', 'episodic', 'Documentary'),
|
||||||
|
('57751942-f0ba-499a-b220-7985059bc194', 'episodic', 'Animated Series'),
|
||||||
|
('e90710dd-cac4-4997-923a-78b19d778876', 'episodic', 'Children''s Programming'),
|
||||||
|
('62c3e54a-cf91-4a01-9eb3-f6e5ba70b74e', 'episodic', 'Variety & Talk Shows'),
|
||||||
|
('03e341d5-0338-406b-9672-64a06cf2b831', 'episodic', 'News & Current Affairs'),
|
||||||
|
('094777d5-5926-43bf-a384-60f800fb6010', 'episodic', 'Game Shows'),
|
||||||
|
('7e32a2d4-9615-49c0-9238-d10f997c43d5', 'episodic', 'Sports'),
|
||||||
|
('b492be4d-0011-443a-9094-9b927e2650a5', 'episodic', 'Music Television')
|
||||||
|
ON CONFLICT ("id") DO NOTHING
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.manager.delete(Genre, {
|
await queryRunner.query(
|
||||||
type: 'episodic',
|
`DELETE FROM "genres" WHERE "type" = 'episodic'`,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,12 +44,12 @@ services:
|
|||||||
|
|
||||||
# ── Backend API (NestJS) ────────────────────────────────────
|
# ── Backend API (NestJS) ────────────────────────────────────
|
||||||
api:
|
api:
|
||||||
image: indeehub-api:v2
|
image: indeehub-api:v3
|
||||||
build:
|
build:
|
||||||
context: ./backend
|
context: ./backend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
CACHEBUST: "2"
|
CACHEBUST: "3"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
# ── Core ─────────────────────────────────────────────
|
# ── Core ─────────────────────────────────────────────
|
||||||
@@ -177,12 +177,12 @@ services:
|
|||||||
|
|
||||||
# ── FFmpeg Transcoding Worker ───────────────────────────────
|
# ── FFmpeg Transcoding Worker ───────────────────────────────
|
||||||
ffmpeg-worker:
|
ffmpeg-worker:
|
||||||
image: indeehub-ffmpeg:v2
|
image: indeehub-ffmpeg:v3
|
||||||
build:
|
build:
|
||||||
context: ./backend
|
context: ./backend
|
||||||
dockerfile: Dockerfile.ffmpeg
|
dockerfile: Dockerfile.ffmpeg
|
||||||
args:
|
args:
|
||||||
CACHEBUST: "2"
|
CACHEBUST: "3"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
ENVIRONMENT: production
|
ENVIRONMENT: production
|
||||||
|
|||||||
Reference in New Issue
Block a user