Oracle deployments have a reputation. They're slow to set up, painful to automate, and the tooling ecosystem tends to assume you have deep pockets. If you've tried to build a reliable Oracle deployment pipeline, you've probably hit at least one of these walls:
- No consistent audit trail of what was deployed, when, and whether it succeeded
- Pre/post deployment steps scattered across runbooks and tribal knowledge
- Connection strings with credentials in environment files and CI/CD config
- Multi-schema releases stitched together with shell scripts
drm-cli layers on top of Flyway or Liquibase — adding release tracking, encrypted credentials, retry logic, and pre/post deployment scripting. It's free and open-source, which means Oracle-grade deployment management without an extra licensing cost on the tooling layer.
This tutorial walks through a complete Oracle deployment using drm-cli + Flyway.
Prerequisites
Before you start, you'll need:
- Python 3.7+ installed on the host running drm-cli
- git to clone the repo
- Flyway installed and on your PATH — download here
-
Oracle JDBC driver (
ojdbc11.jar) — available from Oracle's driver download page - An Oracle database you can connect to (Oracle XE works fine for testing)
Step 1 — Install drm-cli
Clone the repository and run the installer:
git clone https://github.com/dband-drm/drm-cli.git
cd drm-cli
python3 ./install.py
The installer is interactive — it will prompt you for:
- Installation path — where drm-cli will be installed (defaults to your home directory)
- Encryption key — to encrypt sensitive data like connection strings at rest (optional but recommended)
-
Storage type —
json(file-based, no extra dependencies) orsqlite
For a non-interactive install:
python3 ./install.py -d json -p none
(-p none means no encryption — use only for local test environments)
Once complete:
INFO - DRM installation finished successfully!!!
Step 2 — Prepare Your Flyway Migrations
drm-cli works with your existing Flyway migration scripts. Standard Flyway naming conventions apply — nothing needs to change:
my-oracle-migrations/
├── V1__create_accounts_table.sql
├── V2__add_account_status.sql
└── V3__create_transactions_table.sql
Example migrations:
-- V1__create_accounts_table.sql
CREATE TABLE accounts (
account_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
account_name VARCHAR2(100) NOT NULL,
created_at TIMESTAMP DEFAULT SYSTIMESTAMP
);
-- V2__add_account_status.sql
ALTER TABLE accounts
ADD status VARCHAR2(20) DEFAULT 'ACTIVE';
Note the path to this directory — you'll need it in the next step.
Step 3 — Configure Your Release
drm-cli stores all release configuration in a central database. Depending on the storage type you chose at install, this is either drm_db.json or drm_db.sqlite inside the db/ folder in your drm-cli installation directory.
JSON style
Open <install-path>/db/drm_db.json in any editor. Find the releases array and add your release with a solution and connection:
{
"id": 10,
"name": "oracle-release-v1",
"solutions": [
{
"name": "core-schema-flyway",
"solution_type_id": 3,
"path": "/path/to/my-oracle-migrations",
"connections": [
{
"name": "oracle-prod",
"connection_type_id": 2,
"connection_string": "url=jdbc:oracle:thin:@//127.0.0.1:1521/XEPDB1;username=deploy_user;password=your-password;"
}
]
}
]
}
Key fields:
-
solution_type_id: 3— Flyway (use2for Liquibase) -
path— the directory containing your Flyway migration scripts -
connection_type_id: 2— Oracle -
connection_string— the JDBC connection string Flyway uses
SQLite style
Insert via SQL:
-- Add the release
INSERT INTO releases (id, name) VALUES (10, 'oracle-release-v1');
-- Add the Flyway solution
INSERT INTO solutions (id, name, release_id, ordinal, solution_type_id, path)
VALUES (100, 'core-schema-flyway', 10, 1, 3, '/path/to/my-oracle-migrations');
-- Add the Oracle connection
INSERT INTO connections (id, name, solution_id, connection_type_id, connection_string)
VALUES (1001, 'oracle-prod', 100, 2,
'url=jdbc:oracle:thin:@//127.0.0.1:1521/XEPDB1;username=deploy_user;password=your-password;');
Step 4 — Run Your First Deployment
Navigate to your drm-cli installation directory and run:
python3 ./drm_deploy.py -c oracle-prod -r 10 --deploy
Parameters:
-
-c oracle-prod— the connection name you defined in the config -
-r 10— the release ID -
--deploy— execute the deployment (use--dryrunto generate scripts without running them)
You'll see output as drm-cli invokes Flyway, captures the result, and records it:
INFO - DRM Deploy started
INFO - Running solution: core-schema-flyway
INFO - Executing Flyway migrate...
INFO - Flyway: Successfully applied 3 migrations to schema "DEPLOY_USER"
INFO - Deployment recorded successfully
INFO - DRM Deploy finished successfully!!!
That last line is what makes drm-cli different from running Flyway directly. Every deployment is written to the release history — timestamp, connection, release ID, outcome.
Step 5 — View Deployment History
After a deployment runs, drm-cli records the full event.
JSON style
Browse to <install-path>/deployments/. Each deployment creates a log file named:
Deploy_{GUID}_C{connection-name}_R{release-id}.json
Open it to see the full deployment record: every step, its start/end time, status, and any error messages. This audit trail lives entirely in your own infrastructure — no cloud service, no external dependency.
SQLite style
Query the deployments table:
SELECT d.*, ds.name AS status
FROM deployments AS d
INNER JOIN deployment_statuses AS ds ON ds.id = d.deployment_status_id
ORDER BY d.start_time DESC
LIMIT 10;
Step 6 — What Happens When a Migration Fails
If your network connection to Oracle drops mid-deployment, drm-cli retries automatically. Retry behavior is configured in drm_deploy.config inside your drm-cli installation:
"retry_attempts": 3,
"retry_delay_seconds": 10
With this config, a failed step will retry up to 3 times with a 10-second delay. If all retries are exhausted, the deployment is marked failed and the full error is recorded in the deployment log — so you know exactly what ran, what didn't, and when.
Step 7 — Encrypting Your Oracle Credentials
Storing plaintext connection strings is a habit worth breaking. If you installed drm-cli with an encryption key, use drm_crypto.py to encrypt your connection string:
python3 ./drm_crypto.py
The utility prompts you for your encryption key and the value to encrypt, then returns the encrypted string. Replace the plaintext value in your connection config with the result:
"connection_string": "url=jdbc:oracle:thin:@//127.0.0.1:1521/XEPDB1;username=deploy_user;password=ENCRYPTED_VALUE_HERE;"
drm-cli decrypts credentials at deploy time — they never appear in logs or trace output.
Using Liquibase Instead of Flyway
Swap solution_type_id: 3 for solution_type_id: 2 and set path to your Liquibase changelog directory. The connection config is identical:
{
"name": "core-schema-liquibase",
"solution_type_id": 2,
"path": "/path/to/liquibase/changelogs",
"connections": [
{
"name": "oracle-prod",
"connection_type_id": 2,
"connection_string": "url=jdbc:oracle:thin:@//127.0.0.1:1521/XEPDB1;username=deploy_user;password=your-password;"
}
]
}
The deployment command is identical:
python3 ./drm_deploy.py -c oracle-prod -r 10 --deploy
What's Next
- Week 6 — Pre/post deployment scripts: automating steps that always run before and after every deployment
- Week 7 — Multi-database releases: SQL Server, PostgreSQL, and Oracle in a single coordinated release
The full source and documentation is at github.com/dband-drm/drm-cli. Open issues there if you hit anything unexpected.
drm-cli is free and open-source. No license tiers, no paid features.
Top comments (0)