Drone CI 基本設定 (.drone.yml)

[Drone CI](https://www.drone.io) を使って CI/CD をおこなうには、リポジトリのトップレベルに .drone.yml という名前のファイルを作成する。

参考) [公式ドキュメント](https://docs.drone.io)

## 実行内容の設定 (Pipeline)

### ステップの設定

参考) [Pipelines > Docker > Configuration > Steps](https://docs.drone.io/pipeline/docker/syntax/steps/)

steps に実行手順を記述する。step ごとに指定した Docker イメージでコンテナが生成され、その上でコマンドが実行される。Docker イメージは基本的には [Docker Hub](https://hub.docker.com) から適当なものを選択する。適当なイメージが Docker Hub に存在しない場合は、別の Docker リポジトリと連携したり、その場で作成するなどする。

```yaml
---
kind: pipeline
type: docker
name: default

steps:
  - name: (任意の名前)
    image: (Docker イメージ名)
    command:
      - (実行するコマンド)
```

ステップは記述した順に実行され、デフォルトでは失敗した場合は後続のステップは実行されない。失敗した場合も実行するには when で条件を記述する。

```yaml
steps:
  - name: ...
    image: ...
    when:
      status: [ success, failure ]
```

### トリガーの設定

何をトリガーに実行するかを指定する。

参考) [Pipelines > Docker > Configuration > Triggers](https://docs.drone.io/pipeline/docker/syntax/trigger/)

例) master ブランチへの push/merge をトリガーに実行する場合

```yaml
trigger:
  branch:
    - master
  event:
    - push
```

この場合すべての条件に一致する場合しか指定できないため、複数の組み合わせパターンを指定したい場合は、ref を使う。

例) master ブランチへの Push/Merge、Pull Request、タグづけをトリガーに実行する場合

```yaml
trigger:
  ref:
    - refs/heads/master     # master ブランチへの push/merge
    - refs/pull/**          # Pull Request
    - refs/tags/**          # タグ付け
```

それぞれ実行するステップを変更したい場合は、各ステップで同じように when で指定する。

例) タグづけ時のみステップを実行する場合

```yaml
steps:
  - name: タグづけ時のみ実行するステップ
    image: ...
    when:
      event:
        - tag
```

## 自作 Docker イメージの使用

ホストの Docker 上にイメージを作成し、それを使用する。

★ホスト上に生成するため、他リポジトリで生成するイメージとかぶらないイメージ名を指定すること。

 1. イメージをビルドする Dockerfile を作成する。

 1. .drone.yml にイメージをビルドする step を記述する。

    ```yaml
    steps:
      - name: build-worker
        image: docker
        volumes:                  # ホストの Docker を使用するための設定
          - name: docker.sock
            path: /var/run/docker.sock
        commands:
          - docker build -f (Dockerfileのファイル名) -t (イメージ名) .

    volumes:                      # ホストの Docker を使用するための設定
      - name: docker.sock
        host:
          path: /var/run/docker.sock
    ```

 1. このイメージを使って実行する step で、作成したイメージと `pull: never` を記述する。

    ```yaml
      - name: (任意の名前)
        image: (作成したイメージ名)
        pull: never
        commands:
          - (実行するコマンド)
    ```

## キャッシュ

参考) [Plugins | Drone > Drillsters > Volume Cache](http://plugins.drone.io/drillster/drone-volume-cache/)

以下の設定をすることで、指定したパスがホストの /tmp/(リポジトリ名)/(ブランチ名).tar に保存され、次回ビルド時に復元される。

```yaml
steps:
  - name: restore-cache
    image: plugins/volume-cache
    settings:
      mount:
        - (キャッシュするパス)
      restore: true
    volumes:
      - name: cache
        path: /cache

  (実行する steps を記述)

  - name: rebuild-cache
    image: plugins/volume-cache
    settings:
      mount:
        - (キャッシュするパス)
      rebuild: true
    volumes:
      - name: cache
        path: /cache

volumes:                      # キャッシュの保存先 (ホストの /tmp を指定)
  - name: cache
    host:
      path: /tmp
```

## Docker の実行 (Docker in Docker)

処理内で docker を実行したい場合、DinD コンテナを使用する。(ホストの Docker には影響しない)

docker:19-dind 以降では TLS を無効にするため `DOCKER_TLS_CERTDIR: ""` を指定する必要がある。([参考](https://about.gitlab.com/blog/2019/07/31/docker-in-docker-with-docker-19-dot-03/))

```yaml
steps:
  - name: (任意の名前)
    image: (Docker イメージ)
    environment:                    # DinD コンテナの Docker を使用する設定
      DOCKER_HOST: tcp://docker:2375
    command:
      - sleep 10                    # Docker の準備完了を待つ (必要に応じて)
      - (実行するコマンド)

services:                           # DinD コンテナを起動する設定
  - name: docker
    image: docker:dind
    privileged: true
    environment:
      DOCKER_TLS_CERTDIR: ""
```

## 環境変数

### 定義済み変数の使用

参考) [Environment > Reference](https://docs.drone.io/pipeline/environment/reference/)

ここに定義されている変数が使用できる。

### 暗号化した変数の使用

[Encrypted](https://docs.drone.io/configure/secrets/encrypted/) を使用する方法。

Drone CLI を使って以下のコマンドを実行し、リポジトリ毎に暗号化した文字列を生成する。

```shell
$ drone encrypt (リポジトリ名) (平文)
(暗号化文字列)
```

Slack 通知先の Webhook URL を暗号化した例

```yaml
steps:
  - name: notify
    image: plugins/slack
    settings:
      webhook:
        from_secret: (変数名)

---
kind: secret
name: (変数名)
data: (暗号化文字列)
```

## Slack への通知

参考 [Plugins | Drone > Drone-plugins > Slack](http://plugins.drone.io/drone-plugins/drone-slack/)

Slack で Webhook URL を作成しておく。(作成済みの場合は設定から Webhook URL を確認する。)

 1. Slack > Slack をカスタマイズ > App管理 > カスタムインテグレーション > Incoming Webhook > 設定を追加
 1. 通知先チャンネルを指定: #droneci

作成した URL を Secrets に登録し、プラグインに指定する。

```yaml
steps:
  - name: notify
    image: plugins/slack
    settings:
      webhook:
        from_secret: slack_webhook
    when:
      status: [ success, failure ]
```

メッセージを変更したい場合は template で指定する。

```yaml
    settings:
      template: |-
        *{{build.status}}* <{{build.link}}|{{repo.owner}}/{{repo.name}}#{{truncate build.commit 8}}> ({{build.branch}}) by {{build.author}}
```

## その他

- [別の IAM ロールで AWS にアップロード・デプロイする](https://qiita.com/yh1224/items/809441a13640e478f13f)
- [Docker Hub にログインしてイメージを Pull する](https://qiita.com/yh1224/items/5596973dfecb4f347c22)