GitHub Actionを使ってCI/CDについて考えてみた

普段はSFTPを使っていてファイルをアップすることが多い僕でございますが、人間考え方がちょっとずつ変わったりもします。今作っているWEBサイトでは以下のようにしてます

現在の仕組み

  • ソースコード管理:GitHub
  • 本番適用:CICD

githubにソースコードをプッシュすると、自動で適用されるという事になります。そのためSFTPでファイルアップとか、FTPによるファイルアップというのが不要となっております。この辺りは楽かなと思います。

そもそもなぜCI/CDをやろうと思ったのか

極論ですが、個人のWEBサイトなのでソース管理だけで考えればSFTPとかFTPでも充分と言えば充分でございます。無理にGitHub Actionを使う必要性はないと思います。yml書いたりしないといけないのもあります
※AI使えばすぐなのでこの辺りは楽ですが、それでも多少の知識が必要になったりします。

きっかけはお金がない

開発はWindowsでやってますが、Macでも修正するかもしれないと頭の中で思いました。そこでSFTPとかでもよいかと思いましたが、残念ながら僕にはMacの有料版のFTPソフトを更新するお金(年間数千円)を支出する余裕がありませんでした。

当然新規にサーバーを契約できるということもないので、ドメイン代だけ捻出をして、後はどれだけお金をかけないかがとても重要になりました。考えた結果、以下のようになりました

  1. SFTPでファイルアップ→お金がなくてMacではできないので無し
  2. Githubでソースコード管理→採用
  3. GithubAction使ってファイルをおくればいいんじゃないか

となりました。こうすればSFTPの費用を捻出しなくても自動でサーバーにファイルをアップすることができます。

技術的な向上

どうせgithub使うなら、技術的な向上も視野にいれてみようと思いました。お金かけないで技術的な向上もついでにしてみるかという感じもあります。

楽したい

僕が新しい技術を取得するための一番の目的でもあります「楽したい」。これもあります。githubを使うことのどこが楽なのか?とありますが、実際にSFTPを使わなくて済むというのはとても楽であり、ストレス減ります。

  • プッシュするだけでファイルが反映される
  • ヒューマンエラーが減る(ファイルアップの誤操作など)

フレームワークによってはファイルのアップするのにディレクトリが異なったりなどします。自分でファイルをアップルするとなると、間違って別の場所にアップしてしまうなどのヒューマンエラーが発生する可能性があります。こうなったときはちょっと面倒です。

githubactionを使うことにより、ヒューマンエラーがほぼ減ります。基本的にリポジトリにプッシュをして後は待つだけになります。SFTPよりも楽です。

CI/CDのためのymlファイル

name: Deploy Laravel

on:
push:
branches:
- deploy # deployブランチへのプッシュ時に実行

jobs:
deploy:
runs-on: ubuntu-latest # GitHub Actionsが実行される仮想環境

steps:
- name: Checkout code
uses: actions/checkout@v4 # リポジトリのコードをチェックアウト

- name: github環境にてPHPの準備
uses: shivammathur/setup-php@v2
with:
php-version: '8.3' # あなたのLaravelが動作するPHPバージョンに合わせる
extensions: mbstring, pdo_mysql, dom, gd, curl # Laravelに必要な拡張機能

- name: Install Composer dependencies
run: composer install --no-dev --prefer-dist # 本番環境用に依存関係をインストール

- name: Create .env file
run: |
echo "APP_NAME='Laravel'" >> .env
echo "APP_ENV=production" >> .env
echo "APP_KEY=${{ secrets.APP_KEY }}" >> .env # APP_KEYをSecretsから取得
echo "DB_CONNECTION=mysql" >> .env
echo "DB_HOST=${{ secrets.DB_HOST }}" >> .env
echo "DB_PORT=${{ secrets.DB_PORT }}" >> .env
echo "DB_DATABASE=${{ secrets.DB_DATABASE }}" >> .env
echo "DB_USERNAME=${{ secrets.DB_USERNAME }}" >> .env
echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> .env

- name: Generate Laravel application key (if not already in .env)
run: php artisan key:generate --ansi # APP_KEYが.envにない場合のみ

- name: Install Node.js dependencies
uses: actions/setup-node@v4
with:
node-version: '20' # あなたのNode.jsバージョンに合わせる

- name: Compile assets
run: npm install && npm run build # ViteやMixを使っている場合

# SSH秘密鍵を準備してrsyncでファイル転送
- name: Deploy files with rsync
run: |
# SSH秘密鍵をファイルに保存
echo "${{ secrets.SSH_PRIVATE_KEY }}" > private_key
chmod 600 private_key

