🐧

Linux 使いになりたい人向けの Intel N100 ミニ PC で構築する開発環境(14)- Gitea Act Runner

2024/08/03に公開

はじめに

これは、Linux 使いになりたい人向けに Intel N100 ミニ PC を使って開発環境を構築する方法を解説する記事の第14弾です。第1弾はLinux 使いになりたい人向けの Intel N100 ミニ PC で構築する開発環境(1) - 構築する開発環境について にあり、そこから第2弾へと続いています。そちらからご覧ください。

ここで使用する Intel N100 ミニ PC の仕様は次のものを前提とします。

項目 内容
OS Windows 11 Pro
CPU Intel N100
メモリ 16GB
ストレージ SSD 512 GB
画面出力端子 HDMI×2
WiFi 5G/2.4G
イーサネット RJ45×1
Bluetoot BT4.2
USB USB3.0×2/USB2.0×2

このマシンで最終的に Windows と Ubuntu Desktop が使えるように環境構築することを目指します。zenn.dev を購読している人のレベルを考えると、画面キャプチャはそれほど必要がないと考えているため少なめです。また、説明についても明示しないとわかりにくいと思われるものに絞っているので少なめです。

今回は、Gitea Act Runner を使った CI/CD(Continuous Integration / Continuous Delivery)の環境を構築する方法について説明します。開発環境構築にあたって、バージョン管理システムの Git を使っている場合は、CI/CD についても対応したいはずです。ここでは、Git システム利用時の CI/CD 対応について説明します。

最近、開発環境構築にあたっては、Docker のようなコンテナー技術が必須となっています。本格的な CI/CD 環境でも Docker は必須のものとなっていますから、ここでは Docker が動作する環境を前提とした CI/CD の環境構築について説明します。

インストールするソフトウェア

インストールするソフトウェアは Gitea Act Runner です。これを使って CI/CD 環境を構築します。

ソフトウェア名 公式サイト
Gitea Act Runner https://gitea.com/gitea/act_runner

ここでは、すでに Gitea、WSL Ubuntu が使えるようになっているとして説明します。また、WSL Ubuntu で Docker Engine が動作する環境としておいてください。Windows であれば Docker Desktop をインストールして、WSL と統合しておけば良いです。

CI/CD とは

Git Act Runner を使う前に、CI/CD(Continuous Integration / Continuous Delivery)について簡単に説明しておきます。

CI/CD は、継続的インテグレーション(Continuous Integration) と 継続的デリバリー(Continuous Delivery)の略称です。ソフトウェア開発において、コード変更からリリースまでのプロセスを自動化し、迅速かつ確実に高品質なソフトウェアを提供するための手法や機能を指します。CI/CD を導入することで、ソフトウェア開発の効率化、ソフトウェア品質の向上などのメリットを得られます。

CI/CD 利用のメリット

CI は、開発者がコード変更を頻繁に Git リモートリポジトリーに統合し、自動テストを実行することや、それを実現する機能を指します。この機能を利用することによる主なメリットは次の通りです。

  • コードの品質向上: コード変更を頻繁に統合・テストすることで、問題の早期発見・修正が可能
  • 開発効率の向上: 手動による統合・テスト作業を減らすことで、単純作業による開発リソースの浪費を減少
  • 開発環境の統一: 共通のリポジトリーとテスト環境を使用することで、開発者間の環境差異による問題を排除

CD は、CI でテストされたコードを自動的に本番環境にデプロイすることや、それを実現する機能を指します。この機能を利用することによる主なメリットは次の通りです。

  • リリース時間の短縮: 手動によるデプロイ作業を減らすことで、新しい機能を迅速にユーザーへ提供
  • リリースの信頼性向上: 自動化されたデプロイプロセスにより、手動によるデプロイ作業によるミスやエラーの排除
  • リスクの低減: 段階的なデプロイやロールバック機能などにより、リリースに伴うリスクを低減

CI/CD 環境の実現に必要なもの

CI/CD を実現するにあたり、個人でソフトウェアとその稼働環境を用意するとしたら、次のようなものが候補となります。

ソフトウェア 説明
Jenkins Java で実装されたオープンソースの CI/CD 用ソフトウェア
nectos/act GitHub Actions をローカルで実行できる CI/CD 用ソフトウェア
Gitea Act Runner Gitea で利用できる nectos/act ベースのCI/CD 用ソフトウェア
Forgejo Runner Forgejo で利用できる nectos/act CI/CD 用ソフトウェア
GitLab Runner GitLab で利用できる CI/CD 用ソフトウェア
Gitness Go で実装されたオープンソースの CI/CD 用機能搭載の Git システム用ソフトウェア

どれを利用するのかは、個人で用意した Git システム用ソフトウェアが何かによって変わってきます。有名な Git システム用サービスやソフトウェアは、次のように CI/CD をサポートするための機能を搭載しています。

機能 説明
GitHub Actions GitHub 上で利用できる CI/CD 用機能
GitLab CI/CD GitLab 上で利用できる CI/CD 用機能
Gitea Actions Gitea 上で利用できる CI/CD 用機能
Forgejo Actions Forgejo 上で利用できる CI/CD 用機能
Gitness Pipeline Gitness 上で利用できる CI/CD 用機能
gitbucket-ci-plugin GitBucket 用 CI/CD 用プラグイン

CI/CD のための環境を構築するのは、それなりに大変なので、クラウドサービスでも提供されています。無料枠があるものもあるので、個人で環境構築するのが大変だと感じる場合は、これらを使うこともできます。ただし、公開リポジトリでないと無料で使えなかったり、使用時間やリソースに制限があったりします。ビジネス用途なら有料で利用することも検討できるでしょうが、個人だとそこまではできないことも多いでしょう。

サービス 説明
CircleCI CircleCI が提供するクラウド型の CI/CD 用サービス
Travis CI Travis CI 社が提供するクラウド型の CI/CD 用サービス
Gloud Build Google Cloud Platform の CI/CD 用サービス
Azure DevOps Pipeline Microsoft Azure の CI/CD 用サービス
AWS CodePipeline AWS の CI/CD 用サービス
CloudBees CI CloudBees の CI/CD 用サービス

