00. Concepts - intersystems/ipm GitHub Wiki
Every operation IPM performs on a module, e.g. loading, compiling, testing or publishing, is expressed as a lifecycle phase. When you run a command like load or test, IPM resolves it to an ordered sequence of phases and executes them in turn against the module (and optionally its dependencies).
The lifecycle class for a module type defines a method for each phase. Resource processors attached to the module's resources can also hook into each phase, executing before or after the lifecycle method runs. This separation means the same phase sequence can behave differently depending on what resources a module contains.
Phases run in a fixed order. When you invoke a compound command (e.g. test), IPM resolves it to all the prerequisite phases automatically, so you don't need to run them individually.
The canonical order is:
Clean → Initialize → Reload → Validate → ExportData → Compile →
Activate → Document → MakeDeployed → Test → Package → Verify →
Publish → Configure → Unconfigure → ApplyUpdateSteps
| Phase | What it does | Standalone? |
|---|---|---|
| Activate | Performs post-compilation installation/configuration steps: runs projections, activates interoperability productions, etc. Default phase for <FileCopy>. |
|
| ApplyUpdateSteps | Runs migration steps when upgrading from a prior version. | |
| Clean | Removes the module's resources from the namespace. Recurses into dependencies unless they are required by something else; use -force to remove those too. Modules with <GlobalScope> set to 1 are skipped by default; pass -global to include them. |
|
| Compile | Compiles all resources within the module. | |
| Configure | Applies configuration that should run after installation, e.g. setting system settings, merging CPF entries. Default phase for <Invoke>. |
|
| Document | Regenerates the API documentation for the module. | Yes |
| ExportData | Exports data associated with the module (globals, lookup tables, etc.). | Yes |
| Initialize | Pulls and compiles module source code from the /preload directory. Used to set up namespace mappings, globals, or other prerequisites before resources are loaded. |
|
| MakeDeployed | Deploys resources within the module for which deployment is enabled (source-stripped form). | |
| Package | Exports the module's resources and bundles them into a module artifact (.tgz file). |
|
| Publish | Saves that artifact to the repository for which deployment is enabled. Currently, there may only be one of these per namespace. | |
| Reload | Pulls module source code into the namespace from disk. Does not compile. | |
| Test | Runs any unit tests associated with the module, in the current namespace. | |
| Unconfigure | Reverses configuration applied by Configure. | |
| Validate | Ensures that module resource processor attributes are valid, and that the resources exported to the filesystem (and possibly to source control) are consistent with what is in the database. | |
| Verify | Installs that artifact in a separate namespace, then runs integration tests (if any). |
Most commands don't run a single phase in isolation, but rather run a chain of prerequisites first. For example, the test command runs Initialize → Reload → Validate → Compile → Activate → Test. These chains are defined in %IPM.Lifecycle.Base:GetCompletePhasesForOne. Phases that invoke another phase directly from their own implementation, rather than declaring it as a prerequisite, are marked with * below. Document and ExportData never appear as a row or column: they're standalone, so nothing runs them and they run nothing else.
| Command | Initialize | Reload | Validate | Compile | Activate | MakeDeployed | Test | Package | Verify | Publish | Configure | Unconfigure | ApplyUpdateSteps |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Clean | * | ||||||||||||
| Reload | X | X | |||||||||||
| Validate | X | X | X | ||||||||||
| Compile | X | X | X | X | |||||||||
| Activate | X | X | X | X | X | * | |||||||
| Test | X | X | X | X | X | X | |||||||
| Package | X | X | X | X | X | * | X | ||||||
| Verify | X | X | X | X | X | X | X | ||||||
| Publish | X | X | X | X | X | * | X | ||||||
| ApplyUpdateSteps | X | X | X | X | X | X |
* Invoked explicitly from within the phase's own implementation, rather than declared as a prerequisite.
module-action runs a lifecycle phase against a module. Call it explicitly, or use the shorthand where the module name leads the command:
zpm "module-action mymodule compile"
zpm "mymodule compile"
compile, reload, package, publish, makedeployed, test, verify, and update are all aliases for module-action <module> <phase> with the phase already filled in. module-action (or the <module> <phase> shorthand) also works with any phase that doesn't have its own dedicated command, e.g. activate, validate, clean, configure, unconfigure.
By default, running a phase also runs its prerequisite chain from the table above. Pass -only (or -o) to run just the named phase, skipping its prerequisites. It works with module-action and any of its aliases from above.
zpm "mymodule verify -only"
-only is typically used with verify. Either way, verify runs integration tests in an isolated -VERIFY namespace; -only just changes how the module gets there. Without it, verify first rebuilds and packages the module in your current namespace, then hands that package to -VERIFY. With -only, that current-namespace rebuild is skipped entirely, and -VERIFY instead loads and builds the module straight from its Root directory on disk. That makes -only handy in a dev namespace, where you want to test what's on disk without also recompiling/reactivating your current working copy.
-only skips the declared chain, not the *-marked explicit calls: package -only still runs MakeDeployed if the module has resources to deploy, since that call lives inside Package's own implementation rather than in its prerequisite chain.
Custom phases let a module expose named operations that aren't part of the standard install/build/test flow. Common use cases:
- A one-off data migration step that should only run when explicitly requested, not on every install.
- Applying a CPF merge only in a specific deployment scenario.
- A developer convenience command (e.g.
seed-data,reset-config) that invokes application-specific logic.
Custom phases are not part of any command's default phase chain, so they only run when explicitly requested by name.
Custom phases are defined in module.xml using the CustomPhase attribute on <Invoke> or <CPF> elements. See Custom Phase Example in the manifest reference for worked examples.
ipm> mymodule custom-phase-name
Custom phases are case-insensitive. IPM resolves them against the phases registered by the module's invokes and resource processors at runtime.
The -dev flag marks a module as being actively developed in the current namespace. It applies to load, install, reinstall, reload, update, and any direct lifecycle phase command.
zpm "load /path/to/mymodule -dev"
zpm "install mymodule -dev"
zpm "reinstall mymodule -dev"
Configures ^Sources for module resources
IPM sets up the ^Sources global to map each resource back to its file on disk. This is what makes Studio and VS Code aware of where source files live so edits go to the right place.
Passes DeveloperMode=1 to installer methods
Any <Invoke> or custom lifecycle code that reads pParams("DeveloperMode") can branch on it. Convention is to skip write-once setup (e.g. seeding production data) and enable extra debug output.
Suppresses automatic transaction rollback on failure In normal mode, the entire load/install is wrapped in a transaction; any failure rolls the namespace back to its previous state. In dev mode, the module manifest is committed before resource loading begins. If a later step fails, you are left with a partial install you can inspect and fix, rather than a clean rollback that hides the problem.
Marks the module as not deployed
The module's Deployed flag is set to 0, keeping source code accessible for editing. A module loaded in dev mode cannot be overwritten by a non-dev install (you'll get ERROR! Cannot install 'X' over previously installed in developer mode). Uninstall first, or use -force.
Use -dev whenever you are loading your own module's source from disk for active development. Do not use it for modules you are consuming as dependencies. Those should remain in normal (production) mode so rollback safety and deployment state work correctly.
Note: Read-only repository sources always force
DeveloperMode=0, regardless of the flag.
Several built-in -D flags control low-level installation behavior. They apply to install, load, and update. You can pass them on the command line or set them as persistent defaults with default-modifiers.
Note: These flags are expected to be revamped in IPM 1.0.0.
Disables the IRIS transaction that normally wraps a module load. By default, IPM wraps the entire load/install operation in a transaction so that a failure mid-way through is fully rolled back. With NoTransaction=1, any failure leaves the namespace in a partially-installed state.
Use when some modules in the install conflict with an outer wrapping transaction, or when the transaction overhead is unacceptable, because wrapping a large install in a single transaction can add significant time and memory pressure.
Disables IRIS journaling at the process level for the duration of the load. Disabling the journal can drastically cut install time, making this particularly useful in dev environments where you're loading modules repeatedly. It also implicitly disables transactions (a journaled rollback is not possible without a journal), so NoJournal=1 is a strict superset of NoTransaction=1.
The trade-off is that if the process crashes mid-install, changes cannot be rolled back and the namespace may be left in an inconsistent state. Avoid this in production namespaces where data integrity matters.
Suppresses the automatic creation of global and document (class/package) mappings for the module's resources during installation. See <NoMapping> in the manifest reference for full details and examples, including how to embed this as a default in module.xml.
On the command line:
zpm "load /path/to/module -DNoTransaction=1"
zpm "install mymodule -DNoMapping=1"
zpm "install mymodule -DNoJournal=1 -DNoMapping=1"
As a persistent namespace default (applied to every subsequent command):
zpm "default-modifiers -set -DNoTransaction=1"
Embedded in module.xml (applied whenever this module is installed):
<Defaults>
<Parameter Name="NoMapping">1</Parameter>
</Defaults>