xMatix
Sign in Request demo
xMatix
PRODUCTS
SalesField SalesCRMRewardsClaimsInventoryProcurementWarehouse ManagementField ServiceServiceSupportTelephony & MessagingFinance & AccountingPayrollExpense ManagementCommercePortalsAnalytics & ReportingData StudioMobile AppSee all products →
PLATFORM
Platform overviewApp BuilderAutomationIntegrationsSecurity & GovernanceChange ManagementDevelopers
SENSE AI
Sense AI overviewSense AssistSense ControlSense VisionAI StudioTrust & governanceIn Claude & ChatGPTUse cases
SOLUTIONS
FMCG & DistributionManufacturing & Dealer NetworksAutomotive & DealershipsPharma & HealthcareConsumer DurablesAgri-InputsBuilding MaterialsService NetworksWarehousing & 3PLFinancial AccountingERP SoftwareIndia GST ComplianceUAE VAT & e-InvoicingSaudi ZATCA & VATAll solutions →
RESOURCES
Knowledge CenterDeveloper & CLIBlogGuidesWhat is xMatix?Company facts
COMPANY
AboutCareersPartnersEventsContactAuthorsLegal
Sign in Request demo
Home/Docs/Developer/CI recipes
REFERENCE · Last reviewed

CI recipes

The CLI's verbs compose into three pipeline patterns: a drift gate that fails a build when the live tenant no longer matches the repository, a promotion job that applies a tagged repository state to a tenant, and a release-time snapshot that proves the repo captured everything before shipping. All three start with xmatix doctor so auth, config and connectivity problems fail fast with a named cause.

One constraint shapes everything on this page: the CLI signs in with a device-code flow only — there is no service-principal sign-in yet (see Authentication). Pipelines therefore run on a persistent, access-controlled runner where xmatix login was completed once; the encrypted token cache then serves silent sign-ins across jobs. On ephemeral runners the recipes below will fail at doctor's token check until non-interactive sign-in ships.

Drift gate

Fails the build if any artifact changed on the live tenant since the last commit — run it on pull requests and on a schedule:

name: drift-gate
on: [pull_request, schedule]
jobs:
  drift:
    runs-on: [self-hosted, xmatix-runner]
    steps:
      - uses: actions/checkout@v4
      - run: |
          xmatix doctor
          xmatix migrate plan
          jq -e '.counts.modified == 0 and .counts.removed == 0' \
            xmatix/.snapshot/migrate-plan.json

migrate plan exports a fresh snapshot from the tenant and hash-compares it against the checkout (how the plan works); the jq assertion turns its counts into a pass/fail. A failing gate means someone changed the tenant in the product without exporting — the fix is a fresh snapshot export committed through review, not a forced apply.

Promote a release

Applies the repository state to the tenant when a release tag is pushed:

name: promote
on:
  push:
    tags: ['v*']
jobs:
  promote:
    runs-on: [self-hosted, xmatix-runner]
    steps:
      - uses: actions/checkout@v4
      - run: xmatix doctor
      - run: xmatix migrate apply --dry-run
      - run: xmatix migrate apply

The --dry-run before the real apply is cheap insurance: it prints exactly what will be pushed, so a mis-scoped checkout or a missing folder aborts before anything is written. Remember that apply never deletes server artifacts — removals stay manual by design.

Release-time snapshot

For any CI system — three commands and a git check prove the repository captured the tenant as shipped:

xmatix doctor
xmatix snapshot export
git diff --exit-code xmatix/

A non-zero exit from git diff means the export produced changes the repo did not have — the release is drifting from its own record. Archive the diff as a build artifact when this gate fails; it is the exact list of what was changed in-product.

Local pre-commit hook

A lightweight local guard that keeps metadata honest before it ever reaches CI — in .git/hooks/pre-commit:

#!/usr/bin/env bash
set -e
xmatix doctor
git diff --cached --name-only | grep -q '^xmatix/' \
  && xmatix metadata diff xmatix/metadata/tenant-owned.json

When a commit touches the artifact tree, metadata diff compares the committed seed-pack against a live export, so a stale metadata file gets caught at commit time rather than at review.

Common questions

Which user should the pipeline sign in as?

A dedicated integration account with exactly the customization capabilities the pipeline needs — the CLI acts with the signed-in user's permissions, so the account's grants are the pipeline's blast radius. Sign that account in once on the runner, and treat the runner's home directory (where the encrypted token cache lives) with the same care as any credential store.

How does the pipeline know which tenant it targets?

From the checked-out .xmatix/config.json — the workspace is the targeting. This is worth making explicit in the repo structure: one repository (or one directory with its own workspace) per tenant, so a pipeline can never apply the right files to the wrong tenant by picking up an unexpected config.

Can the drift gate and promotion target different tenants?

Yes, with one workspace each — for example, drift-gating a production tenant while promoting to a staging tenant first. Each job checks out (or cds into) the workspace for its tenant; nothing else changes, because every command resolves tenant, API and identity from the workspace it runs in.