Help Generation Deep Dive
This page documents the comment-based help generation pipeline, which transforms inline help in PowerShell functions into comprehensive .mdx documentation files and module help.
Overview
Help generation is a multi-phase process that:
- Inventories functions that still need help
- Applies or regenerates comment-based help with the dedicated helper scripts
- Validates help coverage with ScriptAnalyzer
- Regenerates
.mdxdocumentation from the source help - Optionally exports generated docs for downstream publishing workflows
The pipeline is coordinated by Orchestrate-HelpGeneration.ps1.
For local development, documentation generation ends at updateHelp. The publishDocs step is a CI/export step that copies already-generated docs into .build\docs for downstream publishing automation.
The important distinction in the current repo is that the orchestrator is not a full end-to-end executor. It is best treated as an inventory and guidance entrypoint, while the actual file-writing work is performed by the dedicated scripts in DevOps\Help.
Phases
Phase: Generate
File: Generate-CommentBasedHelp.ps1
Reads comment-based help from function declarations and generates structured help objects.
What it does:
- Parses PowerShell comment blocks (
<#...#>) - Extracts
.SYNOPSIS,.DESCRIPTION,.PARAMETER,.EXAMPLE,.OUTPUTS,.NOTES - Validates required sections are present
- Outputs structured help JSON
Example comment block:
<#
.SYNOPSIS
Retrieves a NinjaOne device by ID.
.DESCRIPTION
Gets the device details for a specified device ID from the NinjaOne API.
Returns comprehensive device information including status, location, and last contact.
.PARAMETER deviceId
The device ID to retrieve
.PARAMETER filter
Optional filter expression to apply
.EXAMPLE
PS> Get-NinjaOneDevice -deviceId 123
Retrieves device with ID 123.
.EXAMPLE
PS> Get-NinjaOneDevice -deviceId 456 -filter "status:active"
Retrieves device 456 with status filter applied.
.OUTPUTS
[PSCustomObject]
Device details object with properties: id, name, status, location, lastContact
.NOTES
Requires authentication via Set-NinjaOneSecrets
#>
function Get-NinjaOneDevice {
# ...
}
Run individually:
pwsh -File .\DevOps\Help\Generate-CommentBasedHelp.ps1
Phase: ApplyPublic
Files: Apply-CommentBasedHelpToFunctions.ps1, Apply-GeneratedHelpToFunctions.ps1
Applies generated or regenerated help blocks to source files.
What it does:
Apply-CommentBasedHelpToFunctions.ps1scans files, generates help for functions missing it, inserts blocks, and validates syntaxApply-GeneratedHelpToFunctions.ps1uses the generated help database and applies help to specific named functionsOrchestrate-HelpGeneration.ps1 -Phase ApplyPubliccurrently prints next-step guidance and does not perform the writes itself
Run individually:
pwsh -File .\DevOps\Help\Apply-CommentBasedHelpToFunctions.ps1 -SourcePath .\Source\Public
Phase: Verify
File: (part of orchestration)
Validates that all public functions have complete help documentation.
Checks:
- All public functions have SYNOPSIS
- Public functions have DESCRIPTION
- Parameter documentation is present in source comments and/or retained help content
- At least one
.EXAMPLEpresent .OUTPUTSsection present when the help block includes one
What passes verification:
<#
.SYNOPSIS
Retrieves device information.
.DESCRIPTION
Gets detailed information about a NinjaOne device.
.PARAMETER deviceId
The device ID
.EXAMPLE
Get-NinjaOneDevice -deviceId 123
.OUTPUTS
[PSCustomObject] Device information
#>
What fails verification:
<#
.SYNOPSIS
Gets a device.
# Missing DESCRIPTION, PARAMETER, EXAMPLE, OUTPUTS
#>
Orchestrate-HelpGeneration.ps1 -Phase Verify currently prints the suggested validation command rather than running a full write-and-verify cycle itself.
Private Function Help
File: Apply-PrivateFunctionHelp.ps1
Generates and applies help for private functions (used internally, not exported).
Purpose:
- Allows module developers to understand internal functions
- Generates help visible via
Get-Helpduring module development - Not included in public-facing documentation
Run individually:
pwsh -File .\DevOps\Help\Apply-PrivateFunctionHelp.ps1
Use the standalone helper directly for private help application. The current orchestrator script advertises an ApplyPrivate phase, but its main execution path does not currently wire that phase in.
Full Request Example Generation
File: Generate-FullRequestExamples.ps1
For POST/PUT/PATCH cmdlets that accept request bodies, this generates realistic example requests from the OpenAPI schema and injects them into help.
Why it exists:
- API request bodies can be complex with many nested objects
- Examples should show real request structure
- Manual examples get outdated when API schema changes
How it works:
- Downloads or loads OpenAPI YAML specification
- Parses request body schema for each endpoint
- Builds minimal example object from schema
- Inserts example into help between markers:
# FULL REQUEST EXAMPLE (AUTO-GENERATED) - BEGIN
$RequestBody = @{
firstName = "John"
lastName = "Doe"
email = "john.doe@example.com"
}
# FULL REQUEST EXAMPLE (AUTO-GENERATED) - END
Run with defaults (downloads from EU tenant):
pwsh -File .\DevOps\Help\Generate-FullRequestExamples.ps1
Target a local OpenAPI file:
pwsh -File .\DevOps\Help\Generate-FullRequestExamples.ps1 -YamlPath C:\NinjaRMM-API-v2.yaml
Target specific endpoint:
pwsh -File .\DevOps\Help\Generate-FullRequestExamples.ps1 -EndpointPath /v2/user/end-users
Target specific cmdlet:
pwsh -File .\DevOps\Help\Generate-FullRequestExamples.ps1 -CommandName New-NinjaOneEndUser
Options:
| Parameter | Default | Purpose |
|---|---|---|
-YamlPath | Downloads from API | Path to local OpenAPI YAML or URL |
-BaseUrl | https://eu.ninjarmm.com | NinjaOne tenant to download schema from |
-SourcePath | Source\Public | Functions to process |
-EndpointPath | (all) | Filter to specific API endpoint |
-CommandName | (all) | Filter to specific cmdlet |
Running the Pipeline
Current Orchestrator Flow
Run the orchestrator when you want the inventory plus the printed next steps:
pwsh -File .\DevOps\Help\Orchestrate-HelpGeneration.ps1 -Phase All
Today, -Phase All is best read as:
- generate the missing-help inventory
- preview the public-apply next step
- print the verification command
Recommended Working Flow
# 1. Generate inventory / review missing help
pwsh -File .\DevOps\Help\Orchestrate-HelpGeneration.ps1 -Phase Generate
# 2. Apply help to public functions
pwsh -File .\DevOps\Help\Apply-CommentBasedHelpToFunctions.ps1 -SourcePath .\Source\Public
# 3. Apply help to private functions if needed
pwsh -File .\DevOps\Help\Apply-PrivateFunctionHelp.ps1
# 4. Regenerate request examples when body schemas changed
pwsh -File .\DevOps\Help\Generate-FullRequestExamples.ps1
# 5. Rebuild generated docs
pwsh -File .\DevOps\Build\build.ps1 -TaskNames generateShortNamesMapping,updateHelp
# 6. Validate with the repo analyzer wrapper
pwsh -File .\DevOps\Quality\run-pssa.ps1
After Help Updates
Local workflow (publishDocs not required):
# 1. Generate new help content
pwsh -File .\DevOps\Help\Orchestrate-HelpGeneration.ps1 -Phase All
# 2. Generate request examples from latest schema
pwsh -File .\DevOps\Help\Generate-FullRequestExamples.ps1
# 3. Update documentation and manifest
pwsh -File .\DevOps\Build\build.ps1 -TaskNames updateHelp
# Optional (CI/export only): copy generated docs to .build\docs for publishing workflows
pwsh -File .\DevOps\Build\build.ps1 -TaskNames publishDocs
updateHelp writes the generated .mdx files to docs\NinjaOne\commandlets, which is the canonical local output to review and commit.
.mdx Documentation Generation
After help content is finalized, updateHelp writes the generated command docs into the repo:
pwsh -File .\DevOps\Build\build.ps1 -TaskNames updateHelp
Canonical local output: docs\NinjaOne\commandlets\
If you also need the export artifact used by publishing automation, run:
pwsh -File .\DevOps\Build\build.ps1 -TaskNames publishDocs
Export output: .build/docs/docs/ninjaone/commandlets/
Each public function generates one .mdx file with:
- Function signature
- Synopsis and description
- Parameter documentation
- Usage examples
- Output object structure
- Links to related functions
Generated file example: Get-NinjaOneDevice.mdx
Troubleshooting Help Generation
"Help generation failed on [phase]"
Check the phase immediately before:
# If ApplyPublic fails:
pwsh -File .\DevOps\Help\Orchestrate-HelpGeneration.ps1 -Phase Generate
# If Verify fails:
pwsh -File .\DevOps\Help\Orchestrate-HelpGeneration.ps1 -Phase ApplyPublic
Treat the orchestrator as inventory plus guidance. If a real write step fails, run the underlying helper script directly so you can see the actual parser or file-write failure.
"Verify phase reports missing documentation"
Use the repo analyzer wrapper, or run the specific help rule directly:
pwsh -File .\DevOps\Quality\run-pssa.ps1
# Or target the help rule directly
Get-ChildItem -Path . -Recurse -File -Include *.ps1,*.psm1,*.psd1 |
Where-Object { $_.FullName -notmatch '\\output\\' -and $_.FullName -notmatch '\\HelpGeneration\\' } |
Invoke-ScriptAnalyzer -Settings .\PSScriptAnalyzerSettings.psd1 -IncludeRule PSRequiredCommentBasedHelp
Add missing sections to function comment blocks:
.SYNOPSIS- One-line summary.DESCRIPTION- Detailed explanation.EXAMPLE- At least one usage example.OUTPUTS- Output type and description
Note that we do not use .PARAMETER sections instead parameters are documented "inline" with comments.
"Generated examples are wrong for my endpoint"
Inspect the OpenAPI schema being used:
# Point at the YAML file:
pwsh -File .\DevOps\Help\Generate-FullRequestExamples.ps1 -YamlPath C:\my-api.yaml -CommandName MyNewFunction -Verbose
# Run just that function:
Get-Content C:\my-api.yaml | Select-String "/v2/path/to/endpoint" -Context 10
If the schema is incorrect, update the OpenAPI YAML or run with -YamlPath pointing to a corrected version.
"Build says UpdateHelp failed but script succeeded"
The build script runs three tasks: generateShortNamesMapping, updateHelp, publishDocs
# Run individually to identify which failed:
pwsh -File .\DevOps\Build\build.ps1 -TaskNames generateShortNamesMapping
pwsh -File .\DevOps\Build\build.ps1 -TaskNames updateHelp
pwsh -File .\DevOps\Build\build.ps1 -TaskNames publishDocs
"Fill parameter Description appears in generated docs"
This indicates stale or incomplete help content. In this repo, the first place to check is the source function's inline parameter comments and comment-based help block.
Regenerate docs after fixing:
pwsh -File .\DevOps\Build\build.ps1 -TaskNames generateShortNamesMapping,updateHelp,publishDocs
"Get-Help returns incomplete information"
Ensure the help was applied to the module:
# Reload the module
Remove-Module NinjaOne -Force -ErrorAction SilentlyContinue
Import-Module .\Output\NinjaOne\2.x.x\NinjaOne.psd1 -Force
# Check help
Get-Help Get-NinjaOneDevice -Full
If still incomplete, regenerate and reapply:
pwsh -File .\DevOps\Help\Orchestrate-HelpGeneration.ps1 -Phase All
pwsh -File .\DevOps\Help\Apply-CommentBasedHelpToFunctions.ps1 -SourcePath .\Source\Public
Comment Block Best Practices
Structure
<#
.SYNOPSIS
One-line description.
.DESCRIPTION
Detailed explanation. Can span multiple lines.
Explain the purpose, behavior, and any important details.
.PARAMETER paramName
Description of this parameter.
.PARAMETER anotherParam
Description of another parameter.
.EXAMPLE
PS> Command-Name -param1 value -param2 value
Explanation of what this example does.
.EXAMPLE
PS> Command-Name -param1 value
Another example showing different usage.
.OUTPUTS
[OutputType]
Description of return value.
.NOTES
Any additional information like authentication requirements.
.LINK
Related function name
#>
SYNOPSIS Style
- One line only, no periods at end
- Verb-noun format preferred
- Be specific: "Retrieves" not "Gets things about"
DESCRIPTION Style
- 2-4 sentences typical
- Explain what it does and why
- Not a tutorial, but clear to first-time users
PARAMETER Style
- Brief description (one sentence if possible)
- Explain valid values for enums
- Document defaults if non-obvious
EXAMPLE Style
- Show realistic usage scenarios
- Include parameters that matter
- Add explanatory comment after
OUTPUTS Style
- Specify type in
[brackets] - List important properties
- Note if output can be $null