A command-line tool written in Python that loads Circle CI config.yml and runs it locally inside Docker containers.
Note: The project name "elipse-ci" is intentional branding, not a misspelling of "eclipse-ci".
- 🚀 Run Circle CI configs locally without pushing to CI
- 🐳 Containerized Execution: All commands run inside Docker containers matching your Circle CI environment
- 📂 Directory Mounting: Current directory is mounted with read-write permissions
- ⚡ Configurable concurrent job execution
- 🎨 Clear, colored console output
- 📝 Detailed logging to temp files with option to show only results/errors
- 🔌 Support for common pre-built orbs (Node, Python, Docker)
- 🔧 Easy plugin system for custom orbs
- 🔄 Dependency-aware job execution
- 🔀 Multi-Container Parallel Execution: Run multiple containers in parallel with intelligent step execution
- All containers start simultaneously
- 10-second initialization period
- Steps execute on the first container to exit successfully
- All containers terminated after steps complete
- Graceful Ctrl+C handling for clean shutdown
- Python 3.8+
- Docker (must be installed and running)
pip install -e .Run the default workflow from .circleci/config.yml:
elipse-cielipse-ci --config path/to/config.ymlelipse-ci --workflow build-test-deployelipse-ci --job buildRun jobs concurrently (respecting dependencies):
elipse-ci --concurrent --max-workers 4Show only results and errors (detailed logs still saved to file):
elipse-ci --quietelipse-ci --log-dir /path/to/logsSpecify the target platform for Docker images (useful for multi-architecture builds):
elipse-ci --platform linux/amd64
elipse-ci --platform linux/arm64Set the working directory inside the container where commands are executed:
elipse-ci --workdir /home/circleciBy default, commands are executed from /project (where your code is mounted). Use --workdir to change this to the Docker image's home directory or any other path.
Export environment variables to containers:
elipse-ci --env NODE_ENV=production --env DEBUG=trueYou can use the -e shorthand:
elipse-ci -e NODE_ENV=production -e DEBUG=trueThe --env option can be used multiple times to set multiple environment variables. Each variable should be in the format KEY=VALUE.
Export secret environment variables from your host OS to containers:
elipse-ci --secret DATABASE_PASSWORD --secret API_KEYYou can use the -s shorthand:
elipse-ci -s DATABASE_PASSWORD -s API_KEYThe --secret option reads the value from your host OS environment variables and passes it to containers without exposing them on the command line. This is useful for sensitive data that you don't want visible in command history or process listings. If a secret is not found in the OS environment, a warning is logged and the secret is skipped.
Note: While secrets are not visible in the command-line invocation, they are still passed to Docker containers as environment variables and may be visible in Docker process listings, container inspection, and logs. For production use cases requiring stronger security guarantees, consider using Docker secrets or other secret management solutions.
Example:
export DATABASE_PASSWORD="my-secret-password"
export API_KEY="sk-1234567890"
elipse-ci --secret DATABASE_PASSWORD --secret API_KEYImport SSH key files into containers for Git operations or other SSH-based operations:
elipse-ci --ssh-key ~/.ssh/id_rsa --ssh-key ~/.ssh/id_ed25519The --ssh-key option mounts SSH key files from your host system into the container at /project/.ssh/ with read-only permissions. Commands running inside containers can copy these keys to a writable location like /tmp/ssh/ with proper permissions for SSH authentication (e.g., cloning private repositories, connecting to remote servers).
Example:
# Mount your default SSH key
elipse-ci --ssh-key ~/.ssh/id_rsa
# Mount multiple SSH keys
elipse-ci --ssh-key ~/.ssh/id_rsa --ssh-key ~/.ssh/deploy_keyUsage in your CI config:
- run:
name: Setup SSH
command: |
mkdir -p /tmp/ssh
chmod 700 /tmp/ssh
cp /project/.ssh/id_rsa /tmp/ssh/id_rsa
chmod 600 /tmp/ssh/id_rsa
# Use the key: ssh -i /tmp/ssh/id_rsa user@hostNote: SSH keys are mounted as read-only volumes at /project/.ssh/ and are only accessible within the container during job execution. Copy them to a writable location like /tmp/ssh/ with proper permissions (600) before using them with SSH commands.
Options:
-c, --config PATH Path to Circle CI config file (default: .circleci/config.yml)
-w, --workflow TEXT Workflow name to run (default: first workflow in config)
-j, --job TEXT Run a specific job instead of a workflow
--concurrent/--sequential Run jobs concurrently (default: sequential)
--max-workers INTEGER Maximum number of concurrent jobs (default: 4)
-q, --quiet Show only results and errors
--log-dir PATH Directory for log files (default: .elipse-ci-logs/)
--platform TEXT Target platform for Docker images (e.g., linux/amd64, linux/arm64)
--workdir TEXT Working directory inside container (default: /project)
-e, --env TEXT Environment variables to export to containers (format: KEY=VALUE, can be used multiple times)
-s, --secret TEXT Secret environment variable names to export to containers (reads values from host OS, can be used multiple times)
--ssh-key PATH SSH key file(s) to import into containers (can be used multiple times)
--help Show this message and exit
-
circleci/node: Node.js commands
node/install: Install Node.jsnode/install-packages: Install npm/yarn packages
-
circleci/python: Python commands
python/install: Install Pythonpython/install-packages: Install pip/pipenv/poetry packages
-
circleci/docker: Docker commands
docker/build: Build Docker imagesdocker/push: Push Docker images
checkout: Check out source code (simulated locally)run: Execute shell commandssave_cache: Save cache (simulated)restore_cache: Restore cache (simulated)
You can define reusable commands in your config file using the commands section (CircleCI 2.1+):
version: 2.1
commands:
greet:
description: "Say hello to someone"
parameters:
to:
type: string
default: "World"
steps:
- run:
name: Greeting
command: echo "Hello << parameters.to >>!"
jobs:
my-job:
docker:
- image: cimg/base:stable
steps:
- greet:
to: "Elipse CI"See examples/commands-config.yml for a complete example with reusable commands.
You can create custom orbs by extending the Orb class:
from elipse_ci.orbs import Orb, OrbCommand, OrbRegistry
class MyCustomCommand(OrbCommand):
def execute(self, params, logger, docker_image=None, platform=None):
logger.info("Executing custom command")
# Your custom logic here
return True
class MyCustomOrb(Orb):
def get_commands(self):
return {
'custom-command': MyCustomCommand(),
}
# Register the orb
registry = OrbRegistry()
registry.register_orb('mycompany/custom', MyCustomOrb)See examples/sample-config.yml for a complete example with multiple jobs, orbs, and dependencies.
See examples/commands-config.yml for an example with reusable commands.
See examples/multi-container-config.yml and examples/multi-container-demo.yml for multi-container execution examples.
Elipse CI executes all commands inside Docker containers to provide an isolated environment that closely matches your Circle CI setup:
- Container Selection: Uses the Docker image specified in each job's
dockerconfiguration - Directory Mounting: Mounts your current working directory into the container at
/projectwith read-write permissions - User Permissions: Runs containers with your current user/group ID to maintain proper file permissions
- Working Directory: Commands execute from
/projectby default, or from a custom directory specified with--workdir - Command Execution: All steps (run, orb commands, etc.) execute inside the container
When a job defines multiple Docker containers, Elipse CI implements a specialized execution flow:
- Simultaneous Start: All containers start at the same time
- Initialization Period: A 10-second wait allows all containers to initialize
- First-Success Selection: The first container to exit successfully (code 0) is selected
- Step Execution: Job steps execute using the selected container's image
- Cleanup: All remaining containers are terminated after steps complete
- Signal Handling: Pressing Ctrl+C gracefully terminates all containers
- Failure Handling: If no container exits successfully, the job fails
This behavior is useful for testing applications with service dependencies (databases, caches, etc.) where you want to run tests against the first service that becomes ready. Only containers that exit successfully (code 0) are considered for step execution.
This ensures that:
- No commands execute directly on your local machine
- Your local files remain accessible and modifiable within containers
- File permissions are preserved between container and host
- The execution environment matches your Circle CI configuration
- You can control where commands execute using the
--workdiroption - Multi-container jobs execute steps on the fastest-initializing container
pip install -r requirements.txtpython -m elipse_ci --helpThis tool executes commands from Circle CI configuration files inside Docker containers. The containers have access to your current working directory with read-write permissions. Only run configuration files from trusted sources. The tool is designed for local development and testing purposes, not for production use with untrusted configs.
MIT License - see LICENSE file for details