Bitbucket Pipelinesを使ってNestJSバックエンドアプリをHerokuに自動デプロイする

# はじめに

デプロイ職人芸、辞めませんか。
インフラ達人芸、諦めませんか。

# 対象読者

- Bitbucketで管理するソースコードを手動でビルドしてデプロイしている開発者
- リリースする環境ごとにソースコードを手作業で修正する必要があるなど、デプロイが職人芸と化しているデプロイ職人
- インフラエンジニアがチームに存在しないが、環境を準備しないといけないスクラムチーム
- 夜中でもアラートがとんできたらすぐ対応しないといけないインフラエンジニア

# 前提条件

- NestJSのソースコードが存在している
- Bitbucketのリポジトリにソースコードをプッシュしている
- Herokuのアカウントを作成済 

NestJSでのバックエンド構築は、拙著で恐縮ですが[こちら](https://qiita.com/hiyasichuka/items/a0d895f3ce80f8adc329)をご参照ください。


# 手順

1. Herokuにデプロイできるようソースコードを一部修正する
1. Herokuをセットアップする
1. Bitbucketのリポジトリ設定を行う
1. BitbucketのPipelinesをセットアップする
1. CICDパイプラインを動かしてみる

# 内容

## 1. Herokuにデプロイできるようソースコードを修正する

NestJSのデフォルトのソースコードでは、ポート3000でリクエストを受けるようになっています。
```js:main.ts (修正前)
// 該当箇所のみ抜粋
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.listen(3000);
}
```

Herokuでアプリケーションを実行する場合、Heroku側で動的にポートを指定するらしく、正常に動かないことがあります。
したがって、このポートの部分を環境変数に変更します。環境変数名をPORTとして、引数として渡すように修正しました。

```js:main.ts (修正後)
// 該当箇所のみ抜粋
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.listen(process.env.PORT);
}
```

続いて、Herokuのプラットフォーム上にあるWebアプリの実行コマンドをファイルに記述します。
ルートディレクトリに**Procfile**を作成して、実行コマンドを記述します。

```js:Procfile
web: npm run start:prod
```

ちなみにVSCodeでvscode-iconsの拡張機能を導入されている場合、以下のようにHerokuのアイコンになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/81916512-ca04-ac1f-72f7-7e4d5b76177d.png)

以上でソースコード側の修正作業は完了です。

# 2. Herokuをセットアップする

Herokuにログインして、Create new appをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/b661363f-5fba-0da9-3d9f-4f6270988e77.png)

重複しないApp nameを入力します。（画像では、すでに同じApp nameが存在するため、エラーとなっている。）
regionはお好きなように選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/01b72601-3c47-4659-6672-6c5dd195b7f5.png)


App作成後、SettingsからReveal Config Varsをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/3aaa055b-36ee-dc26-296f-f256c78aeac0.png)



こちらに先程の環境変数PORTを作成します。
KEYにPORT、VALUEに3000を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/04b59d93-a01d-f923-6ec4-729686d8577e.png)

続いて、HerokuのAPI KEYをコピーするなどして控えておきます。
Account SettingsからAPI Keyの項目に移動して、Revealを押下することでKeyを表示できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/6f49d48c-ec2f-7700-4c26-b24371f15235.png)


以上でHeroku側のセットアップは完了です。


# 3. Bitbucketのリポジトリ設定を行う

リポジトリのSettingsからRepository variablesを選択します。
こちらに以下２つの項目を追加します。
- HEROKU_STAGING_APP_NAME: Herokuで作成したApp name
- HEROKU_API_KEY: HerokuのAPI Key

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/5da14ec0-cffd-f12b-d17c-6bc7a4f4513f.png)


# 4. BitbucketのPipelinesをセットアップする

BitbucketのPipelinesをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/5403b0df-7dc1-1b9d-c52c-690fbdef7df0.png)

Build and test a NodeJS codeをSelectします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/aec50ae4-ce4f-a24a-8223-e94b8e6c0794.png)

サンプルコードが表示されるので、こちらをベースにNestJSバックエンドアプリ用のCICDパイプラインを構築します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/47cb193b-3030-f33b-0964-525687edd4bc.png)

以下は私の方で作成したCICDパイプラインコードです。

```yml:bitbucket-pipelines.yml
image: node:16

pipelines:
  branches:
    develop:
        - step:
            name: linting & test
            caches:
              - node
            script:
              - echo "Install Node Packages"
              - npm install
              - echo "Linting"
              - npm run lint
              - echo "Testing"
              - npm test
        - step:
            name: deploy
            caches:
              - node
            script:
              - git push -f https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_STAGING_APP_NAME.git master
```

- developブランチの変更のみ実行するようにしています。
- step1でリンターとテストを実行して、step2でHerokuにデプロイするようにしました。
- ですので、step1のリンターとテストが失敗するとデプロイされません。
- Heroku側にソースコードをアップロードすれば、Heroku側で自動でアプリを起動してくれます。

OSパッチ適用やら、リソース監視、スケールアウト/アップなどといったインフラ達人芸は、すべてHerokuに任せることができます。
世の中便利になったもんですね。

# 5. CICDパイプラインを動かしてみる。

developブランチに何か変更を加えても良いのですが、一旦、作成したパイプラインを手動で実行してみます。
先程のdevelopブランチ用のパイプラインを選択して、Runをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/192eecaa-af44-7496-4344-ee74e86e4cfb.png)


正常に実行するとグリーンとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/b45e6438-f829-1f88-2a0b-4a77bcb423c2.png)


実際にデプロイできたかHerokuで確認します。
先程作成したAppを選択して、Open appをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/af37a722-83f1-84bc-43b3-2a53a784b1fb.png)

NestJSのバックエンドプログラムが動いていることが確認できました！
このバックエンドは、APIルートにアクセスするとHello world!の文字列をレスポンスする仕様です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533960/a50e3281-f997-7381-1f42-e0536d7cbb89.png)




以上です。