Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
3c89c43
feat: add Start-FinOpsMultitool cmdlet for interactive FinOps scanner…
May 19, 2026
1a63159
feat(multitool): cost access warnings, tag query fixes, MG hierarchy …
May 27, 2026
8db8eaa
perf(multitool): optimize tag cost query pacing and filter low-covera…
May 27, 2026
981e4c9
perf: parallel per-sub cost queries in Get-CostByTag
May 27, 2026
d3d7c1f
fix: filter Azure system tags in Get-CostByTag
May 27, 2026
a5fd3e3
fix: dynamic tag cap, remove Contact from system filter
May 27, 2026
54129e2
Add TUI, Hub data routing, and display fixes for FinOps Multitool
May 28, 2026
35790a6
Add TUI README
May 28, 2026
9455685
Add contextual FinOps guidance after each scan result
May 28, 2026
e65b62d
Add tenant picker to TUI for multi-tenant support
May 28, 2026
f09870d
Auto-invoke when script is run directly
May 28, 2026
c735364
Severity-colored guidance with FinOps education context
May 28, 2026
a5e4190
Enrich Hub cost data with live forecast from Cost Management API
May 28, 2026
c976654
Colorize dollar amounts green, budget rows by risk severity
May 28, 2026
1fbc9c0
Fix variable collision: forecast total was overwriting scan count
May 28, 2026
92d17d9
Fix forecast: show full-month projection (actual + remaining forecast)
May 28, 2026
caf4cb2
Fix tag coverage: query ARG for true total/untagged counts when using…
May 28, 2026
62e27b8
Remove Hub coverage caveat from tag guidance, lower resource cost thr…
May 28, 2026
e730754
Fix Cost by Tag guidance: use max untagged cost per tag instead of su…
May 28, 2026
74127a7
Add permission context and diagnostics for missing scan data
May 28, 2026
af92edf
Update TUI README with multi-tenant, guidance, permissions, and Hub e…
May 28, 2026
5215c38
Add styled HTML report export, pre-populated export path, enhanced su…
May 28, 2026
a8654bf
Add MCP server exposing all scan modules as AI-callable tools
May 28, 2026
0d2c2d5
feat(agent-skills): add FinOps multitool skill ecosystem
Jun 1, 2026
0be59a2
Add cost data source routing to FinOps multitool
Jun 1, 2026
3febeda
Fix: throttle-resilient MG cost-scope resolution in FinOps Multitool
Jun 2, 2026
53f9b86
perf(cost-trend): single grouped MG query + single-sub fast path
Jun 2, 2026
f57b4a9
perf(savings): MG query grouped by SubscriptionId + single-sub fast path
Jun 2, 2026
10fc88b
feat(finops-multitool): friendly rotating throttle messages, Budget H…
Jun 2, 2026
cb593b3
feat(finops-multitool): add carbon, unit economics, and legacy resour…
Jun 3, 2026
4f4fee9
fix(finops-multitool): use KQL verbatim string for legacy VM regex
Jun 3, 2026
26d8c1e
feat(finops-multitool): derive AI workload KPIs from FinOps Hub expor…
Jun 3, 2026
9b4e761
Show a single status message while waiting out rate limits
Jun 3, 2026
c779195
Port ResourceId-based cost-by-tag engine to FinOps Multitool
Jun 3, 2026
285239d
Quietly handle management group access denial in hierarchy load
Jun 3, 2026
4802b27
fix(finops-multitool): correct MACC consumption reading (consumed = o…
Jun 4, 2026
e8b1f12
feat(finops-multitool): permission-aware commitment & reservation sca…
Jun 4, 2026
9ee96a4
Update FinOps Multitool
Jun 4, 2026
ad4d9b6
Update FinOps Multitool
Jun 5, 2026
94d31ce
Update FinOps Multitool
Jun 5, 2026
a409555
Update FinOps Multitool
Jun 5, 2026
3c8eaa1
Update FinOps Multitool
Jun 5, 2026
7d6b5e3
Update FinOps Multitool
Jun 6, 2026
78c90ac
Update FinOps Multitool
Jun 6, 2026
423735c
Update FinOps Multitool
Jun 6, 2026
d4ee137
Update FinOps Multitool
Jun 7, 2026
83af32c
Update FinOps Multitool
Jun 7, 2026
6263227
Update FinOps Multitool
Jun 7, 2026
b7f7867
Update FinOps Multitool
Jun 7, 2026
151a223
Update FinOps Multitool
Jun 7, 2026
687bfe9
Update FinOps Multitool
Jun 8, 2026
b550f15
Update FinOps Multitool
Jun 8, 2026
44c1118
Update FinOps Multitool
Jun 11, 2026
8290178
Update FinOps Multitool
Jun 11, 2026
3e6df7c
Update FinOps Multitool
Jun 11, 2026
ead35b3
Update FinOps Multitool
Jun 15, 2026
20474c0
Update FinOps Multitool
Jun 15, 2026
e58931b
Update FinOps Multitool
Jun 15, 2026
532b176
Update FinOps Multitool
Jun 15, 2026
1ef543e
Update FinOps Multitool
Jun 15, 2026
3ba8107
Update FinOps Multitool
Jun 18, 2026
ca47281
Update FinOps Multitool
Jun 19, 2026
ae181d7
Update FinOps Multitool
Jun 19, 2026
0540b94
Update FinOps Multitool
Jul 2, 2026
a13b7a0
Update FinOps Multitool
Jul 2, 2026
8c0dab8
Documentation for multitool
Aug 17, 2026
d551f10
Update FinOps multitool
Aug 17, 2026
959ac15
Update FinOps multitool
Aug 18, 2026
a3ad502
Update FinOps multitool
Aug 18, 2026
59cf0f1
Update FinOps multitool
Aug 18, 2026
caf7d5d
Update FinOps multitool
Aug 20, 2026
19e0d85
Update FinOps multitool
Aug 20, 2026
39eaf0e
Update FinOps multitool
Aug 20, 2026
76910ec
Update FinOps multitool
Aug 20, 2026
5f5deaa
Update FinOps multitool
Aug 20, 2026
a8da2f4
fix(multitool): address review findings 1, 2, 3, 4, 6, 9
Aug 21, 2026
69add06
fix(multitool): correct realized savings math (review finding 7)
Aug 21, 2026
4974f36
fix(multitool): resolve explicit subscription scope before the picker…
Aug 21, 2026
08e945a
fix(multitool): project scan results to flat rows before CSV export (…
Aug 21, 2026
5e3a1b2
fix(multitool): support consoles without arrow-key input and add a no…
Aug 22, 2026
ddc72db
fix(multitool): remove the unreachable write path and correct the doc…
Aug 22, 2026
fa442bf
chore(multitool): remove a scratch test script committed by mistake
Aug 22, 2026
4e4615e
Merge origin/dev into feature/finops-multitool
Aug 22, 2026
a9f1690
docs(multitool): drop the production safety claim from the read-only …
Aug 22, 2026
6311634
fix(multitool): render scan guidance in the HTML report and scope the…
Aug 22, 2026
9a8fcf4
chore(multitool): remove three unreachable modules
Aug 22, 2026
b336ab0
fix(multitool): address the three issues from the 08/23 review
Aug 24, 2026
cdb9680
Merge remote-tracking branch 'origin/dev' into feature/finops-multitool
Aug 24, 2026
801c6ac
fix(multitool): correct tag allocation KPIs and measure coverage per …
Aug 24, 2026
6744f0a
chore(multitool): ignore the scan output folder
Aug 24, 2026
05c00ea
fix(multitool): default export path outside the working folder
Aug 24, 2026
6478445
Update FinOps Multitool
Aug 25, 2026
b92ac4f
Update FinOps Multitool
Aug 25, 2026
5588974
Update FinOps Multitool
Aug 25, 2026
e6ab672
Update FinOps Multitool
Aug 25, 2026
bd868d1
Update FinOps Multitool
Aug 25, 2026
3d14bbb
Update FinOps Multitool
Aug 25, 2026
fa57b3d
Update FinOps Multitool
Aug 25, 2026
5478627
Update FinOps Multitool
Aug 25, 2026
c10ee78
Update FinOps Multitool
Aug 25, 2026
3c3b3b7
Update FinOps Multitool
Aug 25, 2026
3d14393
Update FinOps Multitool
Aug 25, 2026
82558ef
Update FinOps Multitool
Aug 25, 2026
e5ab880
Update FinOps Multitool
Aug 25, 2026
736bb27
Update FinOps Multitool
Aug 25, 2026
346c405
Update FinOps Multitool
Aug 26, 2026
20c38f3
Update FinOps Multitool
Aug 26, 2026
f5c1d60
Update FinOps Multitool
Aug 26, 2026
fcb24ab
Update FinOps Multitool
Aug 26, 2026
4037641
Merge remote-tracking branch 'origin/dev' into feature/finops-multitool
Aug 26, 2026
bf2d27b
Update FinOps Multitool
Aug 27, 2026
859178d
Merge remote-tracking branch 'origin/dev' into feature/finops-multitool
Sep 7, 2026
215001f
Update FinOps Multitool
Sep 7, 2026
4c5ec11
FinOps Multitool Update - Sep 07-08 Review findings
Sep 9, 2026
ab1c349
FinOps Multitool Update - Sep 07-08 Review findings
Sep 9, 2026
cc458b4
FinOps Multitool Update - Sep 07-08 Review findings
Sep 9, 2026
595ca0a
FinOps Multitool Update - Sep 07-08 Review findings
Sep 9, 2026
940c027
FinOps Multitool Update - Sep 07-08 Review findings
Sep 9, 2026
97a7159
Update FinOps Multitool
Sep 9, 2026
45f6a4e
Update FinOps Multitool
Sep 9, 2026
4c99844
FinOps Multitool Update - Sep 09-14 Review findings
Sep 14, 2026
435e895
FinOps Multitool Update - Sep 14 Review findings
Sep 15, 2026
89fb634
FinOps Multitool Update - Sep 14 Review findings
Sep 15, 2026
582ff2f
FinOps Multitool Update - Sep 14 Review findings
Sep 15, 2026
93b0339
FinOps Multitool Update - Sep 14 Review findings
Sep 15, 2026
478ab89
Documentation update
Sep 15, 2026
8ce188f
Update documentation
Sep 15, 2026
1d90c50
FinOps Multitool Update - Sep 15 Review findings
Sep 15, 2026
582aca3
FinOps Multitool Update - Sep 15 Review findings
Sep 15, 2026
250652f
Merge remote-tracking branch 'origin/dev' into feature/finops-multitool
Sep 15, 2026
018dba5
FinOps Multitool Update - Sep 15 Review findings
Sep 16, 2026
b37d3e9
FinOps Multitool Update - Sep 15 Review findings
Sep 16, 2026
8b1d68c
FinOps Multitool Update - Sep 16 Review findings
Sep 16, 2026
d3c99d1
FinOps Multitool Update - Sep 16 Review findings
Sep 16, 2026
1fe0cda
Documentation update
Sep 16, 2026
9fd8a4c
FinOps Multitool Update - Sep 16 Review findings
Sep 17, 2026
e11f860
chore: merge dev into finops-multitool
Sep 17, 2026
1af4f06
fix(multitool): FinOps Multitool Update - Sep 17 Review findings
Sep 17, 2026
787504a
fix(multitool): FinOps Multitool Update - Sep 17 Review findings
Sep 17, 2026
791de7d
fix(multitool): FinOps Multitool Update - Sep 17-18 Review findings
Sep 18, 2026
839276d
fix(multitool): auto-save reports and correct Hub output
Sep 19, 2026
dc5be03
fix(multitool): improve reports and policy coverage
Sep 20, 2026
7de42fc
fix(multitool): harden data handling
Sep 20, 2026
ed43aab
fix(multitool): honor budget history filters
Sep 20, 2026
87e03fa
fix(multitool): handle incomplete scan results
Sep 21, 2026
ae36741
fix(multitool): FinOps Multitool Update - Sep 23-24 Review findings
Sep 24, 2026
f11f861
fix(ci): scope multitool temporary paths to test steps
Sep 24, 2026
a1b3537
feat(multitool): explain KPI values and scan thresholds
Sep 24, 2026
fe9ddf1
fix(multitool): FinOps Multitool Update - Sep 30-Oct 01 Review findings
Oct 1, 2026
0962de3
feat(multitool): add Cost Management export source and apply Oct 1-2 …
Oct 2, 2026
2dc0e1b
Update FinOps Multitool
Oct 3, 2026
fae5ce0
Update FinOps Multitool
Oct 4, 2026
fba4d01
Update FinOps Multitool
Oct 4, 2026
0989e6d
Update FinOps Multitool
Oct 7, 2026
825d895
FinOps Multitool Update - Oct 07 Review findings
Oct 8, 2026
a678205
Update FinOps Multitool
Oct 8, 2026
4f6f913
FinOps Multitool Update - Oct 07-08 Review findings
Oct 8, 2026
278b7ae
FinOps Multitool Update - Oct 08-10 Review findings
Oct 11, 2026
a115283
Update FinOps Multitool
Oct 12, 2026
6cc7d31
Merge remote-tracking branch 'origin/dev' into feature/finops-multitool
Oct 13, 2026
80c11ab
FinOps Multitool Update - Oct 14 Review findings
Oct 14, 2026
60a2fdb
Merge remote-tracking branch 'origin/dev' into feature/finops-multitool
Oct 14, 2026
0a1cab8
FinOps Multitool Update - Oct 14 CI findings
Oct 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .build/BuildHelper/Build-PsModule.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ function Build-PsModule
$moduleName = 'FinOpsToolkit'
$moduleFullName = "$moduleName.psm1"
$modulePath = Join-Path -Path $rootPath -ChildPath "src/powershell/$moduleFullName"
$privatePath = Join-Path -Path $rootPath -ChildPath "src/powershell/private"
$publicPath = Join-Path -Path $rootPath -ChildPath "src/powershell/public"
$privatePath = Join-Path -Path $rootPath -ChildPath "src/powershell/Private"
$publicPath = Join-Path -Path $rootPath -ChildPath "src/powershell/Public"
$stringsPath = Join-Path -Path $rootPath -ChildPath 'src/powershell/en-US'
$releasePath = Join-Path -Path $rootPath -ChildPath "release/$moduleName/$baseVersion"
$manifestPath = Join-Path -Path $releasePath -ChildPath "$moduleName.psd1"
Expand Down
130 changes: 130 additions & 0 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ name: 'PowerShell Tests'
on:
pull_request:
paths:
- '.github/workflows/dev.yml'
- '.build/BuildHelper/**'
- '.build/BuildHelper.psm1'
- 'package.json'
- 'src/scripts/Get-Version.ps1'
- 'src/powershell/**'
# KQL sources are covered by unit tests (HubsKqlOperators.Tests.ps1)
- 'src/templates/finops-hub/**/*.kql'
Expand All @@ -11,6 +16,10 @@ on:
- 'src/templates/finops-hub/**/timeZones.bicep'
- 'docs/deploy/finops-hub-latest.json'
- 'docs/deploy/finops-hub-preview.json'

permissions:
contents: read

jobs:
run_pester_tests:
name: Pester
Expand All @@ -25,3 +34,124 @@ jobs:
- name: Run Tests
shell: pwsh
run: .build/start.ps1 -Task Test.PowerShell.All

multitool_native:
name: Multitool (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
env:
DOTNET_CLI_TELEMETRY_OPTOUT: '1'
DOTNET_NOLOGO: '1'
steps:
- name: Install and cache test dependencies
uses: potatoqualitee/psmodulecache@9e4b63833c22c1768d648e115a9c849afdda22a5 # v6.3
with:
modules-to-cache: Pester:6.0.0, Az.Accounts, Az.Resources, Az.ResourceGraph, Az.Storage
shell: pwsh
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install SDK for native Parquet restore
if: runner.os == 'Linux'
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5
with:
dotnet-version: '8.0.x'
- name: Run native multitool tests
shell: pwsh
env:
TMPDIR: ${{ runner.temp }}
run: |
$ErrorActionPreference = 'Stop'
Import-Module Pester -RequiredVersion 6.0.0 -Force
$names = @(
'AzGraphPagination', 'BudgetCoverage', 'CommitmentUtilizationDedupe'
'CostQueryPagination', 'CurrencyLabel', 'FOHubProvider', 'HubSizeProbe'
'MultitoolResultIntegrity', 'MultitoolSafety', 'ParquetPackageClient', 'PolicyEffect'
'RetryJitter', 'Start-FinOpsMultitool'
)
$paths = @($names | ForEach-Object {
Join-Path 'src/powershell/Tests/Unit' "$_.Tests.ps1"
})
foreach ($path in $paths) {
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { throw "Missing test: $path" }
}
$configuration = New-PesterConfiguration
$configuration.Run.Path = $paths
$configuration.Run.PassThru = $true
$configuration.Run.Exit = $false
$configuration.Output.Verbosity = 'Detailed'
$configuration.TestResult.Enabled = $true
$configuration.TestResult.OutputFormat = 'NUnitXml'
$configuration.TestResult.OutputPath = Join-Path $env:RUNNER_TEMP 'multitool-unit.xml'
$result = Invoke-Pester -Configuration $configuration
$result | Select-Object Result, TotalCount, PassedCount, FailedCount, SkippedCount, FailedContainersCount
@(
'## Multitool validation'
"Tested merge commit: $env:GITHUB_SHA"
"Host: $([Runtime.InteropServices.RuntimeInformation]::OSDescription); PowerShell: $($PSVersionTable.PSVersion)"
"Unit tests: $($result.Result); passed $($result.PassedCount), failed $($result.FailedCount), skipped $($result.SkippedCount)."
) | Add-Content -LiteralPath $env:GITHUB_STEP_SUMMARY
if ($null -eq $result -or $result.Result -ne 'Passed' -or
$result.TotalCount -le 0 -or $result.PassedCount -le 0 -or
$result.FailedCount -ne 0 -or $result.FailedContainersCount -ne 0 -or
$result.FailedBlocksCount -ne 0 -or $result.Containers.Count -ne $paths.Count) {
throw 'Native multitool tests failed or discovery was incomplete.'
}
exit 0
- name: Run package and real Parquet integration tests
if: ${{ !cancelled() }}
shell: pwsh
env:
TMPDIR: ${{ runner.temp }}
run: |
$ErrorActionPreference = 'Stop'
Import-Module Pester -RequiredVersion 6.0.0 -Force
$paths = @('src/powershell/Tests/Integration/MultitoolPackage.Tests.ps1')
$minimumPassed = 3
$parquetCoverage = 'Not run on macOS: NuGet signed-package verification is not supported. https://learn.microsoft.com/dotnet/core/tools/nuget-signed-package-verification#macos'
if (-not $IsMacOS) {
$paths += 'src/powershell/Tests/Integration/MultitoolParquet.Tests.ps1'
$minimumPassed += 2
$parquetCoverage = 'Real signed Parquet restore and cold/cached reads in separate processes.'
}
foreach ($path in $paths) {
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { throw "Missing test: $path" }
}
$configuration = New-PesterConfiguration
$configuration.Run.Path = $paths
$configuration.Run.PassThru = $true
$configuration.Run.Exit = $false
$configuration.Output.Verbosity = 'Detailed'
$configuration.TestResult.Enabled = $true
$configuration.TestResult.OutputFormat = 'NUnitXml'
$configuration.TestResult.OutputPath = Join-Path $env:RUNNER_TEMP 'multitool-integration.xml'
$result = Invoke-Pester -Configuration $configuration
$result | Select-Object Result, TotalCount, PassedCount, FailedCount, SkippedCount, FailedContainersCount
@(
"Integration tests: $($result.Result); passed $($result.PassedCount), failed $($result.FailedCount), skipped $($result.SkippedCount)."
'Checks: isolated module build and public launch; CSV, HTML, and text reports.'
"Parquet coverage: $parquetCoverage"
'Azure access is replaced with synthetic responses. Package downloads and signature verification require network access.'
) | Add-Content -LiteralPath $env:GITHUB_STEP_SUMMARY
if ($null -eq $result -or $result.Result -ne 'Passed' -or
$result.PassedCount -lt $minimumPassed -or $result.FailedCount -ne 0 -or
$result.SkippedCount -ne 0 -or $result.NotRunCount -ne 0 -or
$result.FailedContainersCount -ne 0 -or $result.FailedBlocksCount -ne 0 -or
$result.Containers.Count -ne $paths.Count) {
throw 'Multitool integration tests failed, were skipped, or discovery was incomplete.'
}
exit 0
- name: Upload multitool test evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: multitool-tests-${{ matrix.os }}
path: |
${{ runner.temp }}/multitool-unit.xml
${{ runner.temp }}/multitool-integration.xml
if-no-files-found: error
retention-days: 14
12 changes: 12 additions & 0 deletions docs-mslearn/TOC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,12 @@
href: toolkit/alerts/finops-alerts-overview.md
- name: Configure alerts
href: toolkit/alerts/configure-finops-alerts.md
- name: FinOps multitool
items:
- name: Overview
href: toolkit/multitool/finops-multitool-overview.md
- name: Commands
href: toolkit/powershell/multitool/finops-multitool-commands.md
- name: Optimization engine
items:
- name: Overview
Expand Down Expand Up @@ -242,6 +248,12 @@
href: toolkit/powershell/cost/remove-finopscostexport.md
- name: Start-FinOpsCostExport
href: toolkit/powershell/cost/start-finopscostexport.md
- name: FinOps multitool
items:
- name: FinOps multitool commands
href: toolkit/powershell/multitool/finops-multitool-commands.md
- name: Start-FinOpsMultitool
href: toolkit/powershell/multitool/start-finopsmultitool.md
- name: FinOps hubs
items:
- name: FinOps hubs commands
Expand Down
Loading