こんにちは、小幡です。
本日はGithub Actionsを使ったCI/CDについての備忘録です。
実務ではありませんが、個人サービス開発で行っている実際のCI/CDの状況も交えながら記載します。
そもそものCI/CDを実践しようとした背景には、以前記事にした『エクストリームプログラミング』の考えが強く影響していますので、そちらの記事も参考にしてください。
そして『Clean Agile 基本に立ち戻れ』も強く影響しています。
この中では、継続的な改善にも触れました。
自分自身への備忘録的な記事なので、検証を行っていないところや、間違いもあると思いますのでご注意ください。
小さいことを短期間で改善する
まず前提として、今回は個人開発での活用ですので、本来であれば自分で好きな様にリリースタイミングや、リリース内容が決められますので、そんなにプロジェクトの進行について気にする必要はありませんでしたが、これまで実際にCI/CDを導入から活用までを一人で行ったことがありませんでしたので、やってみることにしました。
そして上でもあげたように、よりアジャイル開発を意識したイメージで、継続的な改善を短い期間で実践することを意識しました。
サイト自体の更新頻度を高めることで、ユーザの注目度が高まることや、運営側の早い対応を確認してもらうことで、信頼感も高まれば良いと期待しているところもあります。
リリース回数が多くなれば、その分のリスクも増えるかもしれませんが、それはやってみてから考えることにします。これは以前の記事でインフラについて再度学びなおした環境があるので、こちらを使って進めていきます。
ちなみに利用者数はあまり多くない見込みなので、EC2インスタンス1つで運用していますが、それでも1月に利用料を支払うのはサーバレスでサービス開発していた身からすると少し気が引けましたが、自己投資だと割り切ります。
CI(継続的インテグレーション)
CIとは何か?CDとは何か?については、以前紹介した書籍を参考にしていただきたいですが、自分なりの理解は以下の通りです。
CI (Continuous Integration) は、日本語で「継続的インテグレーション(統合)」なので、今回の場合は主にGitでのコードを管理をする際に、継続的にコードが統合されることを指すと考えています。
ウォーターフォール開発では、それぞれの開発者がローカルで開発したコードを長期的に所持しており、一定のタイミングでプッシュとマージが行われている印象です。
これには古い慣習や、当時のコードを統合することの難しさなどが起因することだと思いますが、Githubなどを使えば、とても簡単にマージまでを行うことができます。
ブランチ管理
もちろんmaster(main)ブランチからどのようにブランチを切り出して、どのように運用していき、最終的にはどのようにマージしていくかについては、多数の手法があると思いますが、ここでも私はシンプルさを重視して、git-flowのmaster-develop-featureの切り方で進めています。
またこの切り出し方をするためには、それぞれ開発するファイルについてもコンフリクトが起きないように構成をあらかじめ決めておくことが必要です。
例えば、1つの巨大なCSSファイルに全てを記述している場合、すぐにコンフリクトが起きることは簡単に想像できると思います。ではチームごとにCSSファイルを分割するのが良いのか?そういった設計は慎重に進めていかなければなりません。
ビルド管理
基本的にはPythonでの開発をしているのでコードのビルドは実施しません。
今回のサービス開発の場合、多言語対応する際に、各言語への変換はビルド実行が必要となりました。なので、ブランチにプッシュする前に、ビルドを実行し多言語対応用のファイルが作成されるようにしています。
最初のころは、このビルドをプッシュ後にも実行するように設定してしまい、ローカルとリモートの差異が生まれてしまいコンフリクトを起こしてしまう事故もありましたが、これもまたいい経験でした。
どのタイミングでビルドを実行するか、あるいはビルドした成果物についての管理方法についても慎重に検討しておくことが必要だと学びました。
テスト管理
そしてブランチ管理が一通り終わり、マージが機能していくと、その先にはテストが控えています。
マージされたコードに対して継続的にテストを実施することで、品質を保証と開発者の心理的安全性が確保されます。
マージ完了した都に自動でテストを実施するのはGithub Actionsの設定ファイルに記述すれば容易に実行可能です。
しかしながら、1つの開発に対してテストコードが作成されているかについて監視する方法がまだ決められていません。開発者全員が同じ思想のもとテスト駆動開発を実践できていれば心配することはありませんが、基本的に開発が理想通りうまくいくことはありません。
そういった意味でもペアプログラミングをしてお互いがお互いのテストコードについて確認しながら作業を進めていける環境づくりが大切なのかもしれないと改めて感じました。これはGitにPull Requestが作成されたときにレビューをすることでもある程度は品質が担保されるかもしれませんが、Pull Requestが作成された後から指摘されるときの精神的な辛さを考えると、やはりペアプログラミングも実践の価値が高いと考えています。
そもそも開発者のモチベーションなどの管理も含めて単純にCI/CDの実践だけでなくアジャイル開発、スクラムの導入など、人と人とのコミュニケーション手法にも関わるところだなと感じています。
CD(継続的デリバリー / 継続的デプロイ)
継続的デリバリー / 継続的デプロイこの2つがとても重要です。リリースされ、ユーザに成果物が提供されなければ、そのコードには価値がうまれません。
Gitでのコードの統合、自動のビルド、テストの自動実行で全てがグリーンとなれば、次はこれらをユーザに届ける作業です。
これもGithub Actionsにどのようにデプロイするかを記載するだけで全てうまく行きます。簡単ですね。
実際に使用している設定ファイルの一部抜粋を以下に掲載します。
name: CI and CD
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master", "develop" ]
jobs:
# --- 1. テストを実行するジョブ ---
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11' # あなたのPythonバージョン
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r ./django/requirements.txt
- name: Run Tests
run: |
python ./django/manage.py test
# --- 2. デプロイを実行するジョブ ---
deploy:
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
steps:
- name: Checkout
uses: actions/checkout@v4
# EC2にSSHで接続してデプロイを実行
- name: Deploy to EC2 via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
# 以下省略
ここで重要なところは以下です。
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
このif条件でPushかつターゲットがmasterの場合のみ、デプロイをすることができます。
developへのpull requestなどではテストを実施することは、もちろんですがこの時はデプロイはしません。
上記条件になったときに最終的なデプロイが実施されるので、必要以上にテストが実行されているように感じますが、テストは予想外の時に失敗するものです。
Github Actionsの実行結果
Github Actionsのの実行結果は以下のように表示されます。