ここで、CI/CD が世の中に普及するきっかけを与えたのは Jenkins で、これは CI/CD のための自動処理を実行する環境を提供するソフトウェアです。Jenkins と、Git リポジトリー管理システムが連携して、CI/CD の機能を実現することができます。

CI/CD が普及した結果、Jenkins が提供する機能は Git リポジトリー管理システムでも標準的に提供する機能となりつつあり、GitHub Actions や GitLab CI/CD といった機能が追加されるようになっています。

なお、Gitea は GitHub を参考にして開発されているため、CI/CD のための機能も GitHub Actions と同じようなものとなっていて、Gitea Actions という名前で提供されています。Gitea で管理する Git リモートリポジトリーについて、Gitea Actions の設定をすると、CI/CD を効率よく行うことができるようになります。ドキュメントは Gitea Actions にあります。

個人で CI/CD 環境を構築することの価値

CI/CD 環境構築に必要なものを見ると、種類と組み合わせが多くて大変そうだと感じることでしょう。個人で CI/CD 環境を構築しなくても良いと思う人も多いかと思います。そこで、個人で CI/CD 環境を構築することの価値について、簡単に説明しておきます。

ビジネス上の開発において、CI/CD 対応については、開発が活発なときはスピード重視でコストをかけることが多いですが、ある程度、開発が落ち着いてきたら、コストをあまりかけずに済ませたいとなります。そういった開発環境への要求について、柔軟に対応できるようになるには、開発で使用している Git システム用ソフトウェアと、CI/CD 用のサービスやソフトウェアの組み合わせを自分で切り替えできるようになっている必要があります。

個人開発だと、この後に紹介する Git Hook の機能だけで十分な場合が多いことでしょう。しかし、個人的には、いまどきのソフトウェア開発をする場合は、日常的な開発作業時、リリース作業時に自動で処理したいことは、それなりに多くあるので、毎回 Git Hook で対応するよりは、Git システムと連携する CI/CD 用ソフトウェアを動くように環境を用意しておいて方が楽だと考えています。また、開発者として、そういった環境を構築できるスキルも当然あった方が良いと考えています。

CI/CD のための環境構築は、それなりにコストが必要となるので、個人開発で用意するのは敷居が少し高くなります。そのため、自分で構築して、日常的に使ってみようという人は、あまりいないかもしれません。しかし、1回でも自分で構築しておくと、CI/CD 環境についての理解が深まります。また、実際に環境構築をしなくても、知識としてある程度理解しておくだけでも価値があります。そうやって CI/CD 環境についての理解を深めておくと、クラウドサービスを利用するにしても、必要な設定やコストに影響しそうな部分というのが推測しやすくなるはずです。ですから、長期的な視点からすると、価値のある経験となるはずです。

なお、GitHub などのクラウドサービスを使った開発に参加する場合は、CI/CD もクラウドサービスのものを使っていることが多いでしょうから、CI/CD の環境についてあまり気にすることはないかもしれません。しかし、自分が参加するプロジェクトで少ない予算で開発をする必要があるといった場合は、クラウドサービスを利用できないこともあります。そういったときに、CI/CD 環境が欲しい場合は自分達で用意する必要が出てきます。そういったときにも、ここで紹介している内容を参考にしながら、どこまで自分たちで対応するか検討できるようになっておきたいと思うのではないでしょうか。

他には、実際に利用している CI/CD 用のクラウドサービスを効率よく利用するにあたって、ローカルで個人的に試してみたり、学習をしてみたいこともあるでしょう。無料枠を使い切ることを気にせずに、そういったことを試せる環境はあると便利なはずです。なお、そういったことも考えると、普段使っている CI/CD 用のサービスと互換性が高い環境を用意したいと思うはずです。どのサービスも、Docker で CI/CD 用の処理を動かすようにしておけば、使うことはできますが、設定ファイルの書き方が変わると、そのままでは使えずに大変です。この場合は、環境構築するときに使う機能、ソフトウェアについて、きちんと目的にあったものを選択するようにしましょう。

手軽に CI/CD

準備がそれなりに大変な CI/CD 用ソフトウェアを使わなくても、手軽に CI/CD をすることができます。そのためには、Git の機能である Git Hook を使います。ここでは、Git Hook について説明します。

なお、CI/CD 用ソフトウェアの多くは、この Git Hook 機能をベースとして実装されています。この機能について知っておくと、CI/CD 用ソフトウェアの仕組みを理解しやすくなります。

Git Hook とは

Git Hook(Git フック) を使うと、Git リポジトリーでバージョン管理をしているファイルについて、内容を更新するタイミングなどで、自動処理を実行することができるようになります。

自動処理用のスクリプトファイルを .git/hooks/ ディレクトリーに特定の名前で配置することで、自動処理が動くようになります。特定の処理と連携して自動処理を実行する仕組みのため、フック(hook、鉤)という用語が使われていて、使用するディレクトリー名が hooks となっています。

自動処理が動作するタイミングは、コミット前、コミット後などいくつかあります。どのタイミングで自動処理するのかは、ファイル名で決まっていて、たとえば、コミット前の処理は pre-commit というファイルに記述します。

この仕組みについて、筆者は「コミット前」というラベルがついたフックがあって、そこへ自作の pre-commit をひっかけておくと、あらかじめ用意されている git コマンドのプログラムが、それを自動で実行するというイメージを持っています。

Git フックのサンプルについては、git init コマンドを実行して Git リポジトリーを初期化したときに、.git/hooks/ ディレクトリーに作成されています。初期の設定だと、ファイル名の末尾に .sample がついているため、各フックは無効となっています。.sample を削除することで有効化できます。

Ubuntu/WSL Ubuntu で標準インストールできる git コマンドを使ったときに、用意されるサンプルファイルの一覧の例は次のようになります。

