Skip to content
maintainx-ci-integration logo

MaintainX CI Integration

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...

SKILL.md

Full skill instructions

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

# .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/

Step 2: Test Configuration

// 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
});

Step 3: Unit Tests with Mocks

// 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' });
    });
  });
});

Step 4: Integration Tests

// 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);
    });
  });
});

Step 5: GitLab CI Configuration

# .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

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

  1. Separate test types: Unit tests run fast on every commit; integration tests on main only
  2. Use test API keys: Never use production keys in CI
  3. Rate limit awareness: Add delays between integration tests
  4. Clean up test data: Delete test work orders after tests
  5. Cache dependencies: Speed up CI with npm caching

Resources

Next Steps

For deployment automation, see maintainx-deploy-integration.

More skills from Dicklesworthstone

environment-setup-guide logo
Dicklesworthstone/pi_agent_rust

environment-setup-guide

Guide developers through setting up development environments with proper tools, dependencies, and configurations

1.8K 0
View
exa-policy-guardrails logo
Dicklesworthstone/pi_agent_rust

exa-policy-guardrails

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...

1.8K 0
View
documenso-ci-integration logo
Dicklesworthstone/pi_agent_rust

documenso-ci-integration

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".

1.8K 0
View
openrouter-model-availability logo
Dicklesworthstone/pi_agent_rust

openrouter-model-availability

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'.

1.8K 0
View
langfuse-enterprise-rbac logo
Dicklesworthstone/pi_agent_rust

langfuse-enterprise-rbac

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"...

1.8K 0
View
cursor-compliance-audit logo
Dicklesworthstone/pi_agent_rust

cursor-compliance-audit

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".

1.8K 0
View
apollo-ci-integration logo
Dicklesworthstone/pi_agent_rust

apollo-ci-integration

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".

1.8K 0
View
python-script logo
Dicklesworthstone/pi_agent_rust

python-script

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.

1.8K 0
View
posthog-multi-env-setup logo
Dicklesworthstone/pi_agent_rust

posthog-multi-env-setup

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...

1.8K 0
View
ai-agents-architect logo
Dicklesworthstone/pi_agent_rust

ai-agents-architect

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.

1.8K 0
View
insecure-deserialization-checker logo
Dicklesworthstone/pi_agent_rust

insecure-deserialization-checker

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...

1.8K 0
View
path-traversal-finder logo
Dicklesworthstone/pi_agent_rust

path-traversal-finder

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...

1.8K 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View