environment-setup-guide
Guide developers through setting up development environments with proper tools, dependencies, and configurations
maintainx-ci-integration
Integrate MaintainX API testing into CI/CD pipelines. Use when setting up automated testing, configuring CI workflows, or implementing continuous integration for MaintainX integrations. Trigger with phrases like "maintainx ci", "maintainx github actions", "maintainx pipeline", "maintainx automate...
Full skill instructions
Configure continuous integration pipelines for MaintainX integrations with automated testing, security scanning, and quality gates.
# .github/workflows/maintainx-ci.yml
name: MaintainX Integration CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
jobs:
lint:
name: Lint & Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
- name: Run TypeScript type check
run: npm run typecheck
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm run test:unit -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: ./coverage/lcov.info
fail_ci_if_error: true
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
needs: [lint, unit-tests]
# Only run on main branch to avoid rate limits
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run integration tests
env:
MAINTAINX_API_KEY: ${{ secrets.MAINTAINX_API_KEY_TEST }}
NODE_ENV: test
run: npm run test:integration
security-scan:
name: Security Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run npm audit
run: npm audit --production --audit-level=high
- name: Check for secrets
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
extra_args: --only-verified
build:
name: Build
runs-on: ubuntu-latest
needs: [lint, unit-tests]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/tests'],
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts'],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
testTimeout: 30000,
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
// Test suites
projects: [
{
displayName: 'unit',
testMatch: ['<rootDir>/tests/unit/**/*.test.ts'],
},
{
displayName: 'integration',
testMatch: ['<rootDir>/tests/integration/**/*.test.ts'],
},
],
};
// tests/setup.ts
import dotenv from 'dotenv';
// Load test environment
dotenv.config({ path: '.env.test' });
// Global test timeout
jest.setTimeout(30000);
// Global setup
beforeAll(() => {
// Verify test environment
if (!process.env.MAINTAINX_API_KEY) {
console.warn('MAINTAINX_API_KEY not set - integration tests will be skipped');
}
});
// Global teardown
afterAll(() => {
// Cleanup test data if needed
});
// tests/unit/client.test.ts
import { MaintainXClient } from '../../src/api/maintainx-client';
import axios from 'axios';
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;
describe('MaintainXClient', () => {
beforeEach(() => {
process.env.MAINTAINX_API_KEY = 'test_api_key';
jest.clearAllMocks();
mockedAxios.create.mockReturnValue({
get: jest.fn(),
post: jest.fn(),
interceptors: {
request: { use: jest.fn() },
response: { use: jest.fn() },
},
} as any);
});
describe('constructor', () => {
it('should throw if API key not provided', () => {
delete process.env.MAINTAINX_API_KEY;
expect(() => new MaintainXClient()).toThrow('MAINTAINX_API_KEY is required');
});
it('should create client with valid API key', () => {
const client = new MaintainXClient();
expect(client).toBeDefined();
});
});
describe('getWorkOrders', () => {
it('should fetch work orders', async () => {
const mockResponse = {
data: {
workOrders: [{ id: 'wo_1', title: 'Test' }],
nextCursor: null,
},
};
const client = new MaintainXClient();
(client as any).client.get = jest.fn().mockResolvedValue(mockResponse);
const result = await client.getWorkOrders({ limit: 10 });
expect(result.workOrders).toHaveLength(1);
expect(result.workOrders[0].id).toBe('wo_1');
});
it('should handle pagination parameters', async () => {
const client = new MaintainXClient();
(client as any).client.get = jest.fn().mockResolvedValue({ data: { workOrders: [] } });
await client.getWorkOrders({ limit: 50, cursor: 'abc123' });
expect((client as any).client.get).toHaveBeenCalledWith('/workorders', {
params: { limit: 50, cursor: 'abc123' },
});
});
});
describe('createWorkOrder', () => {
it('should create work order with required fields', async () => {
const mockResponse = {
data: { id: 'wo_new', title: 'New WO', status: 'OPEN' },
};
const client = new MaintainXClient();
(client as any).client.post = jest.fn().mockResolvedValue(mockResponse);
const result = await client.createWorkOrder({ title: 'New WO' });
expect(result.id).toBe('wo_new');
expect((client as any).client.post).toHaveBeenCalledWith('/workorders', { title: 'New WO' });
});
});
});
// tests/integration/api.test.ts
import { MaintainXClient } from '../../src/api/maintainx-client';
// Skip if no API key
const describeIfApiKey = process.env.MAINTAINX_API_KEY
? describe
: describe.skip;
describeIfApiKey('MaintainX API Integration', () => {
let client: MaintainXClient;
let createdWorkOrderId: string;
beforeAll(() => {
client = new MaintainXClient();
});
afterAll(async () => {
// Cleanup: Delete test work orders
// Note: Implement if delete endpoint is available
});
describe('Work Orders', () => {
it('should list work orders', async () => {
const response = await client.getWorkOrders({ limit: 5 });
expect(response).toHaveProperty('workOrders');
expect(Array.isArray(response.workOrders)).toBe(true);
});
it('should create a work order', async () => {
const testTitle = `CI Test - ${new Date().toISOString()}`;
const workOrder = await client.createWorkOrder({
title: testTitle,
description: 'Created by CI integration test',
priority: 'LOW',
});
expect(workOrder).toHaveProperty('id');
expect(workOrder.title).toBe(testTitle);
expect(workOrder.status).toBe('OPEN');
createdWorkOrderId = workOrder.id;
});
it('should get a single work order', async () => {
// Skip if create didn't work
if (!createdWorkOrderId) {
console.warn('Skipping: No work order created');
return;
}
const workOrder = await client.getWorkOrder(createdWorkOrderId);
expect(workOrder.id).toBe(createdWorkOrderId);
});
it('should filter work orders by status', async () => {
const response = await client.getWorkOrders({
status: 'OPEN',
limit: 10,
});
response.workOrders.forEach(wo => {
expect(wo.status).toBe('OPEN');
});
});
});
describe('Assets', () => {
it('should list assets', async () => {
const response = await client.getAssets({ limit: 5 });
expect(response).toHaveProperty('assets');
expect(Array.isArray(response.assets)).toBe(true);
});
});
describe('Locations', () => {
it('should list locations', async () => {
const response = await client.getLocations({ limit: 5 });
expect(response).toHaveProperty('locations');
expect(Array.isArray(response.locations)).toBe(true);
});
});
describe('Users', () => {
it('should list users', async () => {
const response = await client.getUsers({ limit: 5 });
expect(response).toHaveProperty('users');
expect(Array.isArray(response.users)).toBe(true);
});
});
});
# .gitlab-ci.yml
stages:
- validate
- test
- build
- deploy
variables:
NODE_VERSION: '20'
.node-setup:
image: node:${NODE_VERSION}
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
lint:
extends: .node-setup
stage: validate
script:
- npm ci
- npm run lint
- npm run typecheck
unit-tests:
extends: .node-setup
stage: test
script:
- npm ci
- npm run test:unit -- --coverage
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
integration-tests:
extends: .node-setup
stage: test
only:
- main
script:
- npm ci
- npm run test:integration
variables:
MAINTAINX_API_KEY: $MAINTAINX_API_KEY_TEST
security-scan:
extends: .node-setup
stage: validate
script:
- npm ci
- npm audit --production --audit-level=high
allow_failure: true
build:
extends: .node-setup
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
{
"scripts": {
"build": "tsc",
"lint": "eslint 'src/**/*.ts' 'tests/**/*.ts'",
"lint:fix": "eslint 'src/**/*.ts' 'tests/**/*.ts' --fix",
"typecheck": "tsc --noEmit",
"test": "jest",
"test:unit": "jest --selectProjects unit",
"test:integration": "jest --selectProjects integration",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"ci": "npm run lint && npm run typecheck && npm run test:unit && npm run build"
}
}
For deployment automation, see maintainx-deploy-integration.
Guide developers through setting up development environments with proper tools, dependencies, and configurations
Implement Exa lint rules, policy enforcement, and automated guardrails. Use when setting up code quality rules for Exa integrations, implementing pre-commit hooks, or configuring CI policy checks for Exa best practices. Trigger with phrases like "exa policy", "exa lint", "exa guardrails", "exa be...
Configure CI/CD pipelines for Documenso integrations. Use when setting up automated testing, deployment pipelines, or continuous integration for Documenso projects. Trigger with phrases like "documenso CI", "documenso GitHub Actions", "documenso pipeline", "documenso automated testing".
Build check model availability and implement fallback chains. Use when building resilient systems or handling model outages. Trigger with phrases like 'openrouter availability', 'openrouter fallback', 'openrouter model down', 'openrouter health check'.
Configure Langfuse enterprise organization management and access control. Use when implementing team access controls, configuring organization settings, or setting up role-based permissions for Langfuse projects. Trigger with phrases like "langfuse RBAC", "langfuse teams", "langfuse organization"...
Execute compliance and security auditing for Cursor usage. Triggers on "cursor compliance", "cursor audit", "cursor security review", "cursor soc2", "cursor gdpr". Use when analyzing or auditing cursor compliance audit. Trigger with phrases like "cursor compliance audit", "cursor audit", "cursor".
Configure Apollo.io CI/CD integration. Use when setting up automated testing, continuous integration, or deployment pipelines for Apollo integrations. Trigger with phrases like "apollo ci", "apollo github actions", "apollo pipeline", "apollo ci/cd", "apollo automated tests".
Create robust Python automation with full logging and safety checks. Use when tasks need complex data processing, authenticated API work, conditional file operations, or error handling beyond simple shell commands.
Configure PostHog across development, staging, and production environments. Use when setting up multi-environment deployments, configuring per-environment secrets, or implementing environment-specific PostHog configurations. Trigger with phrases like "posthog environments", "posthog staging", "po...
Expert in designing and building autonomous AI agents. Masters tool use, memory systems, planning strategies, and multi-agent orchestration. Use when: build agent, AI agent, autonomous agent, tool use, function calling.
Validate insecure deserialization checker operations. Auto-activating skill for Security Fundamentals. Triggers on: insecure deserialization checker, insecure deserialization checker Part of the Security Fundamentals skill category. Use when working with insecure deserialization checker functiona...
Manage path traversal finder operations. Auto-activating skill for Security Fundamentals. Triggers on: path traversal finder, path traversal finder Part of the Security Fundamentals skill category. Use when working with path traversal finder functionality. Trigger with phrases like "path traversa...
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience