関連

ジョブを実行する際の環境に関するアレコレを設定します。ここではsteps以外のすべての値をここに含めることができます。

executors:
  foo:
    environment:
      TOKEN: foobarbaz
    docker:
      - image: alpine
    working_directory: ~/repo

使う時はジョブ側のexecutorに展開したいエグゼキューター名を渡します。

jobs:
  build:
    executor: foo
    steps:
      - run: echo `pwd`
      # 上記は `/root/repo` と表示
      

もしジョブ側にエグゼキューターで定義済の値がある場合、ジョブ側の設定が優先されます。例えばジョブ側でもworking_directoryを設定した場合、ワーキングディレクトリは/root/overwriteになります。

jobs:
  build:
    executor: foo
    steps:
      - run: echo `pwd`
    working_directory: ~/overwrite
    
関連

一連の処理の流れを記載します。これはトップレベルのjobs:以下にジョブの名前となる<job-name>:とネストさせ、その中にジョブの環境や具体的な処理といった内容を置きます。

jobs:
  build:
    executor: alpine
    steps:
      - run: ':'
     

例えばこの書き方ではbuildという名前のジョブを定義してます。そしてこれは、alpine環境(executor)で処理(steps)を順番に実行するということを中に書いてます。このexecutorstepsは必須なので必ず置かなければなりません。

stepsは配列です。上記では1つの処理しか行ってませんが、以下のように複数書くと順番にそれを実行します。

jobs:
  build:
    executor: alpine
    steps:
      - run: echo foo
      - run: echo bar
      - run: echo baz
      

また、buildという名前のジョブがある時、workflowsは無くても構いません。buildというのは特別なジョブ名で、もしもworkflowsがない場合以下のように解釈されます。

workflows:
  workflow:
    jobs:
      - build
      

オプショナルな設定

parameters

stepsと同じ階層にparametersを置くことができます。もし極一部だけ値の違うジョブを使いたいい場合、コピペして極一部だけ値を変えるのではなく、パラメーター値として渡してあげることで行っている事は同じ様なジョブ定義を1つだけにできます。

jobs:
  build:
    parameters
      text:
        type: string
    executor: alpine
    steps:
      - run: echo << parameters.text >>
      

ワークフローでジョブを使う時にtextパラメーターを渡して使うことができます。以下は最終的にecho fooが実行されます。

workflows:
  foo:
    jobs:
      - build:
          text: foo
          

working_directory

ジョブを実行する際にいるディレクトリを設定できます。デフォルトでは~/projectという場所にいいます。また、この値はCIRCLE_WORKING_DIRECTORY環境変数に入ります。

shell

ジョブを実行するシェルを設定できます。ジョブを実行するマシンにbashがある場合はそれが、ない場合はshになります。

environment

ジョブ内で使える環境変数を定義できます。

jobs:
  build:
    environment:
      FOO: foo
    executor: alpine
    steps:
      - run: echo $FOO
      
関連

パラメーターはジョブやコマンドなどに動的な値を渡す為に使えます。以下の3-4つの値を設定できます。

  1. description

  2. type

  3. default

  4. enum (typeenumの時に限る)

description

パラメーターの説明を書きます。この説明は Orb ドキュメントに使われます。

type

パラメーターの型を指定します。これには以下の

  1. boolean

  2. integer

  3. string

  4. enum

  5. executor

  6. steps

  7. env_var_name (環境変数)

boolean

真には、y yes true onが使えます。偽には、n no false offがあります。

integer

数値だけの値はintegerとして扱われます。

string

booleanintegerに含まれない値がこの型になります。ちなみにwhenでの判断時に、空文字列はfalse扱いです。

enum

渡せる値を羅列した値のどれかに制限したい時に使います。この型に限りenumキーも必須になります。

parameters:
  a:
    type: enum
    enum:
      - foo
      - bar
      - baz
      

executor

仕様するexecutorを指定します。これはexecutorsで定義されている名前でなければなりません。もし存在しない名前を渡すと「Cannot find a definition for executor named 渡した名前」のようなエラーになります。