$ ls -a .git/hooks/
.                          post-update.sample       pre-rebase.sample
..                         pre-applypatch.sample    pre-receive.sample
applypatch-msg.sample      pre-commit.sample        prepare-commit-msg.sample
commit-msg.sample          pre-merge-commit.sample  push-to-checkout.sample
fsmonitor-watchman.sample  pre-push.sample          update.sample

フックのタイミングはファイル名から推測できます。最初はわかりやすい pre-commit を使えば良いでしょう。pre-commit フックは、コミットメッセージが入力される前に実行されます。プログラムのコンパイルや静的解析が正常終了するかチェックしたり、フォーマットの自動適用などを自動化するなどの利用が考えられます。

自動デプロイやファイルの自動生成などは、Git リモートリポジトリーで自動実行するように設定することが多いです。その場合はサーバーサイドフックを使います。サーバーサイドフック用のファイルは pre-receiveupdatepost-receive があります。pre-receive フックと update フックは push を受け取ってリポジトリーへ適用する前に実行されます。pre-receive フックではブランチ名を参照するには、そのための処理を自分で記述する必要があります。一方、update はブランチ名が引数で渡ってくるので、スクリプト内で簡単に参照することができます。post-receive フックは、リポジトリーを更新した後に実行されます。

もし、フックファイルが実行可能となっていない場合は、chmod コマンドで実行可能ファイルにする必要があります。

なお、git init 実行時に有効なフック用ファイルを自動生成したい場合は ${HOME}/.git_template/hooks/ ディレクトリーを用意して、そこにファイルを配置しておきます。そこにあるファイルは、git init 実行時に自動的にリポジトリー内の hooks/ ディレクトリーに同じファイルを作成します。

サーバーサイドフック用スクリプトの例

ここでは、サーバーサイドフック用スクリプトの例を紹介します。次の順番で作業します。なお、Git の操作方法についての細かい説明はしません。ここでは、サーバーサイドフック用スクリプトを用意することで、Git リポジトリーの更新時に自動処理が実行されることが理解できれば良いです。

  1. サンプル用リモートリポジトリー proj001.git の作成
  2. ローカル作業用リポジトリーを proj001 をクローンして用意
  3. 動作確認のため proj001 を更新して proj001.git と同期
  4. proj001.git へサーバーサイドフック用スクリプトを追加
  5. 自動処理の動作確認のため proj001 を更新して proj001.git と同期

まずは、Ubuntu/WSL Ubuntu で、ベアリポジトリーを作成します。たとえば、${HOME}/workspace/git-sample/bare を用意して、そこをカレントディレクトリーとして、proj001.git リポジトリーを用意します。

mkdir -p ${HOME}/workspace/git-sample/bare
cd ${HOME}/workspace/git-sample/bare
git init --bare proj001.git

次に、${HOME}/workspace/git-sample/local を用意して、そこをカレントディレクトリーとして、proj001.git をクローンしてローカルリポジトリー proj001 を用意します。

mkdir -p ${HOME}/workspace/git-sample/local
cd ${HOME}/workspace/git-sample/local
git clone "file:///$(pwd)/proj001.git"

ローカルリポジトリーにバージョン管理するファイルをコミットします。

touch proj001/README.md
git -C proj001 add README.md
git -C proj001 config user.email user001@example.jp
git -C proj001 config user.name user001
git -C proj001 commit -m "init"

リモートリポジトリーへローカルリポジトリーの内容を反映するために git push コマンドで同期します。

git -C proj001 push

それから、サーバーサイドフック用スクリプトを用意します。具体的には、リモートリポジトリーのディレクトリーである proj001.git ディレクトリー内の hooks/update に次のファイルを用意します。実行に時間がかかる処理の代わりに sleep 10 を入れてあります。

proj001.git/hooks/update
#!/bin/sh

# ${REPO_DIR_PATH}/.git/hooks/update に置いてある想定
if [ "${PROJECT_DIR_PATH}" = "" ]; then
  SCRIPT_DIR_PATH=$(dirname "$0")
  PROJECT_DIR_PATH=$(cd "${SCRIPT_DIR_PATH}/.." || exit 1; pwd)
fi
PROJ_NAME=$(basename "${PROJECT_DIR_PATH}")
LOG_FILE=/tmp/${PROJ_NAME}.log

echo "PROJECT_DIR_PATH=${PROJECT_DIR_PATH}" > "${LOG_FILE}"

# 簡単な実装とするため、最初のパラメーターでブランチを判定
BRANCH=$1
echo "BRANCH=${BRANCH}" >> "${LOG_FILE}"

# ブランチによって処理を分岐
if [ "refs/heads/prod" = "${BRANCH}" ]; then
  echo "deploy production" >> "${LOG_FILE}"
#  ssh prod-server "git -C=${PROJECT_DIR_PATH} pull origin prod"
elif [ "refs/heads/staging" = "${BRANCH}" ]; then
  echo "deploy staging" >> "${LOG_FILE}"
#  ssh staging-server "git -C=${PROJECT_DIR_PATH} pull origin staging"
fi

# 実行に時間がかかる処理の代わり
sleep 10

# リポジトリーがHTTP公開の場合は下記を有効化
# exec git update-server-info

スクリプトファイルを用意したら、chmod コマンドで実行可能にします。

cd ${HOME}/workspace/git-sample/bare
chmod 755 proj001.git/hooks/update

これで、リモートリポジトリーが更新されたときに、proj001.git/hooks/update スクリプトが自動で実行されます。

その動作を確認するために、まずは、ローカルリポジトリーで prod ブランチを作成してから、リポジトリーを更新します。

cd ${HOME}/workspace/git-sample/local
git -C proj001 switch -c prod
echo "hello" >> proj001/README.md
git -C proj001 add README.md
git -C proj001 commit -m "prod 1st"

それから、リモートリポジトリーへ git push して同期します。このとき、ローカルリポジトリーの prod ブランチのアップストリームブランチは設定されていないので、--set-upstream オプションを指定しながら実行します。

git -C proj001 push --set-upstream origin prod

