Skip to content

Multi-Platform Support

Overview

Sentinel CI provides a unified interface to multiple CI/CD platforms. This document compares platform capabilities, configuration, and usage patterns.

Supported Platforms

Platform Status API Version Auth Method Read-Only
Jenkins ✅ Full REST Basic Auth (user:token) Yes
GitHub Actions ✅ Full v3 Bearer Token Yes
GitLab CI ✅ Full v4 Private Token Yes
Generic CI 🚧 Planned N/A Configurable Yes

Feature Comparison

Feature Jenkins GitHub Actions GitLab CI Generic CI
List Jobs/Workflows ✅ ✅ ✅ 🚧
Build Summary ✅ ✅ ✅ 🚧
Failed Stages ✅ ✅ ✅ 🚧
Failed Tests ✅ JUnit ⚠️ Limited ✅ Native 🚧
Log Access ✅ Full ✅ Full ✅ Full 🚧
Pipeline Visualization ✅ Blue Ocean ✅ Workflow Graph ✅ Pipeline Graph 🚧
Artifact Access ✅ ✅ ✅ 🚧
Branch/Tag Filtering ✅ ✅ ✅ 🚧
Parallel Jobs ✅ ✅ ✅ 🚧
Cache Support ✅ ✅ ✅ ✅

Legend: - ✅ Full support - ⚠️ Partial support or requires additional setup - 🚧 Planned/In development - ❌ Not supported

Platform-Specific Configuration

Jenkins

Requirements: - Jenkins 2.x or higher - Installed plugins: wfapi (for Pipeline), junit (for tests) - API token (user:token format)

Configuration:

# .env
CI_PLATFORM=jenkins
JENKINS_URL=https://jenkins.example.com
JENKINS_TOKEN=username:api_token_here

Features: - Classic and Pipeline job support - Blue Ocean integration - JUnit test result parsing - Console log access - Folder support (/job/folder/job/name)

API Endpoints:

# List all jobs
GET /api/json?tree=jobs[name,url,color,lastBuild[number,result]]

# Get build details
GET /job/{name}/{build}/api/json

# Get pipeline stages (wfapi plugin)
GET /job/{name}/{build}/wfapi/describe

# Get test results
GET /job/{name}/{build}/testReport/api/json

# Get console log
GET /job/{name}/{build}/consoleText

Status Mapping:

{
    'blue': 'SUCCESS',
    'red': 'FAILURE',
    'yellow': 'UNSTABLE',
    'aborted': 'ABORTED',
    'notbuilt': 'NOT_BUILT',
    'blue_anime': 'IN_PROGRESS',
    'red_anime': 'IN_PROGRESS',
}

Example:

from mcps.jenkins.client import JenkinsClient

client = JenkinsClient(
    base_url="https://jenkins.example.com",
    token="user:token"
)

# List all jobs
jobs = client.list_jobs()

# Get specific build
build = client.get_build_summary("backend-service", "123")

# Get failed tests
tests = client.get_failed_tests("backend-service", "123")

GitHub Actions

Requirements: - GitHub repository with Actions enabled - Personal Access Token (PAT) or GitHub App - Permissions: actions:read, contents:read

Configuration:

# .env
CI_PLATFORM=github-actions
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
GITHUB_OWNER=your-org
GITHUB_REPO=your-repo

Features: - Workflow runs - Job and step details - Log downloads - Artifact access - Check run integration

API Endpoints:

# List workflow runs
GET /repos/{owner}/{repo}/actions/runs

# Get run details
GET /repos/{owner}/{repo}/actions/runs/{run_id}

# Get jobs for a run
GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs

# Download logs
GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs

Status Mapping:

{
    'completed': 'SUCCESS' or 'FAILURE',
    'in_progress': 'IN_PROGRESS',
    'queued': 'PENDING',
    'cancelled': 'ABORTED',
}

Example:

from mcps.github_actions.client import GitHubActionsClient

client = GitHubActionsClient(
    token="ghp_token",
    owner="your-org",
    repo="your-repo"
)

# List workflow runs
runs = client.list_jobs()

# Get specific run
run = client.get_build_summary("workflow-name", "run-id")

# Get failed steps
steps = client.get_failed_stages("workflow-name", "run-id")

Limitations: - Test reporting requires GitHub Checks API or third-party actions - Logs must be downloaded as ZIP and extracted - Rate limits: 5,000 requests/hour for authenticated requests

GitLab CI

Requirements: - GitLab instance (self-hosted or GitLab.com) - Personal Access Token or Project Access Token - Permissions: read_api