これはある言語の複数バージョンでジョブを走らせたい時などに使えます。以下はechoというジョブを NodeJS が12の環境と10の環境で走らせる例です。エグゼキューターそのものにパラメーターがある場合、ワークフローbのようにエグゼキューター名はnameに置き、同じ階層にエグゼキューターのもつパラメーター値を置くことができます。

version: 2.1

executors:
  node12:
    parameters:
      text:
        type: string
        default: a
    docker:
      - image: circleci/node:12
    environment:
      TEXT: << parameters.text >>
  node10:
    parameters:
      text:
        type: string
    docker:
      - image: circleci/node:10
    environment:
      TEXT: << parameters.text >>

jobs:
  echo:
    parameters:
      e:
        type: executor
    executor: << parameters.e >>
    steps:
      - run: echo $TEXT

workflows:
  a:
    jobs:
      - echo:
          e: node12
  b:
    jobs:
      - echo:
          e:
            name: node10
            text: b

steps

個別にstepsを切り替えたい時などに使えます。渡せるのはjob.stepsと同じ構造のものです。パラメータで渡されたステップはstepsjob.stepsの中のsteps)に渡します。

version: 2.1

jobs:
  echo:
    parameters:
      s:
        type: steps
        default:
          - run: echo a
    docker:
      - image: alpine
    steps:
      - steps: << parameters.s >>

workflows:
  a:
    jobs:
      - echo
  b:
    jobs:
      - echo:
          s:
            - run: echo b

なお、stepsを使ったあとに書き直すなどしてsteps: echo ...などとしてしまうとパースエラーという分かりづらいエラーメッセージしか吐かなく、ハマりやすいので注意が要りそうです。

env_var_name

環境変数を渡す為に使います。渡されてた値を使う時は展開前のただの環境変数名が入っているだけなので、展開するには${ }で囲ってあげる必要があります。

この型は特に存在しない環境変数を指定したとしても問題ありません。以下は、

  • CIRCLE_BRANCH (ciがデフォルトで設定する環境変数)

  • PROJECT_ENV_VAR (設定ページで設定した環境変数)

  • JOB_ENV_VAR (ジョブで定義した環境変数)

  • UNDEFINED_ENV_VAR (存在しない環境変数)

echoった例ですが、それぞれ値があればちゃんと展開後の値が表示されました。

version: 2.1

jobs:
  echo:
    parameters:
      value:
        type: env_var_name
        default: CIRCLE_BRANCH
    docker:
      - image: alpine
    steps:
      - run: echo ${<< parameters.value >>}
    environment:
      JOB_ENV_VAR: JOB_ENV_VAR

workflows:
  a:
    jobs:
      - echo
  b:
    jobs:
      - echo:
          value: PROJECT_ENV_VAR
  c:
    jobs:
      - echo:
          value: JOB_ENV_VAR
  d:
    jobs:
      - echo:
          value: UNDEFINED_ENV_VAR
関連

ジョブステップを細かく名前を付けて細分化する為に使います。例えばどこかにバックアップする処理を行うのに

  1. tgzに圧縮

  2. どこかへアップロード

というような複数のフローに対してbackupのようなコマンド名を付けることで、それをジョブステップの中の重要なキーのように置いて使うことができます。

commands:
  backup:
    description: ...
    parameters:
      file_name:
        type: string
        default: ...
    steps:
      - run: tar -cvzf << parameters.file_name >>.tgz foo
      - run: ./backup.sh
      
jobs:
  build:
    executor: ...
    steps:
      - backup:
          file_name: ...

形から分かる用にcheckoutなどは CircleCI が定義してるコマンドなのです。

関連

ジョブでは環境とその中で行う処理フローを定義してきましたが、ワークフローはそのジョブをいつ・どんな時に実行するかの制御を行います。例えばそれは

  • いつ

    • 毎週土曜の0時に

    • 1時間おきに

  • どんな時に

    • masterブランチにコミットがプッシュされた時

    • v0.1.0がプッシュされた時

    • 前のワークフローが終わった時

    • 権限を持つ者が承認した時

のような場合です。

その前にまずデフォルトの動作の話。以下のような設定の時、ワークフローabは、「いつ」と「どんな時に」どちらも設定していませんが、何かしらコミットがプッシュされた時にどちらも実行されます。

