Module CLI Commands

AutoCom provides a comprehensive set of Artisan commands for managing modules from the command line. These commands help you create new modules, manage their state, and debug issues.

Available Commands

Command Description
module:make Generate a new module with proper structure
module:list List all modules and their status
module:sync Sync filesystem module.json files into the database
module:enable Enable a disabled module
module:disable Disable an enabled module
module:packages Check and install package dependencies
module:lock Generate or update modules/manifests/<ring>.lock.json (Versioning)
module:verify Validate filesystem modules match the lock file + compat constraints
module:compat Report platform compatibility status of every module
module:install Install a module from the GitLab Package Registry
module:upgrade Upgrade an installed module to a newer version
module:rollback Roll back a module to a previously installed version

Creating Modules

module:make

Generate a new module with the complete directory structure, service provider, routes, and frontend scaffolding.

php artisan module:make ModuleName [options]

Options

Option Description Default
--type= Module type (core, store, shipping, channel, payment, ai, reseller, standard) standard
--core Mark as core module (cannot be disabled) false
--priority= Loading priority (lower = earlier) 50
--description= Module description Auto-generated
--depends= Module dependencies (repeatable) ['Core']

Examples

Basic module:

php artisan module:make Inventory

Store integration module:

php artisan module:make StoreWooCommerce --type=store --depends=Core --depends=Orders

Core module with high priority:

php artisan module:make Analytics --type=core --core --priority=5

Module with custom description:

php artisan module:make Reports --description="Advanced reporting and analytics"

Generated Structure

When you run module:make, it creates:

modules/ModuleName/
├── module.json                    # Module configuration
├── backend/
│   ├── ModuleNameServiceProvider.php
│   ├── App/
│   │   ├── Controllers/
│   │   ├── Models/
│   │   └── Services/
│   ├── routes/
│   │   └── api.php
│   └── database/
│       └── migrations/
└── frontend/
    ├── pages/
    │   └── index.tsx
    ├── components/
    ├── hooks/
    ├── types/
    │   └── index.ts
    └── index.ts

Listing Modules

module:list

Display all discovered modules with their status, type, priority, and dependencies.

php artisan module:list [options]

Options

Option Description
--type= Filter by module type
--graph Show dependency graph
--json Output as JSON

Examples

List all modules:

php artisan module:list

Output:

Discovered Modules

+----------------+--------------+----------+----------+---------+-----------------+
| Name           | Alias        | Type     | Priority | Status  | Dependencies    |
+----------------+--------------+----------+----------+---------+-----------------+
| Core           | core         | core     | 0        | CORE    | -               |
| CoreDashboard  | dashboard    | core     | 5        | CORE    | Core            |
| Orders         | orders       | core     | 10       | LOADED  | Core            |
| Products       | products     | core     | 15       | LOADED  | Core            |
| Customers      | customers    | core     | 20       | LOADED  | Core            |
| StoreShopify   | store-shopify| store    | 50       | DISABLED| Core, Orders    |
| Workflows      | workflows    | automation| 30       | LOADED  | Core            |
+----------------+--------------+----------+----------+---------+-----------------+

Total: 7 modules, 5 loaded

Filter by type:

php artisan module:list --type=store

Show dependency graph:

php artisan module:list --graph

Output:

Dependency Graph:

  Core
    └── (no dependencies)
  Orders
    └── Core
  StoreShopify
    └── Core, Orders

Reverse Dependencies (dependents):

  Core
    └── used by: Orders, Products, Customers, StoreShopify, Workflows
  Orders
    └── used by: StoreShopify

Export as JSON (useful for CI/CD):

php artisan module:list --json > modules.json

Enabling Modules

module:enable

Enable a module, check package dependencies, and optionally install them.

php artisan module:enable ModuleName [options]

Options

Option Description
--with-deps Automatically enable all module dependencies
--install-packages Automatically install missing Composer/JS packages
--skip-packages Skip package dependency check entirely

Examples

Enable a single module:

php artisan module:enable StoreShopify

If dependencies are missing, you'll be prompted:

Module 'StoreShopify' has disabled dependencies: Orders
Enable dependencies as well? (yes/no) [yes]:

Enable with all dependencies automatically:

php artisan module:enable StoreShopify --with-deps

Output:

Enabling dependency: Orders
Module 'StoreShopify' has been enabled
Run 'php artisan module:list' to see all modules

