Feature/multi tenant report#1558
Conversation
- New TenantContext provider for tenant selection state management - Tenant selector in sidebar (visible when multiple tenants present) - All pages use useTenant() hook instead of direct testResults import - New Merge-MtMaesterResult function to combine tenant results - Updated Get-MtHtmlReport with proper JSON depth and marker validation - Full dark mode support across all pages - Backwards compatible: single-tenant reports work unchanged
Demonstrates how to run Maester against multiple tenants using separate service connections and merge results into a single HTML report with tenant selector.
Example pipeline now supports Global, China (21Vianet) and other cloud environments via an environment parameter per tenant. Get-MtHtmlReport uses -Compress and LastIndexOf to fix blank reports. Added blog post for multi-tenant reports feature.
ConfigPage state (emergency accounts, test settings) was not resetting when switching tenants, leaking previous tenant config. Added useEffect to reset state when tenant changes. Get-MtHtmlReport now handles both Vite minifier formats (classic testResults= and newer mangled variable names with backtick strings) using LastIndexOf and pattern scanning. Also uses -Compress to prevent newlines breaking minified JS.
Added Merge-MtMaesterResult.ps1 and New-MtMultiTenantHtmlReport.ps1 to powershell/examples so people can copy them into their repos. Fixed missing -AsSecureString on Teams token request. Updated blog post with prerequisites, parameter docs, and full pipeline YAML with China cloud support.
The environment switch only handled China and Global. Added all national cloud endpoints for Graph, Exchange and Compliance.
Since the blog post ships with the release, Merge-MtMaesterResult and Get-MtHtmlReport are part of the installed module. Removed standalone New-MtMultiTenantHtmlReport and dot-source references from the example pipeline and blog post.
… diff - Added 16 Pester tests covering Merge-MtMaesterResult and Get-MtHtmlReport for both single and multi-tenant scenarios - Exported Merge-MtMaesterResult in module manifest - Fixed operator precedence bug in validation (-not -contains) - Reverted SettingsPage dark mode changes to keep diff minimal (pre-existing issue, not related to multi-tenant feature)
- Add 3+ tenant merge test and empty TenantName edge case - Add ReportTemplate.html availability check with graceful skip
- Get-MtMaesterConfig: add -TenantId parameter with GUID validation,
look for maester-config.{tenantId}.json with fallback to default
- Invoke-Maester: resolve tenant ID from MgContext for config lookup
- ConfigPage: show loaded config filename for multi-tenant reports only
- Add Pester tests for tenant-specific config, fallback, and GUID validation
- Rebuild ReportTemplate.html with updated ConfigPage
- Add tenant-specific config section to blog post
- Add sample report generator and pre-built HTML reports
|
@SebastianClaesson this is super neat!! Wow. Love it. Thank you so much for going into detail in the blog post. If I can make a suggestion, it will be good to update the site navigation to include a new 'Multi-tenant' section and include most of the content from the blog post including the overview and how to combine with the cmdlet and pipeline. We can then update the blog post to be just the announcement about the new feature and point the user to the docs page. This is because the blogs page will move down and it will be hard for folks to navigate and find out about this feature. Thanks for samples folder it was handy, feel free to remove it though, it clutters the repo. |
… samples Move substantive multi-tenant content from the blog post into a proper docs section (overview, merging results, configuration, Azure DevOps pipeline) so users can find it via site navigation. Trim the blog post to a short announcement linking to the docs. Delete the samples/ folder as requested by the project owner. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
I have now broken out the instructions into the docs - great call! Samples folders has also been removed :) |
Not up to standards ⛔
|
Keep upstream's function wrapper and indented comment block while preserving our multi-tenant documentation additions and example.
|
The 4 test failures are pre-existing in main and unrelated to this PR. They come from PSScriptAnalyzer's PSUseSingularNouns rule flagging three AI agent test files that were recently added to main:
None of the multi-tenant changes in this PR are affected. |
Description
Multi-Tenant Report Support
Adds the ability to run Maester tests across multiple tenants and view all results in a single HTML report with a tenant selector sidebar.
Fixes #1551
What's new
PowerShell:
Merge-MtMaesterResult(new exported function) — merges multiple Invoke-Maester -PassThru results into a single object with a Tenants arrayGet-MtHtmlReport— now supports both single-tenant and multi-tenant result objectsGet-MtMaesterConfig— new -TenantId parameter enables tenant-specific config files (maester-config.{tenantId}.json) with automatic fallback to maester-config.jsonInvoke-Maester— automatically resolves the connected tenant ID and passes it to config lookupReport UI (React):
TenantContext— new React context that normalizes single/multi-tenant data and manages tenant selectionExamples & Docs:
powershell/examples/multi-tenant-pipeline.yml— full Azure DevOps pipeline example with per-tenant service connections, supporting Global, China, USGov, USGovDoD, and Germany cloud environmentsBackward compatibility
Single-tenant reports are unaffected. The
TenantContextwraps legacy single-tenant data in a one-element array and all pages use a destructured alias (const { selectedTenant: testResults } = useTenant()) that preserves existing property access. The tenant selector is hidden for single-tenant reports. The-TenantIdparameter inGet-MtMaesterConfigis optional and only activates when a valid GUID is provided.Tenant-specific configuration
Each tenant can have its own config file named
maester-config.{tenantId}.json. Resolution order:maester-config.{tenantId}.json(if connected to Graph and file exists)maester-config.json(default fallback)Custom/maester-config.json(merged on top, existing behavior)How to test
Open the sample reports in
samples/to verify:sample-report-single-tenant.html— no tenant selector, no ConfigSource banner, everything works as beforesample-report-multi-tenant.html— tenant selector in sidebar, switch between 3 tenants, Config page shows "Loaded from" per tenantContribution Checklist
Before submitting this PR, please confirm you have completed the following:
/powershell/tests/pester.ps1on your local system. (All 4317 tests passed, zero failures. )