GithubActionsでMaven/SpringBootアプリケーションをHerokuにデプロイする
『俺の妹がこんなに可愛いわけがない』みたいに長いタイトルになってしまい、申し訳ございません。
GitHubActionsというのを体験してみたいと思います。
これはとんでもないActionの集合ということらしいです。
以下のことを行ってギャラクシーを体感します。
とても大事な所を太字で書いています。
- Mavenでプロジェクトを作成する
- IntelliJで開く
- コントローラーを作成する
- アプリケーションをテストする
- アプリケーションを実行する
- Procfileの作成
- system.propertiesの作成
mvn installの実施.gitignoreの修正- herokuで新規アプリを作成する
- GitHubActionsを設定する
- アプリケーションを確認する
Mavenでプロジェクトを作成する
サイト"Spring Initializr"でプロジェクトを作成します。
以下のようにMavenとJarをチェックした状態にして、右側の依存モジュールには、lombokとSpringWebを指定します。
任意のフォルダに解凍します。
IntelliJで開く
Openから先ほど解凍したプロジェクトを選択して開きます。
時間かかります。
コントローラーを作成する
超簡単なモデルとコントローラーを作成してアプリケーションを実行してみます。
モデル
package com.example.demo;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class Hasira {
private String name;
public String getInfo(){
return this.name + " : sama";
}
}
コントローラー
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SampleController {
@GetMapping("/sample")
public String sample(){
Hasira hasira = new Hasira("uzui");
return hasira.getInfo();
}
}
lombokについて
設定(File>Setting)からプラグインのlombokを有効化しておきます。
ここでIntelliJをプロジェクトを閉じて再度開きます。
アプリケーションをテストする
コントローラーのテストコードを書いておきます。
package com.example.demo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
public class SampleControllerTest {
private MockMvc mock;
@BeforeEach
public void prepare(){
this.mock = MockMvcBuilders.standaloneSetup(new SampleController()).build();
}
@Test
public void test_sample() throws Exception {
System.out.println("----テストの開始----");
this.mock.perform(MockMvcRequestBuilders.get("/sample"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("uzui : sama"));
System.out.println("----テストの終了----");
}
}
ターミナルから以下のコマンドを実施します
mvn test
成功ログが出ればOKです
----テストの開始----
----テストの終了----
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.067 s - in com.example.demo.SampleControllerTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.029 s
[INFO] Finished at: 2022-01-31T17:34:38+09:00
[INFO] ------------------------------------------------------------------------
アプリケーションを実行する
ターミナルから以下コマンドを実施
mvn spring-boot:run
にアクセスする
Procfileの作成
重要シリーズ第一弾です。
プロジェクトのルートにProcfileという名前のファイルを作成します。
そして以下の内容を記載します
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
これはアプリケーションがtarget/demo-0.0.1-SNAPSHOT.jarを見るということ意味しています。
system.propertiesの作成
重要シリーズ第二弾です。
プロジェクトのルートにsystem.propertiesという名前のファイルを作成します。
そして以下の内容を記載します
java.runtime.version=11
Javaのバージョンを指定しています。これがないとherokuでbuildエラーになります。(なることがあります)
↓こんなエラーです
Error: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project demo: Fatal error compiling: invalid target release: 11 -> [Help 1]
Error: [ERROR]
Error: [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
Error: [ERROR] Re-run Maven using the -X switch to enable full debug logging.
Error: [ERROR]
Error: [ERROR] For more information about the errors and possible solutions, please read the following articles:
Error: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
mvn installの実施
※後に解説をしますが、githubactionsでパッケージングを行うので、ここでは必須の処理ではありませんでした。
重要シリーズ第三弾です。
mvn installを行ってtargetフォルダにjarファイルを出力します。
先ほどもProcfileで書きましたがjarファイルが必要になります。
.gitignoreの修正
※後に解説をしますが、githubactionsでパッケージングを行うので、ここでは必須の処理ではありませんでした。
重要シリーズ第四弾です。
.gitignoreというのはステージング対象からも除外する、githubにcommitの対象から外すものをリスト化したファイルです。
実はtargetフォルダはこの対象になっているので、せめて先ほど作ったjarファイルだけは除外してあげる必要があります。
- target/
+ target/*
+ !target/*.jar
herokuで新規アプリを作成する
ここからようやくherokuが出現します。
きっとherokuは大掛かりなことをするのでしょう。まずはアプリケーションを作成します。
適当な名前をつけてcreate appします。
GitHubActionsを設定する
githubの適当な新規リポジトリにSpringbootアプリケーションをpushします。ブランチ名はmainにしておいてください。
シークレットの登録をする
pushしたらリポジトリのSettingsから左メニューのSecretsのActionsをクリックします。
そしてNew repository secretボタンを押して
- HEROKU_API_KEY
- HEROKU_EMAIL
- HEROKU_APP
それぞれ作成します。
HEROKU_API_KEYはherokuのAccount Settingsから確認できるAPI Keyです。
HEROKU_EMAILはherokuに登録しているメールアドレスです。
HEROKU_APPは、先ほど作成したherokuのアプリケーション名です。
全て作成すると以下のように表示されます
Actionの設定をする
GithubのリポジトリページからActionsをクリックする
Java With Mavenを選択します
するとワークフローを定義しているymlファイルが作成されます。
ここでherokuに対してデプロイ作業を行うなどの記載をすることになります。
右側のMarketplaceからDeploy to Herokuをクリックします。
そうすると使い方(コード)が表示されます。AkhileshNS/heroku-deployというActionを利用することでデプロイします。そして先ほど登録したAPI_KEYなどはここで使うために定義していました。また直接このファイルに定義するのはセキュリティ上よろしくないということで、secretsという形で埋め込んで利用します。
ファイルを以下のように修正したら、StartCommitからCommitします。
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Java CI with Maven
on:
push:
branches: [ main ]
- pull_request:
- branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn -B package --file pom.xml
+ - name: Test With Maven
+ run: mvn test
+ - name: Deploy to Heroku
+ uses: AkhileshNS/heroku-deploy@v3.12.12
+ with:
+ heroku_api_key: ${{secrets.HEROKU_API_KEY}}
+ heroku_email: ${{secrets.HEROKU_EMAIL}}
+ heroku_app_name: ${{secrets.HEROKU_APP}}
mainブランチにpushした時をトリガーにしてこのファイルに定義しているActionが実行されます。
on:
push:
branches: [ main ]
Actionを実行する環境はubuntuを使っています
runs-on: ubuntu-latest
リポジトリをチェックアウトしてワークフローがアクセスできるようにします。
usesというのが利用するActionです。
steps:
- uses: actions/checkout@v2
パッケージングを行います
runというのはコマンドを記載します。
- name: Build with Maven
run: mvn -B package --file pom.xml
nameはstepを目視できるようになりますし、処理の塊を意味します。
Actionのサマリー画面で以下のように表示されます。
Actionはうまくいくと緑色、失敗すると赤で表示され、それぞれログも見ることができます。
テストも実施されていることが確認できます。
アプリケーションを確認する
herokuの画面からOpen appでアプリケーションを開きます。
今回githubにpushしたアプリケーションが実行されていることが確認できます。
githubactionはymlで書きやすいので、わかりやすいというメリットがあります。
今回はherokuということなので敷居が低いこともありますが、とても簡単にテスト→デプロイまでが出来てしまいました。
Gradleの場合
せっかくなのでGradleの場合もザックリですが試してみます。
Procfileは以下のように記載します。Spring Bootの場合、Procfileは以下のようなものになります。ということらしいです。
web: java -Dserver.port=$PORT $JAVA_OPTS -jar build/libs/damo-0.0.1-SNAPSHOT.jar
gradleの場合はgradle buildコマンドを使ってjarが、build/libsフォルダに出力されます
※前回demoだったのでdamoにしました。
またActionsはJava with Gradleを選択します。
workflowのymlファイルは同じように作成しましたが
以下のようなエラーが発生
Error: Error: Gradle script '/home/runner/work/gradle-heroku-deploy/gradle-heroku-deploy/gradlew' is not executable.
権限を与えてあげると実行できました。
name: Java CI with Gradle
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'temurin'
+ - name: permit Gradle
+ run: chmod +x gradlew
- name: Build with Gradle
uses: gradle/gradle-build-action@bc3340afc5e3cc44f2321809ac090d731c13c514
with:
arguments: build
- name: Deploy to Heroku
uses: AkhileshNS/heroku-deploy@v3.12.12
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_email: ${{secrets.HEROKU_EMAIL}}
heroku_app_name: ${{secrets.HEROKU_APP}}
これでうまくできました。
コードは以下です。(ちょっと修正入ってます)
ちなみに
Command failed: git push heroku HEAD:refs/heads/main --force
このエラーはProcfileとsystem.propertiesが入ってない場合に起きるかもしれません。
実行画面
Discussion