この記事で作ったサンプルリポジトリは以下になります。
dotnet-ci-example
TL:DR
- Windows / Linux(ubuntu) / MacOS のそれぞれで単体テストを実行
-
v0.1.0
のようなタグがあった場合はGithub Releaseを作成 - それぞれのOS向けの実行ファイルをビルド・アップロード
するGithubのWorkflowを作ります。
プロジェクトの作成
# ソリューション, コンソールプロジェクト, テストプロジェクトを作成
> dotnet new sln
> dotnet new console -o ./Sample.Core
> dotnet new xunit -o ./Sample.Test
# ソリューションに2つのプロジェクトを紐付け
> dotnet sln add ./Sample.Core/Sample.Core.csproj ./Sample.Test/Sample.Test.csproj
# テストプロジェクトにコンソールプロジェクトを紐付け
> cd ./Sample.Test/
> dotnet add reference ../Sample.Core/Sample.Core.csproj
dotnet-formatのローカルインストール
.NET Core版ESLint。
設定は.editorconfig
ファイルから読み込むので、別途用意してください。
(自分は別プロジェクトでVisual Studioから作成したものを引っ張ってきました)
# ローカルインストールに必要なマニフェストファイルを作成
# ちなみにリストアはdotnet tool restoreでできます
> dotnet new tool-manifest
# インストール
> dotnet tool install dotnet-format
(2019/12/16追記)
.NET Coreツールについては別記事を書きましたので、そちらをご参照ください。
ロジックとテストの実装
説明は割愛。
ワークフローの作成
Github上で作成します。(vscodeで作ってpushしようとしたらエラーになった)
流用する際は適宜パスやバージョン等変更してください。
YAMLファイル
dotnet.yaml
name: .NET Core CI/CD
on: [push, pull_request]
jobs:
test:
name: Debug Build & Test
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
dotnet-version: ['3.0.100', '3.1.100-preview3-014645']
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
NUGET_XMLDOC_MODE: skip
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core ${{ matrix.dotnet-version }}
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ matrix.dotnet-version }}
- name: Restore Tool
run: dotnet tool restore
- name: Lint
run: dotnet format --check --dry-run
- name: Build
run: dotnet build -c Debug
- name: Test
run: dotnet test -c Debug --no-build
release:
name: Create Github Release
if: contains(github.ref, 'tags/v')
needs: [test]
runs-on: ubuntu-latest
steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Output Release URL File
run: echo "${{ steps.create_release.outputs.upload_url }}" > release_url.txt
- name: Save Release URL File for publish
uses: actions/upload-artifact@v1
with:
name: release_url
path: release_url.txt
publish:
if: contains(github.ref, 'tags/v')
needs: [test, release]
runs-on: ubuntu-latest
strategy:
matrix:
rid: [win-x64, linux-x64, osx-x64]
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
NUGET_XMLDOC_MODE: skip
steps:
- uses: actions/checkout@v1
- name: Load Release URL File from release job
uses: actions/download-artifact@v1
with:
name: release_url
- name: Setup .NET Core 3.0 (current)
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.0.100
- name: Build
run: |
dotnet publish ./Sample.Core/Sample.Core.csproj -c Release -r ${{ matrix.rid }} /p\:PublishSingleFile=true /p\:PublishTrimmed=true -o ./${{ matrix.rid }}
zip -r ${{ matrix.rid }} ./${{ matrix.rid }}
- name: Get Release File Name & Upload URL
id: get_release_info
run: |
echo ::set-output name=file_name::${REPOSITORY_NAME##*/}-${TAG_REF_NAME##*/v}
value=`cat release_url/release_url.txt`
echo ::set-output name=upload_url::$value
env:
TAG_REF_NAME: ${{ github.ref }}
REPOSITORY_NAME: ${{ github.repository }}
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.get_release_info.outputs.upload_url }}
asset_path: ./${{ matrix.rid }}.zip
asset_name: ${{ steps.get_release_info.outputs.file_name }}-${{ matrix.rid }}.zip
asset_content_type: application/zip
実録
ちなみにプログラムは1-20までFizzBuzzするだけのものです。
所感
- 並列テストの実行速度がMacOS > ubuntu >> Windowsといった感じ。
- Windowsもうちょっとがんばって
- NuGetのキャッシュをするなどしてもっと速度改善したほうがいいかも
- キャッシュを組み込んでみました。ハマったところもあったので記事にしました