CircleCI

CI/CDCircleCIクラウドDocker自動化DevOps並列実行パフォーマンス

CI/CDツール

CircleCI

概要

CircleCIはクラウドファーストのCI/CDプラットフォームです。高速実行、Dockerサポート、並列処理、優秀な開発者体験が特徴で、エリートDORAベンチマークで50%以上の顧客が成果を実現しています。

詳細

CircleCI(サークルシーアイ)は、2011年に設立されたクラウドネイティブなCI/CD(継続的インテグレーション・継続的デリバリー)プラットフォームです。GitHub、GitHub Enterprise、Bitbucketとの統合により、新しいコード行がコミットされると自動的にビルドを作成します。コンテナを活用して複数のビルドとデプロイメントを並列実行し、高いパフォーマンスと効率性を実現します。2024年には中央集約化設定、テンプレート、オーバーライド機能が導入され、プラットフォームチームが中央テンプレートからパイプラインを管理しながら、開発チームの自律性を保つことが可能になりました。Mac M4 Proリソースの提供により、Apple最先端シリコンを直接CI/CDパイプラインに導入し、最適化されたCPUとメモリ構成で高度なパフォーマンスを実現します。クラウド管理オプションとプライベートインフラストラクチャでの実行の両方に対応し、動的設定やPre/Postステップによる柔軟なワークフロー制御を提供します。

メリット・デメリット

メリット

  • 高いパフォーマンス: 50%以上の顧客がエリートDORAベンチマーク達成
  • 並列実行: コンテナ技術による複数ビルドの同時実行
  • クラウドネイティブ: インフラ管理不要のマネージドサービス
  • 優秀な開発者体験: 直感的なUI/UXとセットアップの簡単さ
  • 豊富な統合: GitHub、Bitbucket、主要クラウドサービス対応
  • 柔軟な実行環境: Linux、macOS、Windows、ARM対応
  • 中央集約化設定: テンプレート管理によるガバナンスと自律性の両立
  • 最新ハードウェア: Mac M4 Pro等最先端リソース利用可能

デメリット

  • 料金体系: 大規模利用時の従量課金制による高コスト
  • ベンダーロックイン: CircleCI固有の機能への依存リスク
  • セルフホスト制限: 完全にクラウド依存でオンプレミス不可
  • カスタマイズ制限: Jenkins等と比較して設定の自由度が低い
  • 実行時間制限: プランによる月間実行時間の制約
  • デバッグの難しさ: ローカル環境での再現困難
  • 依存関係管理: 外部サービス障害時の影響

主要リンク

書き方の例

基本的な設定

# .circleci/config.yml
version: 2.1

jobs:
  build:
    docker:
      - image: cimg/base:2024.12
    resource_class: xlarge
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: |
            sudo apt-get update
            sudo apt-get install -y nodejs npm
      - run:
          name: Build application
          command: |
            npm install
            npm run build
      - persist_to_workspace:
          root: .
          paths:
            - dist

  test:
    docker:
      - image: cimg/node:18.20
    steps:
      - checkout
      - restore_cache:
          keys:
            - node-deps-{{ checksum "package-lock.json" }}
      - run:
          name: Install dependencies
          command: npm ci
      - save_cache:
          key: node-deps-{{ checksum "package-lock.json" }}
          paths:
            - node_modules
      - run:
          name: Run tests
          command: npm test
      - store_test_results:
          path: test-results
      - store_artifacts:
          path: coverage

workflows:
  build_and_test:
    jobs:
      - build
      - test:
          requires:
            - build

Docker統合と並列実行

version: 2.1

executors:
  node-executor:
    docker:
      - image: cimg/node:18.20
        environment:
          NODE_ENV: test
  
  docker-executor:
    docker:
      - image: cimg/base:2024.12
    resource_class: large

jobs:
  install_dependencies:
    executor: node-executor
    steps:
      - checkout
      - restore_cache:
          keys:
            - deps-{{ checksum "package-lock.json" }}
            - deps-
      - run:
          name: Install dependencies
          command: npm ci
      - save_cache:
          key: deps-{{ checksum "package-lock.json" }}
          paths:
            - node_modules
      - persist_to_workspace:
          root: .
          paths:
            - node_modules

  lint:
    executor: node-executor
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: ESLint
          command: npm run lint
      - run:
          name: Prettier check
          command: npm run format:check

  unit_tests:
    executor: node-executor
    parallelism: 4
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: Run unit tests
          command: |
            TESTFILES=$(circleci tests glob "test/**/*.test.js" | circleci tests split --split-by=timings)
            npm test $TESTFILES
      - store_test_results:
          path: test-results

  build_docker:
    executor: docker-executor
    steps:
      - checkout
      - attach_workspace:
          at: .
      - setup_remote_docker:
          version: 20.10.18
          docker_layer_caching: true
      - run:
          name: Build Docker image
          command: |
            docker build -t myapp:${CIRCLE_SHA1} .
            docker tag myapp:${CIRCLE_SHA1} myapp:latest
      - run:
          name: Push to registry
          command: |
            echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
            docker push myapp:${CIRCLE_SHA1}
            docker push myapp:latest