左側にはjobsが一覧化されており、今回の場合は、testのジョブとdeployのジョブでわかれていることがわかります。
deployのジョブではそれぞれ実施された内容を確認できます。
ここで注意したいのは、明らかなテストのNGなどでは失敗となりデプロイは中止となりますが、deployに設定しているgit pullなどでデプロイ先に変更点があり、プルが失敗する場合などはデプロイ中止とならないことがあることです。
ログを確認するとerrorの表示が出ているのですが、正常終了となってしまうパターンもあるようなので、しっかりと最終的には自分の目でデプロイが正常終了しているかを確認した方が良いです。
まとめ
以上でCI/CDについて備忘録は終わりです。
上にあげた設定ファイルではまだまだ不足の部分もあり、このファイルの継続的な改善はもちろん必要ですが、これまで手動でデプロイ作業を行っていたところから見れば、ものすごい作業の効率化が実現でてきると感じます。
CI/CDが理想的な状態で常に正常動作できていれば、プロジェクトメンバーに単体試験の結果について報告を求めたり、リリース管理について記録を取ってもらったりなど、手動での作業がほとんど必要なくなります。素晴らしいですね
テストの実施についての箇所でも触れましたが、CI/CDは単独で全てを達成できることではなく、プロジェクト全体の動きに合わせて柔軟に適応させることが必要だと感じています。そもそも単体試験も自動化できないような状況も多数見られますので、まずはそのような所から少しずつ改善が必要なことも忘れてはいけないと感じています。
以上です。



