AI-powered tool to migrate CircleCI configurations to GitHub Actions, following Mozilla's specific patterns and requirements.
- 🤖 AI-Powered Migration - Uses Google Gemini to intelligently convert CircleCI configs
- 🎯 Mozilla-Specific Patterns - Follows Mozilla's GAR, OIDC, and Workload Identity standards
- 📋 Migration Checklists - Generates comprehensive checklists for infrastructure changes
- 🔍 Configuration Analysis - Analyzes CircleCI configs and provides migration plans
- 🗑️ Automatic Cleanup - Optionally removes CircleCI configs after migration
- 📁 Smart Output - Automatically saves workflows to the repository's
.github/workflows/directory
# Clone the repository
git clone https://github.com/mozilla/circleci-to-gha.git
cd circleci-to-gha
# Install in development mode
pip install -e .This tool uses Google Vertex AI (Gemini) for AI-powered migrations:
circleci-to-gha generate --project-id mozdata --location globalAuthenticate with Google Cloud:
gcloud auth application-default loginThe migrate command analyzes CircleCI configs and generates GitHub Actions workflows in one step:
# Migrate repo in current directory (writes files by default)
circleci-to-gha migrate
# Preview without writing files
circleci-to-gha migrate --no-write
# Migrate specific repo
circleci-to-gha migrate --repo /path/to/repo
# Migrate and remove CircleCI config
circleci-to-gha migrate --remove-circleci
# Custom output directory
circleci-to-gha migrate --output /custom/pathWhat it does:
- 📊 Analyzes all CircleCI configs in
.circlecidirectory - ⚙️ Generates GitHub Actions workflows
- 💾 Saves workflows to
.github/workflows/(unless--no-write) - Shows detailed migration analysis and generated files
Example Output:
Found 2 CircleCI configs:
1. config.yml
2. config-nightly.yml
================================================================================
Processing config.yml
================================================================================
📊 Analyzing config.yml...
Migration Analysis:
[Analysis details...]
⚙️ Generating workflows from config.yml...
✓ Workflows saved to .github/workflows
- build.yml
- deploy.yml
- test.yml
================================================================================
✓ Migration complete!
================================================================================
Get a detailed checklist for the migration:
# Generate checklist for current directory
circleci-to-gha checklist
# Generate checklist for specific repo
circleci-to-gha checklist --repo /path/to/repo
# Save to file
circleci-to-gha checklist > MIGRATION_CHECKLIST.mdOutput:
- Repository secrets to configure
- Infrastructure changes needed (with specific file/line references)
- Workflow files to create
- Manual verification steps
- Testing recommendations
Generate PR content for adding GAR access:
circleci-to-gha infra-pr mozanalysisOutput:
## Add GAR access for mozanalysis
This PR adds the `mozanalysis` repository to the list of repositories
that can push images to Google Artifact Registry.
### Changes
- Added `mozanalysis` to the repository list in `data-artifacts/tf/prod/locals.tf`
### Testing
- [ ] Terraform plan shows expected changes
- [ ] No other resources affected
Related to CircleCI → GitHub Actions migration.Here's a step-by-step guide for migrating a repository:
cd /path/to/your/repo
circleci-to-gha migrate --no-writeThis will show you:
- Migration analysis and complexity assessment
- Generated workflows (preview only, no files written)
- Required infrastructure changes
- What secrets need to be configured
circleci-to-gha checklist > MIGRATION_CHECKLIST.mdSave the checklist for tracking migration progress.
If the analysis indicates Docker builds or Airflow DAG triggers create PR in dataservices-infra or cloudops-infra.
Based on the analysis, configure required secrets in GitHub:
- Go to your repository → Settings → Secrets and variables → Actions
- Add required secrets:
GCP_SERVICE_ACCOUNT_EMAILGCP_DRYRUN_SERVICE_ACCOUNT_EMAIL(if needed)- Any other secrets identified in the checklist
# Generate and save workflows
circleci-to-gha migrate
# Or remove CircleCI config in one step
circleci-to-gha migrate --remove-circleci# Create a migration branch
git checkout -b circleci-to-gha-migration
# Commit the new workflows
git add .github/
git commit -m "Migrate from CircleCI to GitHub Actions"
# Push and create PR
git push origin circleci-to-gha-migrationBefore merging, test the workflows to ensure they work correctly:
- Go to your PR on GitHub
- Review the
.github/workflows/*.ymlfiles in the "Files changed" tab - Check for any syntax errors or issues flagged by GitHub
The workflows will automatically run based on their triggers. Common scenarios:
For Pull Request Workflows:
# The PR itself will trigger workflows with:
# on:
# pull_request:
# Check the "Actions" tab to see workflows runningFor Path-Based Workflows:
# Make a change to a file that should trigger the workflow
echo "# test" >> relevant-file.py
git add relevant-file.py
git commit -m "Test workflow trigger"
git push origin circleci-to-gha-migration
# Check Actions tab - only workflows matching the changed paths should runFor Push to Main Workflows:
# These won't run on the PR branch
# After merging, check the Actions tab on main branch- Go to the Actions tab in your repository
- Click on a running/completed workflow
- Review each job and step for:
- ✅ Authentication success (GCP, Docker, etc.)
- ✅ Checkout working correctly
- ✅ Dependencies installing properly
- ✅ Tests passing
- ✅ Docker builds succeeding (if applicable)
⚠️ Any warnings or failures
Test Docker Build (if applicable):
# Add a small change to trigger Docker build
echo "# trigger build" >> Dockerfile
git add Dockerfile
git commit -m "Test Docker build workflow"
git push origin circleci-to-gha-migration
# Check Actions tab for Docker build job
# Verify it doesn't try to push (should only push on main)Test with workflow_dispatch (Manual Trigger):
If you want to test workflows without code changes, add workflow_dispatch temporarily:
# In .github/workflows/your-workflow.yml
on:
pull_request:
workflow_dispatch: # Enables manual triggeringThen:
- Go to Actions tab
- Select your workflow
- Click "Run workflow" dropdown
- Choose your branch
- Click "Run workflow" button
Workflows Not Running:
- Check that workflow triggers match your branch/changes
- Verify
.github/workflows/directory path is correct - Check for YAML syntax errors (GitHub will show these in PR)
Authentication Failures:
Error: Failed to authenticate to GCP
- Verify repository secrets are configured
- Check service account has correct permissions
- Confirm Workload Identity Federation is set up
Permission Errors:
Error: Resource not accessible by integration
- Add required permissions to workflow file:
permissions:
contents: read
id-token: write
pull-requests: write # If commenting on PRsDocker Push Failures:
Error: denied: Permission "artifactregistry.repositories.uploadArtifacts" denied
- Ensure dataservices-infra PR is merged
- Verify service account has GAR permissions
- Check that
if: github.ref == 'refs/heads/main'is protecting push steps
For workflows that push or deploy, verify protection:
# Check that dangerous operations only run on main
- name: Push Docker image
if: github.ref == 'refs/heads/main' # Should NOT run on PR
uses: mozilla-it/deploy-actions/[email protected]If workflows fail, enable debug logging:
- Go to repository Settings → Secrets and variables → Actions
- Add repository variable:
- Name:
ACTIONS_STEP_DEBUG - Value:
true
- Name:
- Re-run the workflow
Or add temporarily to workflow:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Debug info
run: |
echo "GitHub ref: ${{ github.ref }}"
echo "GitHub event: ${{ github.event_name }}"
echo "GitHub actor: ${{ github.actor }}"Add status badges to PR description to track progress:
## Workflow Status

- All workflows run successfully on PR
- No authentication errors
- Tests pass
- Docker builds succeed (if applicable)
- No secrets exposed in logs
- Protected operations only run on main (check
if:conditions) - Path filtering works correctly
- Reusable workflows function properly
- PR comments/automation work (if applicable)
- CircleCI workflows disabled or removed
After verifying the GitHub Actions workflows work on main:
# Remove CircleCI config
rm -rf .circleci/
# Commit and push
git add .circleci/
git commit -m "Remove CircleCI configuration"
git push origin main--project-id TEXT Google Cloud Project ID (default: mozdata, env: GOOGLE_CLOUD_PROJECT)
--location TEXT Google Cloud Location (default: global, env: GOOGLE_CLOUD_LOCATION)Analyze and generate GitHub Actions workflows in one step.
circleci-to-gha migrate [OPTIONS]
Options:
-r, --repo PATH Path to repository to migrate (default: current directory)
-o, --output PATH Output directory (default: <repo>/.github/workflows)
--project-id TEXT Google Cloud Project ID (default: mozdata)
--location TEXT Google Cloud Location (default: global)
--write/--no-write Write generated workflows to files (default: write)
--remove-circleci Remove CircleCI config directory after generating
--help Show this message and exitNote: Automatically discovers all CircleCI configs in the .circleci directory.
Generate migration checklist.
circleci-to-gha checklist [OPTIONS]
Options:
-r, --repo PATH Path to repository to migrate (default: current directory)
--project-id TEXT Google Cloud Project ID (default: mozdata)
--location TEXT Google Cloud Location (default: global)
--help Show this message and exitNote: Generates checklists for all CircleCI configs found in the .circleci directory.
# Navigate to repository
cd ~/projects/my-mozilla-repo
# Preview migration (doesn't write files)
circleci-to-gha migrate --no-write
# Generate workflows and remove CircleCI config
circleci-to-gha migrate --remove-circleci# Use specific project and location with preview
circleci-to-gha migrate \
--repo /path/to/complex-repo \
--project-id moz-fx-data-shared-prod \
--location us-central1 \
--no-write
# Generate to custom location
circleci-to-gha migrate \
--repo /path/to/complex-repo \
--output /tmp/workflows# Script to migrate multiple repos
for repo in repo1 repo2 repo3; do
echo "Migrating $repo..."
cd ~/projects/$repo
circleci-to-gha migrate
circleci-to-gha infra-pr $repo > ~/migrations/$repo-infra-pr.md
doneIf you see authentication errors:
# Re-authenticate with gcloud
gcloud auth application-default login
# Verify credentials
gcloud auth application-default print-access-token# Check if variables are set
echo $GOOGLE_CLOUD_PROJECT
echo $GOOGLE_CLOUD_LOCATION
# Set if missing
export GOOGLE_CLOUD_PROJECT=mozdata
export GOOGLE_CLOUD_LOCATION=globalIf circleci-to-gha command is not found:
# Add to PATH
export PATH="$HOME/.local/bin:$PATH"
# Or reinstall
pip install -e . --force-reinstallThe tool generates production-ready GitHub Actions workflows following Mozilla's standards:
- ✅ OIDC Authentication - Workload Identity Federation for GCP
- ✅ GAR Integration - Proper Docker image push patterns
- ✅ Secrets Management - Repository secrets and variables
- ✅ Path Filtering - Conditional workflow execution based on file changes
- ✅ Reusable Workflows - For common patterns like changed file detection
- ✅ Proper Permissions - Minimal required permissions per job
- ✅ Caching - Python pip caching and custom cache patterns
- ✅ Container Jobs - For jobs requiring specific Docker images
- ✅ PR Automation - Comments, reviews, and status checks
The tool identifies when additional infrastructure changes are needed:
- GAR Access - Detects Docker builds and notes dataservices-infra PR requirements
- Service Accounts - Lists required GCP service accounts
- Airflow DAG Triggers - Detects and converts Airflow triggering patterns
- GKE Operations - Converts Kubernetes operations properly
# Install development dependencies
pip install -e ".[dev]"
# Run linting
ruff check circleci_to_gha/
ruff format --check circleci_to_gha/circleci_to_gha/
├── __init__.py # Package initialization
├── cli.py # CLI interface
├── ai_client.py # Gemini AI client
├── config_parser.py # CircleCI config parser
├── generator.py # Workflow generation
└── prompts/
├── __init__.py # Prompts package
├── system_prompt.txt # AI system prompt with Mozilla patterns
└── examples.txt # Real-world migration examples
For issues or questions:
- Create an issue in this repository
- Reach out to the Data Engineering team