SpringBoot + GradleのプロジェクトのCIをGitHub Actions + Dockerで回してみる

## はじめに

Spring Boot + GradleのプロジェクトのCIをGitHub Action + Dockerで回してみる。
下のページを参考にした。

https://help.github.com/ja/actions/building-actions/creating-a-docker-container-action

<追記>
こちらのドキュメントのやり方が良いケースもあるかもしれませんが、
あまり効率的ではなく、手順も多いので、改めてこちらの記事で別の方法を試しています。

https://qiita.com/shavada/items/d3a76b1d1cb59c848d98

## Dockerコンテナを選ぶ

今回はAmazon CorretoのDockerイメージを使う。 
下のページでどのイメージを使用するか選択する。
ここでは`11.0.7`のイメージを使用する。

https://hub.docker.com/_/amazoncorretto?tab=tags

## ワークフローを定義

メインのワークフロー定義ファイルは、下のような感じ。
ここにはDockerの情報は出てこないが、後ほど`./.github/workflows/build/`の各ファイルで設定する。

1. リポジトリからソースコードをチェックアウト
2. Dockerコンテナ内でテスト&ビルド
3. ビルドで出来たアーティファクトをアップロード
4. テストリポートをアップロード

```yml:./workflow.yml
name: SpringBoot CI with Gradle

on:
  push:
    branches: [ master ]

jobs:
  test-build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Test and Build with Gradle
        uses: ./.github/workflows/build/
      - name: Archive production artifacts
        uses: actions/upload-artifact@v2
        with:
          name: demo.zip
          path: build/libs/demo-0.0.1-SNAPSHOT.jar
      - name: Archive test reports
        uses: actions/upload-artifact@v2
        with:
          name: test-reports.zip
          path: build/reports/tests/test
```

### 専用のディレクトリを掘る

ビルドの具体的なコマンドはメインの`workflow.yml`には書かない。
ビルドアクション専用のディレクトリを作成し、そこに下記のようなファイルを配置する。

```
.github
└── workflows
    ├── build
    │   ├── Dockerfile
    │   ├── action.yml
    │   └── entrypoint.sh
    └── workflow.yml
```

### Dockerfileを作成する

下のようなDockerfileを作成する。
DockerHubからAmazon Corretoのイメージをプルし、コンテナ起動時に`entrypoint.sh`を実行するという簡単なもの。

```Docker:./build/Dockerfile
FROM amazoncorretto:11.0.7
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
```

### 起動時に実行されるスクリプト

`entrypoint.sh`にビルドコマンドを書く。
`gradlew`に実行のパーミッションが付いていないことがあるので、`chmod`で実行できるようにする。

```sh:./build/entrypoint.sh
#!/bin/sh -l

chmod +x gradlew
./gradlew build
```

### アクション定義ファイル

ymlファイルに下のように書く。
先ほど書いたDockerfileを使うように指定する。
`./build/action.yml`は`workflow.yml`から参照される。

```yml:./build/action.yml
name: 'build'
description: 'build'
runs:
  using: 'docker'
  image: 'Dockerfile'
```


## プッシュする

プッシュすると、ビルドが成功し、生成物がダウンロード可能になる。

ログを見ると、ホストの仮想マシンの`/home/runner/work/{repository-name}/{repository-name}`がコンテナの`/github/workspace`にマウントされていることがわかる。

コンテナで作られた生成物がそのまま仮想マシンのファイルシステムに永続化されている。

```
Run ./.github/workflows/build/
Dockerfile for action: '/home/runner/work/spring-gradle-action/spring-gradle-action/./.github/workflows/build/Dockerfile'.
/usr/bin/docker build -t c27d31:e779a38f78ba5c273eb184ff73d88906 "/home/runner/work/spring-gradle-action/spring-gradle-action/.github/workflows/build"
Sending build context to Docker daemon  4.096kB

Step 1/3 : FROM amazoncorretto:11.0.7
 ---> dcce9e8293ec
Step 2/3 : COPY entrypoint.sh /entrypoint.sh
 ---> a2d22490e03e
Step 3/3 : ENTRYPOINT ["/entrypoint.sh"]
 ---> Running in be12839e2113
Removing intermediate container be12839e2113
 ---> dda1009a1a84
Successfully built dda1009a1a84
Successfully tagged c27d31:e779a38f78ba5c273eb184ff73d88906
/usr/bin/docker run --name c27d31e779a38f78ba5c273eb184ff73d88906_0c4942 --label c27d31 --workdir /github/workspace --rm -e HOME -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_ACTOR -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e RUNNER_OS -e RUNNER_TOOL_CACHE -e RUNNER_TEMP -e RUNNER_WORKSPACE -e ACTIONS_RUNTIME_URL -e ACTIONS_RUNTIME_TOKEN -e ACTIONS_CACHE_URL -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/spring-gradle-action/spring-gradle-action":"/github/workspace" c27d31:e779a38f78ba5c273eb184ff73d88906
Downloading https://services.gradle.org/distributions/gradle-6.3-bin.zip
.........10%..........20%..........30%.........40%..........50%..........60%.........70%..........80%..........90%..........100%

Welcome to Gradle 6.3!

Here are the highlights of this release:
 - Java 14 support
 - Improved error messages for unexpected failures

For more details see https://docs.gradle.org/6.3/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :bootJar
> Task :jar SKIPPED
> Task :assemble
> Task :compileTestJava UP-TO-DATE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test UP-TO-DATE
> Task :check UP-TO-DATE
> Task :build

BUILD SUCCESSFUL in 22s
5 actionable tasks: 1 executed, 4 up-to-date
```

## おわりに

ステップ間でコンテナを共有したいとか、パブリックイメージではなく自前のイメージを使いたいとか
いろいろとやりたいことが出てくると思うが、ひとまずざっくりした流れだけ追ってみた。