はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【.NET】dotnet toolが要求している.NET SDKのバージョンを調べることができるOSS「DotnetToolInspector」を作りました

はじめに

先日dotnet toolが要求している.NET SDKのバージョンを調べることができるOSSを公開しました。

今回はそれを紹介したいと思います。

モチベ

dotnet toolを活用したGitHub Actionsのワークフローを作成することが普段C#に馴染みのある方ならあるかなと思います。その際にdotnet toolが要求する.NET SDKのバージョンを検出し、それに応じてactions/setup-dotnetできたらいいのにな思いました。それがOSSを作成する発端になります。

github.com

一応actions/setup-dotnetglobal.jsonを読み込んでセットアップできるので、自分で作成しているものであればそれを読み込むとかでも良いとは思います。

steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
  with:
    global-json-file: csharp/global.json
- run: dotnet build <my project>
  working-directory: csharp

DotnetToolInspectorとは

DotnetToolInspectorはインストール済みのdotnet toolruntimeconfig.jsonを取得することができるPowerShellのモジュールです。最初はdotnet cliでそこら辺調べられるのかなと思っていたのですが、調べても全然見つからなかったので自分で作ってみました。

runtimeconfig.jsonってなんやねんと思うかと思いますが、global.jsonに書き込まれた内容などを元にビルド時に作成される.NETアプリケーションの実行時設定を定義するためのJSONファイルです。
learn.microsoft.com

{
  "runtimeOptions": {
    "tfm": "net6.0",
    "rollForward": "LatestMajor",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "6.0.0"
    },
    "configProperties": {
      "System.Reflection.Metadata.MetadataUpdater.IsSupported": false
    }
  }
}

上記はdotnet-t4 v3.0.0runtimecofig.jsonの中身ですが、tfm(Target Framework Moniker)より.NET 6.0向けにビルドされていることが分かり、rollForwardLatestMajorframework.version6.0.0なのでバージョンが6.0.0以上なら動作することが分かります。
learn.microsoft.com

インストール方法

PowerShellのモジュールなので、PowerShellがインストールされている環境で下記コマンドを実行してください。

$ Install-Module -Name DotnetToolInspector

www.powershellgallery.com

またGitHub Actionsで利用したい場合はaction.ymlが提供されているのでそちらを利用してください。

- name: Example -global
  uses: hanachiru/DotnetToolInspector@main
  with:
    package-id: dotnet-t4
    command-name: t4
    global: true

DotnetTool RuntimeConfig Inspector · Actions · GitHub Marketplace · GitHub

使い方

どの利用方法をするにしても、インストール済であるdotnet toolを解析してruntimeconfig.jsonを取り出します。ですので、マシンにインストールされていないと情報を取得できないので注意してください。ローカルツールではdotnet tool restoreを実行する必要があります。

PowerShellを利用する場合

# for 'dotnet tool install dotnet-t4 --local'
$ Get-DotnetToolRuntimeConfig -packageID "dotnet-t4" -commandName "t4"
{
  "runtimeOptions": {
    "tfm": "net6.0",
    "rollForward": "LatestMajor",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "6.0.0"
    },
    "configProperties": {
      "System.Reflection.Metadata.MetadataUpdater.IsSupported": false
    }
  }
}


# for 'dotnet tool install dotnet-t4 --tool-path <path-to-your-tool-path>'
$ Get-DotnetToolRuntimeConfig -packageID "dotnet-t4" -commandName "t4" -toolPath "path\to\your\tool-path"
{
  "runtimeOptions": {
    "tfm": "net6.0",
    "rollForward": "LatestMajor",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "6.0.0"
    },
    "configProperties": {
      "System.Reflection.Metadata.MetadataUpdater.IsSupported": false
    }
  }
}


# for 'dotnet tool install dotnet-t4 --global'
$ Get-DotnetToolRuntimeConfig -packageID "dotnet-t4" -commandName "t4" -global
{
  "runtimeOptions": {
    "tfm": "net6.0",
    "rollForward": "LatestMajor",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "6.0.0"
    },
    "configProperties": {
      "System.Reflection.Metadata.MetadataUpdater.IsSupported": false
    }
  }
}

GitHub Actionsで利用する場合

--local
- name: Example -local
  uses: hanachiru/DotnetToolInspector@main
  with:
    package-id: dotnet-t4
    command-name: t4
    working-directory: ./Tests/Data/local

working-directoryを利用して、プロジェクトへのパスを指定してあげてください。
dotnet-tools.jsonを読み取り、そこからキャッシュされているdotnet toolを読み取ります。

--tool-path
# Check .NET SDK Version
- name: Example -toolPath
  id: toolpath
  uses: hanachiru/DotnetToolInspector@main
  with:
    package-id: dotnet-t4
    command-name: t4
    tool-path: ./Tests/Data/tool-path

tool-pathを指定してあげます。

--global
- name: Example -global
  uses: hanachiru/DotnetToolInspector@main
  with:
    package-id: dotnet-t4
    command-name: t4
    global: true

global: trueを指定してあげます。

さいごに

割と便利だなと思うものの、マシンにインストール済みでないと調べれないのがやや難点かなという気はしています。nuget.orgあたりからいい感じに情報取得できるようになったり良いのかなと思ったりしつつ、そこらへん後で見てみようかなと思います。