This guide walks through installing the dbpm CLI, configuring a Linux environment, bootstrapping Core, installing a package, and publishing a package artifact.
dbpm is an Oracle database package manager. It resolves package artifacts, plans dependency order, executes package manifests through SQL*Plus or SQLcl, and records deployment state in Core. Core is the in-database substrate for dbpm-managed deployments; ordinary packages depend on Core being present, but they should not list Core as a normal package dependency.
You need:
- Linux or another Unix-like shell environment.
- Python 3.11 or newer.
- Oracle SQLcl or SQL*Plus on the machine where dbpm runs.
- A target Oracle schema and connect string.
- A GitHub token if you consume private GitHub Packages artifacts.
- GPG if you publish packages with
dbpm publish.
Confirm the basic tools:
python3 --version
sql -versionIf you use SQL*Plus instead of SQLcl, confirm sqlplus is on your PATH or set DBPM_SQL_RUNNER to its full path.
Install dbpm as a user-level CLI tool:
# Stable released CLI version.
python3 -m pip install --user git+https://github.com/512itconsulting/dbpm.git@v1.1.1
# Latest development version from the default branch.
python3 -m pip install --user git+https://github.com/512itconsulting/dbpm.git
dbpm --helpIf you use pipx, the equivalent install is:
pipx install git+https://github.com/512itconsulting/dbpm.git@v1.1.1For development from a local checkout, use a virtual environment:
git clone https://github.com/512itconsulting/dbpm.git
cd dbpm
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'
dbpm --helpThe examples below use dbpm directly. Contributors who prefer uv may use
uv sync and uv run dbpm ..., but uv is not required to run dbpm.
Create a local environment file. Do not commit this file; it can contain credentials.
cp dbpm-env.sh.example dbpm-env.shEdit dbpm-env.sh:
export TNS_ADMIN="$HOME/.oracle/tns_admin"
export DBPM_SQL_RUNNER="$HOME/opt/sqlcl/bin/sql"
# Option A: raw Oracle connect string.
export DBPM_CONNECT="user/password@service_name"
# Option B: SQLcl saved connection name local to this OS user.
# Do not put a saved connection name in DBPM_CONNECT.
# unset DBPM_CONNECT
# export DBPM_CONNECT_NAME="Development Database (APP_USER)"
# Required for private GitHub Packages.
export DBPM_GITHUB_TOKEN="github_token_with_package_read_access"
export DBPM_GITHUB_USER="github_username"
# Runtime directories.
export DBPM_CACHE_DIR="$HOME/.local/cache/dbpm"
export DBPM_LOG_DIR="$HOME/.local/state/dbpm_logs"Load it before running dbpm:
source ./dbpm-env.shCheck that dbpm can find the SQL runner and database connection setting:
printf '%s\n' "$DBPM_SQL_RUNNER"
printf '%s\n' "${DBPM_CONNECT:-$DBPM_CONNECT_NAME}"DBPM_CONNECT is for raw Oracle connect strings, such as
user/password@service_name. DBPM_CONNECT_NAME is for SQLcl saved
connections from SQLcl's local connection store. It requires SQLcl
(DBPM_SQL_RUNNER=sql or a SQLcl executable path) and cannot be set at the
same time as DBPM_CONNECT. If your database is saved in SQLcl as
dev_database, use DBPM_CONNECT_NAME=dev_database and unset DBPM_CONNECT.
To scaffold a new package repository from scratch:
mkdir my_package
dbpm init package my_package --name my_package --description "My Oracle package"To scaffold a new workspace with multiple packages:
mkdir my_workspace
dbpm init workspace my_workspace --package billing --package ordersdbpm init creates the standard directory layout, a self-documented dbpm.yaml
manifest, a README, a LICENSE placeholder, and git-friendly placeholder files.
Edit dbpm.yaml to fill in description, dependencies, and publishing config as
needed.
See dbpm init for the full option reference.
dbpm accepts several source formats:
- A local package directory containing
dbpm.yaml,dbpm.yml,dbpm.json, orpackage.dbpm.yaml. - A local ZIP package.
- A GitHub Packages Maven coordinate.
- A generic Maven coordinate.
- A dbpm registry source such as
registry:package@constraint. - A direct HTTPS ZIP URL for lockfile-driven installs.
Common GitHub Packages source form:
gh-maven:owner/repo:group:artifact:version[:extension]
Example:
gh-maven:512itconsulting/core:com.512itconsulting.database:core:3.5.0
See source types for the full syntax.
Core must be installed before dbpm can run ordinary package deployments.
Preview the bootstrap plan:
dbpm bootstrap-core \
gh-maven:512itconsulting/core:com.512itconsulting.database:core:3.5.0 \
--dry-runBootstrap Core into an empty or prepared schema:
dbpm bootstrap-core \
gh-maven:512itconsulting/core:com.512itconsulting.database:core:3.5.0 \
--policy unlocked \
--deploy-environment DEVVerify Core:
dbpm check-core --minimum-version 3.5.0Use bootstrap-core only for the initial Core installation. If Core already exists, dbpm will block bootstrap and tell you to use upgrade, resume, or an explicit destructive reinstall path.
Preview a package install:
dbpm plan \
gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0 \
--mode installInstall the package:
dbpm install \
gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0Validate it if the package declares a validation script:
dbpm validate \
gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0When dependencies are declared and all sources are known, provide dependency sources so dbpm can resolve the full graph before any script runs.
dbpm plan \
gh-maven:rsantmyer/simple_scheduler:com.512itconsulting.database:simple_scheduler:1.1.0 \
--mode install \
--dependency-source gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0dbpm install \
gh-maven:rsantmyer/simple_scheduler:com.512itconsulting.database:simple_scheduler:1.1.0 \
--dependency-source gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0Dependencies are installed before consumers. Core remains an implicit substrate prerequisite, not a normal dependency to resolve and install as part of every package graph.
For repeatable deployments, create a lockfile:
dbpm lock \
gh-maven:rsantmyer/simple_scheduler:com.512itconsulting.database:simple_scheduler:1.1.0 \
--dependency-source gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0Install from the lockfile:
dbpm install --lockfile dbpm-lock.jsonCheck that a lockfile still matches package resolution:
dbpm lock \
gh-maven:rsantmyer/simple_scheduler:com.512itconsulting.database:simple_scheduler:1.1.0 \
--dependency-source gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0 \
--checkCommit release-oriented lockfiles so production deployments use exact artifact identities and checksums.
Upgrade an installed package:
dbpm upgrade \
gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.1.0If a deployment failed or was interrupted, prefer resume:
dbpm resume \
gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0Use reinstall only when a clean slate is acceptable:
dbpm reinstall \
gh-maven:512itconsulting/utl_interval:com.512itconsulting.database:utl_interval:1.0.0 \
--allow-destructiveCore reinstall is a schema-level dbpm system teardown. Treat it as equivalent to wiping dbpm-managed state from the schema. It requires both destructive flags:
dbpm reinstall \
gh-maven:512itconsulting/core:com.512itconsulting.database:core:3.5.0 \
--allow-destructive \
--confirm-delete-system COREAvoid destructive reinstall in established environments unless Core deployment-lock policy and operator intent are absolutely clear.
dbpm can build and publish a ZIP artifact to GitHub Packages or a generic Maven repository. It generates:
{artifact_id}-{version}.zip- checksums
- a detached GPG signature
{artifact_id}-{version}.pommaven-metadata.xml
The uploaded POM is generated from the dbpm manifest. A checked-in pom.xml is optional legacy compatibility for repositories that still have other Maven-based workflows.
Add publish metadata to dbpm.yaml:
publish:
group: com.512itconsulting.database
artifact_id: coreConfigure GPG:
gpg --list-secret-keys --keyid-format=long
export DBPM_SIGNING_KEY="your-key-id-or-fingerprint"Dry run:
dbpm publish ~/repos/core \
--target gh-maven:512itconsulting/core \
--group com.512itconsulting.database \
--artifact-id core \
--signing-key "$DBPM_SIGNING_KEY" \
--dry-runPublish:
dbpm publish ~/repos/core \
--target gh-maven:512itconsulting/core \
--group com.512itconsulting.database \
--artifact-id core \
--signing-key "$DBPM_SIGNING_KEY"After verification, dbpm writes dbpm-publish-receipt.json in the package root.
The receipt contains immutable artifact metadata but no credentials. To index it
in a dbpm registry:
export DBPM_REGISTRY_URL="https://registry.dbpm.io"
export DBPM_REGISTRY_TOKEN="your-publisher-token"
dbpm registry index ~/repos/core --dry-run
dbpm registry index ~/repos/coreUse --index-registry on dbpm publish to perform both steps in one command.
If indexing fails, the verified publish receipt remains available for retry.
See dbpm publish for details. See dbpm registry index for indexing details.
If dbpm cannot connect to the database, confirm:
source ./dbpm-env.sh
"$DBPM_SQL_RUNNER" -L "$DBPM_CONNECT"For SQLcl saved connections, confirm with -name instead:
source ./dbpm-env.sh
"$DBPM_SQL_RUNNER" -S -L -name "$DBPM_CONNECT_NAME"If artifact downloads fail from GitHub Packages, confirm DBPM_GITHUB_TOKEN has package read access and DBPM_GITHUB_USER is set.
If paths show a literal ~, use $HOME in environment files:
export DBPM_CACHE_DIR="$HOME/.local/cache/dbpm"
export DBPM_LOG_DIR="$HOME/.local/state/dbpm_logs"If GPG signing fails, test signing outside dbpm:
echo "test" > /tmp/dbpm-gpg-test.txt
gpg --armor --detach-sign --local-user "$DBPM_SIGNING_KEY" /tmp/dbpm-gpg-test.txt
gpg --verify /tmp/dbpm-gpg-test.txt.asc /tmp/dbpm-gpg-test.txt- Read the command reference in commands.
- Review source type syntax.
- Read the project philosophy and vision.
- Run
dbpm <command> --helpfor command-specific flags.