๐ง .NET Tool Install Action
A comprehensive GitHub Action for installing and managing .NET tools with support for global, local, and manifest-based installations. Includes version management, restoration, update capabilities, and advanced tool configuration options.
โจ Features
- ๐ Multiple Installation Modes - Global, local, and tool manifest installations
- ๐ฆ Flexible Tool Management - Install specific versions, restore from manifests, or update existing tools
- ๐ฏ Source Configuration - Support for custom NuGet sources and package feeds
- ๐ Performance Optimization - Tool existence checking and conditional installations
- ๐ง Advanced Configuration - Custom tool paths, verbosity control, and architecture specification
- ๐ Rich Action Summaries - Detailed installation reports with tool inventory and statistics
- ๐ Bulk Operations - Install multiple tools from manifests or batch configurations
- ๐ Tool Discovery - Automatic detection of existing tools and version conflicts
๐ Basic Usage
Install a global .NET tool:
- name: "Install Entity Framework tools"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
- name: "Install specific version"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-sonarscanner"
version: "5.7.2"
- name: "Install local tool"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-format"
global: "false"
๐ง Advanced Usage
Complete tool installation with custom configuration:
- name: "Advanced tool installation"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-sonarscanner"
version: "5.7.2"
global: "true"
source: "https://api.nuget.org/v3/index.json"
tool-path: "/usr/local/share/dotnet-tools"
verbosity: "normal"
prerelease: "false"
architecture: "x64"
skip-if-exists: "true"
show-summary: "true"
๐ Permissions Required
This action requires standard repository permissions:
permissions:
contents: read # Required to checkout repository code
For tool manifest modifications:
permissions:
contents: write # Required to update tool manifests
๐๏ธ CI/CD Example
Complete workflow for .NET tool management:
name: ".NET Tool Management"
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
permissions:
contents: write
jobs:
setup-tools:
runs-on: ubuntu-latest
steps:
- name: "๐ฅ Checkout repository"
uses: actions/checkout@v4
- name: "๐ง Setup .NET"
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
- name: "๐ง Install Entity Framework CLI"
id: ef-tools
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
skip-if-exists: "true"
show-summary: "true"
- name: "๐ Install SonarScanner"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-sonarscanner"
version: "5.7.2"
global: "true"
skip-if-exists: "true"
- name: "๐จ Install Code Formatter"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-format"
global: "false"
tool-path: "./tools"
- name: "๐ Install Coverage Tools"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-reportgenerator-globaltool"
global: "true"
prerelease: "false"
- name: "๐ Install Security Scanner"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "security-scan"
source: "https://myget.org/F/security-tools/api/v3/index.json"
global: "true"
verbosity: "detailed"
- name: "๐ฆ Restore tool manifest tools"
if: hashFiles('./.config/dotnet-tools.json') != ''
run: dotnet tool restore
- name: "๐งช Run Entity Framework migrations"
if: steps.ef-tools.outputs.installed == 'true'
run: dotnet ef database update
working-directory: ./src/MyProject
- name: "๐จ Format code"
run: ./tools/dotnet-format --verify-no-changes
continue-on-error: true
- name: "๐ Run SonarScanner"
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
dotnet sonarscanner begin /k:"project-key" /d:sonar.login="$SONAR_TOKEN"
dotnet build --no-restore
dotnet sonarscanner end /d:sonar.login="$SONAR_TOKEN"
cross-platform-tools:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: ubuntu-latest
tool-path: "/usr/local/share/dotnet-tools"
- os: windows-latest
tool-path: "C:\\Tools\\dotnet"
- os: macos-latest
tool-path: "/usr/local/share/dotnet-tools"
runs-on: ${{ matrix.os }}
steps:
- name: "๐ฅ Checkout repository"
uses: actions/checkout@v4
- name: "๐ง Setup .NET"
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
- name: "๐ง Install cross-platform tools"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
tool-path: ${{ matrix.tool-path }}
architecture: "x64"
skip-if-exists: "true"
show-summary: "true"
- name: "โ
Verify tool installation"
run: dotnet ef --version
๐ Inputs
| Input | Description | Required | Default | Example |
|---|---|---|---|---|
package-name |
Name of the .NET tool package to install | โ Yes | - | dotnet-ef, dotnet-format, dotnet-sonarscanner |
version |
Specific version of the tool to install | โ No | latest |
5.7.2, 3.1.0, 6.0.0-preview.1 |
global |
Install tool globally (true) or locally (false) | โ No | true |
true, false |
source |
NuGet source URL for package installation | โ No | '' |
https://api.nuget.org/v3/index.json |
tool-path |
Custom path for tool installation | โ No | '' |
./tools, /usr/local/share/dotnet-tools |
verbosity |
Verbosity level for installation | โ No | minimal |
quiet, minimal, normal, detailed, diagnostic |
prerelease |
Allow prerelease versions | โ No | false |
true, false |
architecture |
Target architecture for tool | โ No | '' |
x86, x64, arm, arm64 |
skip-if-exists |
Skip installation if tool already exists | โ No | false |
true, false |
show-summary |
Show detailed action summary | โ No | false |
true, false |
๐ค Outputs
| Output | Description | Example |
|---|---|---|
installed |
Whether the tool was successfully installed | true, false |
skipped |
Whether installation was skipped (tool exists) | true, false |
version |
Version of the installed tool | 7.0.5, 6.0.2 |
tool-path |
Path where the tool was installed | /home/runner/.dotnet/tools |
global |
Whether the tool was installed globally | true, false |
execution-time |
Time taken for installation in seconds | 12.34 |
๐ Related Actions
| Action | Purpose | Repository |
|---|---|---|
| ๐จ dotnet | Build .NET projects | laerdal/github_actions/dotnet |
| ๐งช dotnet-test | Run .NET tests | laerdal/github_actions/dotnet-test |
| ๐ฆ dotnet-nuget-upload | Publish NuGet packages | laerdal/github_actions/dotnet-nuget-upload |
| ๐ง dotnet-nuget-feed-setup | Configure NuGet feeds | laerdal/github_actions/dotnet-nuget-feed-setup |
๐ก Examples
Popular .NET Tools
# Entity Framework CLI tools
- name: "Install EF Core CLI"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
# Code formatting tools
- name: "Install dotnet-format"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-format"
global: "true"
# SonarScanner for code analysis
- name: "Install SonarScanner"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-sonarscanner"
version: "5.7.2"
global: "true"
# Report Generator for coverage
- name: "Install ReportGenerator"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-reportgenerator-globaltool"
global: "true"
Version-Specific Installations
# Install specific version
- name: "Install specific EF version"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
version: "7.0.5"
global: "true"
# Install prerelease version
- name: "Install prerelease tool"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-format"
version: "6.0.0-preview.1"
prerelease: "true"
global: "true"
# Install latest stable
- name: "Install latest stable"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-sonarscanner"
global: "true"
Local Tool Installations
# Install to specific directory
- name: "Install to custom path"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-format"
global: "false"
tool-path: "./build-tools"
# Install for local use only
- name: "Install local tool"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "false"
Custom Source Installations
# Install from custom NuGet source
- name: "Install from MyGet"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "custom-analyzer"
source: "https://www.myget.org/F/mycompany/api/v3/index.json"
global: "true"
# Install from Azure Artifacts
- name: "Install from Azure Artifacts"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "internal-tool"
source: "https://pkgs.dev.azure.com/myorg/_packaging/myFeed/nuget/v3/index.json"
global: "true"
env:
NUGET_AUTH_TOKEN: ${{ secrets.AZURE_ARTIFACTS_TOKEN }}
Conditional Installations
# Skip if tool already exists
- name: "Install if not exists"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
skip-if-exists: "true"
# Install based on file existence
- name: "Install EF if migrations exist"
if: hashFiles('**/Migrations/*.cs') != ''
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
# Install based on project type
- name: "Install Web API tools"
if: contains(steps.detect-project.outputs.type, 'web')
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-aspnet-codegenerator"
global: "true"
Architecture-Specific Installations
# Install for specific architecture
- name: "Install x64 tool"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "performance-profiler"
architecture: "x64"
global: "true"
# Install ARM64 tool for Apple Silicon
- name: "Install ARM64 tool"
if: runner.arch == 'ARM64'
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "native-analyzer"
architecture: "arm64"
global: "true"
Batch Tool Installation
strategy:
matrix:
tool:
- { name: "dotnet-ef", version: "latest" }
- { name: "dotnet-format", version: "5.1.250801" }
- { name: "dotnet-sonarscanner", version: "5.7.2" }
- { name: "dotnet-reportgenerator-globaltool", version: "latest" }
steps:
- name: "Install ${{ matrix.tool.name }}"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: ${{ matrix.tool.name }}
version: ${{ matrix.tool.version }}
global: "true"
skip-if-exists: "true"
show-summary: "true"
๐ง Tool Manifest Management
Working with .NET Tool Manifests
The action integrates with .NET tool manifests (.config/dotnet-tools.json):
Create Tool Manifest
- name: "Create tool manifest"
run: dotnet new tool-manifest
- name: "Install tool to manifest"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "false"
Restore from Manifest
- name: "Restore tools from manifest"
if: hashFiles('./.config/dotnet-tools.json') != ''
run: dotnet tool restore
- name: "Install additional tool"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-format"
global: "false"
Example Tool Manifest (.config/dotnet-tools.json)
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "7.0.5",
"commands": ["dotnet-ef"]
},
"dotnet-format": {
"version": "5.1.250801",
"commands": ["dotnet-format"]
}
}
}
๐ฅ๏ธ Requirements
- .NET SDK 6.0 or later installed on the runner
- Internet access to download tools from NuGet sources
- Appropriate permissions for tool installation location
- PowerShell Core (for Windows runners) or Bash (for Unix runners)
๐ Troubleshooting
Common Issues
Tool Installation Fails
Problem: Installation fails with permission or path errors
Solution: Check installation path and permissions:
- name: "Debug tool installation"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
verbosity: "detailed"
show-summary: "true"
- name: "Check tool path permissions"
run: |
echo "User: $(whoami)"
echo "Tool path: ${{ steps.install.outputs.tool-path }}"
ls -la ${{ steps.install.outputs.tool-path }} || echo "Path does not exist"
Version Conflicts
Problem: Tool version conflicts with existing installations
Solution: Use specific versions and check existing tools:
- name: "List existing tools"
run: dotnet tool list --global
- name: "Install specific version"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
version: "7.0.5"
global: "true"
skip-if-exists: "false" # Force reinstall
Custom Source Authentication
Problem: Authentication fails for private NuGet sources
Solution: Configure authentication properly:
- name: "Configure NuGet authentication"
run: |
dotnet nuget add source "https://nuget.example.com/v3/index.json" \
--name "CustomSource" \
--username "${{ secrets.NUGET_USERNAME }}" \
--password "${{ secrets.NUGET_PASSWORD }}" \
--store-password-in-clear-text
- name: "Install from authenticated source"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "private-tool"
source: "https://nuget.example.com/v3/index.json"
global: "true"
Tool Not Found After Installation
Problem: Tool command not available after installation
Solution: Verify PATH configuration:
- name: "Install tool"
id: install
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
show-summary: "true"
- name: "Verify tool availability"
run: |
echo "Tool path: ${{ steps.install.outputs.tool-path }}"
echo "PATH: $PATH"
which dotnet-ef || echo "Tool not in PATH"
dotnet tool list --global | grep dotnet-ef
Debug Mode
Enable comprehensive debugging:
- name: "Debug tool installation"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
verbosity: "diagnostic"
show-summary: "true"
env:
ACTIONS_STEP_DEBUG: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
๐ง Advanced Features
Performance Optimization
# Cache tool installations
- name: "Cache .NET tools"
uses: actions/cache@v3
with:
path: ~/.dotnet/tools
key: dotnet-tools-${{ hashFiles('.config/dotnet-tools.json') }}
- name: "Install tools with cache"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
skip-if-exists: "true"
Tool Version Management
# Update tool to latest version
- name: "Update tool"
run: dotnet tool update --global dotnet-ef
# Uninstall and reinstall
- name: "Reinstall tool"
run: |
dotnet tool uninstall --global dotnet-ef || true
- name: "Install fresh tool"
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
Tool Validation
- name: "Install and validate tool"
id: install
uses: laerdal/github_actions/dotnet-tool-install@main
with:
package-name: "dotnet-ef"
global: "true"
show-summary: "true"
- name: "Validate tool installation"
run: |
if [ "${{ steps.install.outputs.installed }}" = "true" ]; then
echo "โ
Tool installed successfully"
dotnet ef --version
else
echo "โ Tool installation failed"
exit 1
fi
๐ License
This action is part of the GitHub Actions collection by Francois Raminosona.
๐ก Tip: Use this action to standardize .NET tool management across your development workflow and ensure consistent tooling in all environments.