これでサーバーサイドフック用スクリプトの update が動作します。動作したことを確認するには /tmp/proj001.git.log ファイルを確認します。確認例は次のようになります。

$ cat /tmp/proj001.git.log
PROJECT_DIR_PATH=/home/user001/workspace/git-sample/bare/proj001.git
BRANCH=refs/heads/prod
deploy production

ここでは、cat コマンドを使っています。また、この実行例は、/home/user001/workspace/git-sample/bare/proj001.git にプロジェクト用のベアリポジトリーを作成した場合のものです。

デプロイ処理について

サンプルではデプロイ処理のコマンドについてはコメントにしてあります。サンプルでは、ssh コマンドを使ってリモートマシンのデプロイ用処理を実行することを想定したものになっています。

このように ssh コマンドを使う場合は、あらかじめ ${HOME}/.ssh/config で prod-server と staging-server へ接続するための設定をして、ssh コマンドでリモートからコマンド実行ができるようにしておく必要があります。

なお、サーバーサイドフックの update の処理が終了しないと、git push コマンドを実行したパソコンの方ではコマンドが終了しません。ここの例では、sleep 10 の処理により、git push コマンドが終了するまで 10 秒以上かかります。

そのため、サーバーサイドフックの update の処理では、リモートリポジトリーと同期してデプロイ処理をキックするところまでにして、実際のデプロイ処理については非同期で実行する仕組みを用意して対応することが多いです。

非同期で実行する仕組みを用意することになると、手軽に CI/CD というわけにはいかなくなります。

非同期実行への対応

非同期実行の仕組みについては、サーバーサイドフック用スクリプトを実行するプロセスと、デプロイ処理を実行するプロセスとは、完全に別プロセスで実行される仕組みとなるようにした方がシステム全体は安定します。

プロセスの管理はコンピュータリソースの管理と直結するので、正常終了と異常終了をきちんと判別して管理できるようにしないと、メモリリークなどが発生してシステムが不安定になります。ただし、そういった対処をしようとすると、システムは複雑になります。

きちんと対応するなら、別途 CI/CD 用のプログラムを用意して、Git リモートリポジトリーの処理をするプロセスとは別プロセスで動作するようにした上で、連携する設定をします。

CI/CD 用のプログラムとして何が良いかは、難しいところです。これは、用意できるハードウェア、使用できる OS、使えるソフトウェアなどによって、変わってくるからです。筆者の場合は、次のように分類して、プロジェクトによって使い分けています。

  • CI/CD 用ソフトウェア以外
  • CI/CD 用ソフトウェア

CI/CD 用ソフトウェア以外で非同期実行に対応

CI/CD 用ソフトウェア以外で非同期実行に対応するにあたっては、次の方法があります。ここで紹介する方法は、個人で使う用途に適しています。ただし、基本的に Git システムと同じマシン上で CI/CD の処理を非同期に実行することになります。CI/CD の処理でリソース不足が起きた場合は、Git システムにも影響が出るため、ビジネス用途で使用する Git システムでは採用しにくいかもしれません。

利用する機能・ソフトウェア 説明
バックグラウンド処理 子プロセスの利用
inotify Ubuntu 環境で利用しやすい
docker Docker 環境で利用しやすい

バックグラウンド処理を使う方法は、コマンド実行時に & をつけるだけで済むので簡単です。これを使うと、プログラムを実行している親プロセスとは別に、新たに子プロセスを生成して並列処理を実現することができます。

この場合は、OS の機能を使って親子関係にあるプロセスの管理ができるため、自作プログラム内にプロセス管理の機能を組み込まなくても、ある程度のことができるようになります。とはいえ、サーバーサイドフック用スクリプトとは別に、OS の機能を使って親子関係にあるプロセスの管理をする必要が出てくるので、きちんとしたシステム運用をしようとすると面倒になります。

ただ、「複雑な管理をしてシステムを安定稼働させることより、定期的に OS を再起動して安定稼働させる」と割り切れるなら、面倒なことを考えたり、実行しなくても済みます。個人で使っているシステムなら、OS の再起動について制限されることもないでしょうから、それで大丈夫なはずです。

inotify を使う方法を使うと、ファイルの作成・削除といったシステムイベントを監視することで、プロセスの起動や停止をコントロールできるようになります。これにより、Git Hook 用のスクリプトで特定の CI/CD 用のファイルを作成することで、CI/CD 用のプロセスを起動するといったことができます。つまり、CI/CD 用に特定のファイルとプロセスを 1 対 1 で対応させて、ある程度自動で CI/CD 用プロセスの生成と終了について管理することができます。inotify に慣れていれば手軽に使えて、管理もしやすいので便利です。Ubuntu であれば簡単に使えます。

docker を使う方法では、docker コマンドを使って間接的にデプロイ用のプロセス管理ができます。docker コマンドの豊富なオプションを利用して、Docker コンテナーを管理することができるため、OS のプロセスを直接操作してプロセス管理するよりも簡単です。OS を使うと、使用する OS によって必要な知識が変わりますが、docker コマンドなら Docker についての知識があれば大丈夫です。Docker が動く環境も開発環境なら標準で用意するでしょうし、その環境があれば簡単に使えます。Docker に慣れているなら、お薦めです。

なお、docker はクライアントサーバーシステムで、ソケットファイルを使った通信で動作しています。この通信を TCP/IP 経由でも利用可能にすることができるので、別のマシンで稼働する Docker デーモン(dockerd)を利用することも可能ですが、安全な通信をするための設定がそれなりに大変となります。その設定をするなら、CI/CD 用ソフトウェアを導入した方が良いはずなので、ここでは Git システムと同じマシン上で動作させる dockerd を使うことを想定しています。

これらを使う方法についての詳細は、ここでは解説しません。CI/CD 用ソフトウェアを使う方法が一般的で、この方法は経験のある開発者向けとなるからです。経験のある開発者であれば、ここで説明した内容から具体的な利用方法がわかるはずです。もし、わからない場合は、先に CI/CD 用ソフトウェアを使ってみた方が良いです。CI/CD 用ソフトウェアを使って慣れてきてから、コンピューターリソースが少ないマシンで CI/CD の処理をさせたいと思ったときに再検討すれば良いでしょう。

