| name | maintainx-ci-integration |
| description | 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 automated testing", "maintainx ci/cd".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*), Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
MaintainX CI Integration
Overview
Configure continuous integration pipelines for MaintainX integrations with automated testing, security scanning, and quality gates.
Prerequisites
- Git repository with MaintainX integration
- CI/CD platform (GitHub Actions, GitLab CI, etc.)
- Test environment with API access
Instructions
Step 1: GitHub Actions Workflow
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]
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/
Step 2: Test Configuration
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/'],
projects: [
{
displayName: 'unit',
testMatch: ['<rootDir>/tests/unit/**/*.test.ts'],
},
{
displayName: 'integration',
testMatch: ['<rootDir>/tests/integration/**/*.test.ts'],
},
],
};
import dotenv from 'dotenv';
dotenv.config({ path: '.env.test' });
jest.setTimeout(30000);
beforeAll(() => {
if (!process.env.MAINTAINX_API_KEY) {
console.warn('MAINTAINX_API_KEY not set - integration tests will be skipped');
}
});
afterAll(() => {
});
Step 3: Unit Tests with Mocks
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 ()).();
});
(, {
client = ();
(client).();
});
});
(, {
(, () => {
mockResponse = {
: {
: [{ : , : }],
: ,
},
};
client = ();
(client ).. = jest.().(mockResponse);
result = client.({ : });
(result.).();
(result.[].).();
});
(, () => {
client = ();
(client ).. = jest.().({ : { : [] } });
client.({ : , : });
((client )..).(, {
: { : , : },
});
});
});
(, {
(, () => {
mockResponse = {
: { : , : , : },
};
client = ();
(client ).. = jest.().(mockResponse);
result = client.({ : });
(result.).();
((client )..).(, { : });
});
});
});
Step 4: Integration Tests
import { MaintainXClient } from '../../src/api/maintainx-client';
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 () => {
});
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);
});
(, () => {
testTitle = ;
workOrder = client.({
: testTitle,
: ,
: ,
});
(workOrder).();
(workOrder.).(testTitle);
(workOrder.).();
createdWorkOrderId = workOrder.;
});
(, () => {
(!createdWorkOrderId) {
.();
;
}
workOrder = client.(createdWorkOrderId);
(workOrder.).(createdWorkOrderId);
});
(, () => {
response = client.({
: ,
: ,
});
response..( {
(wo.).();
});
});
});
(, {
(, () => {
response = client.({ : });
(response).();
(.(response.)).();
});
});
(, {
(, () => {
response = client.({ : });
(response).();
(.(response.)).();
});
});
(, {
(, () => {
response = client.({ : });
(response).();
(.(response.)).();
});
});
});
Step 5: GitLab CI Configuration
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:
Step 6: Package.json Scripts
{
"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"
}
}
Output
- GitHub Actions workflow configured
- GitLab CI pipeline configured
- Unit tests with mocks
- Integration tests with real API
- Security scanning enabled
Best Practices
- Separate test types: Unit tests run fast on every commit; integration tests on main only
- Use test API keys: Never use production keys in CI
- Rate limit awareness: Add delays between integration tests
- Clean up test data: Delete test work orders after tests
- Cache dependencies: Speed up CI with npm caching
Resources
Next Steps
For deployment automation, see maintainx-deploy-integration.