Disabling Modules

module:disable

Disable a module. Core modules cannot be disabled.

php artisan module:disable ModuleName [options]

Options

Option Description
--force Force disable even if other modules depend on it

Examples

Disable a module:

php artisan module:disable StoreShopify

Force disable with dependents warning:

php artisan module:disable Orders --force

Output:

The following enabled modules depend on 'Orders':
  - StoreShopify
Disable anyway? (dependent modules may break) (yes/no) [no]:

Attempting to disable a core module:

php artisan module:disable Core

Output:

Module 'Core' is a core module and cannot be disabled

Managing Package Dependencies

module:packages

Check and install Composer and JS (Bun) package dependencies for all enabled modules.

php artisan module:packages [options]

Options

Option Description
--module= Check a specific module only
--install Automatically install all missing packages
--json Output results as JSON

Examples

Check all enabled modules:

php artisan module:packages

Output:

Package Dependency Report

PHP Version: 8.2.15

+----------------+-----+------------------+------------+--------+
| Module         | PHP | Composer Missing | JS Missing | Status |
+----------------+-----+------------------+------------+--------+
| Core           | ✓   | 0                | 0          | OK     |
| Orders         | ✓   | 0                | 0          | OK     |
| StoreShopify   | ✓   | 1                | 1          | MISSING|
+----------------+-----+------------------+------------+--------+

Missing Packages:

StoreShopify:
  composer: guzzlehttp/guzzle
  bun: @shopify/polaris

To install all missing packages:
  composer require guzzlehttp/guzzle
  cd frontend && bun add @shopify/polaris

Or run: php artisan module:packages --install

Install all missing packages:

php artisan module:packages --install

Check a specific module:

php artisan module:packages --module=StoreShopify

Export as JSON (useful for CI/CD):

php artisan module:packages --json

Module Status File

Module states are persisted in modules/modules_statuses.json:

{
  "ChannelLiveChatWidget": true,
  "Core": true,
  "CoreDashboard": true,
  "Customers": true,
  "Orders": true,
  "Products": true,
  "ResellerCatalog": false,
  "ResellerFinance": false,
  "ResellerOrders": false,
  "StoreShopify": false,
  "Workflows": true
}

Note: Core modules (isCore: true in module.json) are always loaded regardless of this file.


Troubleshooting

Module not loading

  1. Check if the module is enabled:

    php artisan module:list
    
  2. Look for errors in the log:

    tail -f storage/logs/laravel.log | grep ModuleLoader
    
  3. Verify module.json is valid JSON:

    cat modules/ModuleName/module.json | jq .
    

Dependency errors

If you see dependency errors:

Module 'StoreShopify' requires module 'Orders' which is not available or not enabled

Enable the dependency first:

php artisan module:enable Orders
php artisan module:enable StoreShopify

Or use --with-deps:

php artisan module:enable StoreShopify --with-deps

Circular dependency detected

If you see:

Circular dependency detected: ModuleA -> ModuleB -> ModuleC -> ModuleA

Review your module.json files and remove the circular reference. Use the dependency graph to visualize:

php artisan module:list --graph

Versioning Commands

The commands in this section power the module versioning system. They handle reproducible builds, release artifacts, install/upgrade/rollback flows, and platform compatibility checks.

module:lock

Generate or update a deployment ring's lock file at modules/manifests/<ring>.lock.json so it captures the exact (version, sha256) of every module on disk. Defaults to the stable ring.

php artisan module:lock                         # regenerate stable.lock.json
php artisan module:lock --ring=edge             # regenerate edge.lock.json
php artisan module:lock --check                 # exit non-zero if lock is stale
php artisan module:lock --module=Orders         # update one module only
php artisan module:lock --ring=canary --module=Orders

See Deployment Rings for the multi-ring story.

module:verify

CI gate that fails if the filesystem doesn't match modules/manifests/<ring>.lock.json (defaults to stable). Checks three things per module:

  1. Version in module.json matches the lock file
  2. Content SHA256 matches the lock file
  3. compatibility.platform constraint is satisfied by /VERSION
php artisan module:verify

Used by the module-lock-validate job in ci/templates/modules-versioning.yml.

module:compat

Report platform compatibility for every module against the current /VERSION.

php artisan module:compat
php artisan module:compat --strict   # fail loudly on any incompatibility

Output is a table of alias@version | directory | constraint | status. Exits non-zero if any module is incompatible with the current platform version.

