sacloudプロダクトのリリース用ピタゴラ装置

当記事は[さくらインターネット Advent Calendar 2017](https://qiita.com/advent-calendar/2017/sakura)の12日目の記事となります。

さて、この度めでたく「リソースマネージャー」機能がリリースされました。
[さくらのクラウドニュース: リソースマネージャー](https://cloud-news.sakura.ad.jp/2017/12/11/resource-manager/)

当記事ではこのリソースマネージャーでも利用されている「Terraform for さくらのクラウド」や公式CLIである「Usacloud」についてどのようにリリースを行なっているのかについてご紹介いたします。

なお、今回ご紹介する構成用のTerraform定義ファイル類(tfファイル)は以下で公開しています。

[GitHub: releases.usacloud.jp](https://github.com/sacloud/releases.usacloud.jp)

## 概要

[sacloud](https://github.com/sacloud)のプロダクトでは開発/リリースに主に以下のようなサービス/プロダクトを利用しています。

- Slack(コミュニティ内でのやり取りやリリース用BOTなど)
- GitHub
- TravisCI/AppVeyor(CI/CD)
- Docker Hub
- Terraform + Terraform for さくらのクラウド
- Usacloud
- さくらのクラウド(リリースサイト用)

この中でも今回はリリースの流れについてフォーカスを当てたいと思います。
リリースの全体像としては以下のような感じです。

![01_overview.png](https://qiita-image-store.s3.amazonaws.com/0/20668/9956845d-8854-2813-695a-59cfc679c804.png)

順番にご紹介していきます。

## (1) Slack BOTへリリース準備をお願いする

リリースを行う場合、まずは[sacloudコミュニティのSlackワークスペース](https://slack.usacloud.jp)のリリース用チャンネルでBOTに対してリリース依頼を行います。

[こちらの記事](https://qiita.com/yamamoto-febc/items/b4eaaaf7da60b267e95d)で紹介しているSlack BOTを用いており、BOTに声をかけるとGitHub APIから現在リリース済みの最新バージョンを取得して、次にリリースするバージョンの候補を表示してくれるようになっています。

![02_slack_select.png](https://qiita-image-store.s3.amazonaws.com/0/20668/682642de-5a6c-d725-b0e8-fa21b8c3b4f9.png)

## (2) Slack BOTがリリース用ブランチを作成 & push

Slack上でリリースするバージョンを選択するとGitHub上にリリース用のブランチを作成&pushされます。

![02_slack_release.png](https://qiita-image-store.s3.amazonaws.com/0/20668/d09f77ef-a3cd-8a88-9b7a-01141e875606.png)

リリース用のブランチ名を`bump-version-nn.nn.nn`(nn.nn.nnはリリースするバージョン)としておくことで後続プロセスでどのバージョンとしてリリースするのかが決定されます。

## (3) TravisCI上にてPullRequest作成

ブランチのpushを契機にTravisCI上でジョブが起動します。
TravisCIでは`script`プロバイダを用いて独自のデプロイ用スクリプトを起動します。

```yaml:.travis.ymlのPR作成部分の抜粋
deploy:
- provider: script
  script: scripts/usacloud-release.pl --task=create-pullrequest --current-branch=$TRAVIS_BRANCH
  skip_cleanup: true
  on:
    all_branches: true
    condition: "$TRAVIS_BRANCH =~ ^bump-version-.*$"
```

`condition`の部分でブランチ名が`bump-version-`で始まるものを対象にしているのがポイントです。

### デプロイ用スクリプト

デプロイ用スクリプトにてPullRequestの作成を行っています。

[Usacloudでのデプロイ用スクリプト:usacloud-release.pl](https://github.com/sacloud/usacloud/blob/v0.7.0/scripts/usacloud-release.pl)

このスクリプトは[少し前のMackerelのリリース用スクリプト](https://github.com/mackerelio/mackerel-agent/blob/v0.43.0/_tools/releng)を参考にしたもので、GitのコミットログからCHANGELOGなどを組み立ててリリース用のPullRequestを作成してくれます。

なお、この部分は近いうちにGoで書きなおす予定です。

## (4) リリース & 各種ソースの更新

リリース用のPullRequestをマージすると実際のリリース作業が行われます。
この作業もTravisCI上で行われます。

```yaml:.travis.ymlのリリース部分抜粋
before_deploy:
- if [ "$TRAVIS_BRANCH" == "master" ]; then
    make docker-build;
    docker pull sacloud/rpm-build:latest;
    docker pull sacloud/deb-build:latest;
    make rpm deb;
  fi
deploy:
- provider: script
  script: scripts/usacloud-release.pl --task=upload-to-github-release && scripts/usacloud-release.pl
    --task=upload-master-to-github-release && scripts/release_homebrew.sh && scripts/release_docker_image.sh
    && scripts/release_website.sh
  skip_cleanup: true
  on:
    branch: master
```

ここでは以下のような処理が行われます。

- 各プラットフォーム用にビルド&アーカイブ
- rpm/debパッケージ作成&署名
- GitHubリリースページへのファイルのアップロード
- `homebrew`用のソースの更新&コミット
- 配布用Dockerfileの更新&コミット
- リリースサイト用Dockerfileの更新&コミット

sacloudプロダクトは基本的にGitHubリリースページにて配布しています。
TravisCI上で配布用のファイル類をビルド&アーカイブしGitHubリリースページにアップロードしています。

加えてsacloudプロダクトはDockerイメージでも配布しているため、リリース時にDockerイメージをビルドしタグづけしておくようにしています。

また、パッケージマネージャから利用するリポジトリやインストール用スクリプトなどを配布するため、別途リリース用サイト(releases.usacloud.jp)も用意しています。このリリースサイト用のコンテンツについてもDockerイメージとしているためリリース時にイメージのビルドが必要です。

このために、TravisCI上でのデプロイ処理の中でDockerHubのAutomation buildを構築済みのリポジトリに対しDockerfileをコミットすることでDockerHubへ通知&イメージのビルドを行っています。

## (5) DockerHubでのDockerイメージビルド

GitHubにてDockerfileが変更&コミットされるとDockerHub上でDockerイメージのビルドが行われます。
DockerHubでは以下のようにビルド設定しておくことで、GitHub上にタグがpushされたら対応するタグを持つイメージをビルドしてくれるようになっています。

![03_dockerhub.png](https://qiita-image-store.s3.amazonaws.com/0/20668/128bfd18-3a43-4e31-4d65-9f93c82d1b20.png)

ビルド後はWebhookでリリース用サイトに通知されるように設定しています。

![04_dockerhub.png](https://qiita-image-store.s3.amazonaws.com/0/20668/eeb51f44-7aee-b0a7-42cb-e4c8977ae6f3.png)

## (6) リリース用サイトのdocker stack更新

DockerHubからのWebhookを受けてリリースサイトのコンテンツの更新が行われます。
リリースサイトは以下のような構成で`docker stack`を利用しており、Webhookを受けると`docker stack deploy`コマンドを実行して利用するイメージを順次更新していきます。

![04_servers.png](https://qiita-image-store.s3.amazonaws.com/0/20668/03f4ec30-c1b8-ca94-f14c-a970af89c971.png)

各サーバのOSにはRancherOSを利用しており、Webhookの受信はRancherOSの「サービス」としてdockerコンテナとして実行しています。`docker stack`とは別でコンテナ起動している部分がポイントですね。

このリリースサイトはTerraform for さくらのクラウドで環境構築しています。
Terraform定義ファイル類は以下で公開していますので、詳細はコードを参照してみてください。

[GitHub: リリースサイト構築用定義ファイルなど](https://github.com/sacloud/releases.usacloud.jp)

あまり整理できてない生々しいコードになっていますが、ある程度停止時間の許容できる甘めの運用要件しかないサイトなのでちょっと手を抜いてます。
とはいえ`docker swarm init`の実行やRancherOSのプロビジョニングなどの実例となっていますので
Terraform for さくらのクラウドの一活用例としてみていただければと思います。

以上でリリース処理が完了となります。

---

今回はsacloudプロダクトでのリリースの流れをご紹介しました。
ピタゴラ装置のように色々と組み合わせることでリリースパイプラインを構築する例でした。
どなたかの参考になれば幸いです。

以上です。