Agent SkillsOpenAEV-Platform/openaev › review-migration

review-migration

GitHub

针对OpenAEV项目的Flyway数据库迁移脚本进行代码审查,涵盖命名规范、类结构、幂等性、租户隔离及数据安全等维度的检查。

.github/skills/review-migration/SKILL.md OpenAEV-Platform/openaev

Trigger Scenarios

PR中包含Flyway迁移文件变更 需要审查数据库迁移逻辑

Install

npx skills add OpenAEV-Platform/openaev --skill review-migration -g -y
More Options

Non-standard path

npx skills add https://github.com/OpenAEV-Platform/openaev/tree/main/.github/skills/review-migration -g -y

Use without installing

npx skills use OpenAEV-Platform/openaev@review-migration

指定 Agent (Claude Code)

npx skills add OpenAEV-Platform/openaev --skill review-migration -a claude-code -g -y

安装 repo 全部 skill

npx skills add OpenAEV-Platform/openaev --all -g -y

预览 repo 内 skill

npx skills add OpenAEV-Platform/openaev --list

SKILL.md

Frontmatter
{
    "name": "review-migration",
    "description": "Step-by-step Flyway migration review for OpenAEV pull requests. Covers naming, class structure, idempotency, tenant isolation, data safety, and Elasticsearch reindex requirements."
}

Review Migration

Step 1 — Identify migrations in this PR

git diff --name-only HEAD~1 | grep "migration"

If no migration files are changed: skip this skill entirely. If migrations are present: review each one following the steps below.

Step 2 — Verify naming format and uniqueness

# List the last 10 migrations to verify naming format consistency
ls openaev-api/src/main/java/io/openaev/migration/ | sort | tail -10

Verify for each new migration:

  • ☐ Name follows V{major}_{yyyyMMddHHmmssSSS}__{description}.java
  • yyyyMMddHHmmssSSS timestamp block is present (17 digits)
  • {description} uses snake_case (letters, digits, underscores)
  • ☐ Migration filename is unique
  • ☐ No existing migration file was modified (Flyway checksums will break)

Step 3 — Verify class structure

cat openaev-api/src/main/java/io/openaev/migration/V{major}_{yyyyMMddHHmmssSSS}__*.java

Verify:

  • @Component annotation present
  • extends BaseJavaMigration
  • migrate(Context context) method implemented
  • ☐ Uses try (Statement statement = context.getConnection().createStatement()) pattern
  • ☐ No Spring beans injected via @Autowired — Flyway runs before Spring context is fully ready

Step 4 — Verify idempotency

Every DDL statement must be guarded:

Statement Required guard
CREATE TABLE CREATE TABLE IF NOT EXISTS
ADD COLUMN ADD COLUMN IF NOT EXISTS
DROP TABLE DROP TABLE IF EXISTS
DROP COLUMN DROP COLUMN IF EXISTS
CREATE INDEX CREATE INDEX IF NOT EXISTS
CREATE UNIQUE INDEX CREATE UNIQUE INDEX IF NOT EXISTS
# Check for unguarded DDL
grep -n "CREATE TABLE\|ADD COLUMN\|DROP TABLE\|DROP COLUMN\|CREATE INDEX" \
  openaev-api/src/main/java/io/openaev/migration/V{major}_{yyyyMMddHHmmssSSS}__*.java | grep -v "IF NOT EXISTS\|IF EXISTS"

Any result = 🟠 HIGH — not idempotent, will fail on re-run.

Step 5 — Verify tenant isolation

# Check if new tables include tenant_id
grep -n "CREATE TABLE\|tenant_id\|REFERENCES tenants\|ON DELETE CASCADE" \
  openaev-api/src/main/java/io/openaev/migration/V{major}_{yyyyMMddHHmmssSSS}__*.java

Cross-reference with the entity class:

# Find the entity to determine if it extends TenantBase
grep -rn "extends TenantBase" openaev-model/src/main/java/ --include="*.java" | grep -i "{EntityName}"

For tenant-scoped tables, verify:

  • tenant_id VARCHAR(255) NOT NULL column
  • REFERENCES tenants(tenant_id) ON DELETE CASCADE
  • CREATE INDEX IF NOT EXISTS ... ON {table}(tenant_id)
  • ☐ Unique constraints are composite: UNIQUE (field, tenant_id) — never UNIQUE (field) alone

Step 6 — Verify data safety

# Check for NOT NULL columns without DEFAULT
grep -n "NOT NULL" openaev-api/src/main/java/io/openaev/migration/V{major}_{yyyyMMddHHmmssSSS}__*.java | grep -v "DEFAULT\|tenant_id\|id"

For each NOT NULL column on an existing (non-new) table:

  • ☐ A DEFAULT value is provided, OR
  • ☐ The table is new (no existing rows) — document this assumption in the review
# Check for DROP statements
grep -n "DROP TABLE\|DROP COLUMN" openaev-api/src/main/java/io/openaev/migration/V{major}_{yyyyMMddHHmmssSSS}__*.java

Any DROP without a prior deprecation migration = 🔴 CRITICAL.

# Check for large data migrations (UPDATE/INSERT without WHERE or LIMIT)
grep -n "UPDATE\|INSERT INTO\|DELETE FROM" openaev-api/src/main/java/io/openaev/migration/V{major}_{yyyyMMddHHmmssSSS}__*.java

Large data migrations must be batched in chunks of 1000 rows.

Step 7 — Verify Elasticsearch reindex

# Check if the migrated entity is indexed
grep -rn "indexing_status" openaev-api/src/main/java/io/openaev/migration/V{major}_{yyyyMMddHHmmssSSS}__*.java

If the migration modifies a table that has a corresponding Elasticsearch index:

  • DELETE FROM indexing_status WHERE indexing_status_type = '...' is present to trigger reindex

To determine if an entity is indexed:

grep -rn "@Document\|@Indexed" openaev-model/src/main/java/ --include="*.java" | grep -i "{EntityName}"

Step 8 — Compile findings

Generate the Migration Review Summary following the output format defined in migration-reviewer.agent.md.

Determine Rollout Safety verdict:

  • SAFE ✅: idempotent, no data risk, tenant isolation correct
  • CONDITIONAL ⚠️: minor issues that can be fixed without blocking
  • UNSAFE 🔴: any CRITICAL finding — PR must not merge

Version History

  • 3.260818.1 Current 2026-08-20 12:00

Same Skill Collection

.github/skills/add-contract-output-type/SKILL.md
.github/skills/add-migration/SKILL.md
.github/skills/add-test/SKILL.md
.github/skills/create-feature-module/SKILL.md
.github/skills/reduce-tx-baseline/SKILL.md
.github/skills/review-code/SKILL.md
.github/skills/review-docs/SKILL.md
.github/skills/review-frontend/SKILL.md
.github/skills/review-multi-tenancy/SKILL.md
.github/skills/review-performance/SKILL.md
.github/skills/review-security/SKILL.md
.github/skills/activate-tenant-table/SKILL.md

Metadata

Files
0
Version
3.260818.1
Hash
7e7d4bf5
Indexed
2026-08-20 12:00

- 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-25 09:32
浙ICP备14020137号-1 $방문자$