mirror of
https://github.com/twentyhq/twenty
synced 2026-04-21 13:37:22 +00:00
Upgrade command internal doc (#19541)
Open to discussion not sure on where to store such documentation
This commit is contained in:
parent
186bc02533
commit
847e7124d7
6 changed files with 178 additions and 37 deletions
|
|
@ -71,10 +71,10 @@ npx nx build twenty-server
|
||||||
# Database management
|
# Database management
|
||||||
npx nx database:reset twenty-server # Reset database
|
npx nx database:reset twenty-server # Reset database
|
||||||
npx nx run twenty-server:database:init:prod # Initialize database
|
npx nx run twenty-server:database:init:prod # Initialize database
|
||||||
npx nx run twenty-server:database:migrate:prod # Run migrations
|
npx nx run twenty-server:database:migrate:prod # Run instance commands (fast only)
|
||||||
|
|
||||||
# Generate migration
|
# Generate an instance command (fast or slow)
|
||||||
npx nx run twenty-server:database:migrate:generate
|
npx nx run twenty-server:database:migrate:generate --name <name> --type <fast|slow>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Database Inspection (Postgres MCP)
|
### Database Inspection (Postgres MCP)
|
||||||
|
|
@ -158,14 +158,17 @@ packages/
|
||||||
- **Redis** for caching and session management
|
- **Redis** for caching and session management
|
||||||
- **BullMQ** for background job processing
|
- **BullMQ** for background job processing
|
||||||
|
|
||||||
### Database & Migrations
|
### Database & Upgrade Commands
|
||||||
- **PostgreSQL** as primary database
|
- **PostgreSQL** as primary database
|
||||||
- **Redis** for caching and sessions
|
- **Redis** for caching and sessions
|
||||||
- **ClickHouse** for analytics (when enabled)
|
- **ClickHouse** for analytics (when enabled)
|
||||||
- Always generate migrations when changing entity files
|
- When changing entity files, generate an **instance command** (`database:migrate:generate --name <name> --type <fast|slow>`)
|
||||||
- Migration names must be kebab-case (e.g. `add-agent-turn-evaluation`)
|
- **Fast** instance commands handle schema changes; **slow** ones add a `runDataMigration` step for data backfills
|
||||||
- Include both `up` and `down` logic in migrations
|
- **Workspace commands** iterate over all active/suspended workspaces for per-workspace upgrades
|
||||||
- Never delete or rewrite committed migrations
|
- Commands use `@RegisteredInstanceCommand` and `@RegisteredWorkspaceCommand` decorators for automatic discovery
|
||||||
|
- Include both `up` and `down` logic in instance commands
|
||||||
|
- Never delete or rewrite committed instance command `up`/`down` logic
|
||||||
|
- See `packages/twenty-server/docs/UPGRADE_COMMANDS.md` for full documentation
|
||||||
|
|
||||||
### Utility Helpers
|
### Utility Helpers
|
||||||
Use existing helpers from `twenty-shared` instead of manual type guards:
|
Use existing helpers from `twenty-shared` instead of manual type guards:
|
||||||
|
|
@ -178,7 +181,7 @@ IMPORTANT: Use Context7 for code generation, setup or configuration steps, or li
|
||||||
### Before Making Changes
|
### Before Making Changes
|
||||||
1. Always run linting (`lint:diff-with-main`) and type checking after code changes
|
1. Always run linting (`lint:diff-with-main`) and type checking after code changes
|
||||||
2. Test changes with relevant test suites (prefer single-file test runs)
|
2. Test changes with relevant test suites (prefer single-file test runs)
|
||||||
3. Ensure database migrations are generated for entity changes
|
3. Ensure instance commands are generated for entity changes (`database:migrate:generate`)
|
||||||
4. Check that GraphQL schema changes are backward compatible
|
4. Check that GraphQL schema changes are backward compatible
|
||||||
5. Run `graphql:generate` after any GraphQL schema changes
|
5. Run `graphql:generate` after any GraphQL schema changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ This directory contains Twenty's development guidelines and best practices in th
|
||||||
### Core Guidelines
|
### Core Guidelines
|
||||||
- **architecture.mdc** - Project overview, technology stack, and infrastructure setup (Always Applied)
|
- **architecture.mdc** - Project overview, technology stack, and infrastructure setup (Always Applied)
|
||||||
- **nx-rules.mdc** - Nx workspace guidelines and best practices (Auto-attached to Nx files)
|
- **nx-rules.mdc** - Nx workspace guidelines and best practices (Auto-attached to Nx files)
|
||||||
- **server-migrations.mdc** - Backend migration and TypeORM guidelines for `twenty-server` (Auto-attached to server entities and migration files)
|
- **server-migrations.mdc** - Upgrade command guidelines (instance commands and workspace commands) for `twenty-server` (Auto-attached to server entities and upgrade command files)
|
||||||
- **creating-syncable-entity.mdc** - Comprehensive guide for creating new syncable entities (with universalIdentifier and applicationId) in the workspace migration system (Agent-requested for metadata-modules and workspace-migration files)
|
- **creating-syncable-entity.mdc** - Comprehensive guide for creating new syncable entities (with universalIdentifier and applicationId) in the workspace migration system (Agent-requested for metadata-modules and workspace-migration files)
|
||||||
|
|
||||||
### Code Quality
|
### Code Quality
|
||||||
|
|
@ -81,10 +81,8 @@ npx nx run twenty-server:typecheck # Type checking
|
||||||
npx nx run twenty-server:test # Run unit tests
|
npx nx run twenty-server:test # Run unit tests
|
||||||
npx nx run twenty-server:test:integration:with-db-reset # Run integration tests
|
npx nx run twenty-server:test:integration:with-db-reset # Run integration tests
|
||||||
|
|
||||||
# Migrations
|
# Upgrade commands (instance + workspace)
|
||||||
npx nx run twenty-server:database:migrate:generate
|
npx nx run twenty-server:database:migrate:generate --name <name> --type <fast|slow>
|
||||||
|
|
||||||
# Workspace
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage Guidelines
|
## Usage Guidelines
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,8 @@ If feature descriptions are not provided or need enhancement, research the codeb
|
||||||
- Services: Look for `*.service.ts` files
|
- Services: Look for `*.service.ts` files
|
||||||
|
|
||||||
**For Database/ORM Changes:**
|
**For Database/ORM Changes:**
|
||||||
- Migrations: `packages/twenty-server/src/database/typeorm/`
|
- Instance commands (fast/slow): `packages/twenty-server/src/database/commands/upgrade-version-command/`
|
||||||
|
- Legacy TypeORM migrations: `packages/twenty-server/src/database/typeorm/`
|
||||||
- Entities: `packages/twenty-server/src/entities/`
|
- Entities: `packages/twenty-server/src/entities/`
|
||||||
|
|
||||||
### Research Commands
|
### Research Commands
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,46 @@
|
||||||
---
|
---
|
||||||
description: Guidelines for generating and managing TypeORM migrations in twenty-server
|
description: Guidelines for generating and managing upgrade commands (instance commands and workspace commands) in twenty-server
|
||||||
globs: [
|
globs: [
|
||||||
"packages/twenty-server/src/**/*.entity.ts",
|
"packages/twenty-server/src/**/*.entity.ts",
|
||||||
"packages/twenty-server/src/database/typeorm/**/*.ts"
|
"packages/twenty-server/src/database/commands/upgrade-version-command/**/*.ts"
|
||||||
]
|
]
|
||||||
alwaysApply: false
|
alwaysApply: false
|
||||||
---
|
---
|
||||||
|
|
||||||
## Server Migrations (twenty-server)
|
## Upgrade Commands (twenty-server)
|
||||||
|
|
||||||
- **When changing an entity, always generate a migration**
|
The upgrade system uses two types of commands instead of raw TypeORM migrations:
|
||||||
- If you modify a `*.entity.ts` file in `packages/twenty-server/src`, you **must** generate a corresponding TypeORM migration instead of manually editing the database schema.
|
- **Instance commands** — schema and data migrations that run once at the instance level.
|
||||||
- Use the Nx command from the project root:
|
- **Workspace commands** — commands that iterate over all active/suspended workspaces.
|
||||||
|
|
||||||
|
See `packages/twenty-server/docs/UPGRADE_COMMANDS.md` for full documentation.
|
||||||
|
|
||||||
|
### Instance Commands
|
||||||
|
|
||||||
|
- **When changing a `*.entity.ts` file**, generate an instance command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx nx run twenty-server:database:migrate:generate
|
npx nx run twenty-server:database:migrate:generate --name <name> --type <fast|slow>
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Prefer generated migrations over manual edits**
|
- **Fast commands** (`--type fast`, default) are for schema-only changes that must run immediately. They implement `FastInstanceCommand` with `up`/`down` methods and use the `@RegisteredInstanceCommand` decorator.
|
||||||
- Let TypeORM infer schema changes from the updated entities; only adjust the generated migration file manually if absolutely necessary (for example, for data backfills or complex constraints).
|
|
||||||
- Keep schema changes (DDL) in these generated migrations and avoid mixing in heavy data migrations unless there is a strong reason and clear comments.
|
|
||||||
|
|
||||||
- **Keep migrations consistent and reversible**
|
- **Slow commands** (`--type slow`) add a `runDataMigration` method for potentially long-running data backfills that execute before `up`. They only run when `--include-slow` is passed. Use the decorator with `{ type: 'slow' }`.
|
||||||
- Ensure the generated migration includes both `up` and `down` logic that correctly applies and reverts the entity change when possible.
|
|
||||||
- Do not delete or rewrite existing, committed migrations unless you are explicitly working on a pre-release branch where history rewrites are allowed by team conventions.
|
- The generator auto-registers the command in `instance-commands.constant.ts` — do not edit that file manually.
|
||||||
|
|
||||||
|
- **Keep commands consistent and reversible**: include both `up` and `down` logic. Do not delete or rewrite existing, committed commands unless on a pre-release branch.
|
||||||
|
|
||||||
|
### Workspace Commands
|
||||||
|
|
||||||
|
- Use the `@RegisteredWorkspaceCommand` decorator alongside nest-commander's `@Command` decorator.
|
||||||
|
- Extend `ActiveOrSuspendedWorkspaceCommandRunner` and implement `runOnWorkspace`.
|
||||||
|
- The base class provides `--dry-run`, `--verbose`, and workspace filter options automatically.
|
||||||
|
|
||||||
|
### Execution Order
|
||||||
|
|
||||||
|
Within a given version, commands run in this order (timestamp-sorted within each group):
|
||||||
|
1. Instance fast commands
|
||||||
|
2. Instance slow commands (only with `--include-slow`)
|
||||||
|
3. Workspace commands
|
||||||
|
|
||||||
|
|
|
||||||
21
CLAUDE.md
21
CLAUDE.md
|
|
@ -71,10 +71,10 @@ npx nx build twenty-server
|
||||||
# Database management
|
# Database management
|
||||||
npx nx database:reset twenty-server # Reset database
|
npx nx database:reset twenty-server # Reset database
|
||||||
npx nx run twenty-server:database:init:prod # Initialize database
|
npx nx run twenty-server:database:init:prod # Initialize database
|
||||||
npx nx run twenty-server:database:migrate:prod # Run migrations
|
npx nx run twenty-server:database:migrate:prod # Run instance commands (fast only)
|
||||||
|
|
||||||
# Generate migration
|
# Generate an instance command (fast or slow)
|
||||||
npx nx run twenty-server:database:migrate:generate
|
npx nx run twenty-server:database:migrate:generate --name <name> --type <fast|slow>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Database Inspection (Postgres MCP)
|
### Database Inspection (Postgres MCP)
|
||||||
|
|
@ -158,14 +158,17 @@ packages/
|
||||||
- **Redis** for caching and session management
|
- **Redis** for caching and session management
|
||||||
- **BullMQ** for background job processing
|
- **BullMQ** for background job processing
|
||||||
|
|
||||||
### Database & Migrations
|
### Database & Upgrade Commands
|
||||||
- **PostgreSQL** as primary database
|
- **PostgreSQL** as primary database
|
||||||
- **Redis** for caching and sessions
|
- **Redis** for caching and sessions
|
||||||
- **ClickHouse** for analytics (when enabled)
|
- **ClickHouse** for analytics (when enabled)
|
||||||
- Always generate migrations when changing entity files
|
- When changing entity files, generate an **instance command** (`database:migrate:generate --name <name> --type <fast|slow>`)
|
||||||
- Migration names must be kebab-case (e.g. `add-agent-turn-evaluation`)
|
- **Fast** instance commands handle schema changes; **slow** ones add a `runDataMigration` step for data backfills
|
||||||
- Include both `up` and `down` logic in migrations
|
- **Workspace commands** iterate over all active/suspended workspaces for per-workspace upgrades
|
||||||
- Never delete or rewrite committed migrations
|
- Commands use `@RegisteredInstanceCommand` and `@RegisteredWorkspaceCommand` decorators for automatic discovery
|
||||||
|
- Include both `up` and `down` logic in instance commands
|
||||||
|
- Never delete or rewrite committed instance command `up`/`down` logic
|
||||||
|
- See `packages/twenty-server/docs/UPGRADE_COMMANDS.md` for full documentation
|
||||||
|
|
||||||
### Utility Helpers
|
### Utility Helpers
|
||||||
Use existing helpers from `twenty-shared` instead of manual type guards:
|
Use existing helpers from `twenty-shared` instead of manual type guards:
|
||||||
|
|
@ -178,7 +181,7 @@ IMPORTANT: Use Context7 for code generation, setup or configuration steps, or li
|
||||||
### Before Making Changes
|
### Before Making Changes
|
||||||
1. Always run linting (`lint:diff-with-main`) and type checking after code changes
|
1. Always run linting (`lint:diff-with-main`) and type checking after code changes
|
||||||
2. Test changes with relevant test suites (prefer single-file test runs)
|
2. Test changes with relevant test suites (prefer single-file test runs)
|
||||||
3. Ensure database migrations are generated for entity changes
|
3. Ensure instance commands are generated for entity changes (`database:migrate:generate`)
|
||||||
4. Check that GraphQL schema changes are backward compatible
|
4. Check that GraphQL schema changes are backward compatible
|
||||||
5. Run `graphql:generate` after any GraphQL schema changes
|
5. Run `graphql:generate` after any GraphQL schema changes
|
||||||
|
|
||||||
|
|
|
||||||
117
packages/twenty-server/docs/UPGRADE_COMMANDS.md
Normal file
117
packages/twenty-server/docs/UPGRADE_COMMANDS.md
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
# Upgrade Commands
|
||||||
|
|
||||||
|
The upgrade process relies on two types of commands:
|
||||||
|
|
||||||
|
- **Instance commands** — schema and data migrations that run once at the instance level (replacing raw TypeORM migrations).
|
||||||
|
- **Workspace commands** — commands that iterate over all active or suspended workspaces to apply per-workspace changes.
|
||||||
|
|
||||||
|
Both are registered via decorators and automatically discovered by the upgrade pipeline.
|
||||||
|
|
||||||
|
## Instance Commands
|
||||||
|
|
||||||
|
### Generating an instance command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx nx run twenty-server:database:migrate:generate --name <name> --type <fast|slow>
|
||||||
|
```
|
||||||
|
|
||||||
|
This generates a timestamped file and auto-registers it in `instance-commands.constant.ts` — do not edit that file manually.
|
||||||
|
|
||||||
|
### Fast instance commands
|
||||||
|
|
||||||
|
Fast commands run immediately during the upgrade. They are used for schema changes that could introduce breaking inconsistencies between the database and the server if delayed.
|
||||||
|
|
||||||
|
A fast command implements `FastInstanceCommand` and provides `up` / `down` methods:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
@RegisteredInstanceCommand('1.22.0', 1775758621017)
|
||||||
|
export class AddWorkspaceIdToTotoFastInstanceCommand
|
||||||
|
implements FastInstanceCommand
|
||||||
|
{
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."toto" ADD "workspaceId" uuid`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."toto" DROP COLUMN "workspaceId"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Slow instance commands
|
||||||
|
|
||||||
|
Slow commands are used when a potentially long-running data migration must happen before the schema change. They only run when the `--include-slow` flag is passed.
|
||||||
|
|
||||||
|
A slow command implements `SlowInstanceCommand`, which extends `FastInstanceCommand` with an additional `runDataMigration` method that executes before `up`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
@RegisteredInstanceCommand('1.22.0', 1775758621018, { type: 'slow' })
|
||||||
|
export class BackfillWorkspaceIdSlowInstanceCommand
|
||||||
|
implements SlowInstanceCommand
|
||||||
|
{
|
||||||
|
async runDataMigration(dataSource: DataSource): Promise<void> {
|
||||||
|
// Backfill logic (can be slow — e.g. iterating over workspaces, cache recomputation)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."toto" ALTER COLUMN "workspaceId" SET NOT NULL`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."toto" ALTER COLUMN "workspaceId" DROP NOT NULL`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A common pattern is to pair a **fast** command (add a nullable column) with a **slow** command (backfill existing rows, then set `NOT NULL`).
|
||||||
|
|
||||||
|
## Workspace Commands
|
||||||
|
|
||||||
|
Workspace commands run per-workspace logic across all active or suspended workspaces. They are registered with the `@RegisteredWorkspaceCommand` decorator alongside nest-commander's `@Command` decorator:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
@RegisteredWorkspaceCommand('1.22.0', 1780000002000)
|
||||||
|
@Command({
|
||||||
|
name: 'upgrade:1-22:backfill-standard-skills',
|
||||||
|
description:
|
||||||
|
'Backfill standard skills for existing workspaces',
|
||||||
|
})
|
||||||
|
export class BackfillStandardSkillsCommand
|
||||||
|
extends ActiveOrSuspendedWorkspaceCommandRunner
|
||||||
|
{
|
||||||
|
constructor(
|
||||||
|
protected readonly workspaceIteratorService: WorkspaceIteratorService,
|
||||||
|
// inject any services you need
|
||||||
|
) {
|
||||||
|
super(workspaceIteratorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
override async runOnWorkspace({
|
||||||
|
workspaceId,
|
||||||
|
options,
|
||||||
|
}: RunOnWorkspaceArgs): Promise<void> {
|
||||||
|
// Per-workspace logic goes here
|
||||||
|
// options.dryRun, options.verbose are available for free
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The base class `ActiveOrSuspendedWorkspaceCommandRunner` handles workspace iteration and provides `--dry-run`, `--verbose`, and workspace filter options automatically.
|
||||||
|
|
||||||
|
## Execution Order
|
||||||
|
|
||||||
|
Within a given version of Twenty, the upgrade pipeline runs commands in this order, sorted by timestamp within each group:
|
||||||
|
|
||||||
|
1. **Instance fast** commands
|
||||||
|
2. **Instance slow** commands
|
||||||
|
3. **Workspace commands**
|
||||||
|
|
||||||
|
Workspace commands are executed sequentially across all active/suspended workspaces.
|
||||||
Loading…
Reference in a new issue