はじめに
GitHub ActionsでCI/CDパイプラインを構築する際に、デプロイ時のデータ転送がうまくいかずにハマったので、解消方法を残しておきます。
備考
おそらくあまり環境に依存しない内容だと思いますが、以下を使用しています
- Java21とSpringBoot3を使用したアプリケーションを開発
- AWSのEC2にデプロイ
やりたいこと
CI/CDパイプラインとして以下の挙動を実現したい
- プルリクエスト作成時にはCIとして自動テストを走らせる
- マージ後にはCDとしてデプロイする
変更前の状態
以下のような設定をしていたため、プルリクエスト作成時にデプロイされてしまっていました
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
EC2_USER: 'ec2-user'
EC2_HOST: 'hogehoge'
SRC_PATH: 'build/libs/*.jar'
DEST_PATH: '/home/ec2-user/portfolio-student-management.jar'
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Test with Gradle Wrapper
run: ./gradlew test
- name: Build with Gradle Wrapper
run: ./gradlew bootJar
# 以下がそのまま動くため、プルリク時にデプロイされてしまう
- name: SCP Copy Application to EC2
env:
PRIVATE_KEY: ${{ secrets.AWS_EC2_PRIVATE_KEY }}
run: |
echo "$PRIVATE_KEY" > private_key && chmod 600 private_key
scp -o StrictHostKeyChecking=no -i private_key $SRC_PATH $EC2_USER@$EC2_HOST:$DEST_PATH
- name: SSH Application Deploy
uses: appleboy/ssh-action@master
with:
host: ${{ env.EC2_HOST }}
username: ${{ env.EC2_USER }}
key: ${{ secrets.AWS_EC2_PRIVATE_KEY }}
envs: DEST_PATH
script: |
sudo yum update -y
if sudo systemctl status portfolio-student-management 2>&1 | grep "Active: active (running)" ; then
sudo systemctl restart portfolio-student-management
else
sudo systemctl start portfolio-student-management
変更後の状態(エラーあり)
以下のようにjobをbuild-and-test
とdeploy
に分けたところ、エラーが発生するようになりました
.
.
.
# ジョブを分ける
jobs:
build-and-test:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
- name: Setup Gradle
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Test with Gradle Wrapper
run: ./gradlew test
- name: Build with Gradle Wrapper
run: ./gradlew bootJar
# ここまでは動く
deploy:
if: github.event_name == 'push'
runs-on: ubuntu-latest
needs: build-and-test
steps:
# 以下で落ちる
- name: SCP Copy Application to EC2
env:
PRIVATE_KEY: ${{ secrets.AWS_EC2_PRIVATE_KEY }}
run: |
echo "$PRIVATE_KEY" > private_key && chmod 600 private_key
scp -o StrictHostKeyChecking=no -i private_key $SRC_PATH $EC2_USER@$EC2_HOST:$DEST_PATH
.
.
.
エラー内容
scp: stat local "build/libs/*.jar": No such file or directory
Error: Process completed with exit code 255.
原因
- GitHub Actionsの仕様上、異なるjobは独立した仮想環境で実行される
-
build-and-test
とdeploy
は別のマシンで動いているということ - つまり、
build-and-test
で作成したファイルは、deploy
に引き継がれない
-
解決策
-
actions/upload-artifact
とactions/download-artifact
を使用する -
actions/download-artifact
の保存先はディレクトリは$GITHUB_WORKSPACE
で取得可能なため、$GITHUB_WORKSPACE
を利用して送信元ファイルを特定する
.
.
.
build-and-test:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
.
.
.
- name: Build with Gradle Wrapper
run: ./gradlew bootJar
# 作成したjarファイルをアップロード
- name: Upload Build Artifact
uses: actions/upload-artifact@v3
with:
name: built-jar
path: build/libs/*.jar
deploy:
if: github.event_name == 'push'
runs-on: ubuntu-latest
needs: build-and-test
steps:
# アップロードしたファイルをダウンロード
- name: Download Build Artifact
uses: actions/download-artifact@v3
with:
name: built-jar
# $GITHUB_WORKSPACEを使用して送り元ファイルを特定
- name: SCP Copy Application to EC2
env:
PRIVATE_KEY: ${{ secrets.AWS_EC2_PRIVATE_KEY }}
run: |
echo "$PRIVATE_KEY" > private_key && chmod 600 private_key
scp -o StrictHostKeyChecking=no -i private_key $GITHUB_WORKSPACE/*.jar $EC2_USER@$EC2_HOST:$DEST_PATH
おわりに
自身の使っているchatGPTでは初動でうまく解消できませんでしたが、最初の状態でデプロイができていたことをヒントにGitHub Actionsの仕様を疑うことで比較的早めに解消できました。
CDのテストのために何回かGitHub上でPR->マージを繰り返してしまったので、GitHubが汚れてしまったのが少し残念…
マージしなくても挙動のテストをする方法を調べてみようと思います…