CI/CD 用ソフトウェアで非同期実行に対応

CI/CD 用ソフトウェアを使うと、CI/CD 用の処理を非同期実行することが簡単にできるようになります。CI/CD 用ソフトウェアの例としては次のものがあります。

利用するソフトウェア 説明
Act Runner Gitea 用 CI/CD 用ソフトウェア
Forgejo runner Forgejo 用 CI/CD 用ソフトウェア
Woodpecker CI 汎用 CI/CD 用ソフトウェア

Act RunnerForgejo runnerWoodpecker CI を利用すると、CI/CD で必要な機能が揃っているので管理が楽になります。ただし、最初のインストールや設定が面倒だと感じるかもしれません。また、個人で使うには、少し大げさな印象があります。とはいえ、一度設定して使えるようになると、できることが多く、便利な機能も使えるようになります。

なお、Act RunnerForgejo runnerWoodpecker CI の使い分けは、使用している Git システム用ソフトウェアに応じて連携しやすいものを選べば良いでしょう。Gitea を使っていたら Act Runner、Forgejo を使っていたら Forgejo runner を使えば良いです。ただし、機能的に足りなかったり安定しないと感じるようだったら、Woodpecker CI を使うと良いでしょう。

Java 実装の CI/CD 用ソフトウェア

著者が CI/CD 用ソフトウェアを知ったのは、Jenkins というソフトウェアからです。これは Java で実装されていて、ビジネスでもよく使われています。

Java 実装の CI/CD 用ソフトウェアは、Java Runtime が動作する環境が必要な分、Java に慣れていない開発者には敷居が高く感じるはずです。そのため、Java で開発するプロジェクト以外では、採用しにくいのですが、現在は Docker を使えば手軽に動かすことができます。CI/CD がどういうものか試用したり、学習用途で使うなら、個人で利用しやすいものだと考えています。

もちろん、ビジネス用途で使われていることもあるため、仕事で使っているものと同じものを手元でも使いたい場合も、選択対象に入ることでしょう。

個人的に選択肢としているものは、次のとおりです。

利用するソフトウェア 説明
Jenkins Java 実装の CI/CD 用ソフトウェア
GitBucket + gitbucket-ci-plugin Java 実装の Git システム用ソフトウェアとプラグイン

Jenkins は CI/CD 用ソフトウェアの先駆けとなったものなので、資料が多く使える機能も充実しています。Java が使える環境が必要で、CI/CD のための処理は JavaVM のサンドボックス内での実行となります。セキュリティ的に安全性が高い環境で処理を実行できます。

GitBucket + gitbucket-ci-plugin は、Git システム用ソフトウェアの GitBucket へプラグインの gitbucket-ci-plugin を追加することで CI/CD を手軽にするためのものです。GitBucket 自体が Git システム用ソフトウェアなので、このプラグインを追加すると、単独で CI/CD 対応ができる Git システムの環境が用意できます。

ただし、この場合は、Git リポジトリー管理のための処理と CI/CD のための処理が同じマシン上で動くことになり、システムリソースへの要求が高くなります。また、gitbucket-ci-plugin は非同期実行のための機能を提供するわけではないという点にも注意が必要です。

CI/CD のための処理について、非同期実行する場合は、CI/CD 用システムを GitBucket とは別に用意して、連携させるのが現実的です。CI/CD 用システムを別途用意しない場合は、gitbucket-ci-plugin の機能を使って実行するスクリプト内で「 CI/CD 用ソフトウェアで非同期実行に対応」で紹介したものを使って実装することになります。

なお、筆者の個人的な意見としては、Git システムの環境を個人で構築するにあたって、Docker か Java が使える前提で、Git システムの環境構築が初めてなら、GitBucket + gitbucket-ci-plugin が良いと考えています。この組み合わせだと、CI/CD を含む環境が非常に手軽に用意できるからです。

ただし、本格的に Git システムを利用するようになってくると、この構成だと物足りなくなってきて、専用の CI/CD システムを構築して連携させたいと思うようになります。そうなったときに、Git システムも軽量なものを使いたくなってきて、Java が必要な GitBucket 以外も候補となってきます。

このあたりは、どんな Git システムを使いたいのか、Java が必要なことに対しての抵抗感、といったことも関係するので、難しいところです。今回は、Windows と Linux の両方で手軽に使い始めて、長く利用することを想定して検討した結果、Gitea を採用しています。

Gitea で CI/CD

さて、CI/CD ができるようにするには、非同期実行への対応が必要になり、そのために CI/CD 用ソフトウェアを使うのが良いということを理解したところで、ここまでに環境を用意した Gitea で CI/CD ができるように環境を構築しましょう。

Gitea の CI/CD 関連機能としては、Gitea Actions と Gitea WebHook の機能があります。どちらも CI/CD 用のソフトウェアと連携させて利用するものです。設定の難易度としては、Gitea Actions の方が簡単です。汎用性が高いのは Gitea WebHook の方になります。新規に環境を用意するなら、Gitea Actions を使うのが手軽でしょう。既存の環境で使っている CI/CD 用のソフトウェアがある場合は、Gitea WebHook を使うことを検討すると良いでしょう。

ここでは Gitea Actions を使います。Gitea WebHook は簡単な紹介だけにしておきます。

Gitea Actions の設定

Gitea Actions 機能を使って、CI/CD ソフトウエアと連携させることができます。この機能を使うには、Gitea 設定ファイルの [actions] セクションで ENABLE=true を指定して有効化します。

[actions]
ENABLED=true

Gitea Actions 機能が対応する CI/CD 用ソフトウェアとして、別途 gitea/act_runner をダウンロードしてインストールし、連携のための設定をする必要があります。

後で、具体的な方法について説明します。

Gitea WebHook の設定