module:install

Install a module from the GitLab Generic Package Registry.

export MODULE_REGISTRY_URL=https://gitlab.wexron.io
export MODULE_REGISTRY_TOKEN=<personal-or-deploy-token>

php artisan module:install orders@1.0.0
php artisan module:install orders@1.0.0 --force            # reinstall same version
php artisan module:install orders@1.0.0 --skip-migrations

Refuses if the module is already installed at a different version. Use module:upgrade for that path.

The command:

  1. Downloads Orders-1.0.0.zip + .sha256 + MANIFEST.json from the registry
  2. Verifies SHA256
  3. Extracts to storage/app/module-versions/orders/1.0.0/
  4. Atomic-swaps into modules/Orders/
  5. Runs central database migrations from the new version
  6. Inserts an is_active = true row in module_versions
  7. Fires the onInstall platform lifecycle hook

module:upgrade

Upgrade an installed module to a newer version.

php artisan module:upgrade orders --to=1.0.1
php artisan module:upgrade orders --to=1.0.1 --skip-migrations

Same flow as module:install plus:

  • Records the previous version's module_versions row as is_active = false (kept for rollback)
  • Fires the onUpgrade platform lifecycle hook with {fromVersion, toVersion, sourcePath, manifest}

module:rollback

Roll back to a previously installed version.

php artisan module:rollback orders                # most recent prior version
php artisan module:rollback orders --to=1.0.0     # specific version

Restores the previous version's source from storage/app/module-versions/<alias>/<version>/ (the version is retained from the original install/upgrade — no re-download). Flips module_versions.is_active back. Fires the onDowngrade platform lifecycle hook.

⚠ Schema migrations are NOT auto-reverted. If the version you're rolling back to has a narrower schema, run php artisan migrate:rollback first. The command warns about this every time.


Deployment Ring Commands

The commands in this section operate on deployment rings — independent slices of the platform that allow different tenants to run different module versions on the same shared cluster. Day-1 there's exactly one ring (stable); add more only when needed.

ring:list

Show every ring with its tenant count and status.

php artisan ring:list

Output:

+------------------+---------+---------+------------------------------------+---------------+--------+
| Name             | Display | Tenants | Manifest                           | K8s Namespace | Active |
+------------------+---------+---------+------------------------------------+---------------+--------+
| stable (default) | Stable  | 22      | modules/manifests/stable.lock.json | autocom       | yes    |
| edge             | Edge    | 3       | modules/manifests/edge.lock.json   | autocom-edge  | yes    |
| canary           | Canary  | 1       | modules/manifests/canary.lock.json | autocom-canary| yes    |
+------------------+---------+---------+------------------------------------+---------------+--------+

Promotion order: stable → edge → canary

ring:show

Inspect a single ring in detail. Optionally list its assigned tenants and pinned modules.

php artisan ring:show stable
php artisan ring:show stable --tenants    # also list tenants
php artisan ring:show stable --modules    # also list pinned modules with versions

The --modules flag is the fastest way to answer "which version of Orders is in production right now?"

ring:assign

Move a tenant from one ring to another. The change takes effect on the next request.

php artisan ring:assign acme canary
php artisan ring:assign acme canary --force
php artisan ring:assign acme canary --reason="opted into beta program"

The --reason text is logged for audit purposes. Long-running websocket connections (Reverb) drop and reconnect to the new ring.

ring:promote

Copy a module's pinned version from one ring's manifest to another. This is the bread-and-butter operation: as a new module version soaks on canary, you promote it to edge, then to stable.

# Promote orders @ whatever-version-edge-has → stable
php artisan ring:promote orders --from=edge --to=stable

# Pin a specific version directly (skip --from lookup)
php artisan ring:promote orders --with-version=1.5.0 --to=edge

# Skip confirmation prompt
php artisan ring:promote orders --from=edge --to=stable --force

The command rewrites the destination ring's modules/manifests/<ring>.lock.json file. It does not trigger any deploy — commit + push to main, and CI rolls out the destination ring on the next pipeline.

For audit-trail-friendly promotions (changes that need to land in git history), use the ring-promote CI pipeline instead: GitLab UI → Pipelines → Run Pipeline → set PROMOTE_ALIAS, PROMOTE_FROM, PROMOTE_TO. The pipeline rewrites the manifest, commits with a structured message, and pushes to main.


Next Steps