CircleCI勉強会

# これは?

- 社内勉強会用の資料です

---

# CircleCI 2.0

- 2.0が2017-07-11にリリース
- Dockerコンテナ上で実行
  - 予め環境を作っておける
- 1.0はちゃんと使ったことがありません

---

# CircleCIで解決したこと

- テスト
- AMIの生成

---

# CircleCIを設定する

- Webページでプロジェクトを追加
- **環境変数等を設定**
- **YAMLファイルを実装**
- **Dockerイメージの用意**
- commit & push

---

## 環境変数等を設定

Webから以下のような設定が可能

- Environment Variables
  環境変数の設定

- AWS Permissions
  ジョブ実行時に `~/.aws/credentials` が設定される

- Chat Notifications
  Slackの連携はここ

ほかはヘルプを参照

---

## YAMLファイルを実装

- `.circleci/config.yml`を作成する
  - Dockerの設定
  - 実行するコマンド
  - Workflowの定義
  - など
- https://circleci.com/docs/2.0/configuration-reference/

---

## Workflow

- ジョブの実行順序を定義したもの
- ビルドの実行フェーズを分割できる
- 実行フェーズごとにジョブの成功・失敗を把握しやすい
- 並列実行や条件による実行ができる

---

## Dockerイメージの用意

- DockerHubで**公開されている**イメージが使える
- プライベートなライブラリ等はジョブ実行時にセットアップする

---

# ローカルでの開発

- https://circleci.com/docs/2.0/local-jobs/
- YAMLのバリデーション `circleci config validate`
- YAML定義の実行 `circleci build`
  - 設定変更の度にpushしなくていい

---

## CLIの制約

- Workflowは使えない
- 設定画面で行える設定(AWS Permissionsなどなど)が使えない

---

# Tips

---

## .netrcを使ったclone

- .netrcにGitHubのトークンを記述してHTTPSでcloneする
- ターゲットリポジトリ以外のリポジトリを使うときに有効

---

## shallow clone

- CI環境に歴史はいらない
- リポジトリのサイズが大きいときに有効

`git clone --depth=1`

---

## すでに存在する環境変数を設定(PATH等)

- 環境変数の設定画面やDockerの環境変数からは `export PATH=/path/to/script:$PATH` ができない
- `BASH_ENV`にスクリプトを指定する
- https://discuss.circleci.com/t/how-to-add-a-path-to-path-in-circle-2-0/11554

```yaml
    docker:
      - image: <image>
        environment:
          BASH_ENV: ~/.bashrc
    run:
      name: set path
      command: |
        echo 'export PATH=/path/to/script:${PATH}' > ~/.bashrc
```

---

## アンカーとエイリアスを活用する

- 見通しを良くする
- DRYに書く

```yaml

  container_config: &container_config
    docker:
      - image: ubuntu
        environment:
          API_ENDPOINT: https://circleci.com/api/v1.1/

  branch_config: &branch_config
    branches:
      only:
        - master
        - develop
...
jobs:
  build:
    <<: *container_config
    <<: *branch_config
```

---

# Pitfalls

---

## CLIのValidateに頼らない

- 文法のチェックだけしかしない
- 以下の例ですべてValidationは通る

---

### YAMLの結果が正しくない例

```yaml
jobs:
  build:
    steps:
    - run:
      name: hello
      command: echo hoge
```
```json
{
  "jobs": {
    "build": {
      "steps": [
        {
          "run": null, 
          "command": "echo hoge", 
          "name": "hello"
        }
      ]
    }
  }
}
```

---

### YAMLの結果は正しくない例

`run`以下をインデント

```yaml
jobs:
  build:
    steps:
      - run:
        name: hello
        command: echo hoge
```

```json
{
  "jobs": {
    "build": {
      "steps": [
        {
          "run": null, 
          "command": "echo hoge", 
          "name": "hello"
        }
      ]
    }
  }
}
```

---

### 正しく動作する例

`name`と`command`をインデント

```yaml
jobs:
  build:
    steps:
      - run:
          name: hello
          command: echo hoge
```

```json
{
  "jobs": {
    "build": {
      "steps": [
        {
          "run": {
            "command": "echo hoge", 
            "name": "hello"
          }
        }
      ]
    }
  }
}
```

---

## Dockerイメージの更新の影響

- `latest`なイメージは変更される可能性がある
- CIビルドが走るのはDockerイメージの更新時ではなく、コードのpush時なので気づきにくい

---

## AWS Permissionsにはリージョンがない

- 設定画面から追加できるのはアクセスキーIDとシークレットアクセスキーのみ
- リージョンは直接ファイルに書き出す

```yaml
command: |
  mkdir ~/.aws
  echo -e "[default]\nregion = ap-northeast-1" > ~/.aws/config
  chmod 0600 ~/.aws/config
```

---