133 lines
5.5 KiB
Markdown
133 lines
5.5 KiB
Markdown
---
|
|
name: vitruvio-criar-patch
|
|
description: >
|
|
Use when the user wants to create a new Liquibase database migration patch in a Vitruvio repository.
|
|
Triggers: "create patch", "new patch", "criar patch", "novo patch", "database migration",
|
|
"migração de banco", "changeset", "liquibase", or any request to scaffold oracle/postgresql patch XML files.
|
|
---
|
|
|
|
# Create Vitruvio Patch
|
|
|
|
> All messages shown to the user must be written in Portuguese.
|
|
|
|
You are creating a new Liquibase database migration patch inside a Vitruvio repository. Follow these steps in order.
|
|
|
|
## Step 1 — Confirm you are inside a Vitruvio repo
|
|
|
|
```bash
|
|
ls vitruvio.json 2>/dev/null && echo "OK" || echo "NOT_A_VITRUVIO_REPO"
|
|
```
|
|
|
|
If `NOT_A_VITRUVIO_REPO`, stop and tell the user to `cd` into the correct repo.
|
|
|
|
## Step 2 — Inspect existing patches
|
|
|
|
`vitruvio new patch` auto-detects the next changeset ID by scanning all existing XML files — you don't need to find it manually. For situational awareness you can check:
|
|
|
|
```bash
|
|
find patches/ -name "*.xml" | xargs grep -h 'id="[0-9]' 2>/dev/null | grep -oP 'id="\K[0-9]+' | sort -n | tail -1
|
|
```
|
|
|
|
Next ID = last found + 1. If no patches exist yet, starts at 1. The CLI also creates `patches/oracle/` and `patches/postgresql/` subdirectories if they don't exist yet.
|
|
|
|
## Step 3 — Collect migration details
|
|
|
|
Ask the user (in a single message, only ask what is missing):
|
|
|
|
- **What this migration does** — describe the change (e.g. "add column STATUS to table PEDIDO", "create table AUDIT_LOG", "insert config rows").
|
|
- **Author** — Vitruvio username (e.g. `joao.felix`). Use `git config user.name` if unsure.
|
|
- **Module key** — used in the filename (e.g. `GO`, `checklist`, `faturamento`). Default: the repo's `metadata.key` from `vitruvio.json`.
|
|
|
|
## Step 4 — Create the patch files
|
|
|
|
**Both oracle/ and postgresql/ files must always be created and kept in sync.**
|
|
|
|
Filename convention: `{YYYYMMDDHHmm}_{MODULE_KEY}.xml` (e.g. `202506011430_checklist.xml`).
|
|
|
|
Use `vitruvio new patch` to scaffold — it handles the filename, ID assignment, and directory creation automatically:
|
|
|
|
```bash
|
|
vitruvio new patch <module-key>
|
|
```
|
|
|
|
Find the created files, then replace the SQL placeholder in both with the actual migration for each DB dialect, and set `author` to the correct Vitruvio username:
|
|
|
|
```bash
|
|
ls -t patches/oracle/ | head -1
|
|
```
|
|
|
|
### Absolute rules
|
|
|
|
- **Append-only.** Never edit or delete existing `<changeSet>` entries — modifying a checksum that Liquibase already recorded breaks deployment.
|
|
- **Unique numeric IDs.** Each `<changeSet id="...">` must have a unique ID within the repo. Increment from the last found.
|
|
- **Always use `<preConditions onFail="MARK_RAN">`** — every changeset must be idempotent and safe to re-run on any DB state.
|
|
- **Oracle ≠ PostgreSQL.** Write each file for its target DB — data types, sequences, and quoting differ. Never copy-paste blindly.
|
|
- **One logical change per changeset** — don't batch unrelated changes into a single `<changeSet>`.
|
|
|
|
### File skeleton
|
|
|
|
```xml
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
|
|
http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
|
|
|
|
<changeSet author="<author>" id="<next-id>" objectQuotingStrategy="LEGACY">
|
|
<preConditions onError="WARN" onFail="MARK_RAN" onSqlOutput="IGNORE">
|
|
<!-- guard appropriate for the operation — see examples below -->
|
|
</preConditions>
|
|
<sql endDelimiter=";" splitStatements="true" stripComments="false">
|
|
-- SQL for this DB dialect
|
|
</sql>
|
|
</changeSet>
|
|
|
|
</databaseChangeLog>
|
|
```
|
|
|
|
### preConditions reference
|
|
|
|
| Operation | Guard to use |
|
|
|-----------|-------------|
|
|
| CREATE TABLE | `<not><tableExists tableName="MY_TABLE"/></not>` |
|
|
| ADD COLUMN | `<not><columnExists tableName="MY_TABLE" columnName="MY_COL"/></not>` |
|
|
| CREATE INDEX | `<not><indexExists indexName="IDX_NAME"/></not>` |
|
|
| ADD CONSTRAINT / FK | `<not><foreignKeyConstraintExists foreignKeyName="FK_NAME"/></not>` |
|
|
| INSERT row (by PK) | `<sqlCheck expectedResult="0">SELECT COUNT(*) FROM MY_TABLE WHERE ID = 1</sqlCheck>` |
|
|
| DROP TABLE | `<tableExists tableName="MY_TABLE"/>` |
|
|
| DROP COLUMN | `<columnExists tableName="MY_TABLE" columnName="MY_COL"/>` |
|
|
|
|
### Oracle vs PostgreSQL differences to watch
|
|
|
|
| | Oracle | PostgreSQL |
|
|
|---|---|---|
|
|
| Auto-increment | Separate `CREATE SEQUENCE` + trigger or `DEFAULT seq.NEXTVAL` | `SERIAL` or `GENERATED ALWAYS AS IDENTITY` |
|
|
| String type | `VARCHAR2(n)` | `VARCHAR(n)` |
|
|
| Boolean | `NUMBER(1)` | `BOOLEAN` |
|
|
| Date/time | `DATE`, `TIMESTAMP` | `DATE`, `TIMESTAMP` |
|
|
| Current timestamp | `SYSDATE` | `CURRENT_TIMESTAMP` |
|
|
| Quoting | `LEGACY` strategy (unquoted) | Same |
|
|
|
|
## Step 5 — Check vitruvio.json patches registration
|
|
|
|
The patches directory only needs to be registered once. Check if it is already there:
|
|
|
|
```bash
|
|
grep -A2 '"patches"' vitruvio.json
|
|
```
|
|
|
|
If not registered, add to `vitruvio.json`:
|
|
|
|
```json
|
|
"patches": "patches/"
|
|
```
|
|
|
|
## Step 6 — Report
|
|
|
|
Tell the user:
|
|
- Files created: `patches/oracle/<filename>.xml` and `patches/postgresql/<filename>.xml`
|
|
- Changeset IDs used
|
|
- Summary of what each changeset does
|
|
- Reminder: never edit existing changesets once committed — add new ones instead
|