🚀

CircleCI orb で既存config.ymlの動作を上書きする(override_with)

に公開

前回CircleCIのorbを自作してNodeインストール部分を別定義ファイルでまとめる方法をご紹介しました。
https://zenn.dev/kameoncloud/articles/114fb8aa7b8745

今日はこのorbを用いてconfig.ymlの動作を上書きするパラメータであるoverride_withを試してみたいと思います。

override_with とは

https://circleci.com/docs/how-to-override-config/
config.yml内で定義されたjobをorb内部で定義されたjobで上書きするものです。override_withパラメータで上書きされたjobはorb内部の定義をまず確認してjobの呼び出しを試みます。そのあとorb内部にjobが存在しない場合config.ymlのjobに処理がフォールバックされ実行されます。

つまりorbを呼び出しjobがあればそちらを実行、jobがなければconfig.ymlで定義されているものを実行、という動作になります。

さっそくやってみる

以下のconfig.ymlをマージしてパイプラインを実行してみます。

config.yml
version: 2.1

orbs:
  greeting: testorb/testorb@1.0.0

jobs:
  greet-job:
    docker:
      - image: cimg/base:stable
    steps:
      - run:
          name: Install Python
          command: |
            # Pythonのインストール(Ubuntu/Debian系)
            sudo apt-get update
            sudo apt-get install -y python3 python3-pip
            
            # インストール確認
            echo "Python version: $(python3 --version)"
            echo "pip version: $(pip3 --version)"
      - run:
          name: Fallback greeting with Python
          command: |
            echo "Local fallback: Hello World"
            echo "Python is now installed!"
            python3 --version

workflows:
  test:
    jobs:
      - greet-job:
          override-with: greeting/greet

ここで利用しているorbは以下の通りです。
https://zenn.dev/kameoncloud/articles/114fb8aa7b8745

orb
version: 2.1
description: A greeting command orb with Node.js installation

commands:
    greet:
        description: Greet someone with a "hello" and install Node.js
        parameters:
            to:
                type: string
                default: World
            node_version:
                type: string
                default: "20"
                description: Node.js version to install
        steps:
            - run:
                name: Install Node.js
                command: |
                    # Node.jsのインストール(Ubuntu/Debian系)
                    curl -fsSL https://deb.nodesource.com/setup_<< parameters.node_version >>.x | sudo -E bash -
                    sudo apt-get install -y nodejs
                    
                    # インストール確認
                    echo "Node.js version: $(node --version)"
                    echo "npm version: $(npm --version)"
            - run:
                name: Greet with Node.js
                command: |
                    echo "Hello << parameters.to >>"
                    echo "Node.js << parameters.node_version >> is now installed!"
                    node --version

このテストでは以下の通りPythonがインストールされます。

仕組み

workflows:
  test:
    jobs:
      - greet-job:
          override-with: greeting/greet

では、testというworkflowがgreet-jobというjobを呼び出しています。このjobはgreeting/greetとして上書きが定義されています。
greetingは以下で定義されているorbを呼び出します。

orbs:
  greeting: testorb/testorb@1.0.0

呼び出されたorbの中にはgreetというコマンドは設定されていますがそのコマンドを呼び出すjobが定義されていません。

commands:
    greet:

このためjobの上書きが行われずフォールバックした結果としてconfig.ymlのjobが実行されPythonがインストールされます。

orbの修正(jobを作る)

https://zenn.dev/kameoncloud/articles/114fb8aa7b8745
の記事では、orbの中で定義されているcommandconfig.ymlのjobが呼び出すサンプルとなっています。これをorbの中にjobも定義されている形に作り替えます。

orb.yml
version: 2.1
description: A greeting command orb with Node.js installation

commands:
    greet:
        description: Greet someone with a "hello" and install Node.js
        parameters:
            to:
                type: string
                default: World
            node_version:
                type: string
                default: "20"
                description: Node.js version to install
        steps:
            - run:
                name: Install Node.js
                command: |
                    # Node.jsのインストール(Ubuntu/Debian系)
                    curl -fsSL https://deb.nodesource.com/setup_<< parameters.node_version >>.x | sudo -E bash -
                    sudo apt-get install -y nodejs
                    
                    # インストール確認
                    echo "Node.js version: $(node --version)"
                    echo "npm version: $(npm --version)"
            - run:
                name: Greet with Node.js
                command: |
                    echo "Hello << parameters.to >>"
                    echo "Node.js << parameters.node_version >> is now installed!"
                    node --version

jobs:
    greet:
        description: A job that greets and installs Node.js
        parameters:
            to:
                type: string
                default: World
            node_version:
                type: string
                default: "20"
        docker:
            - image: cimg/base:stable
        steps:
            - greet:
                to: << parameters.to >>
                node_version: << parameters.node_version >>

orb.ymlを上書き保存した後次のコマンドを実行します。

# 開発版として公開
circleci orb publish orb.yml testorb/testorb@dev:first
# 開発版を本番版にプロモート(パッチバージョンアップ)
circleci orb publish promote testorb/testorb@dev:first patch
# 公開されたorbの一覧確認
circleci orb list testorb

これにより新しいバージョンのorbが同じ名前/異なるバージョンで公開されます。
先ほどと同じconfig.ymlのorbバージョン部分を変更して再度マージすると今度は以下の部分が有効化されNodeがインストールされます。

          override-with: greeting/greet

これによりjobがorbに上書きされます。

Discussion