受託開発へ捧ぐBitbucket Pipelinesによるちょうどいいデプロイ

---

この記事は[株式会社LIGのアドベントカレンダー2017](https://qiita.com/advent-calendar/2017/lig)、7日目の記事です。

---

業務で受託によるWeb制作に携わっています。

リリース以後、Bitbucket Pipelinesの噂はあまり聞きませんが、実際に案件に導入することによって気持ちのよい運用を感じているので、その方法をご紹介したいと思います。

<img width="914" alt="スクリーンショット 2017-12-06 20.26.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/146958/c7009e8b-33c8-261e-293b-28df904a4c49.png">

## 前提の課題

弊社のWebの受託開発において承るご要望は、WordPressでのメディアの作成、コーポレートサイト作成、採用サイト作成、外部サービスとの連携、Webサービスの開発などお客様によってさまざまですが、ここではすべてやや強引にWebサイトという言葉で統一したいと思います。それら多くの案件で共通して、リリース後、Webサイトの自社開発とは違った課題が待ち受けています。

その一つがリリース後のデプロイやCIです。自社開発であれば気持ちよく開発を進めるために2017年後半の現代では、ローカルでのDocker開発+github+CircleCI+CodeDeploy+Slackみたいな手法を導入するのが一般的になった頃かと聞いていますが、こちら側の世界ではコストや費用対効果、リソース、ご要望の観点からCIに取り組むことは稀です。

昔から関わらせていただいているサイトですとFTPは余裕しゃくしゃくですし、PHP5系はまだまだご健在ですし、WordPressは自動でアップデートされますし（いいことですけど）、テストのことを考えると胸が苦しくなりますし、ただしsshは殺されてるみたいな、CIの前段で色々と考えることの方が多いです。

そもそもWebサイト制作では、お客様にサーバごとソースコードをお渡しすることが多いのですが、お客様の組織にはWebサイトの開発者が一人もいないということが高確率でありえます。WordPressでの入稿作業は何とか出来るというような。そのようなお客様に対して、マニュアルの整備や運用契約でのサポートは別途行うとして、とくに「運用開始後のソースコードの改修とデプロイ」について、学習コストや管理コストを下げる方法を色々考えていました。

それらの疑問に対してBitbucket Pipelinesは少し納得感のある手法でしたので、ご紹介したいと思います。今回のお客様のインフラはAWS、構成も自由に変更できる想定です。運が良かったケースになりますが、その他の場合でもBitbucket Pipelinesの導入は有効に働くと考えます。

## Bitbucket Pipelinesとは

Dockerコンテナをbitbucketが提供しているリソースの中で立ち上げてテストやデプロイなどのCIに利用できるサービスです。Dockerのイメージを変更することや、スクリプトを実際に実行できることで、様々なアクションを行えます。コンテナが立ち上がり、それらのスクリプトが実行されるトリガは、git pushによって指定のブランチにpushされた場合、もしくはbitbucketの管理画面から実行を明に行った場合などになります。

Pipelinesがリリースされて、ベータ時代から含めると二年くらい経ったでしょうか。代替サービス、ソフトウェアは下記のように多く出ている分野です。

* CircleCI
* TravisCI
* Wercker
* drone.io
* jenkins

ここでお伝えいたしますと、Pipelinesがそれらに対して機能的に圧勝しているものは、残念ながら、**ない**、と思います。（bitbucket好きですいつもありがとう！）ではあえてそれを導入した理由はなんでしょうか。下記のような「ちょうどよさ」を感じたためになります。

* お客様のアカウントにpushして納品という運用の簡易さ
* コード管理＋CIのみという過不足のないベース機能
* 一案件運用においては過不足のない無料枠

過ぎたるは及ばざるが如し。

それでは実際の設定を見ていきましょう。

## Pipelinesの使い方

### Pipelinesを有効化する

bitbucketにリポジトリを作成するとメニューに「Pipelines」が表示されると思います。ここにPipelinesの初期設定サンプルがあります。

<img width="1239" alt="スクリーンショット 2017-12-06 18.24.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/146958/8af1e910-7067-5035-a7b8-3f04a3cc7ec1.png">

### bitbucket-pipelines.ymlを作成する

<img width="912" alt="スクリーンショット 2017-12-06 18.25.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/146958/8449599c-7247-6543-8f36-2edfec5b0d89.png">

Pipelinesを操作するためにはリポジトリのトップに「bitbucket-pipelines.yml」が必要です。「commit file」をクリックすると、実際にリポジトリにそのファイルが追加され、下記のようにPHP用のコンテナが立ち上がり、デフォルトで記載されたタスクが走るかと思います。

<img width="1122" alt="スクリーンショット 2017-12-06 18.38.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/146958/ce01cef7-8c63-5d38-bafe-042c2cf60f5d.png">

**まぁ、いきなり失敗するんですけど。**

## そのディレクトリには何があるのか

失敗したのはリポジトリにcomposer.jsonが置かれていないからです。

ではcomposer.jsonを置いてみます。ついでにテストのファイルを追加して、立ち上がったコンテナの状況を見てみましょう。リポジトリへのpushに反応して、自動的にPipelinesが実行されるはずです。

<img width="1122" alt="スクリーンショット 2017-12-06 19.14.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/146958/0ef05150-2162-8615-fe04-ab7d311e2fa0.png">

今度は成功しました。lsで見てみると、自分がいまいるところにソースコードが展開されているのが分かります。

## 環境変数の設定

起動されるコンテナにbitbucketのリポジトリ管理画面から環境変数を渡すことができます。

<img width="1305" alt="スクリーンショット 2017-12-06 19.18.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/146958/6e2bf017-4f46-14a0-2098-2e9678ab6b28.png">

「Secured」にチェックを入れて「Add」すると、設定された値が表示されなくなります。これによって複数人での管理においても設定者にしかトークンを見せない、などの対応が可能です。実際にコンテナに値が渡るか見てみましょう。

下記がSecuredで渡した場合の値。

<img width="1114" alt="スクリーンショット 2017-12-06 19.28.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/146958/14aa1134-55ba-cc95-16c7-b8d95e077a94.png">

PIPELINE_TESTの中身は見えないですね。ええ、僕も初めて知りましたが考えてみると当たり前で、このログでSecuredの値は見えないのですね。そりゃそうか。でも値は渡っているようです。

次がSecuredをつけずに値を渡した場合。

<img width="1119" alt="スクリーンショット 2017-12-06 19.31.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/146958/6daefadd-0bf7-5951-2543-89d5266ee3fc.png">

値が見えました。この環境変数を使って、コードに記述できない秘匿情報などを保存してテストやデプロイに使用することになります。

## PipelinesによるAWSデプロイ

ここまででPipelinesを起動させる準備、秘匿情報を渡す準備が整いました。このコンテナの中からAWSへデプロイを行いたいと思いますが、CodeDeployを使ってデプロイを行う設定については割愛します。

**それからbitbucketとAWSの相性はよくありません。**

githubを使ってればCodeDeployが直接コードを引っ張ってくれるようにできるのですが、bitbucketからは直接できないので、S3にコードを上げる必要があります。CodeDeploy＆S3の設定を行って、IAMのトークンを取得しておいてください。

その上で下記のページにpythonを使ってCodeDeployをキックするスクリプトがあります。[このサンプル](https://bitbucket.org/awslabs/aws-codedeploy-bitbucket-pipelines-python/src/73b7c31b0a72a038ea0a9b46e457392c45ce76da/bitbucket-pipelines.yml?at=master&fileviewer=file-view-default)やREADMEを参考にしながら、設定をしてください。

[Deploy to AWS CodeDeploy](https://bitbucket.org/awslabs/aws-codedeploy-bitbucket-pipelines-python/)

## メリット・デメリット

ここまで作ってしまえば、受託開発において他のCIサービスと比較して下記のようなメリデメが発生すると考えています。

### メリット

* **bitbucketに閉じた世界でコードのデプロイができる。（実は相当大きい）**
* 少ない人数であれば、お客様とリポジトリを共有することによって、納品がスムーズになる。
* コード管理さえ出来れば、納品後の開発と運用を切り離せるし、bitbucketの全体の説明だけで済む。

### デメリット

* Pipelinesは多機能ではありません。
* [ユーザ全体で50分/月以上コンテナを超えると有料](https://bitbucket.org/product/pricing?tab=host-in-the-cloud)です。無料のまま頻繁にデプロイすることは出来ません。

## その他の情報

* Herokuへデプロイしたい。
    * [この辺をご覧ください。](https://confluence.atlassian.com/bitbucket/deploy-to-heroku-872013667.html)
* FTP、SFTP、rsync、scp……
    * 同胞よ、シェルスクリプトをたくさん書こう。
* コンテナ内で色々インストールするのがしんどい。
    * [Pipelinesはディレクトリをキャッシュすることが出来ます。](https://confluence.atlassian.com/bitbucket/caching-dependencies-895552876.html)
    * もしくは自分でdockerイメージ作ってDocker Hubに上げときましょう。
* 手動でPipelinesを実行したい。
    * [ブランチの代わりにcustomを指定することでbitbucket管理画面からPipelinesが実行できます。](https://confluence.atlassian.com/bitbucket/configure-bitbucket-pipelines-yml-792298910.html)
* 実はPipelinesではなくIntegrationsの機能で[AWSへのデプロイ](https://marketplace.atlassian.com/plugins/bitbucket-aws-codedeploy/cloud/overview)が提供されていますが、試したことがありません。

## 最後に

目指せ、ちょうどよさ。