Development and CI
Directory Layout
src/ Generator module
src/Public/ Exported commands
src/Private/ Internal functions
src/Plugins/ Built-in pipeline plugins
build/ Local build and CI entry points
tests/ Pester unit and integration tests
tests-e2e/ Real Docker end-to-end tests
examples/Minimal/ Maintained runnable example
docs/ Docusaurus project and authored documentation
The documentation build pulls the published docs-template container image from GHCR. It does not require a template repository checkout, Git submodule initialization, or Node dependency setup in this repository.
Documentation Site
Build this project's Docusaurus image locally:
./docs.ps1 -BuildOnly
The script generates docs/docs/index.md from the root README.md. It prepends
stable Docusaurus title, description, and sidebar metadata, then rewrites
https://psgenerator.subzerodev.com/ to / in the generated page. The README
therefore remains the homepage source of truth while local and staging links stay on
their current origin.
Run ./docs.ps1 to serve a baked image, or ./docs.ps1 -Live to bind-mount the
authored Markdown and configuration for local editing.
In CI, docs.yml carries the triggers and calls the shared docs.yml reusable
workflow from The-Running-Dev/GitHub-ActionTemplates, which runs every step inside
the ghcr.io/the-running-dev/build-agent image. A pull request runs only the
docs / Build job, which runs ./build/Test-Documentation.ps1, builds the site, and
archives the Pages artifact without publishing, so a break in the deploy path is
caught before merge. A push to main also runs docs / Deploy, which deploys to
GitHub Pages. The caller grants contents: read, pages: write, and id-token: write
at job level; the Deploy job is skipped on pull requests.
Import the Development Module
Import-Module ./src/SubZeroDev.PSGenerator.psd1 -Force
Get-Command -Module SubZeroDev.PSGenerator
To import the same clean layout CI tests against, stage it first. This is worth doing before trusting a local pass, because the development tree can mask a file missing from the package:
$manifest = ./build/New-GeneratorModulePackage.ps1
Import-Module $manifest.FullName -Force
The staged module is written to artifacts/module/SubZeroDev.PSGenerator by
default.
Static Analysis
./build/Invoke-Quality.ps1 -InstallDependencies
The gate pins PSScriptAnalyzer 1.25.0 and analyzes repository-owned PowerShell under
src, build, examples, tests, and tests-e2e using
.config/PSScriptAnalyzerSettings.psd1. It also runs the repository-hygiene gate,
which confirms nested .NET bin and obj output is ignored without hiding any
tracked source path.
After the dependency is installed:
./build/Invoke-Quality.ps1
Documentation Links and Terminology
./build/Test-Documentation.ps1
The gate validates authored Markdown that the documentation site build never sees.
Docusaurus already fails on unresolved links inside docs/, so this check covers
the rest: root and design/ Markdown such as README.md and design/30-slices.md, plus cross-file relative
links and heading anchors everywhere.
It reports three rule kinds:
-
MarkdownLinkandMarkdownAnchor— a relative target that does not exist on disk, or a#fragmentwith no matching heading in the target document. Explicit{#custom-id}headings and duplicate-heading-1suffixes are both honored. -
Terminology— product-name casing from.config/DocumentationRules.psd1. -
GeneratedFile— a generated file whose committed copy no longer matches its source.docs/docs/index.mdis generated fromREADME.md, so editing the README without regenerating leaves the published homepage stale. The finding names the first line that differs. Generated-file definitions require non-emptyPath,Source,Generator, andSourceParameterstrings, and valid relative generated paths are drift-checked instead of scanned as authored Markdown.Both
docs.ps1and this check callbuild/ConvertTo-DocumentationHomepage.ps1to produce the expected content, so the check cannot drift from the generator. Regenerate with anydocs.ps1run, including./docs.ps1 -BuildOnly.
External and site-absolute links are reported as out of scope rather than fetched, so the gate never depends on network reachability. Terminology rules apply to prose only: fenced code, inline code, link targets, and bare URLs are masked first, so commands, file paths, and URLs are never flagged.
Add terminology rules and path exclusions in .config/DocumentationRules.psd1.
Pass -Path to scan a subset:
./build/Test-Documentation.ps1 -Path ./docs/docs
Unit and Integration Tests
Invoke-Pester -Path ./tests -Output Detailed
CI first stages the generator into a clean module directory and points tests at that manifest. This prevents the development source tree from masking missing package files.
Maintained Fixtures
The suite includes isolated copies of a script-only directory and an authored
build-agent directory, under tests/fixtures/directories. Tests copy them to
temporary directories before initialization or generation, so the tracked fixture
sources stay unchanged.
PowerShell 7.4 Baseline
The baseline script requires an exact 7.4 runtime:
./build/Test-PowerShellBaseline.ps1
It stages and imports the generator, generates the minimal module, verifies both manifests require PowerShell 7.4, imports the generated module, and checks its export.
NuGet Package
./build/Test-GeneratorNuGetPackage.ps1 -InstallDependencies
This:
- stages a clean module;
- creates a genuine
.nupkg; - verifies package identity and repository metadata;
- registers a temporary local PSResource repository;
- saves and imports the package; and
- verifies
Build-PSModuleis exported.
Output is under artifacts/packages.
Container End-to-End Tests
Docker must be running:
$configuration = New-PesterConfiguration
$configuration.Run.Path = './tests-e2e'
$configuration.Run.Exit = $true
$configuration.Output.Verbosity = 'Detailed'
Invoke-Pester -Configuration $configuration
The test builds the minimal image, installs /PSModule, imports it, invokes supported
non-hardware mappings, validates help and documentation, and removes temporary
resources.
Local GitHub Actions with act
Install Docker and act, then run:
./build/Invoke-CI.ps1
The script builds .act/Dockerfile as a local runner and runs:
- PowerShell 7.4 baseline on the Ubuntu matrix leg;
- documentation links and terminology;
- NuGet package verification; and
- container end-to-end tests.
The powershell job calls the shared PowerShell CI workflow (analysis, hygiene, Pester and
coverage on Ubuntu and Windows), which act cannot resolve offline. Run
./build/Invoke-Quality.ps1 and the Pester suite directly for that coverage.
act uses Linux containers and does not reproduce the hosted Windows runner.
GitHub Actions remains authoritative for Windows.
Hosted Reports
GitHub Actions publishes:
- Windows and Ubuntu test reports in the job summary;
- container end-to-end test results in the job summary and as an artifact;
- a JaCoCo line-coverage report and summary; and
- the generated
.nupkgas a workflow artifact.
The packaged generator must remain at or above the configured 85% line coverage threshold.