Configuration:

# .env
CI_PLATFORM=gitlab-ci
GITLAB_URL=https://gitlab.com  # or self-hosted URL
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
GITLAB_PROJECT_ID=12345  # or "group/project"

Features: - Pipeline jobs - Stage details - Native test report support - MR pipeline tracking - Job artifacts - Trace (log) streaming

API Endpoints:

# List pipelines
GET /api/v4/projects/{id}/pipelines

# Get pipeline details
GET /api/v4/projects/{id}/pipelines/{pipeline_id}

# Get pipeline jobs
GET /api/v4/projects/{id}/pipelines/{pipeline_id}/jobs

# Get test report
GET /api/v4/projects/{id}/pipelines/{pipeline_id}/test_report

# Get job trace
GET /api/v4/projects/{id}/jobs/{job_id}/trace

Status Mapping:

{
    'created': 'PENDING',
    'pending': 'PENDING',
    'running': 'IN_PROGRESS',
    'success': 'SUCCESS',
    'failed': 'FAILURE',
    'canceled': 'ABORTED',
    'skipped': 'SKIPPED',
    'manual': 'MANUAL',
}

Example:

from mcps.gitlab_ci.client import GitLabCIClient

client = GitLabCIClient(
    base_url="https://gitlab.com",
    token="glpat-token",
    project_id="12345"
)

# List pipelines
pipelines = client.list_jobs()

# Get specific pipeline
pipeline = client.get_build_summary("pipeline-name", "pipeline-id")

# Get test report
tests = client.get_failed_tests("pipeline-name", "pipeline-id")

Advantages: - Built-in test report support (JUnit XML, JSON) - Rich pipeline graph visualization - MR integration - Self-hosted option

Platform Selection Guide

Choose Jenkins if:

  • ✅ You have complex build pipelines
  • ✅ You need extensive plugin ecosystem
  • ✅ You're using Groovy-based Jenkinsfiles
  • ✅ You have on-premise infrastructure
  • ✅ You need fine-grained access control

Choose GitHub Actions if:

  • ✅ Your code is on GitHub
  • ✅ You want tight Git integration
  • ✅ You prefer YAML-based workflows
  • ✅ You want marketplace actions
  • ✅ You're okay with cloud-hosted runners

Choose GitLab CI if:

  • ✅ Your code is on GitLab
  • ✅ You want native test reporting
  • ✅ You prefer .gitlab-ci.yml format
  • ✅ You need built-in security scanning
  • ✅ You want GitOps integration

Choose Generic CI if:

  • ✅ You're using CircleCI, Travis, Bamboo, etc.
  • ✅ You need custom integration
  • ✅ Your platform has a REST API
  • ✅ You want to define your own mappings

Migration Between Platforms

Jenkins → GitHub Actions

Configuration changes:

# Before (Jenkins)
CI_PLATFORM=jenkins
JENKINS_URL=https://jenkins.example.com
JENKINS_TOKEN=user:token

# After (GitHub Actions)
CI_PLATFORM=github-actions
GITHUB_TOKEN=ghp_token
GITHUB_OWNER=your-org
GITHUB_REPO=your-repo

Code changes: - Job names: job/name → workflow-name - Build IDs: 123 → run-id - No changes to tool calls (same API)

GitLab CI → Jenkins

# Before (GitLab)
CI_PLATFORM=gitlab-ci
GITLAB_URL=https://gitlab.com
GITLAB_TOKEN=glpat-token
GITLAB_PROJECT_ID=12345

# After (Jenkins)
CI_PLATFORM=jenkins
JENKINS_URL=https://jenkins.example.com
JENKINS_TOKEN=user:token

Considerations: - GitLab pipeline IDs are numeric - Jenkins build numbers are also numeric - Test reporting format may differ

Multi-Platform Usage

Running Multiple Platforms Simultaneously

Option 1: Multiple instances

# Terminal 1: Jenkins
export CI_PLATFORM=jenkins
export JENKINS_URL=https://jenkins.example.com
export JENKINS_TOKEN=user:token
python -m sentinel_ci.server

# Terminal 2: GitHub Actions
export CI_PLATFORM=github-actions
export GITHUB_TOKEN=ghp_token
export GITHUB_OWNER=your-org
export GITHUB_REPO=your-repo
python -m sentinel_ci.server --port 8001

Option 2: Docker Compose