WebHook 機能を使うと、リモートリポジトリーに push があったときに、自動で特定の URL へアクセスさせることができるようになります。また、Woodpecker CI や Jenkins などの CI/CD 用ソフトウェアでは、ジョブを実行するためのトリガー用 URL を有効化するための機能があります。これらを組み合わせることで、Gitea のリモートリポジトリーに push があったときに、CI/CD 用ソフトウェアで処理を自動実行することができるようになります。

機能の説明からわかるように、この機能を使う場合は、Gitea で WebHook の設定以外にも、WebHook に対応する CI/CD 用ソフトウェアのインストールと設定が必要です。

CI/CD 用ソフトウェアをインストールし、CI/CD 用のプロジェクトとジョブを用意します。それから、そのジョブを実行するためのトリガー用 URL を有効化します。

次に、Gitea の「リポジトリーの設定」画面で「WebHook」-「WebHook を追加」-「Gitea」をクリックします。それから、表示された画面の入力欄に用意したトリガー用の URL を指定します。

トリガー用 URL へのアクセスについては、認証をいれるなどのアクセス制限のための設定が追加で必要になるでしょう。その設定については、使用するソフトウェアによって変わってきます。

以上のように環境を構築することで、Gitea のリモートリポジトリーへ push などのリポジトリー更新の通信があった時に、CI/CD 用ソフトウェアのトリガ用 URL へ自動でアクセスして、用意したジョブを実行することができるようになります。

Gitea Act Runner の利用

ここでは、Gitea Actions 機能で利用可能な CI/CD 用タスクランナーである Gitea Act Runner のインストールと設定について説明します。なお、Gitea の URL は https://gitea.windev2401eval.local:13000 だとします。

インストール先は WSL Ubuntu として、自動起動はせずに利用する時だけ手動で起動するという方針とします。もし自動起動して利用するぐらいの必要性を感じるのなら、別にマシンを用意して環境を構築した方が良いです。

Act Runner は Windows 版、macOS 版、Linux 版があります。Docker が動作するなら Windows 版でも良いのですが、1台のパソコンで利用することを考えると、WSL Ubuntu へインストールして利用するのが一番コンピューターリソースの利用効率が良くなります。これは、WSL Ubuntu を処理実行用に使えるようにできるからです。Docker を使う場合は処理実行にコンテナーが必須となり、Docker の稼働が必須となってしまいます。ノートパソコンやミニ PC といった使えるリソースが限定される環境だと、この条件は厳しいと感じることでしょう。

開発をするときに、Docker を常時稼働させておくと、パソコンへの負荷が高くなるので、必要な時に必要なものだけ実行すれば良い環境にすることを想定して、環境構築をするのが良いと考えています。

また、将来的に別マシンで Linux 環境を構築することも視野に入れる場合は、WSL Ubuntu で用意しておけば、移行作業も簡単になります。

WSL Ubuntu で ssh の準備

まず、WSL Ubuntu で ssh コマンド用の鍵ファイルがあるか確認します。${HOME}/.ssh/id_ed25519 などの鍵ファイルがない場合は、用意が必要です。Windows 環境に用意してある場合は、それをコピーして使うことができます。Windows 用の鍵ファイルと WSL Ubuntu 用の鍵ファイルを別管理したい場合は、別途 ssh-keygen コマンドを使って用意してください。

Windows のユーザー名 User の .ssh/id_ed25519 ファイルなどがある場合は、WSL Ubuntu の bash を起動して、次のようにコマンド実行することで使えるようになります。