# rsyncでファイル転送
rsync -avz --delete -e "ssh -i private_key -o StrictHostKeyChecking=no" \
--exclude='.git/' \
--exclude='.github/' \
--exclude='private_key' \
--exclude='storage/' \
--exclude='bootstrap/cache/' \
. ${{ secrets.USER }}@${{ secrets.CLOUD_HOST }}:/var/vhost/quickcost/html/cloudcost/

# 秘密鍵ファイルを削除
rm private_key

# デプロイ後の処理
- name: デプロイ後の処理-キャッシュクリア、マイグレーション、ミドルウェアの再起動
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.CLOUD_HOST }}
username: ${{ secrets.USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
DEPLOY_PATH="/var/vhost/quickcost/html/cloudcost/"

echo "Executing post-deployment commands in ${DEPLOY_PATH}"

cd ${DEPLOY_PATH}

# キャッシュクリア
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

# マイグレーション実行 (本番環境での自動マイグレーションは慎重に)
# php artisan migrate --force

# パーミッション設定(Webサーバーがアクセスできるように)
sudo chown -R alma:nobody ${DEPLOY_PATH}storage ${DEPLOY_PATH}bootstrap/cache
sudo chmod -R 775 ${DEPLOY_PATH}storage ${DEPLOY_PATH}bootstrap/cache

# ミドルウェアの再起動を実施
sudo systemctl restart アプリケーション名

echo "Deployment completed successfully!"

これがymlになります。

SFTPと同じで22番ポート接続

別途設定は必要ですが、ホスト名とユーザー名などを設定することでできます。CI/CDでも22番ポートをつかっているので、SFTPで接続しているのとあまり変わらないです。ただ自動でやってくれるのは凄い楽です

rsyncで同期している

今回のymlではrsyncを使ってデータの同期をしてます。今回のymlもAIに聞いたところ差分同期になっているみたいです。手動で毎回接続するよりは楽です

同期の手順

同期の手順としては、基本的に以下のようになってます

  1. ファイルをpush
  2. GitHub側で検知
  3. Actionで設定をしたコマンドが走る
  4. 順番に作業をし、rsyncで差分同期
  5. 終了

1番のpushは自分でやりますが、それ以降は全て自動化となります。時間に関しては僕のサイトではpushして検知してから終わるまでが大体60秒ぐらいですが、準備とかそういうのを考えるとpushしてから2分ぐらい反映までにはかかるかなという印象です。

同期は遅い?SFTPのほうが速い?

これに関してはなんとも言えません。確かに自動化という点では待つというだけなのでよいですが、pushしてから2分ぐらいはまたないと反映されないというのは若干うーんといううとこもあります。ただ手動でアップした場合は2分で終わるのか?というとそんなこともないです。

このあたりを考慮すると、CICDって一度設定すれば楽だなって思います。課題がないか?といえばそんなこともないです

CI/CDの課題

ここでは個人的に思う課題面をだしてみたいなと思います。ただ、これは個人プロジェクトでやっているので、チーム面とかでは関係ないかもしれません。

ブランチの注意

今回はdeployというブランチにpushしたら、CICDが走るようにしてます。例えば本番がmainのリポジトリだと残念ながらCICDは動きません。個人でブランチ切ってそこにアップしているだけをしていると、何も反映されないということになります。CICD動かすならブランチは必ず確認する必要があります。

deploy成功、失敗など通知がこない

ymlを見るとわかりますが、deployに失敗してもどこかに通知がいくわけではないです。僕の場合は自分でリポジトリに設定をしているので、GitHubにアクセスすればdeployが成功しているか失敗しているか確認とれますが、例えばGitHubへのアクセスはできるけどリポジトリは見られないとか、pushのみしかできないなどなんらかの事情でGitHub見れない場合は 成功 or 失敗 がわかりません。メールやSlackでもいいので別途通知設定が必要になります

いつ反映されるかわからない

上の成功、失敗と同じですが更新したとこが反映されるタイミングというのがつかみづらいです。プッシュしたけど反映されてないぞ?あれ?って思ってキャッシュクリアしても反映されないぞっていうのがあります。この時はさすがに困るかなと思います。運用手順でなんとかするしかない・・?

タイムスタンプが書き換わる

差分同期といってますが、実態は全てのファイルを削除→アップとなっております。そのためSFTPで接続すると全てのファイルの時刻は同じになってます。CICDを採用しているのでわざわざSFTPなどで繋いでファイルの確認をするということは希だとは思いますが、こんな事もありますよというこで・・

※これはymlの書き方次第でおそらくなんとかなると思います。設定を差分同期だけにしぼれば、タイムスタンプも変わる事は無いと思います。運用と相談かなと。僕のプロジェクトでは気にしないのでこのymlにしているということになります。

個人支援・寄付について

サイトラボでは個人支援・寄付を受けております。ご協力いただける方はお願いいたします。当サイトではビットコインで受け付けております。

  • ビットコイン:3LHnADwZwUbic2L45EnVJEykiG6KfbqrwS