ADR-034: Internal Deployment Status Log
Status
Proposed
Date
2025-12-08
Deciders
- CloudEmpiere Team
Context and Problem Statement
Internal team members need visibility into deployment status across client environments. Currently, there's no centralized way to answer:
- What version is running on client X's PROD?
- Is STAGING being updated right now?
- Is the build still running?
- What changed since last deployment?
This is for internal CloudEmpiere use only - not customer-facing or compliance audit.
Decision Drivers
- Simplicity: Minimal tables, minimal CLI commands
- Live Status: Show real-time build/deploy progress
- iDempiere Native: Use Application Dictionary, view in iDempiere window
- Multi-Tenant: Track per AD_Client_ID (per customer)
- Integration: Jenkins/AWX can update status via CLI
Considered Options
- Complex tracking system - Separate Build, Deployment, Environment tables with full workflow
- Simple status log - Single table with live status updates
- Query-only - Just query Jenkins/AWX APIs, no storage
Decision Outcome
Chosen option: "Simple status log", because:
- Answers the key questions with minimal complexity
- Single table covers both live status and history
- CLI stays focused on plugin development, not DevOps orchestration
- Jenkins/AWX already handle workflow - we just need visibility
Confirmation
- Internal users can see live deployment status in iDempiere window
env deploy statusshows current state per environment- Historical deployments queryable for troubleshooting
Architecture
┌─────────────────────────────────────────────────────────────────────────────────┐
│ DEPLOYMENT STATUS FLOW │
└─────────────────────────────────────────────────────────────────────────────────┘
Developer Jenkins AWX iDempiere
───────── ─────── ─── ─────────
│ │ │ │
│── git push ──────────>│ │ │
│ │ │ │
│ │── cli deploy start ──┼──────────────────────>│
│ │ (BUILDING) │ │
│ │ │ │
│ │── cli deploy update ─┼──────────────────────>│
│ │ (progress 50%) │ │
│ │ │ │
│ │── build done ───────>│ │
│ │ │ │
│ │ │── cli deploy update ─>│
│ │ │ (DEPLOYING) │
│ │ │ │
│ │ │── cli deploy complete>│
│ │ │ (SUCCESS) │
│ │ │ │
│ │ │ ┌───────────┴───┐
│ │ │ │ Internal user │
│ │ │ │ sees status │
│ │ │ │ in window │
│ │ │ └───────────────┘
Database Schema
XX_Deploy_Log (Single Table)
┌─────────────────────────────────────────────────────────────────────────────────┐
│ XX_Deploy_Log │
│─────────────────────────────────────────────────────────────────────────────────│
│ Column │ Type │ Description │
│──────────────────┼──────────────┼───────────────────────────────────────────────│
│ XX_Deploy_Log_ID │ ID │ Primary key │
│ XX_Deploy_Log_UU │ UUID │ REST API identifier │
│ AD_Client_ID │ TableDirect │ Which client (multi-tenant) │
│ AD_Org_ID │ TableDirect │ Organization │
│──────────────────┼──────────────┼───────────────────────────────────────────────│
│ Environment │ List │ PROD / STAGING / DEV │
│ Status │ List │ BUILDING / DEPLOYING / SUCCESS / FAILED │
│ Progress │ Integer │ 0-100 percentage │
│ CurrentStep │ String(255) │ "Compiling..." / "Restarting..." │
│──────────────────┼──────────────┼───────────────────────────────────────────────│
│ Version │ String(40) │ Target version (2.1.0) │
│ VersionPrevious │ String(40) │ Previous version (2.0.5) │
│ Components │ Text │ What's being updated (plugin list) │
│ Changes │ Text │ What changed (summary) │
│──────────────────┼──────────────┼───────────────────────────────────────────────│
│ DateStarted │ DateTime │ When build/deploy started │
│ DateCompleted │ DateTime │ When finished (null if in progress) │
│ Duration │ Integer │ Seconds (calculated on complete) │
│ ErrorMessage │ Text │ Error details if failed │
│──────────────────┼──────────────┼───────────────────────────────────────────────│
│ Jenkins_BuildNo │ String(50) │ Jenkins build number │
│ Jenkins_URL │ URL │ Link to Jenkins job │
│ AWX_JobID │ String(50) │ AWX job ID │
│ AWX_URL │ URL │ Link to AWX job │
│ DeployedBy │ String(100) │ Who triggered (username) │
│──────────────────┼──────────────┼───────────────────────────────────────────────│
│ IsActive │ YesNo │ Standard │
│ Created │ DateTime │ Audit │
│ CreatedBy │ Table │ Audit │
│ Updated │ DateTime │ Audit │
│ UpdatedBy │ Table │ Audit │
└─────────────────────────────────────────────────────────────────────────────────┘
Reference Lists
XX_DeployEnvironment:
| Value | Name |
|---|---|
PROD |
Production |
STAGING |
Staging |
DEV |
Development |
XX_DeployStatus:
| Value | Name | Description |
|---|---|---|
B |
Building | Jenkins is building artifacts |
D |
Deploying | AWX is deploying to server |
S |
Success | Completed successfully |
F |
Failed | Something went wrong |
R |
Rolled Back | Reverted to previous version |
Status Lifecycle
BUILDING ──────────► DEPLOYING ──────────► SUCCESS
│ │
│ │
▼ ▼
FAILED FAILED
│
▼
ROLLED_BACK
CLI Commands
# ─────────────────────────────────────────────────────────────────────────────────
# START: Create new deployment record (Jenkins calls at build start)
# ─────────────────────────────────────────────────────────────────────────────────
idempiere-cli env deploy start \
--env STAGING \
--version "2.2.0" \
--components "org.idempiere.invoice, org.idempiere.report" \
--jenkins-build "567" \
--jenkins-url "https://jenkins.example.com/job/plugins/567"
# Returns: XX_Deploy_Log_ID for subsequent updates
# ─────────────────────────────────────────────────────────────────────────────────
# UPDATE: Update progress during build/deploy (Jenkins/AWX call periodically)
# ─────────────────────────────────────────────────────────────────────────────────
idempiere-cli env deploy update \
--id 1000042 \
--progress 50 \
--step "Running tests..."
idempiere-cli env deploy update \
--id 1000042 \
--status DEPLOYING \
--progress 0 \
--step "Copying artifacts to server..."
idempiere-cli env deploy update \
--id 1000042 \
--progress 75 \
--step "Restarting iDempiere service..."
# ─────────────────────────────────────────────────────────────────────────────────
# COMPLETE: Mark deployment finished (AWX calls at end)
# ─────────────────────────────────────────────────────────────────────────────────
# Success
idempiere-cli env deploy complete \
--id 1000042 \
--status SUCCESS \
--changes "Invoice tax fix, new Sales by Region report"
# Failed
idempiere-cli env deploy complete \
--id 1000042 \
--status FAILED \
--error "Database migration failed: column already exists"
# ─────────────────────────────────────────────────────────────────────────────────
# QUERY: View status and history
# ─────────────────────────────────────────────────────────────────────────────────
# Current status per environment
idempiere-cli env deploy status
idempiere-cli env deploy status PROD
idempiere-cli env deploy status --client 1000014
# History
idempiere-cli env deploy history
idempiere-cli env deploy history --env PROD --since "2024-12-01"
idempiere-cli env deploy history --status FAILED
CLI Output Examples
Status View
$ idempiere-cli env deploy status
Client: Acme Corp (1000014)
┌───────────┬──────────┬──────────┬─────────────────────┬────────────────────────┐
│ Env │ Version │ Status │ Progress │ Current Step │
├───────────┼──────────┼──────────┼─────────────────────┼────────────────────────┤
│ PROD │ 2.1.0 │ ✅ OK │ ████████████ 100% │ Deployed Dec 8, 10:30 │
│ STAGING │ 2.2.0 │ 🔄 DEPLOY│ ██████░░░░░░ 50% │ Restarting service... │
│ DEV │ 2.2.1 │ 🔨 BUILD │ ████░░░░░░░░ 30% │ Running tests... │
└───────────┴──────────┴──────────┴─────────────────────┴────────────────────────┘
History View
$ idempiere-cli env deploy history --env PROD --limit 5
┌─────────────────────┬──────────┬──────────┬────────────────────────────────────┐
│ Date │ Version │ Status │ Changes │
├─────────────────────┼──────────┼──────────┼────────────────────────────────────┤
│ 2024-12-08 10:30 │ 2.1.0 │ ✅ OK │ Invoice tax fix │
│ 2024-12-05 14:00 │ 2.0.5 │ ✅ OK │ Hotfix for report │
│ 2024-12-01 09:00 │ 2.0.4 │ ❌ FAIL │ Migration failed (rolled back) │
│ 2024-11-28 16:00 │ 2.0.4 │ ✅ OK │ New dashboard feature │
│ 2024-11-25 11:00 │ 2.0.3 │ ✅ OK │ Performance improvements │
└─────────────────────┴──────────┴──────────┴────────────────────────────────────┘
iDempiere Window
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Window: Deployment Status [?] [X] │
│─────────────────────────────────────────────────────────────────────────────────│
│ │
│ [Tab: Current Status] [Tab: History] │
│ │
│ ┌─ Current Status ────────────────────────────────────────────────────────────┐│
│ │ ││
│ │ Environment: [STAGING ▼] Status: 🔄 Deploying ││
│ │ Version: 2.2.0 Progress: [██████░░░░░░] 50% ││
│ │ Current Step: Restarting iDempiere service... ││
│ │ ││
│ │ Started: 2024-12-08 14:30 ││
│ │ Jenkins: #567 (link) ││
│ │ AWX Job: #1234 (link) ││
│ │ Triggered By: john.doe ││
│ │ ││
│ │ Components: ││
│ │ • org.idempiere.invoice (2.0.5 → 2.1.0) ││
│ │ • org.idempiere.report (1.4.2 → 1.5.0) ││
│ │ ││
│ └─────────────────────────────────────────────────────────────────────────────┘│
│ │
│ [Refresh] │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Integration Examples
Jenkins Pipeline
pipeline {
stages {
stage('Build') {
steps {
script {
// Start tracking
def deployId = sh(
script: '''
idempiere-cli env deploy start \
--env STAGING \
--version "${VERSION}" \
--jenkins-build "${BUILD_NUMBER}" \
--jenkins-url "${BUILD_URL}" \
--json | jq -r '.id'
''',
returnStdout: true
).trim()
env.DEPLOY_ID = deployId
}
// Build steps with progress updates
sh "idempiere-cli env deploy update --id ${DEPLOY_ID} --progress 25 --step 'Compiling...'"
sh "mvn compile"
sh "idempiere-cli env deploy update --id ${DEPLOY_ID} --progress 50 --step 'Running tests...'"
sh "mvn test"
sh "idempiere-cli env deploy update --id ${DEPLOY_ID} --progress 75 --step 'Packaging...'"
sh "mvn package"
sh "idempiere-cli env deploy update --id ${DEPLOY_ID} --progress 100 --step 'Build complete'"
}
}
}
post {
failure {
sh '''
idempiere-cli env deploy complete \
--id ${DEPLOY_ID} \
--status FAILED \
--error "Build failed: ${BUILD_URL}console"
'''
}
}
}
AWX/Ansible Playbook
# deploy-plugins.yml
- name: Update status - Deploying
command: >
idempiere-cli env deploy update
--id {{ deploy_id }}
--status DEPLOYING
--progress 0
--step "Starting deployment..."
delegate_to: localhost
- name: Copy plugins to server
copy:
src: "{{ item }}"
dest: /opt/idempiere/plugins/
loop: "{{ plugin_files }}"
- name: Update progress
command: >
idempiere-cli env deploy update
--id {{ deploy_id }}
--progress 50
--step "Restarting iDempiere..."
delegate_to: localhost
- name: Restart iDempiere
service:
name: idempiere
state: restarted
- name: Complete deployment
command: >
idempiere-cli env deploy complete
--id {{ deploy_id }}
--status SUCCESS
--changes "{{ release_notes }}"
delegate_to: localhost
REST API
Uses iDempiere REST Web Services:
# Create deployment record
POST /api/v1/models/xx_deploy_log
{
"Environment": "STAGING",
"Status": "B",
"Version": "2.2.0",
"DateStarted": "2024-12-08T14:30:00Z"
}
# Update progress
PATCH /api/v1/models/xx_deploy_log/1000042
{
"Progress": 50,
"CurrentStep": "Running tests..."
}
# Query current status
GET /api/v1/models/xx_deploy_log?$filter=DateCompleted eq null&$orderby=DateStarted desc
What This Is NOT
- ❌ Not a CI/CD orchestrator - Jenkins/AWX handle that
- ❌ Not a build tracker - Jenkins tracks builds
- ❌ Not approval workflow - AWX handles approvals
- ❌ Not artifact storage - Nexus/Artifactory for that
What This IS
- ✅ Visibility: Internal team sees what's happening
- ✅ Status: Real-time build/deploy progress
- ✅ History: What version is where, what changed
- ✅ Troubleshooting: Quick answer to "what deployed when?"