シナプス技術者ブログ

シナプスの技術者公式ブログ。インターネットで、鹿児島の毎日を笑顔にします。

GitLab CIで、ASP.NET COREのライブラリの自動アップデートを試してみた

技術部システム開発課の蔵坪と申します。

弊社では、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上でアップデート内容を分かりやすく表示することができます。

github.com

  • 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 

検証結果

予定パイプライン経由で動作を確認します。

*

パイプラインが実行された結果です。

*

パイプラインが実行された結果、以下の順番でファイルの変更が確認できました。

  1. mainの最新がNuGetUpdateブランチに反映された
  2. パッケージのアップデートの変更分がNuGetUpdateブランチに反映された
  3. パッケージのアップデートの変更分がmainブランチに反映された

無事、mainブランチでライブラリがアップデートされていることを確認できました。

さいごに

今回の検証結果から、技術的にASP.NET CoreプロジェクトのNuGetライブラリの自動アップデートが可能であることが確認できました。これにより、手動でのライブラリ更新作業の負担を大幅に軽減できる可能性があります。

今後の課題

今回の検証結果から、技術的に自動アップデートが可能であることが確認できました。今後、本番環境に適用するためには以下の課題があります。

  • 競合の問題: 自動マージ時の競合解決方法を確立する必要があります。
  • テストの充実: テストカバレッジを拡充し、CIパイプラインの信頼性を向上させる必要があります。
  • 本番環境への適用: 検証結果を基に、本番環境での適用を目指し、必要な調整を行います。

これらの課題を解決し、プロジェクトの効率化と品質向上を図りたいと考えています。

  翻译: