LoginSignup
14
5

More than 3 years have passed since last update.

Github Actionsで.NET CoreのCI/CDを行う

Last updated at Posted at 2019-11-19

この記事で作ったサンプルリポジトリは以下になります。
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のキャッシュをするなどしてもっと速度改善したほうがいいかも
    • キャッシュを組み込んでみました。ハマったところもあったので記事にしました
14
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
5