jobs:
  echo:
    docker:
      - image: alpine
    steps:
      - run: echo foo

workflows:
  a:
    jobs:
      - echo
  b:
    jobs:
      - echo
      

またjobsに複数のジョブを渡した場合、それぞれのjobは個別に順不同に実行されます。つまり以下の場合bの方が先に実行される可能性があります。

workflows:
  a:
    jobs:
      - a
      - b

いつ

「いつ」を設定するにはtriggersが必要です。もしaを「毎週土曜の0時に」だけ実行されるようにしたい場合以下のように設定します。

workflows:
  a:
    triggers:
      - schedule:
          cron: "0 0 * * 6"
    jobs:
      - echo
      

「一時間おきに」も追加したいなら、schedule.cron: "0 0-23 * * *"も追加してあげます。

これでも良いですが、これはその時存在するすべてのブランチでその時になったら実行されます。もしブランチやタグを指定したい場合はcronと同じ階層にfiltersを置くことができます。

例えばmasterdevelopブランチだけであれば、

cron: ...
filters:
  branches:
    only:
      - master
      - develop

のようにします。またonlyには正規表現も渡すことができ、マッチしたブランチだけというようなこともできます。

cron: ...
filters:
  branches:
    only: /cron.*/
    

onlyとは逆の意味のignoreというキーを変わりに置くこともできます。

cron: ...
filters:
  branches:
    ignore: /master|develop/
    

タグの場合はtagsbranchesと同じ階層に置きます。タグの場合デフォルトではすべて対象となっていないため、すべてのタグも実行対象にしたい場合(多分ない)、

cron: ...
filters:
  tags:
    only: /.*/
    

のようにします。

どんな時に

上記のfiltersでほぼ「どんな時に」の話なのですがこれはトリガー内での話なので、それ単体で設定したい場合はどうすればいいか。それはジョブ毎に設定してあげます。各ジョブにおいてもfiltersを持つことができ、これは上記のものと同じような設定を置けます。

workflows:
  a:
    jobs:
      - echo:
          filters: ...
          

「前のワークフローが終わった時」に関してはrequiresという設定を持てます。これは配列で中には他のジョブ名が入ります。例えば値が["foo"]の時その意味は「fooジョブが終わったらコレを実行しろ」という感じになります。

以下の例のように1つ前のジョブをrequiresで指定することでジョブを狙った通りの順番で実行することができ、最初のジョブに対してフィルターをかけることで対象の指定もできることになります。

workflows:
  workflow:
    jobs:
      - pre:
          filters:
            branches: /master/
      - main:
          requires:
            - pre
      - suf:
          required:
            - main
      

他にtype: approvalを各ジョブは持て、これを指定するとワークフローのそのジョブは待機状態で止まります。そのジョブを実行するには権限ある者がワークフローページで「Approve」する必要があります。

関連

モジュールのように、あることをやるための機能をまとめたものです。使えるものは Explore Orbs にまとまってます。

Orb はトップレベルのorbs以下に持ってきたい Orb を置くことで Orb の中身が使えるようになります。キーは名前空間になり、以下の場合slack/と付けることでcircleci/slack@3.4.2の提供するコマンドなどを扱えます。

orbs:
  slack: circleci/slack@3.4.2
  

これで slack/notify のようなコマンドが使えるようになりました。

jobs:
  build:
    docker:
      - image: circleci/node:12
    steps:
      - slack/notify:
          color: '#42e2f4'
          message: This is a custom message notification
          webhook: 'Webhook URL'
          

結果

各 Orb の使い方は Explore Orbs からの各ドキュメントを読めるのでそれを参考に。

CircleCI CLI (circleciコマンド)を使います。インストールがまだの場合以下で。

curl -fLSs https://circle.ci/cli | bash

このコマンドのconfig validateを実行します。Config file at .circleci/config.yml is valid.と出れば大丈夫です。

circleci config validate
# Config file at .circleci/config.yml is valid.

もしエラーがある場合は以下のようなエラーメッセージが吐き出されるので、エラー文の内容を直して確認…を繰り返します。

