feat!: Migrate markdown and MAML help to Microsoft.PowerShell.PlatyPS 1.x - #173
feat!: Migrate markdown and MAML help to Microsoft.PowerShell.PlatyPS 1.x#173tablackburn wants to merge 3 commits into
Conversation
… 1.x Closes #150. Closes #151. Part of #105, Phase 2 of #120. BREAKING CHANGE: help generation uses Microsoft.PowerShell.PlatyPS 1.x, PlatyPS is no longer a required module, and $PSBPreference.Docs.AlphabeticParamsOrder is removed. The two functions are migrated together because they cannot be split: 2b changes the on-disk markdown schema that an unmigrated Build-PSBuildMAMLHelp would be handed, and the two PlatyPS modules cannot be loaded into one psake session. The 1.x API is not a rename. Three of its differences shape this change: - New-MarkdownCommandHelp and Export-MamlCommandHelp both write to <OutputFolder>/<ModuleName>/, a level deeper than 0.14.x, and the MAML file name comes from the document's front matter with different casing. Both functions generate into a staging directory and move the results, so the published layout stays <Docs.RootDir>/<locale>/<Command>.md and <ModuleOutDir>/<locale>/<ModuleName>-help.xml. Consumers' committed docs trees, site configuration, and .ExternalHelp directives keep working, and tests/build.tests.ps1 already pinned that contract. - Without -Force, both skip existing files with a warning rather than an error, so an Overwrite = $false build would silently produce nothing. Existing documents are refreshed with Update-MarkdownCommandHelp, which preserves hand-written prose, and only new documents are moved in. - A module landing page imports as a CommandHelp but fails on export, and that failure aborts the batch and writes nothing. Landing pages are filtered out with Measure-PlatyPSMarkdown rather than caught. PlatyPS is deliberately NOT in RequiredModules. Adding it there failed 394 tests locally: RequiredModules forces the load into every session that imports PowerShellBuild, and a session already holding platyPS 0.14.2 cannot then load 1.x -- both ship their own YamlDotNet with different assembly identities. Every consumer mid-upgrade is in exactly that state. An optional dependency also matches how the docs tasks have always behaved, probing with Get-Module -ListAvailable and skipping. For the same reason Build-PSBuildUpdatableHelp no longer names New-ExternalHelpCab. Merely resolving that command autoloads platyPS 0.14.2 and poisons the session against 1.x. It warns and returns until #152 migrates the cabinet pipeline; it could never succeed before either, see #169. AlphabeticParamsOrder has no 1.x equivalent -- ordering is unconditional now -- so keeping the setting would have been a lie. UseFullTypeName survives unchanged: 1.x inverted the sense of the option, so $false maps to -AbbreviateParameterTypeName. Suite: 460 passed, 0 failed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012AKaM9i6NyMFDcJNeC34h5
The entry was inserted by a script that joined lines with CRLF and then converted newlines again, turning every added line ending into \r\r\n. That rewrote the whole file as far as git was concerned, burying a twenty-line addition in a 691-line diff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012AKaM9i6NyMFDcJNeC34h5
There was a problem hiding this comment.
Pull request overview
This pull request migrates PowerShellBuild’s markdown and MAML help generation from platyPS 0.14.x to Microsoft.PowerShell.PlatyPS 1.x while preserving the existing on-disk output layout expected by downstream consumers, and makes the new PlatyPS dependency optional to avoid load conflicts during upgrades.
Changes:
- Update
Build-PSBuildMarkdownandBuild-PSBuildMAMLHelpto use PlatyPS 1.x cmdlets, including staging+flattening to preserve existing docs/help output paths and file naming. - Remove the
platyPSRequiredModulesdependency (PlatyPS becomes optional) and update psake/InvokeBuild tasks and tests to probe forMicrosoft.PowerShell.PlatyPS. - Stub
Build-PSBuildUpdatableHelpto warn-and-return without referencing legacy PlatyPS cmdlets, pending the #152 migration.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
PowerShellBuild/Public/Build-PSBuildMarkdown.ps1 |
Migrates markdown generation to PlatyPS 1.x, refreshes existing docs, and stages output to preserve the <Docs>/<locale> layout. |
PowerShellBuild/Public/Build-PSBuildMAMLHelp.ps1 |
Migrates MAML export to PlatyPS 1.x via import/export pipeline and stages output to preserve the <Out>/<locale>/<Module>-help.xml layout. |
PowerShellBuild/Public/Build-PSBuildUpdatableHelp.ps1 |
Temporarily stubs updatable help generation to avoid autoloading legacy platyPS during partial upgrades. |
PowerShellBuild/psakeFile.ps1 |
Updates docs task preconditions and parameters to use the new PlatyPS module name and removes the removed docs preference. |
PowerShellBuild/IB.tasks.ps1 |
Mirrors the psake task updates for InvokeBuild consumers. |
PowerShellBuild/PowerShellBuild.psd1 |
Removes platyPS from RequiredModules to keep PlatyPS optional. |
requirements.psd1 |
Replaces the platyPS dependency with Microsoft.PowerShell.PlatyPS 1.0.3 for bootstrap installs. |
PowerShellBuild/build.properties.ps1 |
Removes AlphabeticParamsOrder and updates docs preference comments for PlatyPS 1.x behavior. |
PowerShellBuild/en-US/Messages.psd1 |
Adds a localized warning message for the updatable-help stub behavior. |
tests/Build-PSBuildHelp.tests.ps1 |
Updates tests to detect PlatyPS 1.x schema markers and validates flattening behavior; updates updatable-help expectations for the stubbed function. |
tests/fixtures/FixtureHelpers.psm1 |
Updates helper parameter scaffolding for the changed Build-PSBuildMarkdown signature. |
docs/migration-v0.8-to-v1.0.md |
Adds migration guide entries describing the PlatyPS 1.x move, optional dependency, schema change, and temporary updatable-help unavailability. |
CHANGELOG.md |
Records the breaking help-generation migration and associated behavioral changes. |
instructions/repository-specific.instructions.md |
Updates dependency documentation to reference Microsoft.PowerShell.PlatyPS as optional. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| $newMarkdownParams = @{ | ||
| ModuleInfo = $moduleInfo | ||
| OutputFolder = $stagingPath | ||
| Locale = $Locale | ||
| Verbose = $VerbosePreference | ||
| } |
There was a problem hiding this comment.
Good catch on the line, though the mechanism is not quite that — and chasing it down turned up a real defect, so this is fixed in 2ec2ea1.
$VerbosePreference is an ActionPreference enum, not a string, and binding it to a cmdlet's common -Verbose parameter converts by the underlying number rather than by truthiness. Measured on PowerShell 7.6.5 against a cmdlet that actually emits verbose output:
SilentlyContinue -> OK, verbose records emitted: 0
Continue -> OK, verbose records emitted: 1
So the default case behaves correctly, and the two most common values work. It is not "any non-empty string coerces to $true".
The real defect is narrower and still worth fixing: because the conversion is numeric, Stop (1) and Inquire (3) also bind as $true, so setting either turns verbose output on despite neither asking for it. Build-PSBuildMAMLHelp already used the explicit comparison in this same pull request, so the two functions disagreed with each other. Both now use:
Verbose = ($VerbosePreference -eq 'Continue')One boundary worth recording for anyone who finds this thread later: the same splat against a custom function's own [switch]$Verbose parameter does not silently coerce at all, it throws — Invalid cast from 'System.Management.Automation.ActionPreference' to 'System.Management.Automation.SwitchParameter'. Cmdlet common parameters and script-function switch parameters take different binding paths here.
Suite after the change: 460 passed, 0 failed.
Test Results 4 files ± 0 724 suites - 8 4m 30s ⏱️ -44s Results for commit 2ec2ea1. ± Comparison against base commit 51468d0. This pull request removes 10 and adds 4 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
…ename PlatyPS 1.x names the MAML file after the document's "external help file" front matter key, which it defaults to "<Module>-Help.xml" where 0.14.x wrote "<Module>-help.xml". The previous commit corrected the casing by renaming the file after export, which fixed the name and left the markdown still claiming the other one. That disagreement is the exact condition upstream punishes: PowerShell/platyPS#797 was closed as expected behavior with "You need to be consistent with the name you use in .EXTERNALHELPFILE", because inconsistent names across a batch cause files to be silently skipped or truncated. Build-PSBuildMarkdown now sets the key explicitly through -Metadata, so the markdown, the exported MAML file name, and any existing .ExternalHelp directive all agree, and the export step no longer renames anything. Verified: generated front matter reads "external help file: TestModule-help.xml" and the exported file matches. Suite: 460 passed, 0 failed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012AKaM9i6NyMFDcJNeC34h5
Closes #150. Closes #151. Part of #105 (PlatyPS migration), Phase 2 of #120.
The first consumer-breaking change of the 1.0.0 cycle. Migration guide entries included.
Build-PSBuildMarkdownandBuild-PSBuildMAMLHelpmove toMicrosoft.PowerShell.PlatyPS1.x together, as the route decision on #120 settled — 2b changesthe on-disk markdown schema that an unmigrated
Build-PSBuildMAMLHelpwould be handed, and thetwo PlatyPS modules cannot be loaded into one psake session.
Baseline to regress against: #170, merged.
The 1.x API is not a rename
Three differences shaped the implementation, all found by running the module rather than reading
its docs (it ships no help content):
Both commands nest their output one level deeper.
New-MarkdownCommandHelpandExport-MamlCommandHelpwrite to<OutputFolder>/<ModuleName>/, and the MAML file name comesfrom the document's front matter — including a casing change from
-help.xmlto-Help.xml.Both functions now generate into a staging directory and move the results, so the published
layout is unchanged:
<Docs.RootDir>/<locale>/<Command>.md<ModuleOutDir>/<locale>/<ModuleName>-help.xmlThat is not a preference.
tests/build.tests.ps1already asserted<out>/en-US/TestModule-help.xml, and consumers' committed docs trees, static-siteconfiguration, and
.ExternalHelpdirectives all point at the old layout. On a case-sensitivefilesystem the casing change alone would silently break help lookup.
Neither command errors on an existing file. Without
-Forcethey skip with a warning andreturn nothing, so an
Overwrite = $falsebuild would quietly produce zero files and reportsuccess. Existing documents are refreshed with
Update-MarkdownCommandHelp— which preserveshand-written prose where regenerating would destroy it — and only genuinely new documents are
moved in.
-NoBackupkeeps it from littering the docs tree with.md.bakfiles.A module landing page poisons the MAML export.
Import-MarkdownCommandHelpaccepts onewithout complaint and returns a bogus
CommandHelp; exporting it throws and aborts the wholebatch, writing nothing. Landing pages are filtered out with
Measure-PlatyPSMarkdownratherthan caught, since by then the batch is already lost.
PlatyPS is deliberately not a required module
This is the part I would most like reviewed.
Adding
Microsoft.PowerShell.PlatyPStoRequiredModulesfailed 394 tests locally — thesuite dropped from 461 passing to 67. Removing that one line restored it to 458.
RequiredModulesforces the module to load into every session that imports PowerShellBuild, including builds
that never generate documentation, and a session already holding
platyPS0.14.2 then cannotload 1.x at all:
Every consumer part-way through this upgrade is in exactly that state. An optional dependency
also matches how the docs tasks have always behaved — they probe with
Get-Module -ListAvailableand skip with a warning — so a hard import-time requirement was arguably always the wrong shape
for an opt-in feature.
The cost is real and is in the migration guide:
Install-Module PowerShellBuildno longerinstalls PlatyPS.
Why
Build-PSBuildUpdatableHelpis stubbedSame root cause, and it surprised me. Merely naming
New-ExternalHelpCabis enough — resolvingthat command autoloads
platyPS0.14.2, which then locks 1.x out of the session:So the "leave updatable help on the old module until #152" intermediate I proposed on #120 does
not actually work. The function now warns and returns, naming no PlatyPS command at all. It could
never succeed in 0.8.x either — see #169, three separate defects — so nothing regresses, and #152
implements it properly. Its parameters are kept so the public signature does not change twice.
Settings
$PSBPreference.Docs.AlphabeticParamsOrderis removed. PlatyPS 1.x always sortsalphabetically and offers no way back, so the setting could only have lied.
UseFullTypeNamesurvives unchanged. 1.x inverted the sense of the option — full names arenow the default — so
$falsemaps to-AbbreviateParameterTypeNameand behavior is preserved.ExcludeDontShowmaps directly.A correction to something I put on #120
I claimed repeatedly that nothing observes these functions, and that the repository does not run
its own docs tasks. The second half is true — the root
psakeFile.ps1never invokes them — butthe conclusion was wrong.
tests/build.tests.ps1buildstests/TestModulethrough-FromModule PowerShellBuild, whoseBuildtask depends onBuildHelp, soGenerateMarkdownand
GenerateMAMLare exercised end to end, andHas MAML help XMLhas been asserting theoutput layout in two contexts all along. Only
GenerateUpdatableHelpwas genuinely unobserved.That existing coverage is what pinned the layout contract this PR preserves. I will correct the
Docs task coverage row on #120.
Verification
tests/build.tests.ps1exercises the real pipeline end to end and still passes in both thecompile and dot-source contexts
schema: 2.0.0, and that no<ModuleName>directory appears under the locale folderMicrosoft.PowerShell.PlatyPS1.0.3 confirmed to import on Windows PowerShell 5.1, re-checkingthe support-floor decision rather than trusting it
Not included
-WithModulePage. 0.14.x never generated a module landing page, and generating one now would adda file to every consumer's docs tree. It belongs with #152, which needs it for the cabinet step.