maintainx-multi-env-setup
Configure multiple MaintainX environments (dev, staging, production). Use when setting up environment-specific configurations, managing multiple MaintainX accounts, or implementing environment promotion. Trigger with phrases like "maintainx environments", "maintainx staging", "maintainx dev prod", "maintainx multi-environment", "maintainx config". allowed-tools: Read, Write, Edit, Bash(npm:*) version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>
Allowed Tools
No tools specified
Provided by Plugin
maintainx-pack
Claude Code skill pack for MaintainX CMMS (24 skills)
Installation
This skill is included in the maintainx-pack plugin:
/plugin install maintainx-pack@claude-code-plugins-plus
Click to copy
Instructions
# MaintainX Multi-Environment Setup
## Overview
Configure and manage multiple MaintainX environments for development, staging, and production workflows.
## Prerequisites
- Multiple MaintainX accounts or organizations
- Secret management solution
- CI/CD pipeline configured
## Environment Strategy
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Environment Promotion Flow โ
โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ DEV โ โโโโถ โ STAGING โ โโโโถ โ PROD โ โ
โ โ โ โ โ โ โ โ
โ โ sandbox โ โ testing โ โ live โ โ
โ โ data โ โ data โ โ data โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ โ โ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ dev- โ โ staging-โ โ prod- โ โ
โ โ api-key โ โ api-key โ โ api-key โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
## Instructions
### Step 1: Environment Configuration
```typescript
// src/config/environments.ts
type Environment = 'development' | 'staging' | 'production';
interface EnvironmentConfig {
name: Environment;
maintainx: {
apiKey: string;
orgId?: string;
baseUrl: string;
};
features: {
caching: boolean;
rateLimit: number;
webhooksEnabled: boolean;
};
logging: {
level: string;
redactPII: boolean;
};
}
const environments: Record EnvironmentConfig> = {
development: () => ({
name: 'development',
maintainx: {
apiKey: process.env.MAINTAINX_API_KEY_DEV!,
orgId: process.env.MAINTAINX_ORG_ID_DEV,
baseUrl: 'https://api.getmaintainx.com/v1',
},
features: {
caching: false, // Disable caching in dev for fresh data
rateLimit: 60,
webhooksEnabled: false,
},
logging: {
level: 'debug',
redactPII: false, // OK in dev
},
}),
staging: () => ({
name: 'staging',
maintainx: {
apiKey: process.env.MAINTAINX_API_KEY_STAGING!,
orgId: process.env.MAINTAINX_ORG_ID_STAGING,
baseUrl: 'https://api.getmaintainx.com/v1',
},
features: {
caching: true,
rateLimit: 120,
webhooksEnabled: true,
},
logging: {
level: 'info',
redactPII: true,
},
}),
production: () => ({
name: 'production',
maintainx: {
apiKey: process.env.MAINTAINX_API_KEY_PROD!,
orgId: process.env.MAINTAINX_ORG_ID_PROD,
baseUrl: 'https://api.getmaintainx.com/v1',
},
features: {
caching: true,
rateLimit: 300,
webhooksEnabled: true,
},
logging: {
level: 'warn',
redactPII: true,
},
}),
};
function getEnvironment(): Environment {
const env = process.env.NODE_ENV as Environment;
if (!['development', 'staging', 'production'].includes(env)) {
return 'development';
}
return env;
}
function getConfig(): EnvironmentConfig {
const env = getEnvironment();
return environments[env]();
}
export { getConfig, getEnvironment, EnvironmentConfig, Environment };
```
### Step 2: Environment-Aware Client Factory
```typescript
// src/api/client-factory.ts
import { getConfig } from '../config/environments';
class MaintainXClientFactory {
private static clients: Map = new Map();
static getClient(environment?: Environment): MaintainXClient {
const config = environment
? environments[environment]()
: getConfig();
const cacheKey = config.name;
if (!this.clients.has(cacheKey)) {
const client = new MaintainXClient({
apiKey: config.maintainx.apiKey,
orgId: config.maintainx.orgId,
baseUrl: config.maintainx.baseUrl,
});
// Apply environment-specific configurations
if (config.features.caching) {
// Wrap with caching
}
this.clients.set(cacheKey, client);
}
return this.clients.get(cacheKey)!;
}
// For cross-environment operations
static getClientForEnvironment(env: Environment): MaintainXClient {
return this.getClient(env);
}
// Clear cached clients (useful for testing)
static clearCache(): void {
this.clients.clear();
}
}
export { MaintainXClientFactory };
```
### Step 3: Environment Variables Template
```bash
# .env.example
# Development
MAINTAINX_API_KEY_DEV=mx_dev_xxxxx
MAINTAINX_ORG_ID_DEV=org_dev_xxxxx
# Staging
MAINTAINX_API_KEY_STAGING=mx_staging_xxxxx
MAINTAINX_ORG_ID_STAGING=org_staging_xxxxx
# Production
MAINTAINX_API_KEY_PROD=mx_prod_xxxxx
MAINTAINX_ORG_ID_PROD=org_prod_xxxxx
# Current environment
NODE_ENV=development
```
```yaml
# docker-compose.override.yml (development)
version: '3.8'
services:
app:
environment:
- NODE_ENV=development
- MAINTAINX_API_KEY=${MAINTAINX_API_KEY_DEV}
- MAINTAINX_ORG_ID=${MAINTAINX_ORG_ID_DEV}
```
### Step 4: Secret Management Integration
```typescript
// src/config/secrets.ts
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
interface SecretConfig {
apiKey: string;
orgId?: string;
}
class SecretLoader {
private client: SecretManagerServiceClient;
private projectId: string;
constructor() {
this.client = new SecretManagerServiceClient();
this.projectId = process.env.GCP_PROJECT_ID!;
}
async loadEnvironmentSecrets(env: Environment): Promise {
const apiKeyName = `maintainx-api-key-${env}`;
const orgIdName = `maintainx-org-id-${env}`;
const apiKey = await this.getSecret(apiKeyName);
const orgId = await this.getSecret(orgIdName).catch(() => undefined);
return { apiKey, orgId };
}
private async getSecret(name: string): Promise {
const [version] = await this.client.accessSecretVersion({
name: `projects/${this.projectId}/secrets/${name}/versions/latest`,
});
return version.payload?.data?.toString() || '';
}
}
// Kubernetes secret mounting alternative
function loadFromMountedSecrets(env: Environment): SecretConfig {
const basePath = '/var/secrets/maintainx';
return {
apiKey: fs.readFileSync(`${basePath}/${env}/api-key`, 'utf8').trim(),
orgId: fs.existsSync(`${basePath}/${env}/org-id`)
? fs.readFileSync(`${basePath}/${env}/org-id`, 'utf8').trim()
: undefined,
};
}
```
### Step 5: Environment Promotion Tools
```typescript
// scripts/promote-config.ts
import { MaintainXClientFactory } from '../src/api/client-factory';
interface PromotionResult {
success: boolean;
itemsPromoted: number;
errors: string[];
}
// Promote configuration from one environment to another
async function promoteConfiguration(
sourceEnv: Environment,
targetEnv: Environment
): Promise {
const result: PromotionResult = {
success: true,
itemsPromoted: 0,
errors: [],
};
const sourceClient = MaintainXClientFactory.getClientForEnvironment(sourceEnv);
const targetClient = MaintainXClientFactory.getClientForEnvironment(targetEnv);
console.log(`Promoting from ${sourceEnv} to ${targetEnv}...`);
// Note: This is conceptual - actual promotion depends on what's configurable via API
// Some configurations may need to be managed manually in MaintainX dashboard
// Example: Sync work order templates (if supported)
// Example: Sync procedure templates (if supported)
console.log('Promotion complete');
console.log(`Items promoted: ${result.itemsPromoted}`);
if (result.errors.length > 0) {
console.log('Errors:', result.errors);
}
return result;
}
// Validate environment configuration
async function validateEnvironment(env: Environment): Promise {
console.log(`Validating ${env} environment...`);
try {
const client = MaintainXClientFactory.getClientForEnvironment(env);
// Test API connectivity
await client.getUsers({ limit: 1 });
console.log(` [OK] API connectivity`);
// Test work order access
await client.getWorkOrders({ limit: 1 });
console.log(` [OK] Work order access`);
// Test asset access
await client.getAssets({ limit: 1 });
console.log(` [OK] Asset access`);
return true;
} catch (error: any) {
console.error(` [FAIL] ${error.message}`);
return false;
}
}
// CLI interface
async function main() {
const args = process.argv.slice(2);
const command = args[0];
switch (command) {
case 'validate':
const env = args[1] as Environment || 'development';
const valid = await validateEnvironment(env);
process.exit(valid ? 0 : 1);
break;
case 'promote':
const source = args[1] as Environment;
const target = args[2] as Environment;
if (!source || !target) {
console.error('Usage: promote ');
process.exit(1);
}
await promoteConfiguration(source, target);
break;
default:
console.log('Commands: validate , promote ');
}
}
main().catch(console.error);
```
### Step 6: CI/CD Environment Matrix
```yaml
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches:
- develop # Deploy to staging
- main # Deploy to production
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
type: choice
options:
- staging
- production
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- branch: develop
environment: staging
- branch: main
environment: production
environment: ${{ matrix.environment }}
steps:
- uses: actions/checkout@v4
- name: Validate environment config
run: |
npm ci
npm run env:validate -- ${{ matrix.environment }}
env:
MAINTAINX_API_KEY_STAGING: ${{ secrets.MAINTAINX_API_KEY_STAGING }}
MAINTAINX_API_KEY_PROD: ${{ secrets.MAINTAINX_API_KEY_PROD }}
- name: Deploy to ${{ matrix.environment }}
run: |
./scripts/deploy.sh ${{ matrix.environment }}
env:
NODE_ENV: ${{ matrix.environment }}
```
## Output
- Environment-specific configurations
- Secret management integration
- Client factory for multi-environment
- Promotion tools for config sync
- CI/CD environment matrix
## Best Practices
1. **Isolate environments**: Use separate MaintainX organizations per environment
2. **Never share API keys**: Each environment gets unique credentials
3. **Validate before promote**: Always test configuration in lower environments
4. **Document differences**: Track what varies between environments
5. **Audit access**: Log which environment is being accessed
## Resources
- [MaintainX API Documentation](https://maintainx.dev/)
- [12-Factor App Configuration](https://12factor.net/config)
- [Google Cloud Secret Manager](https://cloud.google.com/secret-manager)
## Next Steps
For observability setup, see `maintainx-observability`.