version: '3'
services:
  sentinel-jenkins:
    image: sentinel-ci:latest
    environment:
      - CI_PLATFORM=jenkins
      - JENKINS_URL=${JENKINS_URL}
      - JENKINS_TOKEN=${JENKINS_TOKEN}
    ports:
      - "8000:8000"

  sentinel-github:
    image: sentinel-ci:latest
    environment:
      - CI_PLATFORM=github-actions
      - GITHUB_TOKEN=${GITHUB_TOKEN}
      - GITHUB_OWNER=${GITHUB_OWNER}
      - GITHUB_REPO=${GITHUB_REPO}
    ports:
      - "8001:8000"

Aggregating Data Across Platforms

Example: Compare build times

import asyncio
from mcps.jenkins.client import JenkinsClient
from mcps.github_actions.client import GitHubActionsClient

async def compare_platforms():
    jenkins_client = JenkinsClient(...)
    github_client = GitHubActionsClient(...)

    jenkins_builds = jenkins_client.list_jobs()
    github_runs = github_client.list_jobs()

    # Compare average duration
    jenkins_avg = sum(b['duration'] for b in jenkins_builds) / len(jenkins_builds)
    github_avg = sum(r['duration'] for r in github_runs) / len(github_runs)

    print(f"Jenkins avg: {jenkins_avg}s")
    print(f"GitHub avg: {github_avg}s")

Platform-Specific Tips

Jenkins

Performance optimization:

# Use depth parameter to limit tree depth
GET /api/json?tree=jobs[name,lastBuild[number,result]]&depth=1

# Filter by job type
GET /api/json?tree=jobs[name]&filter=org.jenkinsci.plugins.workflow.job.WorkflowJob

Handling folders:

# Jobs in folders use slash notation
job_name = "folder/subfolder/job-name"
build = client.get_build_summary(job_name, "123")

GitHub Actions

Rate limiting:

# Check rate limit status
import requests
response = requests.get(
    'https://api.github.com/rate_limit',
    headers={'Authorization': f'Bearer {token}'}
)
print(response.json())

Using GitHub App:

# Better rate limits with GitHub App
from github import Github

g = Github(app_id, private_key)
installation = g.get_app().get_installation(installation_id)
token = installation.get_access_token().token

GitLab CI

Using project ID vs path:

# Both work
GITLAB_PROJECT_ID=12345
GITLAB_PROJECT_ID=group/project  # URL-encoded: group%2Fproject

Self-hosted GitLab:

# Include API version
GITLAB_URL=https://gitlab.mycompany.com
# API calls will use: https://gitlab.mycompany.com/api/v4/...

Troubleshooting

Jenkins Issues

Problem: "Authentication failed"

# Verify token format
echo $JENKINS_TOKEN  # Should be: username:token

# Test manually
curl -u username:token https://jenkins.example.com/api/json

Problem: "wfapi plugin not found"

# Install plugin or disable pipeline features
# Client will fall back to basic build info

GitHub Actions Issues

Problem: "Rate limit exceeded"

# Check current limit
curl -H "Authorization: Bearer $GITHUB_TOKEN" \
  https://api.github.com/rate_limit

# Solution: Use GitHub App or wait for reset

Problem: "Resource not accessible by integration"

# Verify token permissions
# Ensure: actions:read, contents:read

GitLab CI Issues

Problem: "404 Project not found"

# Verify project ID
curl -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  https://gitlab.com/api/v4/projects/12345

# Or use URL-encoded path
curl -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  "https://gitlab.com/api/v4/projects/group%2Fproject"

Future Platform Support

Planned:

  • 🚧 CircleCI
  • 🚧 Travis CI
  • 🚧 Bamboo
  • 🚧 TeamCity
  • 🚧 Azure DevOps
  • 🚧 Drone CI
  • 🚧 Buildkite

Generic CI Adapter

For unsupported platforms, use the Generic CI adapter:

# generic-ci-config.yaml
platform: circleci
base_url: https://circleci.com/api/v2
auth:
  type: bearer
  token: ${CIRCLECI_TOKEN}
endpoints:
  list_jobs: /project/{project}/pipeline
  build_details: /project/{project}/pipeline/{id}
  logs: /project/{project}/job/{job_id}/logs
mappings:
  status:
    success: SUCCESS
    failed: FAILURE
    running: IN_PROGRESS

Contributing

See CONTRIBUTING.md for how to add support for a new platform.

Quick checklist: 1. Create mcps/<platform>/client.py 2. Implement AbstractCIClient interface 3. Add configuration to .env.example 4. Write tests in tests/test_<platform>.py 5. Update this documentation 6. Add example to examples/

References