技術部システム開発課の蔵坪と申します。
弊社では、ASP.NET Coreを利用しています。今回は、ASP.NET CoreプロジェクトにおいてGitLab CIを使用してNuGetライブラリを自動アップデートできるか技術検証を行いました。
GitLabプロジェクト側の準備
GitLab上にASP.NET Coreのプロジェクトを作成します。
GitLab上で、NuGetライブラリアップデート用のブランチを用意します。このサンプルでは「NuGetUpdate」とします。
Git更新用の公開鍵と、秘密鍵を用意します。
公開鍵をGitLabプロジェクトのデプロイキーとして登録し、書き込み権限を与えます。
- GitLab 17.2では設定>リポジトリ>デプロイキー
秘密鍵をGitLabプロジェクトのCI/CD変数として登録します(例:「SSH_PRIVATE_KEY」)。
- GitLab 17.2では設定>CI/CD>変数
毎日0時にパイプラインが動作するように設定します。
GitLab CIの設定
ステージは2つ用意します。
- merge_main_into_branch : メインブランチの最新の内容をNugetUpdateブランチにマージします。
- update_nuget_and_merge : NuGetライブラリをアップデートし、mainブランチにマージします。
.gitlab-ci.yml
default: image: mcr.microsoft.com/dotnet/sdk:8.0 tags: - ******* stages: - merge_main_into_branch - update_nuget_and_merge merge_main_into_branch: stage: merge_main_into_branch only: refs: - NuGetUpdate before_script: - ./prepare_ssh_access.sh script: - ./merge_main_into_branch.sh update_nuget_and_merge: stage: update_nuget_and_merge only: refs: - NuGetUpdate before_script: - ./prepare_ssh_access.sh script: - ./update_nuget_and_merge.sh artifacts: paths: [ output/*-test-result.xml ] reports: junit: output/*-test-result.xml
prepare_ssh_access.sh
CI上からGitを操作するための準備です。
#!/bin/bash # SSHの設定 apt-get update && apt-get install -y openssh-client mkdir -p ~/.ssh chmod 700 ~/.ssh echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan $CI_SERVER_HOST >> ~/.ssh/known_hosts chmod 644 ~/.ssh/known_hosts # Git設定 git config --global user.name "gitlab-runner@synapse.jp" git config --global user.email "gilab-runner@synapse.jp"
merge_main_into_branch.sh
NuGetライブラリのアップデート用ブランチにmainブランチの最新の変更を取り込み、その結果をリモートリポジトリに反映させます。
ランナー上では、コミットに対してチェックアウトしているため、ブランチにチェックアウトする必要があります。
#!/bin/bash git checkout main git pull git reset --hard origin/main git checkout $CI_COMMIT_REF_NAME git reset --hard origin/$CI_COMMIT_REF_NAME git merge main -m "[ci skip] latest changes from main into $CI_COMMIT_REF_NAME" git push git@${CI_SERVER_HOST}:${CI_PROJECT_PATH}.git HEAD:$CI_COMMIT_REF_NAME
update_nuget_and_merge.sh
プロジェクトの依存関係を自動的に更新し、その変更がテストをパスすることを確認します。成功した場合、変更をコミットしてmainブランチにマージします。
Nugetライブラリのアップデートは、dotnet-outdatedツールを利用しています。dotnet-outdatedは、プロジェクトで使用されている NuGet パッケージの新しいバージョンが利用可能かどうかを簡単に確認でき、CI上でアップデート内容を分かりやすく表示することができます。
- NuGetのアップデートは、dotnet-outdatedコマンドの引数でマイナーバージョンアップデートのみに固定しています(--version-lock Minor)。
- テストが一つでも失敗した場合は、CIを失敗とし、その場合はmainにマージしません。
#!/bin/bash git checkout $CI_COMMIT_REF_NAME git pull git reset --hard origin/$CI_COMMIT_REF_NAME dotnet tool install dotnet-outdated-tool --global export PATH="$PATH:/root/.dotnet/tools" dotnet-outdated --upgrade --version-lock Minor git add . if [[ -n "$(git status --porcelain)" ]]; then dotnet restore EXIT_CODE=0 for project in $(find . -name "*Test*.csproj"); do assemblyName=$(basename ${project%.*}) dotnet test $project \ --logger "trx;LogFileName=$assemblyName-test-result.xml" \ --results-directory ./output # テストの終了コードを保存 TEST_EXIT_CODE=$? # いずれかのテストが失敗した場合、EXIT_CODEを非ゼロに設定 if [ $TEST_EXIT_CODE -ne 0 ]; then EXIT_CODE=$TEST_EXIT_CODE fi done if [ $EXIT_CODE -ne 0 ]; then exit $EXIT_CODE fi git commit -a -m '[ci skip] Push by GitLab runner' git push git@${CI_SERVER_HOST}:${CI_PROJECT_PATH}.git HEAD:$CI_COMMIT_REF_NAME git checkout main git reset --hard origin/main git merge $CI_COMMIT_REF_NAME git push git@${CI_SERVER_HOST}:${CI_PROJECT_PATH}.git main fi
検証結果
予定パイプライン経由で動作を確認します。
パイプラインが実行された結果です。
パイプラインが実行された結果、以下の順番でファイルの変更が確認できました。
- mainの最新がNuGetUpdateブランチに反映された
- パッケージのアップデートの変更分がNuGetUpdateブランチに反映された
- パッケージのアップデートの変更分がmainブランチに反映された
無事、mainブランチでライブラリがアップデートされていることを確認できました。
さいごに
今回の検証結果から、技術的にASP.NET CoreプロジェクトのNuGetライブラリの自動アップデートが可能であることが確認できました。これにより、手動でのライブラリ更新作業の負担を大幅に軽減できる可能性があります。
今後の課題
今回の検証結果から、技術的に自動アップデートが可能であることが確認できました。今後、本番環境に適用するためには以下の課題があります。
- 競合の問題: 自動マージ時の競合解決方法を確立する必要があります。
- テストの充実: テストカバレッジを拡充し、CIパイプラインの信頼性を向上させる必要があります。
- 本番環境への適用: 検証結果を基に、本番環境での適用を目指し、必要な調整を行います。
これらの課題を解決し、プロジェクトの効率化と品質向上を図りたいと考えています。