workflows:
  main:
    jobs:
      - install_dependencies
      - lint:
          requires:
            - install_dependencies
      - unit_tests:
          requires:
            - install_dependencies
      - build_docker:
          requires:
            - lint
            - unit_tests
          filters:
            branches:
              only: main

マルチ環境デプロイメント

version: 2.1

orbs:
  aws-cli: circleci/[email protected]
  kubernetes: circleci/[email protected]

commands:
  deploy_to_environment:
    parameters:
      environment:
        type: string
      image_tag:
        type: string
    steps:
      - run:
          name: Deploy to << parameters.environment >>
          command: |
            helm upgrade --install myapp-<< parameters.environment >> ./helm/myapp \
              --namespace << parameters.environment >> \
              --set image.tag=<< parameters.image_tag >> \
              --set environment=<< parameters.environment >> \
              --wait --timeout=300s

jobs:
  build_and_push:
    docker:
      - image: cimg/base:2024.12
    steps:
      - checkout
      - setup_remote_docker
      - run:
          name: Build and push Docker image
          command: |
            docker build -t $AWS_ECR_REGISTRY/myapp:$CIRCLE_SHA1 .
            aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ECR_REGISTRY
            docker push $AWS_ECR_REGISTRY/myapp:$CIRCLE_SHA1

  deploy_staging:
    docker:
      - image: cimg/aws:2024.03
    steps:
      - checkout
      - kubernetes/install-kubectl
      - aws-cli/setup
      - run:
          name: Configure kubectl
          command: |
            aws eks update-kubeconfig --name staging-cluster --region $AWS_DEFAULT_REGION
      - deploy_to_environment:
          environment: staging
          image_tag: $CIRCLE_SHA1

  deploy_production:
    docker:
      - image: cimg/aws:2024.03
    steps:
      - checkout
      - kubernetes/install-kubectl
      - aws-cli/setup
      - run:
          name: Configure kubectl
          command: |
            aws eks update-kubeconfig --name production-cluster --region $AWS_DEFAULT_REGION
      - deploy_to_environment:
          environment: production
          image_tag: $CIRCLE_SHA1

workflows:
  deploy_pipeline:
    jobs:
      - build_and_push:
          context: aws-credentials
      - deploy_staging:
          requires:
            - build_and_push
          context: aws-credentials
          filters:
            branches:
              only: develop
      - hold_for_approval:
          type: approval
          requires:
            - build_and_push
          filters:
            branches:
              only: main
      - deploy_production:
          requires:
            - hold_for_approval
          context: aws-credentials
          filters:
            branches:
              only: main

Pre/Postステップとパフォーマンス最適化

version: 2.1

jobs:
  test_with_setup:
    docker:
      - image: cimg/node:18.20
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: npm ci
      - run:
          name: Run tests
          command: npm test

  deploy_with_monitoring:
    docker:
      - image: cimg/base:2024.12
    steps:
      - checkout
      - run:
          name: Deploy application
          command: ./deploy.sh

workflows:
  test_and_deploy:
    jobs:
      - test_with_setup:
          pre-steps:
            - run:
                name: Setup custom environment
                command: |
                  echo "export CUSTOM_VAR=value" >> $BASH_ENV
                  source $BASH_ENV
          post-steps:
            - run:
                name: Cleanup test environment
                command: ./cleanup.sh
            - store_artifacts:
                path: logs
      - deploy_with_monitoring:
          requires:
            - test_with_setup
          pre-steps:
            - run:
                name: Pre-deployment checks
                command: ./pre-deploy-check.sh
          post-steps:
            - run:
                name: Post-deployment monitoring
                command: ./monitor-deployment.sh

ARM アーキテクチャとマルチプラットフォーム

version: 2.1

jobs:
  build_x86:
    docker:
      - image: cimg/base:2024.12
    resource_class: large
    steps:
      - checkout
      - run:
          name: Build for x86_64
          command: |
            echo "Building for x86_64 architecture"
            make build ARCH=amd64

  build_arm:
    machine:
      image: ubuntu-2004:2024.01.2
    resource_class: arm.medium
    steps:
      - checkout
      - run:
          name: Check ARM architecture
          command: |
            uname -a
            echo "Hello, ARM!"
      - run:
          name: Build for ARM
          command: |
            echo "Building for ARM64 architecture"
            make build ARCH=arm64

  test_matrix:
    docker:
      - image: cimg/node:18.20
    parallelism: 8
    steps:
      - checkout
      - run:
          name: Matrix testing
          command: |
            case $CIRCLE_NODE_INDEX in
              0) npm run test:unit ;;
              1) npm run test:integration ;;
              2) npm run test:e2e ;;
              3) npm run test:security ;;
              4) npm run test:performance ;;
              5) npm run test:accessibility ;;
              6) npm run test:compatibility ;;
              7) npm run test:load ;;
            esac

workflows:
  multi_arch_build:
    jobs:
      - build_x86
      - build_arm
      - test_matrix:
          requires:
            - build_x86
            - build_arm