AWS CodeBuildでyarnを使えた

# やりたいこと

以下の2つを知りたかった。

* AWS CodeBuildの中で、yarnを使ってパッケージをインストールできるか？
* npmを使った場合とyarnを使った場合でどのくらい時間に差があるのか？

ローカルでの開発にyarnを使っているので、CodeBuildでもyarnを使いたかったのです。

# 結論

* yarnは使える（条件有り）
* yarnを使うと少し速い

計測した時間は以下のとおりです。

パッケージのinstallを1回だけ実行した場合

|      | BuildProject全体 | BUILD Phase | yarnのinstall | install | 
|:-----|-----------------:|------------:|--------------:|--------:|
| yarn |         2min21sec|    1min03sec|          14sec|    40sec|
| npm  |         2min22sec|    1min04sec|              -|    50sec|

パッケージのinstallを3回実行した場合

|      | BuildProject全体 | BUILD Phase | yarnのinstall | install 1 | install 2 | install 3 | 
|:-----|-----------------:|------------:|--------------:|----------:|----------:|----------:|
| yarn |         3min12sec|    1min52sec|          15sec|      47sec|      22sec|      15sec|
| npm  |         3min19sec|    2min12sec|              -|      47sec|      39sec|      40sec|


**yarnは使える（条件有り）とは**

公式によると、`npm install -g yarn`はオススメできないとのことです。

> **Note**: Installation via npm is generally not recommended. npm is non-deterministic, packages are not signed, and npm does not perform any integrity checks other than a basic SHA1 hash, which is a security risk when installing system-wide apps.
>
>For these reasons, it is highly recommended that you install Yarn through the installation method best suited to your operating system.
>https://yarnpkg.com/lang/en/docs/install/#alternatives-tab

公式手順に従って`apt-get`でパッケージをインストールしようとしたのですが、

`sudo apt-get update`でこんなエラーがでたり

```
E: The method driver /usr/lib/apt/methods/https could not be found.
```

`apt-transport-https`でこんなエラーが出たり

```
E: Unable to locate package apt-transport-https
```

したので、あきらめてしまいました。。。。

# 実験方法

こちらのリポジトリからcloneしたものを使います。

https://github.com/monamu/codebuild-npm-yarn.git

ディレクトリ構成はこのようになっています。

``` sh
+---npm
|   |   buildspec.yml
|   |
|   +---app1
|   |       package.json
|   |       yarn.lock
|   |
|   +---app2
|   |       package.json
|   |       yarn.lock
|   |
|   \---app3
|           package.json
|           yarn.lock
|
\---yarn
    |   buildspec.yml
    |
    +---app1
    |       package.json
    |       yarn.lock
    |
    +---app2
    |       package.json
    |       yarn.lock
    |
    \---app3
            package.json
            yarn.lock
```

"npm"ディレクトリと"yarn"ディレクトリからそれぞれzipアーカイブを作成して、
CodeBuildプロジェクトのソースとします。それぞれの"appX"ディレクトリの内容はすべて同一です。

## buildspec.yml の確認

それぞれのディレクトリ直下（zipアーカイブのルートになります）にあるbuildspec.ymlが以下のようになっており、CodeBuild上で実行されるyarnとnpmを使い分けています。

``` yaml:yarn/buildspec.yml
version: 0.1
 
phases:
  install:
    commands:
      - echo Nothing to do in the install phase...
  pre_build:
    commands:
      - echo Nothing to do in the pre_build phase...
  build:
    commands:
      - echo Build started on `date`
      - npm -v
      - node -v
      - npm install -g yarn
      - yarn --version
      - cd app1 && yarn
      - cd app2 && yarn
      - cd app3 && yarn
  post_build:
    commands:
      - echo Build completed on `date`
```


``` yaml:npm/buildspec.yml
version: 0.1
 
phases:
  install:
    commands:
      - echo Nothing to do in the install phase...
  pre_build:
    commands:
      - echo Nothing to do in the pre_build phase...
  build:
    commands:
      - echo Build started on `date`
      - npm -v
      - node -v
      - cd app1 && npm install
      - cd app2 && npm install
      - cd app3 && npm install
  post_build:
    commands:
      - echo Build completed on `date`
```

## zipアーカイブの作成

zipの中身が以下のようになるようにyarn.zipとnpm.zipを作成します。

``` sh
npm.zip
|   buildspec.yml
|
\---app1
|       package.json
|       yarn.lock
\---app1
|       package.json
|       yarn.lock
\---app1
        package.json
        yarn.lock
```

## S3バケットへのupload

作成した2つのzipを任意のS3バケットにアップロードします。

![image](https://qiita-image-store.s3.amazonaws.com/0/117772/4f561a63-93d6-eb5b-9e7c-e7fa178be335.png)

私は新規バケットを作成して、ルートにzipファイルを配置しました。

## CodeBuildでプロジェクト作成

以下の内容でCodeBuild プロジェクトを作成します。

![image](https://qiita-image-store.s3.amazonaws.com/0/117772/5ea4c720-cd79-0ea1-5cbf-6155a4d2aa7d.png)

これはnpm.zipでの実行分です。同じ内容で、"S3 Object key"に"yarn.zip"を指定したCodeBuildプロジェクトも作成します。

## Buildの開始

それぞれのプロジェクトを開始します。

![image](https://qiita-image-store.s3.amazonaws.com/0/117772/c421d100-e3ac-28bd-d380-6d89c1fafe94.png)

状況はBuild historyのページから確認できます。

![image](https://qiita-image-store.s3.amazonaws.com/0/117772/4c165c0d-0f73-3080-15a4-437d157fd560.png)

"Output: Logs"からCloudWatch Logsに記録されたログを確認できます。

今回は、CodeBuildプロジェクトの設定でArtifact（成果物）無しの設定にしたので、実行が完了してもログ以外は何も残りません。

# まとめ

結論は先に書いてしまいましたが、yarnを使うことができました。

yarnを新規にインストールするオーバーヘッドがどれくらいあるかも気になっていたのですが、
実はそれほどかからずに、トータルではyarnの実行速度のメリットが出せていると思います。

では！