Creating a .NET Tool (3 Part Series)
In Part 1 of this series, we created a command line program that can validate JSON files on disk, utilising System.CommandLine.DragonFruit for command line parsing and System.Text.Json for JSON validation. In this post, we'll add the necessary code to package the console app as a .NET Tool that can be published to NuGet. Let's jump right in!
.NET Tools are by all accounts just regular NuGet packages, except they have special tags in their metadata. Given our app is already executable (we started with a console app), there's really only one line of code required to be added to the project file in order to transform the app into a .NET Tool:
Once that line is added, you can package the tool with:
$ cd src/jsonv $ dotnet pack
Which will create a NuGet package
Then we can install the tool globally on our machine with:
$ dotnet tool install -g jsonv --add-source bin/Debug You can invoke the tool using the following command: jsonv Tool 'jsonv' (version '1.0.0') was successfully installed.
Then we can run the tool on our machine:
$ jsonv --file-path ../../global.json --allow-comments File path is: ../../global.json, allowing comments: True File is valid JSON!
Awesome, our tool can be installed and works like we expect.
By default, the command that invokes the tool, e.g.
jsonv, is taken from the project file's name. If you would like a different name, you can add the following tag to the project file:
By default, the NuGet package is published to
bin/[Configuration] path. If you would like a different path, you can add the following tag to the project file:
Great, we are now producing a tool that can be installed and invoked. Let's now add the appropriate metadata to allow this to be published to NuGet.org or a compatible NuGet server.
There are tonnes of articles out there on creating NuGet packages, but I think the best is the Open-source library guidance. It covers all of the OSS library do's and don'ts. There is a specific section on NuGet that provides a nominal list of tags that every package should have. It's also recommended to add SourceLink which will add extra repoository related metadata to the package. Following that guidance, we end up with the following tags:
<PackageId>jsonv</PackageId> <PackageVersion>1.0.0-alpha.1</PackageVersion> <Description>A .NET Tool to validate JSON files on disk</Description> <Authors>Marcus Turewicz, DEVCommunity</Authors> <PackageTags>json json-validation json-validator</PackageTags> <PackageIconUrl>https://github.com/marcusturewicz/jsonv/raw/master/logo.png</PackageIconUrl> <PackageLicenseExpression>MIT</PackageLicenseExpression>
And we should add the SourceLink package with:
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
and add the tag to publish the repository URL with SourceLink:
Finally, our complete project file looks like:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <!-- Console app metadata --> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> <!-- Tool metadata --> <PackAsTool>true</PackAsTool> <!-- NuGet package metadata --> <PackageId>jsonv</PackageId> <PackageVersion>1.0.0-alpha.1</PackageVersion> <Description>A .NET Tool to validate JSON files on disk</Description> <Authors>Marcus Turewicz, DEVCommunity</Authors> <PackageTags>json json-validation json-validator</PackageTags> <PackageIconUrl>https://github.com/marcusturewicz/jsonv/raw/master/logo.png</PackageIconUrl> <PackageLicenseExpression>MIT</PackageLicenseExpression> <!-- SourceLink metadata --> <PublishRepositoryUrl>true</PublishRepositoryUrl> </PropertyGroup> <ItemGroup> <PackageReference Include="System.CommandLine.DragonFruit" Version="0.3.0-alpha.20214.1" /> <!-- SourceLink package for GitHub --> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/> </ItemGroup> </Project>
- I have left out
Titleas I'm happy with the default being
- I'm using SemVer2.0 for the
- I've set the
PackageProjectUrlas the GitHub repo url, but this could be the project website or docs site
- This is guidance for OSS. If you're package is private source, then you should carefully consider which data you are providing and what will be public
Great, the tool is now ready for NuGet!
In this post, we added the necessary metadata to the project file to pack the console app as a .NET Tool and to publish the tool to NuGet. There are great guides provided by Microsoft that detail the steps to create quality OSS libraries and tools.
In the next post, we will setup a CI/CD pipeline that will build, pack and publish the tool to NuGet. Stay tuned!