AcuOps Architecture¶
Pipeline Flow¶
┌─────────────────────────────────────────────────────────────────────┐
│ GitHub Repository │
│ │
│ Customization/_project/project.xml ←── Source of truth │
│ acuops.yaml ←── Pipeline configuration │
│ scripts/ ←── Deployment tooling │
└──────────────────────┬──────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ GitHub Actions Pipeline │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Build │──▸│ Backup │──▸│ Deploy │ │ Validate │ │
│ │ │ │ │ │ │ │ (PR only)│ │
│ │ validate │ │ download │ │ import │ │ │ │
│ │ package │ │ current │ │ publish │ │ import │ │
│ │ .zip │ │ .zip │ │ co-pub │ │ no pub │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└──────────────────────┬──────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Acumatica Customization API │
│ │
│ POST /entity/auth/login ── Session authentication │
│ POST /CustomizationApi/Import ── Upload .zip package │
│ POST /CustomizationApi/publishBegin ── Start compile + publish │
│ POST /CustomizationApi/publishEnd ── Poll completion │
│ POST /CustomizationApi/getProject ── Download (backup) │
│ POST /entity/auth/logout ── Release session │
└─────────────────────────────────────────────────────────────────────┘
Component Responsibilities¶
Build Job¶
- Reads
acuops.yamlfor project config - Runs
validate-project.py(XML structure, C# validation, security scan) - Detects and builds C# extension libraries (
.csproj) - Packages
Customization/_project/into timestamped.zip - Uploads
.zipas GitHub artifact
Backup Job¶
- Authenticates to Acumatica (login with retry)
- Downloads current published package via
getProjectAPI - Saves as timestamped
.zipartifact (30-day retention) - Skipped for PRs and when
backup.enabled: false
Deploy Job¶
- Downloads build artifact
- Resolves target environment (production/staging)
- Authenticates to Acumatica
- Imports package via
ImportAPI - Publishes with co-publish projects via
publishBegin - Polls
publishEnduntil complete or timeout - Posts summary to GitHub and optionally Slack
Validate Job (PR only)¶
- Downloads build artifact
- Authenticates to staging Acumatica
- Imports with
isOnlyValidation: true(compile check, no publish) - Reports result as PR check
Script Architecture¶
scripts/
├── deploy.sh ── Primary deployer (GitHub Actions)
│ ├── load_config() ── Read acuops.yaml via yq
│ ├── login() ── Auth with retry (5 attempts)
│ ├── backup() ── Optional pre-deploy backup
│ ├── import() ── Upload base64-encoded .zip
│ ├── publish() ── publishBegin + poll publishEnd
│ └── cleanup() ── Logout + temp file removal (trap)
│
├── deploy.py ── Python deployer (alternative)
│ └── AcumaticaCustomizationClient
│ ├── login() ── Session with context manager
│ ├── import_package()
│ ├── publish() ── With co-publish support
│ └── download_package()
│
├── backup.sh ── Standalone backup script
├── restore.sh ── Rollback from backup
├── validate-project.py ── 10-check XML + C# validator
├── setup.sh ── Interactive setup wizard
└── generate-solution-objects.py ── ISV certification CSV
Error Handling¶
Login Retry¶
All scripts implement login retry with exponential backoff: - 5 max attempts - Wait: 15s * attempt number (15s, 30s, 45s, 60s, 75s) - Handles API Login Limit (HTTP 500)
Cleanup Trap¶
Bash scripts register a trap cleanup EXIT handler that:
- Logs out of Acumatica (releases session)
- Removes temporary files (cookie jar, response files)
- Runs even on script failure or interruption
publishEnd Response Handling¶
The API returns two different response formats:
- Plain text: "true" (complete) or "false" (in progress)
- JSON: {"isCompleted": true} or {"isFailed": true, "log": "..."}
Both are handled transparently by the deploy scripts.
Configuration Hierarchy¶
The Build job reads acuops.yaml and passes values as job outputs. Deploy and Backup jobs receive config through job dependency outputs.
Compatibility¶
The Customization API is version-independent — the same endpoints work across all Acumatica versions from 2022 R2 onward. No version-specific API paths or behaviors.
Testing focus areas per version:
- Auth behavior (session cookie format)
- publishEnd response format (both handled)
- Import URL casing (case-sensitive in all versions)