Help us understand the problem. What is going on with this article?

CiecleCI の Workflow job に名前をつけて依存を管理する

動機: CircleCI Orbs を使ったときに困ったこと

CircleCI Orbs を使うことで、AWS ECRへのイメージPushなどを行ってくれますが、ブランチごとに別々のリポジトリにpushしたい場合などは少し困ったことになります。

以下、正しく動作しないケースです。

.circleci/config.yml
version: 2.1
orbs:
  aws-ecr: circleci/aws-ecr@6.15.1
  aws-ecs: circleci/aws-ecs@1.4.0
# 中略
workflows:
  build:
    jobs:
      # 中略
      # Staging 用のデプロイ
      - aws-ecr/build-and-push-image
          repo: "Staging用リポジトリ"
          tag: "${CIRCLE_SHA1}"
          requires:
            - test
            - lint
          filters: &staging-filter
            branches:
              only:
                - staging
      - aws-ecs/deploy-service-update:
          requires:
            - aws-ecr/build-and-push-image
          family: 'Staging用ファミリー'
          cluster-name: 'Staging用クラスター名'
          container-image-name-updates: 'container=Staging用コンテナ名,tag=${CIRCLE_SHA1}'
          filters: *staging-filter
      # Production用のデプロイ
      - aws-ecr/build-and-push-image
          repo: "Production用リポジトリ"
          tag: "${CIRCLE_SHA1}"
          requires:
            - test
            - lint
          filters: &master-filter
            branches:
              only:
                - master
      - aws-ecs/deploy-service-update:
          requires:
            - aws-ecr/build-and-push-image
          family: 'Production用ファミリー'
          cluster-name: 'Production用クラスター名'
          container-image-name-updates: 'container=Production用コンテナ名,tag=${CIRCLE_SHA1}'
          filters: *master-filter

こんなかんじのエラーが出てしまいます。

Job 'aws-ecs/deploy-service-update' requires 'aws-ecr/build-and-push-image', which is the name of 2 other jobs in workflow 'build'

You can give a job within a workflow an explicit name by adding a `name` key

Orbs に定義されている、 aws-ecs/deploy-service-update job 実行の前提として必要としている、aws-ecr/build-and-push-image が Staging 用と、Production 用の2つ用意してしまっているため、うまく動作しないとのことです。

ヘルプメッセージに従って、name を Workflow の job に指定すれば良さそうです。

ひとまず、ドキュメントを読んでみたのですが、 今の所 (2021年1月8日現在) この点についての記載はなさそうです。。。

2021/1/9 14:00 修正

ドキュメントに記載はありました。 ドキュメントの解釈を誤っており、namerequires の下で使えるものだと勘違いしておりました。
job の下で namerequires のために使えるという記載っぽいです。 @PanonCotta さんご指摘ありがとうございます。

image.png

修正後

.circleci/config.yml
version: 2.1
orbs:
  aws-ecr: circleci/aws-ecr@6.15.1
  aws-ecs: circleci/aws-ecs@1.4.0
# 中略
workflows:
  build:
    jobs:
      # 中略
      # Staging 用のデプロイ
      - aws-ecr/build-and-push-image
          name: "ecr-build-and-push-image-stg"
          repo: "Staging用リポジトリ"
          tag: "${CIRCLE_SHA1}"
          requires:
            - test
            - lint
          filters: &staging-filter
            branches:
              only:
                - staging
      - aws-ecs/deploy-service-update:
          name: "ecs-deploy-stg"
          requires:
            - ecr-build-and-push-image-stg
          family: 'Staging用ファミリー'
          cluster-name: 'Staging用クラスター名'
          container-image-name-updates: 'container=Staging用コンテナ名,tag=${CIRCLE_SHA1}'
          filters: *staging-filter
      # Production用のデプロイ
      - aws-ecr/build-and-push-image
          name: "ecr-build-and-push-image-prod"
          repo: "Production用リポジトリ"
          tag: "${CIRCLE_SHA1}"
          requires:
            - test
            - lint
          filters: &master-filter
            branches:
              only:
                - master
      - aws-ecs/deploy-service-update:
          name: "ecs-deploy-prod"
          requires:
            - ecr-build-and-push-image-prod
          family: 'Production用ファミリー'
          cluster-name: 'Production用クラスター名'
          container-image-name-updates: 'container=Production用コンテナ名,tag=${CIRCLE_SHA1}'
          filters: *master-filter

これで、ECRにpushするイメージ作成と、ECSによるサービス展開までについてを環境別に分けることができました。

この設定のやりかたは、同じjobを再利用しつつ、環境別にパラメータを変えるといったときにも便利そうです。
検証用に、以下のようなサンプルを作ってみて実行してみたところ、job1, job2 を再利用することができました。

.circleci/config.yml
version: 2.1

executors:
  ruby-executor:
    docker:
      - image: circleci/ruby:3.0.0

jobs:
  job1:
    executor: ruby-executor
    # https://circleci.com/docs/2.0/reusing-config/#authoring-parameterized-jobs
    # Workflow からパラメータを渡すことができる
    parameters:
      env:
        type: string
        default: development
    steps:
      - checkout
      - run: 'ruby --version'
      # パラメータを使う時は、<<parameters.キー>> で呼び出しできる
      - run: 'echo <<parameters.env>>'
  job2:
    executor: ruby-executor
    parameters:
      env:
        type: string
        default: development
    steps:
      - checkout
      - run: 'ruby --version'
      - run: 'echo <<parameters.env>>'

workflows:
  build:
    jobs:
      # master のみ
      - job1:
          name: job1-master
          # env パラメータを production として job にわたす
          env: production
          filters: &master-filter
            branches:
              only:
                - master
      - job2:
          name: job2-master
          env: production
          filters: *master-filter
          requires:
            - job1-master
      # master 以外
      - job1:
          name: job1-non-master
          # env パラメータを指定してないので、job の `<<parameters.env>>` は、
          # default にセットしている、development に置き換わる
          filters: &non-master-filter
            branches:
              ignore:
                - master
      - job2:
          name: job2-non-master
          filters: *non-master-filter
          requires:
            - job1-non-master

まとめ

Workflow Job に名前が使えるようになったのも、Jobにパラメータが渡せるようになったのも、
ドキュメントの雰囲気を見るに2.1からのようです。

昔から運用している、 .circleci/config.yml の場合、環境ごとに別々にjobを作ったり、
command で以下のように書いているケースがありました。

          command: |
            if [ "${CIRCLE_BRANCH}" == "master" ]; then
                bundle exec cap production deploy
            elif [ "${CIRCLE_BRANCH}" == "staging" ]; then
                bundle exec cap staging deploy
            fi

なかなか難儀なのでコンパクトに

          command: bundle exec cap <<parameters.env>> deploy

などに変更するなどして、スマートなCiecleCI設定ライフを送りたいものです。

ooharabucyou
地球に住んでいます。
http://www.bucyou.net
codeal
即戦力複業ならコデアル。高収入×リモートワークの複業・フリーランス・転職求人多数
https://www.codeal.work
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away