Opt-in via installDotnetTools = true during chezmoi init. This role:
- Installs the .NET SDK via mise (
mise use -g dotnet@latest) — same mechanism asrust_cargo_toolsuses for Rust, so nobrew install dotnet/ Microsoft apt repo /dotnet-install.shdance. - Loops over the
dotnet_toolslist and runsdotnet tool install --global <pkg>for each entry. Binaries land in~/.dotnet/tools, which is auto-added toPATHvia00_exports.zshwhen present.
Shipped tools (default):
| Tool | Binary | Description |
|---|---|---|
| azure-cost-cli | azure-cost |
Cost analysis / anomaly detection / budgets / CI cost gates for Azure subscriptions |
Add more tools by editing dot_ansible/roles/dotnet_tools/defaults/main.yml:
dotnet_tools:
- name: azure-cost-cli
binary: azure-cost
- name: dotnet-ef # EF Core CLI
binary: dotnet-ef
- name: PowerShell # cross-platform PowerShell
binary: pwsh- One SDK manager across the stack. mise already owns Node.js / Rust / (optionally) Python for this repo. Adding
dotnetkeeps every language runtime in one place under~/.local/share/mise/installs/. - No sudo / no system package manager.
mise use -g dotnet@latestworks identically on macOS, Ubuntu with sudo, and UbuntunoRoot. Compare to the previous setup which neededbrew install dotnet,packages-microsoft-prod.deb, ordotnet-install.shdepending on platform. - Global pin lives in
~/.config/mise/config.toml.mise upgrade dotnetpromotes cleanly and other mise tools keep working on their pinned versions. - Shims on PATH.
~/.local/share/mise/shims/dotnetresolvesdotnetautomatically once mise is activated in zsh.
# During chezmoi init
chezmoi init --force # re-prompt; answer y to installDotnetTools
# Or ad-hoc
ansible-playbook ~/.ansible/playbooks/macos.yml --tags dotnet_tools
# Verify
dotnet --version
azure-cost --helpazure-cost-cli wraps the Azure Cost Management API. It reuses the same az login session so as long as Azure CLI (from the iac_tools role) is authenticated, it "just works".
# Accumulated cost (current billing month, active subscription)
azure-cost accumulatedCost
# Specific subscription, forced USD
azure-cost accumulatedCost -s <sub-id> --useUSD
# Top 10 costliest resources, markdown output (PR comments / Job Summary)
azure-cost costByResource --top 10 -o markdown
# Daily trends grouped by service
azure-cost dailyCosts --dimension MeterCategory
# Anomaly detection on the last 7 days
azure-cost detectAnomalies --recent-activity-days 7
# Cost by tag (show-back to teams)
azure-cost costByTag --tag cost-center --tag owner
# Budgets + 🟢 OK / 🟡 AT-RISK / 🔴 EXCEEDED status
azure-cost budgets
# CI cost gate: exit 1 if total > $500
azure-cost accumulatedCost -s <sub-id> -o json --fail-if-over 500 > costs.jsonAuthentication notes:
- Uses
ChainedTokenCredential— picks upaz loginfirst, then env vars / managed identity - Account needs Cost Management Reader on the target scope
- Not all subscription types expose the Cost Management API (sponsored / CSP-tier). See the upstream README for the quota-id compatibility check.
# Upgrade .NET SDK (mise-managed)
mise upgrade dotnet
# or pin a specific channel
mise use -g dotnet@8
# Upgrade a specific global tool
dotnet tool update --global azure-cost-cli
# List installed dotnet global tools
dotnet tool list --globalThe dotnet binary comes in via a mise shim. Ensure mise activate ran in your shell:
# Check shims
ls ~/.local/share/mise/shims/dotnet
# Re-activate mise (should be sourced from your shell config already)
eval "$(mise activate zsh)"dotnet tool install --global puts binaries in ~/.dotnet/tools. That directory is prepended to PATH by ~/.config/zsh/00_exports.zsh only when it exists, so open a fresh shell after the first install:
ls ~/.dotnet/tools/ # should show azure-cost
echo $PATH | tr ':' '\n' | rg dotnet
exec zsh # pick up the PATH updateFor bash, add manually:
echo 'export PATH="$HOME/.dotnet/tools:$PATH"' >> ~/.bashrcThe role refuses to continue and prints a skip warning when mise isn't installed. mise is part of the bootstrap phase (see run_once_before_00_bootstrap.sh.tmpl), so the common cause is a partial bootstrap. Re-run:
curl https://mise.run | sh
chezmoi apply- mise dotnet plugin (asdf-dotnet)
- dotnet tool install docs
- NuGet search for global tools
- docs/tools/infrastructure-as-code.md — Azure CLI / Terraform / OpenTofu (separate
installIacToolsopt-in;az loginhere is the auth source forazure-cost)