SpringBootアプリをGithubActionsで超簡単にAWS ElasticBeanstalkにデプロイしてみた 

# はじめに
Githubでなんの追加も必要なく簡単にCI/CDが行える GithubActions が予想以上に手軽で便利でした。
今回は特定のブランチにPushした場合に、自動的にAWSのBeanstalkにデプロイする workflow の作成手順を紹介します。

# 前提
- AWSのアカウント（IAM）があること
- Githubのアカウントがあること

# 開発環境
- macOS Mojave
- OpenJDK 1.8
- IntelliJ IDEA ultimate 2019.3
- SpringBoot 2.2.6
- Gradle 6.3

# 大まかな作業の流れ
- デプロイ用のSpringBootアプリを用意する
- AWSのBeanstalkに手動でデプロイする（初回だけ）
- GithubActionsの workflow をymlで書く
- pushして自動デプロイを確認

# デプロイ用のSpringBootアプリを用意する
まずはBeanstalkで動かすためのデモプロジェクトを用意します。
サクっと [spring initializr で GradleProject に lombok, Spring Web をdependenciesに追加して作成](https://start.spring.io/#!type=gradle-project&language=java&platformVersion=2.2.6.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo&dependencies=lombok,web) します。

```gradle:build.gradle
plugins {
	id 'org.springframework.boot' version '2.2.6.RELEASE'
	id 'io.spring.dependency-management' version '1.0.9.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
}

test {
	useJUnitPlatform()
}
```

これに動作確認用に簡単なControllerを作成しておきます。

```java:DemoController.java

@RestController
public class DemoController {
    @GetMapping("/demo")
    public String demo() {
        return "Hello Demo!!";
    }
}
```

さらに、BeanstalkのWebアプリはサーバーポートを「5000」で受ける必要があるので、application.propertiesを編集します。

```properties:application.properties
server.port=5000
```

以上でデモアプリの作成は完了です。

Beanstalkには executableJar で配置するので、以下のコマンドでjarをビルドします。

```terminal
$ ./gradlew build
```

すると、 `build/libs` 内にjarが生成されるので、試しにローカルでアプリを起動してみましょう。

```terminal
$ java -jar build/libs/demo-0.0.1-SNAPSHOT.jar
```

サーバー起動後、ブラウザで `http://localhost:5000/demo` にアクセスして以下のように表示されればデプロイ用のデモアプリの作成は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/a424ab8a-1036-3322-b628-ea13f8404c7b.png)

# AWSのBeanstalkに手動でデプロイする（初回だけ）
自動デプロイのターゲットとなるElastic Beanstalkアプリケーションを作成します。
手順は以下の通り。

1. AWSコンソールからElastic Beanstalkの「新しいアプリケーションの作成」を選択。
   ![スクリーンショット 2020-05-01 3.34.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/3e753e64-95b1-68b7-c3d6-5db976345cd3.png)

2. 続けて「新しい環境の作成」を押下し、「ウェブサーバー環境」を選択。
   ![スクリーンショット 2020-05-01 3.39.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/78e63a39-fdc3-7d8d-614c-8297290c3272.png)
   ![スクリーンショット 2020-05-01 3.41.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/6c1beea7-f933-81e9-bc50-5d5e3d534518.png)

3. 環境情報ページにて以下を実施。
    - プラットフォーム
        - Java を選択（ブランチとバージョンは自動で選択される）
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/9caccccf-ad63-6590-704b-8b1ddabf11c4.png)
    - アプリケーションコード
        - コードのアップロード を選択して、ビルドしたjarファイル(demo-0.0.1-SNAPSHOT.jar)を選択
   ![スクリーンショット 2020-05-01 3.50.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/d9221083-33fd-9b11-f934-b71304e80aba.png)
    - 「環境の作成」ボタンを押下する。
   ![スクリーンショット 2020-05-01 3.54.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/a3f24f8f-84c1-5a78-b60f-7ddbe2cfbeb7.png)

4. しばらく待ち、ヘルスOKとなるまで待つ。
   ![スクリーンショット 2020-05-01 4.11.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/f6028f3b-b0d5-d79d-6be2-449d685c11cb.png)
   なお、ここで作成したアプリ名と環境名は、後の workflow のActionの設定で必要になります。
       - アプリケーション名：demo-app
       - 環境名：DemoApp-env

5. 「DemoApp-env...elasticbeanstalk.com」をクリックし、末尾に「/demo」を加えてアクセスして問題なければ初回デプロイが完了。
   ![スクリーンショット 2020-05-01 4.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/a448df48-1a95-5eb6-4369-3667b7682bdc.png)

