initial
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
# 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 to determine the next changeset ID
|
||||
|
||||
```bash
|
||||
find patches/ -name "*.xml" | xargs grep -h 'id="[0-9]' 2>/dev/null | grep -oP 'id="\K[0-9]+' | sort -n | tail -1
|
||||
```
|
||||
|
||||
The next ID = last found ID + 1. If no patches exist yet, start at 1.
|
||||
|
||||
Also check whether oracle and postgresql subdirectories already exist:
|
||||
|
||||
```bash
|
||||
ls patches/
|
||||
```
|
||||
|
||||
## 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 the current date and time.
|
||||
|
||||
```bash
|
||||
mkdir -p patches/oracle patches/postgresql
|
||||
```
|
||||
|
||||
### 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
|
||||
Reference in New Issue
Block a user