How to Automate Database Releases Across MSSQL, PostgreSQL, and Oracle with a Single CLI
Managing database releases across multiple platforms is one of the harder parts of a DevOps pipeline. Application code gets clean CI/CD workflows, but databases often end up with a folder of SQL scripts, a shared checklist, and someone holding their breath on release night.
This guide walks through how to use drm-cli — an open-source Data Release Manager — to automate and standardize database releases across MSSQL, PostgreSQL, and Oracle from a single CLI.
What drm-cli does
- Versioned release management backed by a local SQLite or JSON database
- Dry-run mode — generates deployment scripts without executing them so you can review exactly what will happen before anything touches your database
- MSSQL, PostgreSQL, and Oracle support from one tool
- Parallel deployments across multiple target databases
- AES-encrypted credential storage
- CI/CD integration (GitHub Actions, Azure DevOps)
- AI layer: MCP server + natural-language agent for querying release state
Requirements
- Node.js ≥ 16
- Python ≥ 3.10
Installation
npm install -g @d-band-drm/drm-cli
drm-cli install -f /opt/drm -d sqlite -p myencryptionkey
| Flag | Description |
|---|---|
-f |
Target install path |
-d |
Backend: sqlite or json
|
-p |
Encryption key (omit for unencrypted) |
--trace |
Enable debug logging |
This installs DRM into /opt/drm and saves the path to ~/.drm-cli.json so subsequent commands find it automatically.
How DRM is configured
DRM stores its configuration — releases, connections, solutions, and projects — in a local database (SQLite or JSON) that lives in your install path. You define your releases and connections by editing this database directly.
The configuration follows this structure:
Release
└── Solution (the deployment type: MSSQL / Liquibase / Flyway)
├── Connections (named environments: dev, test, prod)
└── Projects (target databases to deploy to)
Here is what a minimal MSSQL release looks like in JSON format:
{
"id": 1,
"name": "Release 1.0 — add orders table",
"is_active": true,
"solutions": [
{
"name": "Orders schema solution",
"solution_type_id": 1,
"path": "../mssql/orders",
"connections": [
{
"name": "dev",
"connection_type_id": 1,
"connection_string": "Server=127.0.0.1;User Id=drm;Password=drm;Encrypt=False;"
},
{
"name": "prod",
"connection_type_id": 1,
"connection_string": "Server=prod-db.internal;User Id=drm;Password=secret;Encrypt=True;"
}
],
"projects": [
{
"name": "OrdersDB",
"targets_compare_db": "OrdersDB",
"targets_type_id": 1,
"targets_list": "[\"OrdersDB\"]",
"fail_on_error": true
}
]
}
]
}
Solution types:
| solution_type_id | Type |
|---|---|
| 1 | Microsoft SQL Server (DACPAC) |
| 2 | Liquibase |
| 3 | Flyway |
Connection types:
| connection_type_id | Type |
|---|---|
| 1 | MSSQL |
| 2 | Oracle |
| 3 | PostgreSQL |
For PostgreSQL with Liquibase, the connection string uses JDBC format:
{
"name": "dev",
"connection_type_id": 3,
"connection_string": "url=jdbc:postgresql://127.0.0.1:5432/mydb;username=drm;password=drm;"
}
For Oracle with Flyway:
{
"name": "dev",
"connection_type_id": 2,
"connection_string": "url=jdbc:oracle:thin:@//127.0.0.1:1521/FREEPDB1;username=drm;password=drm;"
}
If you are using encryption (-p during install), encrypt your connection string passwords first:
drm-cli crypto --encrypt -t "mypassword" -p myencryptionkey
Then use the encrypted value in the connection string.
Step 1: Dry-run before you deploy
Once your release is configured, generate and review the deployment plan without touching any database:
drm-cli deploy -c dev -r 1 --dryrun
DRM generates the full execution plan — every SQL statement, in order — and outputs it for review. You see exactly what will run, against which connection, before anything executes.
Dry-run is especially valuable when:
- Production has data that staging does not
- You want a second pair of eyes on the output before approving
- You need a deployment artifact for change management sign-off
Step 2: Deploy
Once you have reviewed the dry-run output:
drm-cli deploy -c prod -r 1 --deploy
DRM executes the release scripts in order, logs every action, and records the deployment in its history.
Step 3: Align an environment
When environments drift — a hotfix applied directly, or a staging environment that has fallen behind — the --align flag brings a database up to a specific release state:
drm-cli deploy -c staging -r 1 --align
Deploying to multiple databases in parallel
DRM supports parallel deployments across multiple target databases within a single project. To deploy release 12 to four databases at once with a concurrency limit of 2:
{
"name": "MultiDB project",
"targets_type_id": 1,
"targets_list": "[\"DB_A\", \"DB_B\", \"DB_C\", \"DB_D\"]",
"max_degree_in_parallel": 2,
"timeout_in_min": 10,
"fail_on_error": false
}
You can also define priority order (targets_priority) and exclusions (targets_exclude), or use a SQL query to dynamically resolve the target list (targets_type_id: 2).
CI/CD integration
GitHub Actions
name: Deploy Database Release
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install drm-cli
run: npm install -g @d-band-drm/drm-cli
- name: Install DRM
run: drm-cli install -f /opt/drm -d sqlite -p ${{ secrets.DRM_KEY }}
- name: Dry run
run: drm-cli deploy -c ${{ vars.DRM_CONNECTION }} -r ${{ vars.RELEASE_ID }} --dryrun
- name: Deploy
run: drm-cli deploy -c ${{ vars.DRM_CONNECTION }} -r ${{ vars.RELEASE_ID }} --deploy
Store your encryption key as a secret. Connection names and release IDs can be pipeline variables.
AI integration (v1.2.1+)
DRM ships with an MCP server and a natural-language agent:
# Start the MCP server (integrates with Claude Desktop / Claude Code)
DRM_SECRET=myencryptionkey npm run mcp
# Natural language agent (requires ANTHROPIC_API_KEY)
ANTHROPIC_API_KEY=sk-ant-... DRM_SECRET=myencryptionkey node ai/agent/agent.js "list all releases"
ANTHROPIC_API_KEY=sk-ant-... DRM_SECRET=myencryptionkey node ai/agent/agent.js "run dryrun for connection dev release 1"
With the MCP server running inside Claude Code, you can use built-in slash commands:
| Skill | What it does |
|---|---|
/drm-status |
Installation health + last 5 deployments |
/drm-release [id] |
List releases or detail one |
/drm-plan <conn> <rel> |
Dryrun + structured plan |
/drm-deploy <conn> <rel> |
Guided: dryrun → confirm → deploy |
Command reference
| Command | What it does |
|---|---|
drm-cli install -f <path> -d sqlite -p <key> |
Install DRM |
drm-cli deploy -c <conn> -r <id> --dryrun |
Preview deployment |
drm-cli deploy -c <conn> -r <id> --deploy |
Execute release |
drm-cli deploy -c <conn> -r <id> --align |
Align environment to release |
drm-cli crypto --encrypt -t <text> -p <key> |
Encrypt a value |
drm-cli crypto --changepassword -p <old> -n <new> |
Rotate encryption key |
drm-cli uninstall |
Remove DRM |
Resources
- GitHub: github.com/dband-drm/drm-cli
- npm: @d-band-drm/drm-cli
- Website: d-band.com
- Questions: dband.drm@gmail.com
Top comments (0)