Error: ERROR IN CONFIG FILE:
[#] required key [jobs] not found
Error: ERROR IN CONFIG FILE:
[#/workflows/workflow] only 1 subschema matches out of 2
1. [#/workflows/workflow/jobs/0] 0 subschemas matched instead of one
|   1. [#/workflows/workflow/jobs/0] expected type: String, found: Mapping
|   |   SCHEMA:
|   |     type: string
|   |   INPUT:
|   |     build:
|   |       filters:
|   |         branch:
|   |           only: master
|   2. [#/workflows/workflow/jobs/0/build/filters] extraneous key [branch] is not permitted
|   |   This is similar to to other `filters` in config, but has an additional key, `tags`
|   |   Permitted keys:
|   |     - branches
|   |     - tags
|   |   Passed keys:
|   |     - branch

設定ファイルの結合は、

circleci config pack 

で行えます。今はこの<directory-name>configということにします。

例えば、config/以下はこのような構造になります。

config
├── executors
│   └── alpine
│       ├── @docker.yml
│       └── environment.yml
├── jobs
│   └── build.yml
└── meta.yml

.ymlファイルがそれぞれ分割によって生まれたファイルです。慣れてる人にはディレクトリー構造に見覚えがあるかもしれませんがその通りで、分割と言ってもだいたいの場合は、ディレクトリー構造やファイルのベース名(environment.ymlでいうenvironment)がそのまま YAML の構造になるだけです。例えばenvironment.ymlであれば、

executors:
  alpine:
    environment:
      # `environment.yml` の中身
      

のようになります。

例外として@から始まるファイル(@docker.yml)は少し変わり、ベース名を構造化しません。つまり以下ではなく、

executors:
  alpine:
    '@docker':
      # `@docker.yml`の中身
      

こうなります。

executors:
  alpine:
    # `@docker.yml`の中身
      

どう解釈されるかが分かったので結合してみます。circleci config pack config/の結果はこうなりました。

executors:
  alpine:
    '@docker':
    - image: alpine
    environment:
      TOKEN: foobarbaz
jobs:
  build:
    executor: alpine
    steps:
    - run: ':'
version: 2.1

ちなみにjobs/build.ymlversion.ymlはそれぞれ以下でした。

executor: alpine
steps:
  - run: ":"
version: 2.1

CircleCI CLI (circleciコマンド)を使います。インストールがまだの場合以下で。

curl -fLSs https://circle.ci/cli | bash

このコマンドのconfig process <config.ymlへの相対パス>を実行します。ここで対象となる設定には注意しなければならない事が2つほどあります。

  1. jobs.buildが存在する

  2. またはworkflowsがある

以下のような.circleci/config.ymlを変換してみます。

version: 2.1

executors:
  node:
    docker:
      - image: circleci/node:10

jobs:
  build:
    executor: node
    steps:
      - run: node -v

結果は標準出力なので書き込み先も指定します。

circleci config process .circleci/config.yml > .circleci/config2.0.yml

結果はこうなりました。

version: 2
jobs:
  build:
    docker:
    - image: circleci/node:10
    steps:
    - run:
        command: node -v
workflows:
  version: 2
  workflow:
    jobs:
    - build

# Original config.yml file:
# version: 2.1
#
# executors:
#   node:
#     docker:
#       - image: circleci/node:10
#
# jobs:
#   build:
#     executor: node
#     steps:
#       - run: node -v

ちなみに注意することで言ったように以下は変換できません。

version: 2.1

executors:
  node:
    docker:
      - image: circleci/node:10

jobs:
  sandbox:
    executor: node
    steps:
      - run: node -v

jobs.buildがない場合はこのようにします。

version: 2.1

executors:
  node:
    docker:
      - image: circleci/node:10

jobs:
  sandbox:
    executor: node
    steps:
      - run: node -v
      
workflows:
  workflow:
    jobs:
      - sandbox

JavaScript で飯食べたい歴約 5 年、 純( nju33 ) によるノートサイトです。

このサイトではドリンク代や奨学金返済の為、広告などを貼らせて頂いてますがご了承ください。

Change Log