# GithubActionsの workflow をymlで書く
先ほど作成したdemoプロジェクトをGithubにコミット＆プッシュしてリポジトリを作成し、いよいよ GithubActions の workflow の作成を行います。

workflow は 

- YAML形式で記述する(ファイル名は任意)
- `.github/workflows` ディレクトリ内に置く(複数配置可)

ことで実行できるようになります。
今回は、先ほど手動で行なった

- executableJar のビルド
- Elastic Beanstalk へのデプロイ

を自動化する workflow を書いてみます。

#### 雛形を参考にしてみる
GithubActions では公式／非公式問わず workflow の雛形が多数公開されており、
今回使いたい `./gradlew build` も公式にあるので、これを使ってみます。

1. ブラウザからgithubのリポジトリを表示し、「Acitons」タブを選択する。
   ![スクリーンショット 2020-05-01 4.48.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/01c16a77-ea50-ad88-8944-f08cb504bbfe.png)
2. Get started with...　の一覧から「Java with Gradle」の「Set up this workflow」を押下する。
   ![スクリーンショット 2020-05-01 4.50.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/aca0d019-9667-4a02-ccb9-9b3da5d4d93c.png)
3. workflow の yaml の 雛形が表示されるのでこのまま作成（ `Start commit` ボタン）してもよいし、コピペして自分で `.github/workflows/` の下に `hoge.yml` ファイルを作成して貼り付けてもよいです。
   ![スクリーンショット 2020-05-01 5.04.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/c970d9ee-3eb8-f0ba-960b-cd8314de266f.png)
   上記の steps では大まかに以下のことを行なっています。
   
   - uses: actions/checkout@v2 ... 安定板のチェックアウトActionを利用
   - uses: actions/setup-java@v1 ... Javaをセットアップ(with:でバージョンを指定)
   - run: chmod +x gradlew ... gradlewに実行可能属性を追加
   - run: ./gradlew build ... jarをビルド

ここまででjarのビルドが行えます。
次にElastic Beanstalkへのデプロイは、以下のAction（サードパーティ製）を使うと非常に簡単でした。

https://github.com/marketplace/actions/beanstalk-deploy
![スクリーンショット 2020-05-01 5.35.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/99610bf5-540a-fa65-d262-633b880384e3.png)

これを組み込んだ最終的な yaml は以下です。

```yaml:deploy-to-beanstalk.yml
name: deploy to beanstalk

on:
  push:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
      - name: Build with Gradle
        run: ./gradlew build

      - name: deploy
        uses: einaregilsson/beanstalk-deploy@v10
        with:
          aws_access_key: ${{ secrets.AWS_ACCESS_KEY }}
          aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          application_name: demo-app
          environment_name: DemoApp-env
          version_label: ${{ github.run_number }}
          region: ap-northeast-1
          deployment_package: build/libs/demo-0.0.1-SNAPSHOT.jar
```

デプロイに必要なパラメータの `secrets.AWS_ACCESS_KEY` と `secrets.AWS_SECRET_ACCESS_KEY` は、予めAWSで作成したのアクセスキーとシークレットキーをGithubのリポジトリの`Secrets` として登録しておくことで安全に利用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/fa195591-7573-1327-c457-503407198a2d.png)

以上で workflow の作成は完了です。

# pushして自動デプロイを確認
いよいよアプリの自動デプロイを試してみましょう。
せっかくなので、Controllerを一部修正して変更が反映されたことを確認してみます。

```java:DemoController.java

@RestController
public class DemoController {
    @GetMapping("/demo")
    public String demo() {
        return "Hello Github Actions!!"; // 修正
    }
}
```

この変更をコミットして `master` に push して、すぐにGithubのActionsタブをみてると・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/768d996d-3dff-de5d-e77e-dd125b6788c4.png)

workflow が実行されています！
ジョブ名をクリックしてすべての step が正常に完了したことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/0b56206c-ea38-875d-807e-9a183c244adf.png)

最後にBeanstalkのアプリの挙動を確認してみます。
![スクリーンショット 2020-05-01 6.29.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430093/9f4ecafb-fca3-b4eb-e606-046b7d14b276.png)

無事にデプロイされ、変更が反映されていました！

# まとめ
ツールのセットアップなど不要で、すぐにCI/CDを行える！お手軽すぎる！！

# 参考
いざ workflow 書いてみようかな、という時に以下がとても参考になりました。
[Github Actionsの使い方メモ](https://qiita.com/HeRo/items/935d5e268208d411ab5a)