cp -a /mnt/c/Users/User/.ssh/ ${HOME}/
chmod 700 ${HOME}/.ssh
chmod 600 ${HOME}/.ssh/*

WSL ネットワーク設定の確認

WSL Ubuntu で動作する Gitea Act Runner は Windows で動作する Gitea インスタンスへアクセスできる必要があります。そのため、WSL を使用したネットワーク アプリケーションへのアクセス | Microsoft Learn の説明にしたがって、ネットワーク設定を調整する必要があります。

ネットワーク設定については、ネットワークについて詳しくないと、どのようにするのが良いかわからないでしょう。今回は Windows、WSL(Hyper-V)、Docker のネットワークが関係してくるので、かなり複雑です。この複雑なネットワークについて、簡単に対応する方法があります。それは、WSL の設定で networkingMode=mirrored の指定するというものです。

これは、WSL 全体の設定となるため、C:\Users\<ユーザー名>\.wslconfig に指定します。WSL Ubuntu を使っていて、Windows のユーザー名が User の場合は、/mnt/c/Users/User/.wslconfig を編集すれば良いということになります。このファイルがない場合は、新規に作成して用意します。

/mnt/c/Users/User/.wslconfig
[wsl2]
networkingMode=mirrored

設定を反映するには wsl --shutdown コマンドで WSL を終了する必要があります。

wsl --shutdown

それから、管理者特権を使用して PowerShell ウィンドウで次のコマンドを実行します。これで、WSL Ubuntu からのアクセスを Windows のアプリケーションが受信して、接続ができるようになります。

Set-NetFirewallHyperVVMSetting -Name '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -DefaultInboundAction Allow

この後、wsl コマンドで WSL Ubuntu の bash を起動して作業を続けます。

Gitea の設定

念の為、Gitea の設定について確認をしておきます。ここでは、自己署名のサーバー証明書で HTTPS を有効化し、gitea.windev2401eval.local というドメイン名で稼働しているとします。

Windows では C:\gitea にインストールしてあるとすると、WSL Ubuntu から Gitea の設定ファイルは /mnt/c/gitea/custom/conf/app.ini のパスで確認できます。ここでは、その中の [server] セクションは次のようになっているとします。

/mnt/c/gitea/custom/conf/app.ini
[server]
PROTOCOL = https
CERT_FILE = https/cert.pem
KEY_FILE = https/key.pem
LOCAL_ROOT_URL = https://gitea.windev2401eval.local:13000/
DOMAIN = gitea.windev2401eval.local
HTTP_PORT = 13000
ROOT_URL = https://gitea.windev2401eval.local:13000/
APP_DATA_PATH = C:\gitea\data
DISABLE_SSH = false
SSH_PORT = 22
LFS_START_SERVER = true
LFS_JWT_SECRET = (略)
OFFLINE_MODE = false
SSH_USER = User
SSH_DOMAIN = gitea.windev2401eval.local

次に WSL Ubuntu から、この Gitea が使えることを確認します。

GIT_SSL_NO_VERIFY=1 という環境変数の指定をしながら、git コマンドを実行することで、HTTPS のサーバー証明書の妥当性検証を回避することができます。自己認証のサーバー証明書を使っている場合は、これを利用します。

たとえば、Gitea に user001 ユーザーの proj001.git リポジトリーが用意してあるとして、それをクローンするには次のようにします。

$ mkdir -p ${HOME}/workspace/gitea.windev2401eval.local/user001
$ cd ${HOME}/workspace/gitea.windev2401eval.local/user001
$ GIT_SSL_NO_VERIFY=1 git clone https://gitea.windev2401eval.local:13000/user001/proj001.git
Cloning into 'proj001'...
Username for 'https://gitea.windev2401eval.local:13000': user001
Password for 'https://user001@gitea.windev2401eval.local:13000':
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.

このように、自己認証のサーバー証明書による HTTPS のサーバーを使う場合は、証明書の妥当性検証を無視する設定で動かすことになります。その分、安全性は下がりますから、利用にあたっては留意するようにしましょう。ここでは、ローカルマシンで使うという限定された条件となるので、この設定で進めます。

なお、WSL Ubuntu のユーザーで Git 用の初期設定をまだしていない場合は、しておくと良いでしょう。

ここでは、WSL Ubuntu のユーザーは user001 だとして、Git 用の設定として user.nameuser001user.emailuser001@localhost を指定するとします。その場合は、次のように git config コマンドを使って設定します。

git config --global user.name user001
git config --global user.email user001@localhost

Act Runner のインストール

WSL Ubuntu について、ssh とネットワークの用意、Gitea を WSL Ubuntu から利用できることの確認ができたら、Act Runner のインストールをします。

Act Runner のソースコードは Gitea のサービスで管理されていて、gitea/act_runner で公開されています。リリースされたものは https://gitea.com/gitea/act_runner/releases にあるので、ここから必要なものをダウンロードしてインストールします。

ここでは act_runner-0.2.10-linux-amd64checksums.txt をダウンロードするとします。checksums.txt はダウンロードしたファイルが正しいものか確認するために使います。

インストールは ${HOME}/.local/binact_runner コマンドを用意するだけです。具体的なコマンドは次のようになります。

$ curl -s -LO https://gitea.com/gitea/act_runner/releases/download/v0.2.10/act_runner-0.2.10-linux-amd64
$ curl -s -LO https://gitea.com/gitea/act_runner/releases/download/v0.2.10/checksums.txt
$ cat checksums.txt |grep linux-amd|grep -v "amd64\.xz"
b11753c8fe0143dfbaa392ffc5cc035db551fd7254c145dce512aebc8947542a  act_runner-0.2.10-linux-amd64
$ sha256sum act_runner-0.2.10-linux-amd64
b11753c8fe0143dfbaa392ffc5cc035db551fd7254c145dce512aebc8947542a  act_runner-0.2.10-linux-amd64
$ chmod +x act_runner-0.2.10-linux-amd64
$ mkdir ${HOME}/.local/bin
$ mv act_runner-0.2.10-linux-amd64 ${HOME}/.local/bin/act_runner
$ export PATH=${HOME}/.local/bin:${PATH}

コマンドについては難しいものはないので説明はなくても大丈夫でしょう。見慣れないコマンドだと思われるものについてのみ説明しておきます。

sha256sum コマンドでファイルのチェックサムを表示して、それが checksums.txt にあるものと一致しているか目視で確認しています。

export PATH=${HOME}/.local/bin:${PATH} は、このまま作業をするときに act_runner を絶対パスで指定しなくても済むようにするためのものです。新しく bash を起動する場合は、自動で ${HOME}/.local/bin:${PATH} が環境変数 PATH に追加されるので、このコマンドは実行しなくても act_runner コマンドが使えるようになります。

Act Runner の登録

Act Runner 登録にあたっては、Gitea の管理画面でトークンの作成が必要です。次の URL へアクセスして「Create New Runner」をクリックします。すると、sJ65Dg8rrIhzhqfn6rzrOyXy5LHNV29dj2babtNV といったトークン(token)が表示されるので、これをコピーします。

トークンを取得したら、Act Runner をインストールしたマシンで登録のための作業をします。

最初に、act-runner generate-config コマンドで設定ファイルを用意します。設定ファイルは ${HOME}/.local/etc/act_runner/config.yaml に作成して、実行用ディレクトリーは ${HOME}/.local/act_runner とすることにします。

mkdir -p ${HOME}/.local/etc/act_runner
mkdir -p ${HOME}/.local/act_runner
cd ${HOME}/.local/act_runner
act-runner generate-config > ${HOME}/.local/etc/act_runner/config.yaml

生成された config.yaml について、次に示す部分について修正します。

${HOME}/.local/etc/act_runner/config.yaml
  # 略
runner:
  # 略
  envs:
    GIT_SSL_NO_VERIFY: true
  # 略
  insecure: true
  # 略
  labels:
    # 略
    - "ubuntu-22.04:host"
    # 略

container:
  options: "--add-host=gitea.windev2401eval.local:host-gateway --env GIT_SSL_NO_VERIFY=true"
  # 略
  force_pull: false
  # 略

runner: は Act Runner の設定になります。

Gitea のインスタンス用 URL が自己署名のサーバー証明書を使っているものなので、insecure: true として、サーバー証明書の妥当性検証をしないようにしています。また、Act Runner 内で実行するコマンドについてもサーバー証明書の妥当性検証をしないようにする必要があるので、環境変数を指定する env:GIT_SSL_NO_VERIFY: true を追加します。

labels: には、Docker コンテナーを使う前提で、処理実行用のラベル指定がされています。ここでは WSL Ubuntu でも処理が使えるように、ubuntu-22.04 のラベルについては、WSL Ubuntu を表す host へ変更します。

container: は、Act Runner で docker コマンドを使って起動するコンテナー用の設定になります。

options: には docker コマンドのオプション指定ができます。Docker コンテナー内から Gitea へアクセスするときは、Gitea の設定で指定した ROOT_URLLOCAL_ROOT_URL が使われます。ここに含まれる gitea.windev2401eval.local について、Docker コンテナー内で名前解決ができるように --add-host=gitea.windev2401eval.local:host-gateway を指定します。また、Docker コンテナー内のコマンドについてもサーバー証明書の妥当性検証をしないように環境変数の指定 --env GIT_SSL_NO_VERIFY=true をします。

force_pull: true については、Docker イメージのプルについて、強制的に実行するなら true、しないなら false とします。ここでは Docker イメージのプルについては、毎回プルする必要はないので、false にしておきます。

設定ファイルが用意できたら、act_runner register コマンドを使って Gitea へ登録します。

次のように、INSTANCE_URL に Gitea の ROOT_URL である https://gitea.windev2401eval.local:13000 を指定し、TOKEN に Gitea の設定画面から取得したトークン(例だと sJ65Dg8rrIhzhqfn6rzrOyXy5LHNV29dj2babtNV)を指定し、これらを使って act_runner register コマンドを実行します。

INSTANCE_URL=https://gitea.windev2401eval.local:13000
TOKEN=sJ65Dg8rrIhzhqfn6rzrOyXy5LHNV29dj2babtNV
act_runner register \
  --no-interactive \
  --config ${HOME}/.local/etc/act_runner/config.yaml \
  --instance ${INSTANCE_URL} \
  --token ${TOKEN} \
  --name wsl-ubuntu

ここで、--no-interactive は非対話モード、--config は設定ファイルのパス、--instance は Gitea インスタンスの URL、--token は登録時に使うトークン、--name は Act Runner の名前を指定するオプションです。

実際に実行すると、次のようになります。

$ INSTANCE_URL=https://gitea.windev2401eval.local:13000
$ TOKEN=sJ65Dg8rrIhzhqfn6rzrOyXy5LHNV29dj2babtNV
$ act_runner register --no-interactive \
  --config ${HOME}/.local/etc/act_runner/config.yaml \
  --instance ${INSTANCE_URL} \
  --token ${TOKEN} \
  --name wsl-ubuntu

INFO Registering runner, arch=amd64, os=linux, version=v0.2.10.
WARN Runner in user-mode.
INFO Runner name is empty, use hostname 'wsl-ubuntu'.
DEBU Successfully pinged the Gitea instance server
INFO Runner registered successfully.

なお、登録内容は、act_runner コマンドを実行したディレクトリーの .runner ファイルに保存されます。act_runner コマンドをデーモンモードで実行する時に、この .runner ファイルがあるディレクトリーをカレントディレクトリーとする必要があります。

Act Runner の起動

登録ができたら、Act Runner をインストールしたマシンで act_runner daemon コマンドを実行します。これで、Act Runner が起動します。

cd ~/.local/act_runner
act_runner daemon --config ${HOME}/.local/etc/act_runner/config.yaml

Act Runner を起動したら、Gitea の Web 管理画面で連携状態を確認します。インスタンスレベルで登録された Act Runner は、管理者権限のあるアカウントを使って下記の URL で確認することができます。

次に、Act Runner を使うリポジトリーについて、リポジトリーの設定を開きます。例えば、アカウントが user001 で、プロジェクトが proj001 の場合は、下記の URL になります。

それから、「Enable Repository Actions」にチェックをいれます。すると、リポジトリーで Gitea Actions が有効化されます。

リポジトリーレベルで登録された Act Runner は、リポジトリーを利用できるアカウントを使って確認することができます。例えば、アカウントが user001 で、プロジェクトが proj001 の場合は、下記の URL になります。

Act Runner で CI/CD 用処理を実行

Act Runner の用意ができたら、CI/CD 用の設定ファイルを用意します。設定ファイルはリポジトリー内に .gitea/workflows/ ディレクトリーを用意して、その中に YAML フォーマットで作成します。

ここでは、Gitea のリポジトリーを ${HOME}/workspace/gitea.windev2401eval.local/user001/proj001 にクローンしてあるとします。カレントディレクトリーをこのパスにします。また、CI/CD 用の設定ファイルを置くディレクトリーを作成します。

cd ${HOME}/workspace/gitea.windev2401eval.local/user001/proj001
mkdir -p .gitea/workflows

ここでは、Act Runner の処理を実行するための設定ファイルについて、https://docs.gitea.com/usage/actions/quickstart にあるサンプルを使うことにしました。ファイル名は、.gitea/workflows/demo.yaml として、リポジトリーへ追加します。

.gitea/workflows/demo.yaml
name: Gitea Actions Demo
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
on: [push]

jobs:
  Explore-Gitea-Actions:
    runs-on: ubuntu-latest
    steps:
      - run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
      - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
      - run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
      - name: Check out repository code
        uses: actions/checkout@v4
      - run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
      - run: echo "🖥️ The workflow is now ready to test your code on the runner."
      - name: List files in the repository
        run: |
          ls ${{ gitea.workspace }}
      - run: echo "🍏 This job's status is ${{ job.status }}."

ファイルを用意したら、次のようにローカルリポジトリーを更新して、リモートリポジトリーと同期します。

git add .gitea/workflows/demo.yaml
git commit -m "add .gitea/workflows/demo.yaml"
git push

リモートリポジトリーへ git push したら、Gitea の Web 管理画面で、Act Runner のコンソール出力を確認します。そこで、demo.yaml で指定した処理が実行されていたら成功です。

このように Act Runner を使うと、CI/CD のための処理は別マシンで実行させることができるようになり、Gitea のリポジトリー用の処理とは別プロセスでの実行が実現できます。非同期実行のために、並行処理のプログラムを自作する必要がないので、とても簡単に環境構築ができます。

Discussion