CircleCIの環境変数の使い分け

こんにちは。
CircleCI カスタマーサクセスチームの Chisato です。
最近個人的に幸せだった出来事は、かぶの美味しさにあらためて気付けたことです。

今回は CircleCI の環境変数についてご紹介します。

## 環境変数

CircleCIでは環境変数が複数提供されています。
ユーザーが設定できるのは下記の３種類で、名前と値のペアで定義します。

* インライン環境変数
* プロジェクトでの環境変数
* コンテキストでの環境変数
<br>


## インライン環境変数
直接 config.yml ファイル（設定ファイル）に書き込む環境変数です。
ステップ（run ステップまたは deploy ステップ）、ジョブ、イメージと、小さい範囲で簡単に設定できます。
弊社のMakotoさんは、デプロイ先の設定などでよく使っているそうです。
ステップ、ジョブ、コンテナでの設定には、`Environment`キーを用います。

Config.yml ファイルを見れば定義や値を確認できてしまうので、利用の際はご注意ください。
例えば下記に該当する場合は「使用しない」ほうが良いです。
* モノレポ
* 秘匿情報
* 値の影響範囲が大きい
<br>

#### ステップでの設定
環境変数は設定したステップでのみ利用できるため、他のステップには引き継がれません。（[ドキュメンテーション](https://circleci.com/docs/ja/2.0/env-vars/#setting-an-environment-variable-in-a-step)）

```yaml
    steps:
      - checkout
      - run:
          name: こんにちは
          command: echo $SAY
          environment:
           SAY: Hello
```

#### ジョブでの設定
当該ジョブの中で実行されるすべてのステップで利用できます。あるステップで同じ環境変数名を定義すると、値が上書きされます。
（[ドキュメンテーション](https://circleci.com/docs/ja/2.0/env-vars/#setting-an-environment-variable-in-a-job)）

```yaml
jobs:
  build:
    docker:
      - image: cimg/base:stable
    environment:
      MY_ENV_VAR_1: my-value-1
```

#### イメージでの設定
dockerキーのイメージと合わせて設定します。
プライマリ コンテナイメージ (最初にリストされたイメージ) とセカンダリ サービス コンテナイメージにそれぞれ設定できます。
『CircleCI実践入門 CI/CDがもたらす開発速度と品質の両立』(p.102)では、下記のように使い分けることが推奨されています。
* コンテナの中で動作するアプリケーション → イメージで定義
* ステップ内で利用するもの → ステップで定義

```yaml
jobs:
  build:
    docker:
      - image: cimg/base:stable
        auth:
          username: mydockerhub-user
          password: $DOCKERHUB_PASSWORD
        environment:
          MY_ENV_VAR_1: my-value-1
```

（[ドキュメンテーション](https://circleci.com/docs/ja/2.0/env-vars/#setting-an-environment-variable-in-a-container)）
<br>


## プロジェクトでの環境変数

プライベート、パブリックの両方のレポジトリにおいて、シークレットを安全に格納できます。
プロジェクトごとの設定なので、該当するプロジェクトでのみ利用したい環境変数の設定に便利です。

CircleCIのUIから、該当するプロジェクトを選択します。
[Project Settings]ページに移動し、[Environment Variables]をクリックします。
[Add Environment Variables]をクリックして、環境変数を追加します。

|![Screen Shot 2022-04-25 at 17.07.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/9a4225d1-5dd4-b39a-1758-ddc0f58f6fd8.png)
|:--|

### シークレットのマスキング
プロジェクトやコンテキストで設定される環境変数はマスキングされており、`echo`コマンドなどの出力結果にも表示されません。
ただし、次の場合はシークレットが閲覧できるので注意が必要です。
1. 環境変数の値が４文字以下
2. 値が次のどれか：`true, True, false, False`
3. 別の場所に出力する場合（テスト結果やアーティファクト）
4. SSHを使用したデバッグ（これを実行するユーザーは、シークレットにアクセスできる）
<br>


## コンテキストでの環境変数
コンテキストには「環境変数を保護し、プロジェクト間で共有する」役割があります。
複数のプロジェクト間で環境変数を共有したい時にたいへん便利です。
コンテキストの環境変数はジョブ単位の設定も可能です。

下記の手順で設定できます。

[Organization Settings] → [Context]と遷移し、[Create Context]をクリックします。

|![Screen Shot 2022-04-26 at 2.11.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/fc5ab893-daf4-13c9-081d-6ebbd6d1a735.png)
|:--|

コンテキスト名を入力して、[Create Context]をクリックします。
次に、[Add Environment Variables]をクリックして環境変数を入力します。

今回はコンテキストを用いて、人気の Slack orb を試してみました。
[こちら](https://github.com/CircleCI-Public/slack-orb/wiki/Setup)のページを参考に環境変数を設定します。
Slack API website から[Create New App]を選択して該当項目を埋めます。
`SLACK_ACCESS_TOKEN`にはOAuth tokenを、`SLACK_DEFAULT_CHANNEL`にはチャネルのIDをそれぞれ値として設定します。
（チャネルのURLのうち、/archives/の後の文字列がIDにあたります。）
|![Screen Shot 2022-04-26 at 0.24.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/deaa9f85-9416-9a8b-9939-21cc0a34ddea.png)
|:--|


これで、`Slack_notify` というコンテキストの環境変数が設定できました。
デフォルト設定のチャネル #general にSlack通知が届くか検証します。
下記は、[Slack orb](https://circleci.com/developer/orbs/orb/circleci/slack)のページの例を引用しています。
（最下部のコンテキスト名は自分で設定したものに変更）

```
version: '2.1'
orbs:
  slack: circleci/slack@4.1
jobs:
  notify:
    docker:
      - image: 'cimg/base:stable'
    steps:
      - slack/notify:
          custom: |
            {
              "blocks": [
                {
                  "type": "section",
                  "fields": [
                    {
                      "type": "plain_text",
                      "text": "*This is a text notification*",
                      "emoji": true
                    }
                  ]
                }
              ]
            }
          event: always
workflows:
  send-notification:
    jobs:
      - notify:
          context: Slack_notify
```
実行してみると..
<br>

シュットトト（♪)
![Screen Shot 2022-04-25 at 22.41.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/bc2495b0-1298-0b81-c02a-d5ef89639064.png)
無事に通知を受け取ることができました。
<br>




## 制限付きコンテキスト
制限付きコンテキストを設定すると、指定したセキュリティ グループに所属するメンバーのみ、該当するコンテキストにアクセスしたり、そのコンテキストを用いたワークフローを実行したりできます。
（グループに属さないメンバーが実行を試みると、"Unauthorized" でジョブが失敗します。）

下記方法で設定できます。
GitHubで [Your Organization] → [Teams]と遷移し、Team を作成します。

![Screen Shot 2022-04-25 at 16.59.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/2ae12434-9e16-06d8-ff38-7332988b0eb1.png)


CircleCI で該当するコンテキストを開きます。デフォルトでは All members、つまりすべてのメンバーが登録されています。

|![Screen Shot 2022-04-25 at 17.01.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/00038906-fa83-a75f-4bcd-f9de1ada9e5f.png)
|:--|


[Add Security Group] をクリックして、追加したいグループを選択、追加します。
![Screen Shot 2022-04-25 at 17.01.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/01df2958-d0b8-6ea2-701f-b68501422474.png)

セキュリティ グループを追加したら、合わせて All members の削除を行います。

|![Screen Shot 2022-04-25 at 17.02.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/65763b57-d29e-3abe-adc9-ac385e6d6491.png)
|:--|

![Screen Shot 2022-04-25 at 17.02.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/a6fe4c89-6f97-32e4-4a0c-d4d8718a0092.png)

セキュリティ グループの指定が完了しました。

|![Screen Shot 2022-04-25 at 17.04.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/c9421db6-2dfe-f431-1129-5c44452182bd.png)
|:--|

制限付きコンテキストは、スケジュール・パイプラインで設定や実行の管理者を制限したい場合などに便利です。
<br>



## まとめ
今回ブログの執筆にあたり、Customer EngineeringチームのAaronさん、Naoyaさん、そしてMakotoさんにご指導いただきました。
今度お礼に八ヶ岳のかぶを差し上げたいと思います。

読者の皆さまには、環境変数を使いこなして、CircleCIを快適にご利用いただければ幸いです。
最後までお読みいただきありがとうございました。

技術的なご質問はこちら：[サポートセンター](https://support.circleci.com/hc/ja)




## 参考文献

浦井誠人, 大竹智也, 金洋国（2020）.『CircleCI実践入門 CI/CDがもたらす開発速度と品質の両立』.技術評論社
[技術評論社 書籍ページ](https://booklive.jp/product/index/title_id/845365/vol_no/001)

CircleCIドキュメンテーション
https://circleci.com/docs

Slack Orb
https://circleci.com/developer/orbs/orb/circleci/slack

Slack orb のセットアップ
https://github.com/CircleCI-Public/slack-orb/wiki/Setup