diff --git a/src/docs/Capabilities/index.md b/src/docs/Capabilities/index.md index 90b170c..9c55a94 100644 --- a/src/docs/Capabilities/index.md +++ b/src/docs/Capabilities/index.md @@ -27,7 +27,6 @@ the same spec-and-design shape as any other capability. | [Deployment](deployment/index.md) | How a change to managed resources is approved together with its effect and deployed exactly as approved — one spec, and one design for each combination of deploying a service provider from a CI/CD platform. | | [VS Code Extension Framework](vscode-extension-framework/index.md) | How a VS Code extension is built, tested, versioned, packaged, and published — one GitHub-native pipeline, opt-in from a template and a single settings file. | | [PowerShell on GitHub](powershell-on-github/index.md) | How we make GitHub a first-class platform for PowerShell through reusable modules, actions, and capability gaps we close over time. | -| [Process-PSModule](process-psmodule/index.md) | The end-to-end PowerShell module pipeline — what it must guarantee and how it is built, alongside reference documentation for configuration and deployment. | | [Agentic Development](agentic-development/index.md) | The framework for org-scoped docs and memory repositories that give agents project-specific standards, working knowledge, and behavior. | diff --git a/src/docs/Capabilities/powershell-on-github/design.md b/src/docs/Capabilities/powershell-on-github/design.md index edc5637..d399fd9 100644 --- a/src/docs/Capabilities/powershell-on-github/design.md +++ b/src/docs/Capabilities/powershell-on-github/design.md @@ -32,7 +32,7 @@ The model combines two tracks: ## Current canonical references - PSModule initiative overview: ../../Initiatives/PSModule.md -- Process-PSModule capability: ../../Capabilities/process-psmodule/index.md +- [Process-PSModule documentation](https://psmodule.io/docs/Modules/Process-PSModule/) - Coding standards baseline: ../../Coding-Standards/index.md ## Planned evolution diff --git a/src/docs/Capabilities/process-psmodule/configuration.md b/src/docs/Capabilities/process-psmodule/configuration.md deleted file mode 100644 index 86e1b9e..0000000 --- a/src/docs/Capabilities/process-psmodule/configuration.md +++ /dev/null @@ -1,315 +0,0 @@ ---- -title: Configuration -description: The Process-PSModule settings file — every available setting, the full defaults, and worked examples for coverage, rapid testing, linting, and release notes. ---- - -# Configuration - -The workflow is configured using a settings file in the module repository. -The file can be a `JSON`, `YAML`, or `PSD1` file. By default, it will look for `.github/PSModule.yml`. - -The settings listed on this page are the user-facing configuration contract in `.github/PSModule.yml`. During the -Plan phase, Process-PSModule enriches this input into an internal runtime `Settings` object that downstream workflows -consume. Internal runtime paths in workflow docs (for example, `Settings.Publish.Module.Resolution.*`) describe that -enriched inter-workflow contract, not a different authoring format for repository settings files. - -Simple, Standard, and Advanced test profiles are repository conventions, not settings. `.github/PSModule.yml` has no -layout or suite-matrix selector; Process-PSModule [discovers the files under `tests/` recursively](pipeline-stages.md#module-local-test-discovery) -and computes its internal `Settings.Test.Module.Suites` matrix from them. - -Test discovery and change triggering are separate. The default `ImportantFilePatterns` match only `^src/` and -`^README\.md$`, so a test-only change does not enter the important-change build, test, and publish path. Repositories -that need test or automation changes to exercise that path must [add `^tests/` and any relevant settings or workflow -paths](usage.md#customizing-important-file-patterns) while retaining every default they still need. - -The following settings are available in the settings file: - -| Name | Type | Description | Default | -| ----------------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -| `Name` | `String` | Name of the module to publish. Defaults to the repository name. | `null` | -| `ImportantFilePatterns` | `Array` | Regular expression patterns that identify important files. Changes matching these patterns trigger build, test, and publish stages. When set, fully replaces the defaults. | `['^src/', '^README\.md$']` | -| `Test.Skip` | `Boolean` | Skip all tests | `false` | -| `Test.Linux.Skip` | `Boolean` | Skip tests on Linux | `false` | -| `Test.MacOS.Skip` | `Boolean` | Skip tests on macOS | `false` | -| `Test.Windows.Skip` | `Boolean` | Skip tests on Windows | `false` | -| `Test.SourceCode.Skip` | `Boolean` | Skip source code tests | `false` | -| `Test.SourceCode.Linux.Skip` | `Boolean` | Skip source code tests on Linux | `false` | -| `Test.SourceCode.MacOS.Skip` | `Boolean` | Skip source code tests on macOS | `false` | -| `Test.SourceCode.Windows.Skip` | `Boolean` | Skip source code tests on Windows | `false` | -| `Test.PSModule.Skip` | `Boolean` | Skip PSModule framework tests | `false` | -| `Test.PSModule.Linux.Skip` | `Boolean` | Skip PSModule framework tests on Linux | `false` | -| `Test.PSModule.MacOS.Skip` | `Boolean` | Skip PSModule framework tests on macOS | `false` | -| `Test.PSModule.Windows.Skip` | `Boolean` | Skip PSModule framework tests on Windows | `false` | -| `Test.Module.Skip` | `Boolean` | Skip module tests | `false` | -| `Test.Module.Linux.Skip` | `Boolean` | Skip module tests on Linux | `false` | -| `Test.Module.MacOS.Skip` | `Boolean` | Skip module tests on macOS | `false` | -| `Test.Module.Windows.Skip` | `Boolean` | Skip module tests on Windows | `false` | -| `Test.TestResults.Skip` | `Boolean` | Skip test result processing | `false` | -| `Test.CodeCoverage.Skip` | `Boolean` | Skip code coverage tests | `false` | -| `Test.CodeCoverage.PercentTarget` | `Integer` | Target code coverage percentage | `0` | -| `Test.CodeCoverage.StepSummaryMode` | `String` | Step summary mode for code coverage reports | `'Missed, Files'` | -| `Build.Skip` | `Boolean` | Skip all build tasks | `false` | -| `Build.Module.Skip` | `Boolean` | Skip module build | `false` | -| `Build.Docs.Skip` | `Boolean` | Skip documentation build | `false` | -| `Build.Docs.ShowSummaryOnSuccess` | `Boolean` | Show super-linter summary on success for documentation linting | `false` | -| `Build.Site.Skip` | `Boolean` | Skip site build | `false` | -| `Publish.Module.Skip` | `Boolean` | Skip module publishing | `false` | -| `Publish.Module.AutoCleanup` | `Boolean` | Automatically clean up old prerelease tags when merging to main or when a PR is abandoned | `true` | -| `Publish.Module.AutoPatching` | `Boolean` | Automatically patch module version | `true` | -| `Publish.Module.IncrementalPrerelease` | `Boolean` | Use incremental prerelease versioning | `true` | -| `Publish.Module.DatePrereleaseFormat` | `String` | Format for date-based prerelease (uses [.NET DateTime format strings](https://learn.microsoft.com/dotnet/standard/base-types/standard-date-and-time-format-strings)) | `''` | -| `Publish.Module.VersionPrefix` | `String` | Prefix for version tags | `'v'` | -| `Publish.Module.MajorLabels` | `String` | Labels indicating a major version bump | `'major, breaking'` | -| `Publish.Module.MinorLabels` | `String` | Labels indicating a minor version bump | `'minor, feature'` | -| `Publish.Module.PatchLabels` | `String` | Labels indicating a patch version bump | `'patch, fix'` | -| `Publish.Module.IgnoreLabels` | `String` | Labels indicating no release | `'NoRelease'` | -| `Publish.Module.UsePRTitleAsReleaseName` | `Boolean` | Use the PR title as the GitHub release name instead of version string | `false` | -| `Publish.Module.UsePRBodyAsReleaseNotes` | `Boolean` | Use the PR body as the release notes content | `true` | -| `Publish.Module.UsePRTitleAsNotesHeading` | `Boolean` | Prepend PR title as H1 heading with PR number link before the body | `true` | -| `Linter.Skip` | `Boolean` | Skip repository linting | `false` | -| `Linter.ShowSummaryOnSuccess` | `Boolean` | Show super-linter summary on success for repository linting | `false` | -| `Linter.env` | `Object` | Environment variables for super-linter configuration | `{}` | - -
-`PSModule.yml` with all defaults - -```yaml -Name: null - -ImportantFilePatterns: - - '^src/' - - '^README\.md$' - -Build: - Skip: false - Module: - Skip: false - Docs: - Skip: false - ShowSummaryOnSuccess: false - Site: - Skip: false - -Test: - Skip: false - Linux: - Skip: false - MacOS: - Skip: false - Windows: - Skip: false - SourceCode: - Skip: false - Linux: - Skip: false - MacOS: - Skip: false - Windows: - Skip: false - PSModule: - Skip: false - Linux: - Skip: false - MacOS: - Skip: false - Windows: - Skip: false - Module: - Skip: false - Linux: - Skip: false - MacOS: - Skip: false - Windows: - Skip: false - TestResults: - Skip: false - CodeCoverage: - Skip: false - PercentTarget: 0 - StepSummaryMode: 'Missed, Files' - -Publish: - Module: - Skip: false - AutoCleanup: true - AutoPatching: true - IncrementalPrerelease: true - DatePrereleaseFormat: '' - VersionPrefix: 'v' - MajorLabels: 'major, breaking' - MinorLabels: 'minor, feature' - PatchLabels: 'patch, fix' - IgnoreLabels: 'NoRelease' - UsePRTitleAsReleaseName: false - UsePRBodyAsReleaseNotes: true - UsePRTitleAsNotesHeading: true - -Linter: - Skip: false - ShowSummaryOnSuccess: false - env: {} -``` - -
- -## Example 1 - Defaults with Code Coverage target - -This example runs all steps and will require that code coverage is 80% before passing. - -```yaml -Test: - CodeCoverage: - PercentTarget: 80 -``` - -## Example 2 - Rapid testing - -This example ends up running Plan, Build-Module and Test-Module (tests from the module repo) on **ubuntu-latest** only. - -```yaml -Test: - SourceCode: - Skip: true - PSModule: - Skip: true - Module: - MacOS: - Skip: true - Windows: - Skip: true - TestResults: - Skip: true - CodeCoverage: - Skip: true -Build: - Docs: - Skip: true -``` - -## Example 3 - Configuring the Repository Linter - -The workflow uses [super-linter](https://github.com/super-linter/super-linter) to lint your repository code. -The linter runs on pull requests and provides status updates directly in the PR. - -### Disabling the Linter - -You can skip repository linting entirely: - -```yaml -Linter: - Skip: true -``` - -### Configuring Linter Validation Rules - -The workflow supports all environment variables that **super-linter** provides. You can configure these through the `Linter.env` object: - -```yaml -Linter: - env: - # Disable specific validations - VALIDATE_BIOME_FORMAT: false - VALIDATE_BIOME_LINT: false - VALIDATE_GITHUB_ACTIONS_ZIZMOR: false - VALIDATE_JSCPD: false - VALIDATE_JSON_PRETTIER: false - VALIDATE_MARKDOWN_PRETTIER: false - VALIDATE_YAML_PRETTIER: false - - # Or enable only specific validations - VALIDATE_YAML: true - VALIDATE_JSON: true - VALIDATE_MARKDOWN: true -``` - -### Additional Configuration - -Any super-linter environment variable can be set through the `Linter.env` object: - -```yaml -Linter: - env: - LOG_LEVEL: DEBUG - FILTER_REGEX_EXCLUDE: '.*test.*' - VALIDATE_ALL_CODEBASE: false -``` - -### Showing Linter Summary on Success - -By default, the linter only shows a summary when it finds issues. You can enable summary display on successful runs: - -```yaml -Linter: - ShowSummaryOnSuccess: true -``` - -This is useful for reviewing what was checked even when no issues are found. - -**Note:** The `GITHUB_TOKEN` is automatically provided by the workflow to enable status updates in pull requests. - -For a complete list of available environment variables and configuration options, see the -[super-linter environment variables documentation](https://github.com/super-linter/super-linter#environment-variables). - -## Example 4 - Configuring PR-based release notes - -The workflow can automatically generate GitHub release names and notes from your pull request content. -Three parameters control this behavior: - -| Parameter | Description | -|-----------|-------------| -| `UsePRTitleAsReleaseName` | Use the PR title as the GitHub release name instead of the version string | -| `UsePRBodyAsReleaseNotes` | Use the PR body as the release notes content | -| `UsePRTitleAsNotesHeading` | Prepend PR title as H1 heading with PR number link before the body | - -These parameters follow specific precedence rules when building release notes: - -1. **Heading + Body** (`UsePRTitleAsNotesHeading: true` + `UsePRBodyAsReleaseNotes: true`): Creates formatted notes with the PR title as an H1 heading followed by the PR body. The output format is `# PR Title (#123)\n\nPR body content`. Both the PR title and body must be present. -1. **Body only** (`UsePRBodyAsReleaseNotes: true`): Uses the PR body as-is for release notes. Takes effect when heading option is disabled or PR title is missing. -1. **Fallback**: When neither option is enabled or required PR content is missing, GitHub's auto-generated release notes are used via `--generate-notes`. - -### Default configuration (recommended) - -The defaults provide rich release notes with the PR title as a heading: - -```yaml -Publish: - Module: - UsePRTitleAsReleaseName: false - UsePRBodyAsReleaseNotes: true - UsePRTitleAsNotesHeading: true -``` - -This produces release notes like: - -```markdown -# 🚀 Add new authentication feature (#42) - -This PR adds OAuth2 support with the following changes: -- Added `Connect-OAuth2` function -- Updated documentation -``` - -### Version-only release names - -If you prefer version numbers as release names but still want PR-based notes: - -```yaml -Publish: - Module: - UsePRTitleAsReleaseName: false - UsePRBodyAsReleaseNotes: true - UsePRTitleAsNotesHeading: false -``` - -### Auto-generated notes - -To use GitHub's auto-generated release notes instead of PR content: - -```yaml -Publish: - Module: - UsePRTitleAsReleaseName: false - UsePRBodyAsReleaseNotes: false - UsePRTitleAsNotesHeading: false -``` diff --git a/src/docs/Capabilities/process-psmodule/design.md b/src/docs/Capabilities/process-psmodule/design.md deleted file mode 100644 index cacf362..0000000 --- a/src/docs/Capabilities/process-psmodule/design.md +++ /dev/null @@ -1,218 +0,0 @@ ---- -title: Design -description: How Process-PSModule delivers the spec — a single reusable GitHub Actions workflow composing sub-workflows, a settings file contract, and the scenario matrix. ---- - -# Process-PSModule — Design - -The behaviour in the [spec](spec.md) is delivered by a **single reusable GitHub Actions workflow** at `PSModule/Process-PSModule/.github/workflows/workflow.yml`. A repository using the workflow provides a caller workflow and a minimal `.github/PSModule.yml` settings file; everything else uses sensible defaults. - -## Workflow architecture - -### Single entry point - -The reusable workflow accepts a caller workflow and minimal caller configuration: - -```yaml -# .github/workflows/Process-PSModule.yml in the module repository -name: Process-PSModule - -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' - pull_request: - branches: - - main - types: - - closed - - opened - - reopened - - synchronize - - labeled - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: write - pull-requests: write - statuses: write - pages: write - id-token: write - -jobs: - Process-PSModule: - uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 - secrets: - APIKey: ${{ secrets.APIKey }} -``` - -### Composed reusable workflows - -The main workflow composes work across specialized reusable workflows, each owning a pipeline stage: - -- **Plan** — reads the settings file and event context, decides what runs, computes the next version -- **Lint-Repository** — validates repository structure and configuration -- **Build-Module** — compiles the module source and versions the manifest -- **Test-SourceCode** — validates source-code style and standards (PSScriptAnalyzer, framework tests) -- **Lint-SourceCode** — runs static analysis on source -- **Test-Module** — runs framework tests and module-local Pester tests in parallel per platform -- **Get-TestResults** — aggregates test results and enforces pass/fail -- **Get-CodeCoverage** — collects coverage from tests and enforces thresholds -- **Publish-Module** — publishes the module to the PowerShell Gallery -- **Publish-Site** — generates and publishes documentation to GitHub Pages - -Each workflow is reusable so it can be tested and versioned independently, invoked by name in the main orchestration workflow. - -## Settings file contract - -The caller provides `.github/PSModule.yml`: - -```yaml -# Minimal example — defaults apply for everything not specified -Linter: - Repository: - Enabled: true - -Build: - Module: - Enabled: true - -Test: - SourceCode: - Enabled: true - PSModule: - Enabled: true - Module: - Enabled: true - CodeCoverage: - Enabled: true - Threshold: 80 - -Publish: - Module: - Enabled: true - Site: - Enabled: true -``` - -The Plan job reads this settings file, enriches it with computed values (phase enables, test matrices, resolved version, release decision), and passes the enriched settings to downstream jobs as a JSON string in workflow outputs. - -### Runtime settings contract - -| Path | Meaning | -| --- | --- | -| `Settings.Linter.Repository.Enabled` | Whether repository linting runs. | -| `Settings.Build.Module.Enabled` | Whether module build runs. | -| `Settings.Test.SourceCode.Enabled` | Whether source-code tests run. | -| `Settings.Test.PSModule.Enabled` | Whether framework tests run. | -| `Settings.Test.Module.Enabled` | Whether module-local tests run. | -| `Settings.Test.TestResults.Enabled` | Whether test-results aggregation runs. | -| `Settings.Test.CodeCoverage.Enabled` | Whether code-coverage gates run. | -| `Settings.Publish.Module.Enabled` | Whether module publication runs. | -| `Settings.Publish.Site.Enabled` | Whether documentation publication runs. | -| `Settings.Test.SourceCode.Suites` | Computed source-code test matrix (platform × test suite). | -| `Settings.Test.PSModule.Suites` | Computed framework test matrix (platform × test suite). | -| `Settings.Test.Module.Suites` | Computed module-local test matrix (platform × test suite). | -| `Settings.Publish.Module.Resolution.Version` | Resolved semantic version (e.g., `v1.2.3`). | -| `Settings.Publish.Module.Resolution.Prerelease` | Whether the version is prerelease. | -| `Settings.Publish.Module.Resolution.FullVersion` | Full version string (e.g., `v1.2.3-pr.1.5`). | -| `Settings.Publish.Module.Resolution.ReleaseType` | `stable`, `prerelease`, or `none`. | -| `Settings.Publish.Module.Resolution.CreateRelease` | Whether to create a GitHub Release. | - -## Scenario matrix - -### Version labeling - -- **Major** — breaking change; bump `MAJOR` in SemVer -- **Minor** — new feature; bump `MINOR` -- **Patch** — bugfix; bump `PATCH` (default if no label) -- **Prerelease** — publish as prerelease, not promoted to latest -- **NoRelease** — run pipeline, skip publication - -Multiple SemVer labels or conflicting labels (e.g., `Major` + `NoRelease`) are rejected and block the merge. - -### Branch types - -- **Main (stable)** — publishes stable releases. A prerelease label publishes a prerelease from `main`. -- **Development** — optional prerelease branch (e.g., `dev`). Each push publishes a prerelease. -- **Feature branch** — optional feature branch. A prerelease label publishes a prerelease for testing. - -### Platform matrix - -Tests run on: - -- **Windows** (latest) -- **Linux** (Ubuntu latest) -- **macOS** (latest) - -Failures on any platform block the build. - -### Test suites - -Each platform runs in parallel: - -- **Source-code tests** — style, naming, structure (PSModule framework) -- **Framework tests** — module structure, common issues (PSModule framework) -- **Module-local tests** — Pester tests written by the module author -- **Linting** — PSScriptAnalyzer rules - -Test results are aggregated into a single pass/fail and reported to the PR. - -## Alternatives considered - -### Monolithic workflow vs. composable reusable workflows - -**Chosen: Composable reusable workflows** - -Each stage of the pipeline is a reusable workflow so it can be tested independently, versioned, and reused across the ecosystem. This trades orchestration complexity for testability and clarity. - -**Alternative: Single monolithic workflow** - -All logic in one workflow file. Pros: simpler to read end-to-end. Cons: harder to test, version, and reuse; changes in one stage risk all stages; every module repo copies the full logic. - -### Settings file format - -**Chosen: YAML with runtime enrichment** - -The caller provides a simple YAML file; the Plan job enriches it with computed values and passes the enriched settings to all downstream jobs. Pros: simple, readable, minimal to start. Cons: only the Plan job computes the settings; other jobs consume them. - -**Alternative: JSON in workflow outputs** - -Settings live only as workflow outputs, computed by Plan. Pros: single source of truth. Cons: harder to read and edit; no local file to inspect. - -### Version computation - -**Chosen: PR label + current version** - -The bump comes from the PR label; the next version is computed as `current_version + bump`. Pros: explicit, git-traceable (the label is recorded in the PR). Cons: must be re-computed if a PR is re-run or the base version changes. - -**Alternative: Conventional Commits** - -Parse commit messages for `feat:`, `fix:`, `BREAKING CHANGE:` to infer the bump. Pros: automatic. Cons: less explicit; easy to forget the convention; harder to override. - -## External dependencies - -The workflow relies on: - -- **[PSModule/Build-PSModule](https://github.com/PSModule/Build-PSModule)** — compiles and versions the module -- **[PSModule/Test-PSModule](https://github.com/PSModule/Test-PSModule)** — runs framework tests and style validation -- **[PSModule/Invoke-ScriptAnalyzer](https://github.com/PSModule/Invoke-ScriptAnalyzer)** — runs PSScriptAnalyzer linting -- **[Pester](https://pester.dev/)** — runs module tests -- **[GitHub Actions](https://github.com/features/actions)** — workflow engine -- **PowerShell Gallery API** — publishes module packages -- **GitHub Pages** — hosts documentation -- **Zensical** — generates documentation from source - -Each is versioned independently; the main workflow pins versions explicitly. - -## Where this connects - -- [Spec](spec.md) — the requirements this design delivers. -- [Pipeline stages](pipeline-stages.md) — detailed breakdown of each job. -- [Usage](usage.md) — how to invoke and configure. -- [Configuration](configuration.md) — the settings file reference. -- [Principles and practices](principles-and-practices.md) — the principles guiding this design. -- [Repository structure](repository-structure.md) — the repo layout the workflow expects. diff --git a/src/docs/Capabilities/process-psmodule/index.md b/src/docs/Capabilities/process-psmodule/index.md deleted file mode 100644 index d47451f..0000000 --- a/src/docs/Capabilities/process-psmodule/index.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Process-PSModule -description: The end-to-end PowerShell module pipeline — what it must guarantee and how it is built, alongside reference documentation for configuration and deployment. ---- - -# Process-PSModule - -An end-to-end PowerShell module pipeline that automates the entire lifecycle of a module: building from source, running cross-platform tests, enforcing code quality and coverage, generating documentation, and publishing the versioned module to the PowerShell Gallery and its documentation site to GitHub Pages. It is the core workflow used across all PowerShell modules in the [PSModule organization](https://github.com/PSModule), ensuring reliable, automated, and maintainable delivery of PowerShell projects. - - - -| Page | Description | -| --- | --- | -| [Spec](spec.md) | Requirements for Process-PSModule — an end-to-end PowerShell module pipeline that guarantees build, testing, quality gates, documentation generation, and versioned publication to package and docs registries. | -| [Design](design.md) | How Process-PSModule delivers the spec — a single reusable GitHub Actions workflow composing sub-workflows, a settings file contract, and the scenario matrix. | -| [Pipeline stages](pipeline-stages.md) | The job-by-job breakdown of the Process-PSModule workflow, from Plan through Publish Docs. | -| [Usage](usage.md) | How to call the Process-PSModule workflow — inputs, secrets, permissions, the scenario matrix, and important-file change detection. | -| [Configuration](configuration.md) | The Process-PSModule settings file — every available setting, the full defaults, and worked examples for coverage, rapid testing, linting, and release notes. | -| [Skipping framework tests](skipping-framework-tests.md) | How to skip individual PSModule framework tests on a per-file basis, the available test IDs, and the broader configuration alternatives. | -| [Repository structure](repository-structure.md) | The repository and module source layout Process-PSModule expects, and how to declare module dependencies with #Requires -Modules. | -| [Principles and practices](principles-and-practices.md) | The versioning, branching, and colocation principles behind Process-PSModule, and the development practices it is compatible with. | - - - -## How to get started - -1. [Create a repository from the Template-Module](https://github.com/new?template_name=Template-PSModule&template_owner=PSModule&description=Add%20a%20description%20(required)&name=%3CModule%20name%3E). -2. Configure the repository: - 1. Enable GitHub Pages in the repository settings. Set it to deploy from **GitHub Actions**. - 2. This will create an environment called `github-pages` that GitHub deploys your site to. -
Within the github-pages environment, remove the branch protection for main. - Remove the branch protection on main -
- 3. [Create an API key on the PowerShell Gallery](https://www.powershellgallery.com/account/apikeys). Give it permission to manage the module you - are working on. - 4. Create a new secret called `APIKEY` in the repository and set the API key for the PowerShell Gallery as its value. - 5. If you are planning on creating many modules, you could use a glob pattern for the API key permissions in PowerShell Gallery and store the - secret on the organization. -3. Clone the repo locally, create a branch, make your changes, push the changes, create a PR and let the workflow run. - - Adding a `Prerelease` label to the PR will create a prerelease version of the module. -4. Use `.github/zensical.toml` for site generation. Process-PSModule builds documentation with Zensical from this file. -5. When merging to `main`, the workflow automatically builds, tests, and publishes your module to the PowerShell Gallery and maintains the - documentation on GitHub Pages. By default the process releases a patch version, which you can change by applying labels like `minor` or `major` on - the PR to bump the version accordingly. - -## How it works - -Everything is packaged into this single workflow to simplify full configuration of the workflow via this repository. Simplifying management and -operations across all PowerShell module projects. A user can configure how it works by simply configuring settings using a single file. - -### Workflow overview - -The workflow is designed to be triggered on pull requests to the repository's default branch. -When a pull request is opened, closed, reopened, synchronized (push), or labeled, the workflow will run. -Depending on the labels in the pull requests, the [workflow will result in different outcomes](usage.md#scenario-matrix). - -![Process diagram](media/Process-PSModule.png) - -## Reference - -The spec and design own the what and how. The pages below are reference documentation for those who implement, configure, and operate the workflow. - -Process-PSModule composes its work from reusable workflows, actions, a container image, PowerShell modules, and Python packages. For the full dependency tree, including diagrams and a reference of every dependency, see [DEPENDENCIES.md](https://github.com/PSModule/Process-PSModule/blob/main/DEPENDENCIES.md). - - - -| Page | Description | -| --- | --- | -| [Pipeline stages](pipeline-stages.md) | The job-by-job breakdown of the Process-PSModule workflow, from Plan through Publish Docs. | -| [Usage](usage.md) | How to call the Process-PSModule workflow — inputs, secrets, permissions, the scenario matrix, and important-file change detection. | -| [Configuration](configuration.md) | The Process-PSModule settings file — every available setting, the full defaults, and worked examples for coverage, rapid testing, linting, and release notes. | -| [Skipping framework tests](skipping-framework-tests.md) | How to skip individual PSModule framework tests on a per-file basis, the available test IDs, and the broader configuration alternatives. | -| [Repository structure](repository-structure.md) | The repository and module source layout Process-PSModule expects, and how to declare module dependencies with #Requires -Modules. | -| [Principles and practices](principles-and-practices.md) | The versioning, branching, and colocation principles behind Process-PSModule, and the development practices it is compatible with. | - - diff --git a/src/docs/Capabilities/process-psmodule/media/Process-PSModule.png b/src/docs/Capabilities/process-psmodule/media/Process-PSModule.png deleted file mode 100644 index d3d1f85..0000000 Binary files a/src/docs/Capabilities/process-psmodule/media/Process-PSModule.png and /dev/null differ diff --git a/src/docs/Capabilities/process-psmodule/media/pagesEnvironment.png b/src/docs/Capabilities/process-psmodule/media/pagesEnvironment.png deleted file mode 100644 index 59f411d..0000000 Binary files a/src/docs/Capabilities/process-psmodule/media/pagesEnvironment.png and /dev/null differ diff --git a/src/docs/Capabilities/process-psmodule/pipeline-stages.md b/src/docs/Capabilities/process-psmodule/pipeline-stages.md deleted file mode 100644 index f72010c..0000000 --- a/src/docs/Capabilities/process-psmodule/pipeline-stages.md +++ /dev/null @@ -1,297 +0,0 @@ ---- -title: Pipeline stages -description: The job-by-job breakdown of the Process-PSModule workflow, from Plan through Publish Docs. ---- - -# Pipeline stages - -The Process-PSModule workflow composes its work from a set of reusable jobs. Each -one is described below, in the order it runs, with a link to the workflow that -implements it. - -## Plan - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Plan.yml) - -The Plan job is the single decision point of the workflow. It reads the settings file (`.github/PSModule.yml`), -collects event context from GitHub, and decides what should happen in the rest of the process. Using that -situational awareness, it calculates the next module version. - -The user-facing settings file stays in `.github/PSModule.yml`. The workflow enriches that input into an internal runtime -`Settings` object passed between jobs. In this runtime contract, execution decisions are phase-owned (`*.Enabled`), test -suite matrices are computed under each owning test phase, and resolved version metadata is stored under -`Settings.Publish.Module.Resolution`. The `*.Suites` values are workflow outputs, not authorable layout settings. - -### Internal runtime settings contract - -| Runtime path | Meaning | -| --- | --- | -| `Settings.Linter.Repository.Enabled` | Whether repository linting runs. | -| `Settings.Build.Module.Enabled` | Whether module build runs. | -| `Settings.Test.SourceCode.Enabled` | Whether source-code tests run. | -| `Settings.Test.PSModule.Enabled` | Whether framework tests run. | -| `Settings.Test.Module.BeforeAllEnabled` | Whether setup scripts run before module-local tests. | -| `Settings.Test.Module.MainEnabled` | Whether module-local Pester tests run. | -| `Settings.Test.Module.AfterAllEnabled` | Whether teardown scripts run after module-local tests. | -| `Settings.Test.TestResults.Enabled` | Whether test results aggregation runs. | -| `Settings.Test.CodeCoverage.Enabled` | Whether code coverage aggregation/enforcement runs. | -| `Settings.Publish.Module.Enabled` | Whether module publication/release runs. | -| `Settings.Publish.Site.Enabled` | Whether documentation publication runs. | -| `Settings.Test.SourceCode.Suites` | Computed source-code test suite matrix. | -| `Settings.Test.PSModule.Suites` | Computed framework test suite matrix. | -| `Settings.Test.Module.Suites` | Computed module-local test suite matrix. | -| `Settings.Publish.Module.Resolution.Version` | Resolved semantic version used for build and publish. | -| `Settings.Publish.Module.Resolution.Prerelease` | Whether the resolved version is prerelease. | -| `Settings.Publish.Module.Resolution.FullVersion` | Resolved full version string. | -| `Settings.Publish.Module.Resolution.ReleaseType` | Resolved release classification for this run. | -| `Settings.Publish.Module.Resolution.CreateRelease` | Whether this run creates a release. | - -## Lint-Repository - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Lint-Repository.yml) - -## Build module - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Build-Module.yml) - -- Compiles the module source code into a PowerShell module, stamping the version from `Settings.Publish.Module.Resolution.Version` into the manifest. -- Uploads the built artifact. - -## Test source code - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Test-SourceCode.yml) - -- Tests the source code in parallel (matrix) using: - - [PSModule framework settings for style and standards for source code](https://github.com/PSModule/Test-PSModule?tab=readme-ov-file#sourcecode-tests) -- This produces a JSON-based report that is used by [Get-PesterTestResults](#get-test-results) evaluate the results of the tests. - -The [PSModule - SourceCode tests](https://github.com/PSModule/Process-PSModule/blob/main/scripts/tests/SourceCode/PSModule/PSModule.Tests.ps1) verifies the following coding practices that the framework enforces: - -| ID | Category | Description | -|---------------------|---------------------|--------------------------------------------------------------------------------------------| -| NumberOfProcessors | General | Should use `[System.Environment]::ProcessorCount` instead of `$env:NUMBER_OF_PROCESSORS`. | -| Verbose | General | Should not contain `-Verbose` unless it is explicitly disabled with `:$false`. | -| OutNull | General | Should use `$null = ...` instead of piping output to `Out-Null`. | -| NoTernary | General | Should not use ternary operations to maintain compatibility with PowerShell 5.1 and below. | -| LowercaseKeywords | General | All PowerShell keywords should be written in lowercase. | -| FunctionCount | Functions (Generic) | Each script file should contain exactly one function or filter. | -| FunctionName | Functions (Generic) | Script filenames should match the name of the function or filter they contain. | -| CmdletBinding | Functions (Generic) | Functions should include the `[CmdletBinding()]` attribute. | -| ParamBlock | Functions (Generic) | Functions should have a parameter block (`param()`). | -| FunctionTest | Functions (Public) | All public functions/filters should have corresponding tests. | - -## Lint source code - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Lint-SourceCode.yml) - -- Lints the source code in parallel (matrix) using: - - [PSScriptAnalyzer rules](https://github.com/PSModule/Invoke-ScriptAnalyzer) -- This produces a JSON-based report that is used by [Get-PesterTestResults](#get-test-results) evaluate the results of the linter. - -## Framework test - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Test-Module.yml) - -- Tests and lints the module in parallel (matrix) using: - - [PSModule framework settings for style and standards for modules](https://github.com/PSModule/Test-PSModule?tab=readme-ov-file#module-tests) - - [PSScriptAnalyzer rules](https://github.com/PSModule/Invoke-ScriptAnalyzer) -- This produces a JSON-based report that is used by [Get-PesterTestResults](#get-test-results) evaluate the results of the tests. -- **Code coverage for framework-generated code**: This step collects code coverage for framework-generated - boilerplate. During the [build step](#build-module), [Build-PSModule](https://github.com/PSModule/Build-PSModule) - injects boilerplate code into the compiled `.psm1` file — including type accelerator registration for public classes - and enums, and the `OnRemove` cleanup hook. The framework tests in - [Test-PSModule](https://github.com/PSModule/Test-PSModule) exercise these code paths and produce coverage artifacts - that are aggregated with coverage from [Test-ModuleLocal](#test-module) in the - [Get code coverage](#get-code-coverage) step. This keeps framework-generated lines from counting against the module - author's coverage report. - -## Test module - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Test-ModuleLocal.yml) - -- Imports and tests the module in parallel (matrix) using module-local Pester tests. -- Discovers module-local tests recursively under `tests/`, applying the [per-directory precedence](#module-local-test-discovery) independently at every level. -- Module test files declare a Pester **6.x** requirement via `#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '6.0.0'; MaximumVersion = '6.*' }` — a convention module authors add to each `*.Tests.ps1`, not something this pipeline injects. The [Invoke-Pester](https://github.com/PSModule/Invoke-Pester) action installs a matching `6.x`, so minor and patch updates flow in automatically while a new major stays a deliberate, reviewed change. -- Supports two special workflow phase scripts executed via separate dedicated jobs: - - `tests/BeforeAll.ps1`: Runs once before all module-local test matrix jobs to set up the test environment (e.g., deploy infrastructure, download test data). - - `tests/AfterAll.ps1`: Runs once after all module-local test matrix jobs complete to clean up the test environment (e.g., remove test resources, clean up databases). -- The workflow checks only those exact repository-root paths; phase detection is non-recursive. This is separate from the recursive discovery of ordinary module-local test entries described below; nested files named `BeforeAll.ps1` or `AfterAll.ps1` do not create workflow phases. -- The two phase scripts run with the same environment variables as the tests. -- This produces a JSON-based report that is used by [Get-PesterTestResults](#get-test-results) to evaluate the results of the tests. - -### Module-local test discovery - -Simple, Standard, and Advanced are [documentation profiles](../../Coding-Standards/PowerShell/Testing.md#module-test-profiles), not selectable workflow modes. The same discovery engine handles every profile. `.github/PSModule.yml` has no test-layout or suite-matrix setting; `Settings.Test.Module.Suites` is computed internally from the repository files. - -Process-PSModule inspects `tests/` recursively. Within each directory it uses the first matching form: - -1. Exactly one `*.Configuration.ps1`. Discovery fails when a directory contains more than one. When selected, sibling `*.Container.ps1` and `*.Tests.ps1` files are not independently selected. -2. Otherwise, one or more `*.Container.ps1`. When selected, sibling `*.Tests.ps1` files are not independently selected. -3. Otherwise, all `*.Tests.ps1`. - -The selected form takes precedence only in that directory. Child directories are still inspected independently, so a repository may mix configurations, containers, and ordinary test files across different directories. - -Every discovered artifact needs a unique prefix before its first dot because that prefix becomes `TestName`. For example, `Users.Unit.Tests.ps1` and `Users.Integration.Tests.ps1` both become `Users`; use distinct prefixes such as `UsersUnit` and `UsersIntegration`. - -### Setup and Teardown Scripts - -The workflow supports automatic execution of setup and teardown scripts for module tests: - -- `tests/BeforeAll.ps1` and `tests/AfterAll.ps1` are special workflow phase files, not ordinary recursively discovered test entries. -- Each phase is enabled only when its exact file exists at the root of `tests/`. -- If either file is absent, the workflow skips that phase and continues normally. - -#### Setup - `BeforeAll.ps1` - -- Place at the exact repository-root path `tests/BeforeAll.ps1`. -- Runs once before all test matrix jobs to prepare the test environment. -- Deploy test infrastructure, download test data, initialize databases, or configure services. -- Has access to the same environment variables as your tests (secrets, GitHub token, etc.). - -##### Example - `BeforeAll.ps1` - -```powershell -Write-Host "Setting up test environment..." -# Deploy test infrastructure -# Download test data -# Initialize test databases -Write-Host "Test environment ready!" -``` - -#### Teardown - `AfterAll.ps1` - -- Place at the exact repository-root path `tests/AfterAll.ps1`. -- Runs once after all test matrix jobs complete to clean up the test environment. -- Remove test resources, clean up databases, stop services, or upload artifacts. -- Has access to the same environment variables as your tests. - -##### Example - `AfterAll.ps1` - -```powershell -Write-Host "Cleaning up test environment..." -# Remove test resources -# Clean up databases -# Stop services -Write-Host "Cleanup completed!" -``` - -#### Best practices for shared test infrastructure - -Tests run in parallel across multiple OS runners. To avoid rate limits or conflicts from excessive resource creation, -provision shared infrastructure once in `BeforeAll.ps1` and tear it down in `AfterAll.ps1`. Individual test files -should consume the shared infrastructure instead of creating their own. - -##### Use deterministic naming with `$env:GITHUB_RUN_ID` - -Use `$env:GITHUB_RUN_ID` (stable per workflow run, shared across OS runners) to build deterministic resource names. -This lets test files reference shared resources by name without passing state between jobs. - -```powershell -# BeforeAll.ps1 -$os = $env:RUNNER_OS -$id = $env:GITHUB_RUN_ID -$resourceName = "Test-$os-$id" -``` - -Do **not** use `[guid]::NewGuid()` or `Get-Random` for shared resource names — these produce different values on -each runner and cannot be referenced by other jobs. - -##### Clean up stale resources from previous failed runs - -If a previous workflow run failed before teardown completed, stale resources may remain. Start `BeforeAll.ps1` by -removing any resources matching your naming prefix before creating new ones: - -```powershell -# Remove stale resources from previous failed runs -Get-Resources -Filter "Test-$os-*" | Remove-Resource - -# Create fresh shared resources -New-Resource -Name "Test-$os-$id" -``` - -##### Tests reference shared resources — they do not create them - -Test files should fetch the shared resource by its deterministic name, not create new resources: - -```powershell -# Inside a test file -BeforeAll { - $os = $env:RUNNER_OS - $id = $env:GITHUB_RUN_ID - $resource = Get-Resource -Name "Test-$os-$id" -} -``` - -Test-specific ephemeral resources (for example, secrets, variables, or temporary items) can still be created and -cleaned up within each test file. Only long-lived or expensive resources should be shared. - -##### Naming conventions - -Use a consistent naming scheme so that resources are easy to identify and clean up. A recommended pattern: - -| Resource | Pattern | Example | -|-------------------|---------------------------------------|----------------------------| -| Shared resource | `Test-{OS}-{RunID}` | `Test-Linux-1234` | -| Extra resource | `Test-{OS}-{RunID}-{N}` | `Test-Linux-1234-1` | -| Secret / variable | `{TestName}_{OS}_{RunID}` | `Secrets_Linux_1234` | -| Environment | `{TestName}-{OS}-{RunID}` | `Secrets-Linux-1234` | - -When tests use multiple authentication contexts that share the same runner, include a token or context identifier in -the name to avoid collisions (for example, `Test-{OS}-{ContextID}-{RunID}`). - -### Module tests - -The [PSModule - Module tests](https://github.com/PSModule/Process-PSModule/blob/main/scripts/tests/Module/PSModule/PSModule.Tests.ps1) verifies the following coding practices that the framework enforces: - -| Name | Description | -| ------ | ----------- | -| Module Manifest exists | Verifies that a module manifest file is present. | -| Module Manifest is valid | Verifies that the module manifest file is valid. | - -## Get test results - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Get-TestResults.yml) - -- Gathers the test results from the previous steps and creates a summary of the results. -- If any tests have failed, the workflow will fail here. - -## Get code coverage - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Get-CodeCoverage.yml) - -- Gathers the code coverage from the previous steps and creates a summary of the results. -- Aggregates coverage from the [Framework test](#framework-test) step (framework-generated boilerplate) and the - [Test module](#test-module) step (module author code). A command executed in either step counts as covered, so - framework-generated lines do not count against the module author's coverage target. -- If the code coverage is below the target, the workflow will fail here. - -## Publish module - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Publish-Module.yml) - -- Publishes the artifact to the PowerShell Gallery exactly as built — no version mutation. -- Creates a GitHub Release using the version already stamped in the manifest. -- Attaches the built module as a `.zip` asset on the GitHub Release so consumers can download the exact bytes that were tested and pushed to the PowerShell Gallery. -- **Abandoned PR cleanup**: When a PR is closed without merging (abandoned), the workflow automatically cleans up any - prerelease versions and tags that were created for that PR. This ensures that abandoned work doesn't leave orphaned - prereleases in the PowerShell Gallery or repository. This behavior is controlled by the `Publish.Module.AutoCleanup` - setting. - -## Build docs - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Build-Docs.yml) - -- Generates documentation and lints the documentation using: - - [super-linter](https://github.com/super-linter/super-linter). - -## Build site - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Build-Site.yml) - -- Generates a static site using: - - [Zensical](https://zensical.org/). -- Uses `zensical.toml` as the site configuration contract. - -## Publish Docs - -[workflow](https://github.com/PSModule/Process-PSModule/blob/main/.github/workflows/Publish-Docs.yml) diff --git a/src/docs/Capabilities/process-psmodule/principles-and-practices.md b/src/docs/Capabilities/process-psmodule/principles-and-practices.md deleted file mode 100644 index 06e806d..0000000 --- a/src/docs/Capabilities/process-psmodule/principles-and-practices.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Principles and practices -description: The versioning, branching, and colocation principles behind Process-PSModule, and the development practices it is compatible with. ---- - -# Principles and practices - -## Linear versioning - -The contribution and release process is based on the idea that a PR is a release, and we only maintain a single linear ancestry of versions, not going -back to patch and update old versions of the modules. This means that if we are on version `2.1.3` of a module and there is a security issue, we only -patch the latest version with a fix, not releasing new versions based on older versions of the module, i.e. not updating the latest 1.x with the -patch. - -## Release and feature branches - -If you need to work forth a bigger release, create a branch representing the release (a release branch) and open a PR towards `main` for this branch. -For each topic or feature to add to the release, open a new branch representing the feature (a feature branch) and open a PR towards the release -branch. Optionally add the `Prerelease` label on the PR for the release branch, to release preview versions before merging and releasing a published -version of the PowerShell module. - -## Colocation of concerns - -Colocate concerns for long-term maintainability. For example, `#Requires -Modules` statements belong in the function files that use them, not in a -central manifest — this makes it immediately visible which functions drive each external dependency, and avoids silent drift between the manifest and -the actual code. Another example is how parameter descriptions are placed as comments in the `param()` block directly above each parameter -declaration, rather than in the comment-based help at the top of the function — this keeps the description next to the code it documents. - -## Compatibility - -The process is compatible with: - -- [Test-Driven Development](https://testdriven.io/test-driven-development/) using [Pester](https://pester.dev) and [PSScriptAnalyzer](https://learn.microsoft.com/powershell/utility-modules/psscriptanalyzer/overview) -- [GitHub Flow specifications](https://docs.github.com/en/get-started/using-github/github-flow) -- [SemVer 2.0.0 specifications](https://semver.org) -- [Continuous Delivery practices](https://en.wikipedia.org/wiki/Continuous_delivery) diff --git a/src/docs/Capabilities/process-psmodule/repository-structure.md b/src/docs/Capabilities/process-psmodule/repository-structure.md deleted file mode 100644 index 2428d93..0000000 --- a/src/docs/Capabilities/process-psmodule/repository-structure.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Repository structure -description: The repository and module source layout Process-PSModule expects, and how to declare module dependencies with #Requires -Modules. ---- - -# Repository structure - -Process-PSModule expects repositories to follow the staged layout produced by Template-PSModule. The workflow inspects this structure to decide what to compile, document, and publish. - -```plaintext -/ -├── .github/ # Workflow config, doc/site templates, automation policy -│ ├── linters/ # Rule sets applied by shared lint steps -│ │ ├── .markdown-lint.yml # Markdown rules enforced via super-linter -│ │ ├── .powershell-psscriptanalyzer.psd1 # Analyzer profile for test jobs -│ │ └── .textlintrc # Text lint rules surfaced in Build Docs summaries -│ ├── workflows/ # Entry points for the reusable workflow -│ │ └── Process-PSModule.yml # Consumer hook into this workflow bundle -│ ├── CODEOWNERS # Default reviewers enforced by Process-PSModule checks -│ ├── dependabot.yml # Dependency update cadence handled by GitHub -│ ├── zensical.toml # Site config consumed during site builds -│ ├── PSModule.yml # Settings parsed to drive matrices -│ └── release.yml # Release automation template invoked on publish -├── examples/ # Samples referenced in generated documentation -│ └── General.ps1 # Example script ingested by Document-PSModule -├── icon/ # Icon assets linked from manifest and documentation -│ └── icon.png # Default module icon (PNG format) -├── src/ # Module source, see "Module source code structure" below -├── tests/ # Pester suites; the Simple layout is shown -│ ├── AfterAll.ps1 (optional) # Cleanup script for ModuleLocal runs -│ ├── BeforeAll.ps1 (optional) # Setup script for ModuleLocal runs -│ └── .Tests.ps1 # Simple: one root-level module suite -├── .gitattributes # Normalizes line endings across platforms -├── .gitignore # Excludes build artifacts from source control -├── LICENSE # License text surfaced in manifest metadata -└── README.md # Repository overview rendered on GitHub and docs landing -``` - -The tree shows the [Simple PowerShell test profile](../../Coding-Standards/PowerShell/Testing.md#simple), not an exclusive test-file shape. Standard keeps one root-level `tests/.Tests.ps1` file per public function group. Advanced uses recursively discovered subdirectories, and layouts may mix across directories. Process-PSModule defines the exact [per-directory precedence and sibling suppression](pipeline-stages.md#module-local-test-discovery). - -These names describe repository conventions, not settings. `.github/PSModule.yml` does not select a test profile. The optional `tests/BeforeAll.ps1` and `tests/AfterAll.ps1` files are root-only workflow phases and are not discovered recursively. - -Key expectations: - -- Keep at least one exported function under `src/functions/public/` and corresponding tests in `tests/` using a [documented test profile](../../Coding-Standards/PowerShell/Testing.md#module-test-profiles). -- Keep documentation site configuration in `.github/zensical.toml`. -- Optional folders (`assemblies`, `formats`, `types`, `variables`, and others) are processed automatically when present. -- Markdown files in `src/functions/public` subfolders become documentation pages alongside generated help. -- A group's overview page (`/.md` named after the folder, or `/index.md`) becomes that group's section landing page in the docs navigation. -- The build step compiles `src/` into a root module file and removes the original project layout from the artifact. -- Documentation generation mirrors the `src/functions/public` hierarchy so help content always aligns with source. - -## Module source code structure - -How the module is built. - -```plaintext -├── src/ # Module source compiled and documented by the pipeline -│ ├── assemblies/ # Bundled binaries copied into the build artifact -│ ├── classes/ # Class scripts merged into the root module -│ │ ├── private/ # Internal classes kept out of exports -│ │ │ └── SecretWriter.ps1 # Example internal class implementation -│ │ └── public/ # Public classes exported via type accelerators -│ │ └── Book.ps1 # Example public class documented for consumers -│ ├── data/ # Configuration loaded into `$script:` scope at runtime -│ │ ├── Config.psd1 # Example config surfaced in generated help -│ │ └── Settings.psd1 # Additional configuration consumed on import -│ ├── formats/ # Formatting metadata registered during build -│ │ ├── CultureInfo.Format.ps1xml # Example format included in manifest -│ │ └── Mygciview.Format.ps1xml # Additional format loaded at import -│ ├── functions/ # Function scripts exported by the module -│ │ ├── private/ # Helper functions scoped to the module -│ │ │ ├── Get-InternalPSModule.ps1 # Sample internal helper -│ │ │ └── Set-InternalPSModule.ps1 # Sample internal helper -│ │ └── public/ # Public commands documented and tested -│ │ ├── Category/ # Optional: organize commands into categories -│ │ │ ├── Get-CategoryCommand.ps1 # Command file within category -│ │ │ └── Category.md # Group overview -> section landing page (or index.md) -│ │ ├── Get-PSModuleTest.ps1 # Example command captured by Microsoft.PowerShell.PlatyPS -│ │ ├── New-PSModuleTest.ps1 # Example command exported and tested -│ │ ├── Set-PSModuleTest.ps1 # Example command exported and tested -│ │ └── Test-PSModuleTest.ps1 # Example command exported and tested -│ ├── init/ # Initialization scripts executed during module load -│ │ └── initializer.ps1 # Example init script included in build output -│ ├── modules/ # Nested modules packaged with the compiled output -│ │ └── OtherPSModule.psm1 # Example nested module staged for export -│ ├── scripts/ # Scripts listed in 'ScriptsToProcess' -│ │ └── loader.ps1 # Loader executed when the module imports -│ ├── types/ # Type data merged into the manifest -│ │ ├── DirectoryInfo.Types.ps1xml # Type definition registered on import -│ │ └── FileInfo.Types.ps1xml # Type definition registered on import -│ ├── variables/ # Variable scripts exported by the module -│ │ ├── private/ # Internal variables scoped to the module -│ │ │ └── PrivateVariables.ps1 # Example private variable seed -│ │ └── public/ # Public variables exported and documented -│ │ ├── Moons.ps1 # Example variable surfaced in generated docs -│ │ ├── Planets.ps1 # Example variable surfaced in generated docs -│ │ └── SolarSystems.ps1 # Example variable surfaced in generated docs -│ ├── finally.ps1 # Cleanup script appended to the root module -│ ├── header.ps1 # Optional header injected at the top of the module -│ ├── manifest.psd1 (optional) # Source manifest reused when present -│ └── README.md # Module-level docs ingested by Document-PSModule -``` - -### Declaring module dependencies - -Declare module dependencies using -[`#Requires -Modules`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires) -statements at the top of function files in `src/functions/public/` or `src/functions/private/` that genuinely require external modules. For modules we build, the default is to avoid third-party module, DLL, and package dependencies when PowerShell, the .NET base class library, or code we own can carry the feature with reasonable effort. -[Build-PSModule](https://github.com/PSModule/Build-PSModule) collects every `#Requires -Modules` declaration across all -source files, de-duplicates the list, and writes it into the `RequiredModules` field of the compiled manifest -automatically. For the full range of supported syntax variants, see the -[about_Requires](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires) -documentation. - -> **Important:** Adding `RequiredModules` to `src/manifest.psd1` is **not** supported for this purpose. Those entries are silently ignored by the build and will not appear in the compiled manifest. Use `#Requires -Modules` in function files instead. diff --git a/src/docs/Capabilities/process-psmodule/skipping-framework-tests.md b/src/docs/Capabilities/process-psmodule/skipping-framework-tests.md deleted file mode 100644 index d7810c5..0000000 --- a/src/docs/Capabilities/process-psmodule/skipping-framework-tests.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: Skipping framework tests -description: How to skip individual PSModule framework tests on a per-file basis, the available test IDs, and the broader configuration alternatives. ---- - -# Skipping Individual Framework Tests - -The PSModule framework tests run automatically as part of the `Test-Module` and `Test-SourceCode` jobs. While you can skip entire test categories using the configuration settings (e.g., `Test.PSModule.Skip`), you can also skip individual framework tests on a per-file basis when needed. - -## How to Skip Tests - -To skip an individual framework test for a specific file, add a special comment at the top of that file: - -```powershell -#SkipTest:: -``` - -- ``: The unique identifier of the test to skip (see list below) -- ``: A brief explanation of why the test is being skipped - -The skip comment will cause the framework to skip that specific test for that file only, and will log a warning in the build output with the reason provided. - -## Available Framework Tests - -### SourceCode Tests - -These tests run against your source code files in the `src` directory: - -| Test ID | Description | Example Skip Comment | -|---------|-------------|---------------------| -| `NumberOfProcessors` | Enforces use of `[System.Environment]::ProcessorCount` instead of `$env:NUMBER_OF_PROCESSORS` | `#SkipTest:NumberOfProcessors:Legacy code compatibility required` | -| `Verbose` | Ensures code does not pass `-Verbose` to other commands (which would override user preference), unless explicitly disabled with `-Verbose:$false` | `#SkipTest:Verbose:Required for debugging output` | -| `OutNull` | Enforces use of `$null = ...` instead of `... \| Out-Null` for better performance | `#SkipTest:OutNull:Pipeline processing required` | -| `NoTernary` | Prohibits ternary operators for PowerShell 5.1 compatibility (this test is skipped by default in the framework) | `#SkipTest:NoTernary:PowerShell 7+ only module` | -| `LowercaseKeywords` | Ensures all PowerShell keywords are lowercase | `#SkipTest:LowercaseKeywords:Generated code` | -| `FunctionCount` | Ensures each file contains exactly one function | `#SkipTest:FunctionCount:Helper functions included` | -| `FunctionName` | Ensures the filename matches the function name | `#SkipTest:FunctionName:Legacy naming convention` | -| `CmdletBinding` | Requires all functions to have `[CmdletBinding()]` attribute | `#SkipTest:CmdletBinding:Simple helper function` | -| `ParamBlock` | Requires all functions to have a `param()` block | `#SkipTest:ParamBlock:No parameters needed` | -| `FunctionTest` | Ensures all public functions have corresponding tests | `#SkipTest:FunctionTest:Test in development` | - -### Module Tests - -These tests run against the compiled module in the `outputs/module` directory: - -- Module import validation -- Module manifest validation - -Module tests typically don't need to be skipped as they validate the final built module. - -## Example Usage - -Here's an example of a function file that skips the `FunctionCount` test because it includes helper functions: - -```powershell -#SkipTest:FunctionCount:This file contains helper functions for the main function - -function Get-ComplexData { - <# - .SYNOPSIS - Get formatted data from a file. - - .DESCRIPTION - Read data from a file and format it as a structured object. - - .EXAMPLE - Get-ComplexData -Path '.\data.txt' - - Get the file content and its character count. - - .INPUTS - None - - You can't pipe objects to Get-ComplexData. - - .OUTPUTS - System.Management.Automation.PSCustomObject - - The formatted file data. - - .NOTES - This file intentionally skips only the FunctionCount framework test. - - .LINK - https://psmodule.io//Functions/Get-ComplexData - #> - [OutputType([PSCustomObject])] - [CmdletBinding()] - param( - # The path to the data file. - [Parameter(Mandatory)] - [ValidateNotNullOrEmpty()] - [string] $Path - ) - - $data = Get-RawData -Path $Path - Format-ComplexData -Data $data -} - -function Get-RawData { - <# - .SYNOPSIS - Get unformatted data from a file. - - .DESCRIPTION - Read the complete content of a data file as one string. - - .EXAMPLE - Get-RawData -Path '.\data.txt' - - Get the complete content of the data file. - - .INPUTS - None - - You can't pipe objects to Get-RawData. - - .OUTPUTS - System.String - - The unformatted file content. - - .NOTES - This function is a private helper for Get-ComplexData. - - .LINK - https://psmodule.io//Functions/Get-ComplexData - #> - [OutputType([string])] - [CmdletBinding()] - param( - # The path to the data file. - [Parameter(Mandatory)] - [ValidateNotNullOrEmpty()] - [string] $Path - ) - - Get-Content -LiteralPath $Path -Raw -} - -function Format-ComplexData { - <# - .SYNOPSIS - Format raw data as a structured object. - - .DESCRIPTION - Add useful metadata to raw data while preserving its content. - - .EXAMPLE - Format-ComplexData -Data 'example' - - Format the string and include its character count. - - .INPUTS - None - - You can't pipe objects to Format-ComplexData. - - .OUTPUTS - System.Management.Automation.PSCustomObject - - The formatted data and its character count. - - .NOTES - This function is a private helper for Get-ComplexData. - - .LINK - https://psmodule.io//Functions/Get-ComplexData - #> - [OutputType([PSCustomObject])] - [CmdletBinding()] - param( - # The raw content to format. - [Parameter(Mandatory)] - [ValidateNotNullOrEmpty()] - [string] $Data - ) - - [PSCustomObject] @{ - Content = $Data - CharacterCount = $Data.Length - } -} -``` - -Replace `` with the module's published name. If the public function belongs to a group, insert `/` between `Functions/` and `Get-ComplexData`. - -The skip exempts only `FunctionCount`. Every function in the file must still follow the [PowerShell function standard](../../Coding-Standards/PowerShell/Functions.md), including complete comment-based help, matching `[OutputType()]` and `.OUTPUTS` metadata, typed parameters, and implicit output. - -## Best Practices - -- **Use skip comments sparingly**: Framework tests exist to maintain code quality and consistency. Only skip tests when absolutely necessary. -- **Provide clear reasons**: Always include a meaningful explanation in the skip comment to help reviewers understand why the test is being skipped. -- **Consider alternatives**: Before skipping a test, consider whether refactoring the code to comply with the test would be better for long-term maintainability. -- **Document exceptions**: If you skip a test, document the reason in your PR description or code comments. - -## Related Configuration - -For broader test control, use the configuration file settings: - -- Skip all framework tests: `Test.PSModule.Skip: true` -- Skip only source code tests: `Test.SourceCode.Skip: true` -- Skip framework tests on specific OS: `Test.PSModule.Windows.Skip: true` - -See the [Configuration](configuration.md) section for more details. diff --git a/src/docs/Capabilities/process-psmodule/spec.md b/src/docs/Capabilities/process-psmodule/spec.md deleted file mode 100644 index 27d441c..0000000 --- a/src/docs/Capabilities/process-psmodule/spec.md +++ /dev/null @@ -1,153 +0,0 @@ ---- -title: Spec -description: Requirements for Process-PSModule — an end-to-end PowerShell module pipeline that guarantees build, testing, quality gates, documentation generation, and versioned publication to package and docs registries. ---- - -# Process-PSModule — Spec - -## Premise - -A PowerShell module's lifecycle — from source code to versioned, published artifact — MUST be reliable, repeatable, and as automated as possible. Contributors focus on code and tests; the pipeline focuses on build, test, quality, documentation, and release. The pipeline MUST be driven entirely by pull-request labels and merge events, never by manual intervention or external tooling. The result is a versioned, immutable artifact — a module package in the PowerShell Gallery and its documentation site — paired with a GitHub Release and a git tag. - -### Principles - -This capability rests on the [Principles](../../Ways-of-Working/Principles/index.md): - -- **[Everything as Code](../../Ways-of-Working/Principles/Engineering-Practices.md#everything-as-code).** The pipeline and versioning are version-controlled, never a GUI action or manual tag. -- **[Decision before change](../../Ways-of-Working/Principles/AI-First-Development.md#decision-before-change).** The pull request is the decision point; its review and labels encode both code acceptance and release intent. -- **[Extensible by default](../../Ways-of-Working/Principles/Software-Design.md#extensible-by-default).** The pipeline is technology-agnostic at its core, configurable via a single settings file. - -## Scope - -Applies to any PowerShell module in the PSModule ecosystem that produces a versioned, publishable artifact. The pipeline does not govern module design, naming, or structure — only the lifecycle from source to published, versioned release. - -## Requirements - -### Functional Requirements - -### FR1 — Build the module from source { #fr1 } - -The pipeline MUST compile the PowerShell module source code into a module artifact, stamping it with the resolved semantic version and making it available for downstream testing and publication. - -### FR2 — Run cross-platform tests { #fr2 } - -The pipeline MUST execute the module's test suites against multiple platforms — at minimum Windows, Linux, and macOS — and fail the build if any platform's tests fail. Tests MUST include source-code validation (style, standards), framework tests (module structure, common issues), and module-local tests (user-written Pester tests). - -### FR3 — Enforce code quality and coverage gates { #fr3 } - -The pipeline MUST measure and enforce code coverage thresholds and static-analysis results. A build MUST NOT proceed to publication if quality or coverage targets are missed; the gate MUST prevent merge unless explicitly overridden by a label. - -### FR4 — Generate and publish documentation { #fr4 } - -The pipeline MUST generate module documentation from the source (cmdlet help, README, schema) and publish it to a static documentation site. Documentation MUST be versioned and deployable alongside the module release. - -### FR5 — Support label-driven versioning and publication { #fr5 } - -The pipeline MUST read pull-request labels (`Major`, `Minor`, `Patch`, `Prerelease`, `NoRelease`) to decide the semantic-version bump. It MUST compute the next version automatically, never reading or writing a hand-edited version file. A merge to the release branch MUST trigger publication to the PowerShell Gallery and documentation site; a prerelease label MUST result in a prerelease version available for testing before stable release. - -### FR6 — Produce immutable, linkable releases { #fr6 } - -Each publication MUST produce a GitHub Release, a git tag, and a PowerShell Gallery package version — all linked and versioned together so they are discoverable and pinnable for consumers. - -### Non-Functional Requirements - -### NFR1 — Semantic versioning compliance { #nfr1 } - -Versions MUST follow [SemVer 2.0.0](https://semver.org/) (`vMAJOR.MINOR.PATCH` or `vMAJOR.MINOR.PATCH-prerelease.N`). Breaking changes MUST increment `MAJOR`; new functionality MUST increment `MINOR`; bugfixes MUST increment `PATCH`. Prerelease versions MUST be obtainable but not promoted as the latest stable release. - -### NFR2 — Serialized releases { #nfr2 } - -Only one release process MUST run against a given version of the codebase at a time. Concurrent releases to the same ref MUST be prevented, so the tag, version counter, and published artifact remain consistent. - -### NFR3 — Single production authority { #nfr3 } - -Exactly one branch (typically `main`) MUST be authorized to publish stable releases. All other release branches MUST publish only prerelease versions. This ensures consumers have one unambiguous latest stable version. - -### NFR4 — Rapid feedback on failure { #nfr4 } - -Pipeline failures MUST be visible in the pull request and block merge. Contributors MUST know within minutes whether their changes pass quality and test gates, not hours or days later. - -### NFR5 — Reproducible and auditable { #nfr5 } - -The entire pipeline and its decisions MUST be stored in git, so the build is reproducible and auditable from the commit alone. No external configuration, API calls, or out-of-band decisions. - -## Success Criteria - -### Building and testing - -```gherkin -Scenario: Merge a valid pull request to main - Given a pull request with passing tests and quality gates - When the PR is merged to main - Then the module is built - And all tests pass on all configured platforms - And code coverage meets the configured threshold -``` - -### Version computation - -```gherkin -Scenario: Compute the next version from the PR label - Given a pull request with the label "Minor" - When the PR is merged to main and the current version is v1.2.3 - Then the new version is computed as v1.3.0 - -Scenario: Reject ambiguous version labels - Given a pull request with both "Major" and "Minor" labels - When the merge is attempted - Then the build fails and the merge is blocked -``` - -### Publication - -```gherkin -Scenario: Publish a module after a stable release - Given a merged PR to main with a version bump label - When the build completes successfully - Then a new version is published to the PowerShell Gallery - And a GitHub Release is created - And a git tag is pushed - And the documentation site is updated -``` - -### Prerelease workflow - -```gherkin -Scenario: Publish a prerelease version - Given a pull request with the label "Prerelease" - When the PR runs the pipeline - Then a prerelease version is published (e.g., v1.2.3-pr.1.N) - And it is available for testing before the PR is merged - -Scenario: Promote a prerelease to stable - Given a prerelease PR that is merged to main with a version label - When the PR is merged - Then a stable version is computed (e.g., v1.3.0) based on the label and the current main version - And the stable version is published -``` - -### Failure handling - -```gherkin -Scenario: Block merge on quality gate failure - Given a pull request failing code coverage requirements - When the PR is attempted to be merged - Then the build fails - And the merge is blocked - -Scenario: Handle documentation generation failure - Given a PR that breaks documentation generation - When the pipeline runs - Then the build fails - And feedback is provided in the PR - And the module is not published -``` - -## Where this connects - -- [Design](design.md) — how these requirements are delivered. -- [Pipeline stages](pipeline-stages.md) — the job-by-job breakdown of the workflow. -- [Usage](usage.md) — how to invoke and configure the workflow. -- [Configuration](configuration.md) — the settings file and its options. -- [Principles and practices](principles-and-practices.md) — versioning, branching, and development practices. -- [Documentation Model](../../Ways-of-Working/Documentation-Model.md) — why this spec holds only the why and what. diff --git a/src/docs/Capabilities/process-psmodule/usage.md b/src/docs/Capabilities/process-psmodule/usage.md deleted file mode 100644 index d0ae5f3..0000000 --- a/src/docs/Capabilities/process-psmodule/usage.md +++ /dev/null @@ -1,307 +0,0 @@ ---- -title: Usage -description: How to call the Process-PSModule workflow — inputs, secrets, permissions, the scenario matrix, and important-file change detection. ---- - -# Usage - -To use the workflow, create a new file in the `.github/workflows` directory of the module repository and add the following content. -For documentation site generation, use `zensical.toml` as the active site contract. - -
-Workflow suggestion - -```yaml -name: Process-PSModule - -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' - pull_request: - branches: - - main - types: - - closed - - opened - - reopened - - synchronize - - labeled - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: write - pull-requests: write - statuses: write - pages: write - id-token: write - -jobs: - Process-PSModule: - uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 - secrets: - APIKey: ${{ secrets.APIKey }} -``` - -
- -## Inputs - -| Name | Type | Description | Required | Default | -| ---- | ---- | ----------- | -------- | ------- | -| `SettingsPath` | `string` | The path to the settings file. All workflow configuration is controlled through this settings file. | `false` | `.github/PSModule.yml` | -| `Debug` | `boolean` | Enable debug output. | `false` | `false` | -| `Verbose` | `boolean` | Enable verbose output. | `false` | `false` | -| `Version` | `string` | Specifies the version of the GitHub module to be installed. The value must be an exact version. | `false` | `''` | -| `Prerelease` | `boolean` | Whether to use a prerelease version of the 'GitHub' module. | `false` | `false` | -| `WorkingDirectory` | `string` | The path to the root of the repo. | `false` | `'.'` | -| `ImportantFilePatterns` | `string` | Newline-separated list of regular expression patterns that identify important files. Changes matching these patterns trigger build, test, and publish stages. When set, fully replaces the defaults. | `false` | `^src/\n^README\.md$` | - -## Secrets - -The reusable workflow at `.github/workflows/workflow.yml` declares only two workflow-call secrets, -which keeps the calling workflow in full control of the credentials that are exposed. -`secrets: inherit` is intentionally not required. - -| Name | Location | Description | Required | -| ---- | -------- | ----------- | -------- | -| `APIKey` | GitHub secrets | The API key for the PowerShell Gallery, used to publish the module. | Yes | -| `TestData` | GitHub secrets | A single-line JSON object with `secrets` and `variables` maps, exposed as environment variables to the module test jobs. Values under `secrets` are masked; values under `variables` are not. | No | - -### Breaking change: fixed test secrets moved to `TestData` - -The reusable workflow no longer declares or accepts the old fixed test-secret inputs: - -- `TEST_APP_ENT_CLIENT_ID` -- `TEST_APP_ENT_PRIVATE_KEY` -- `TEST_APP_ORG_CLIENT_ID` -- `TEST_APP_ORG_PRIVATE_KEY` -- `TEST_USER_ORG_FG_PAT` -- `TEST_USER_USER_FG_PAT` -- `TEST_USER_PAT` - -If a caller passed any of these secrets directly, move them into the `secrets` map inside `TestData`. -The environment variable names used by the tests can stay the same; only the workflow-call interface -changes: - -```yaml -jobs: - Process-PSModule: - uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 - secrets: - APIKey: ${{ secrets.APIKey }} - TestData: >- - { "secrets": { "TEST_USER_PAT": "${{ secrets.TEST_USER_PAT }}", - "TEST_APP_ORG_CLIENT_ID": "${{ secrets.TEST_APP_ORG_CLIENT_ID }}" } } -``` - -### Passing test phase data (secrets and variables) - -A single `TestData` secret lets a module expose any number of caller-defined values to its test jobs -(`BeforeAll-ModuleLocal`, `Test-ModuleLocal` and `AfterAll-ModuleLocal`) without changing the shared -workflow. It is one JSON object with two maps, so everything the tests need is visible in one place: - -```json -{ "secrets": { "NAME": "value" }, "variables": { "NAME": "value" } } -``` - -Values under `secrets` are masked in the logs; values under `variables` are not. Build it in the -calling workflow and pass it through the `secrets:` block (so the whole blob is masked). Reference each -secret directly as `"${{ secrets. }}"` and each variable as `${{ toJSON(vars.) }}`. A -folded `>-` scalar keeps the source readable while producing a single-line value, as long as the JSON -content lines stay at the same indentation level: - -```yaml -jobs: - Process-PSModule: - uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 - secrets: - APIKey: ${{ secrets.APIKey }} - TestData: >- - { "secrets": { "CONFLUENCE_API_TOKEN": "${{ secrets.CONFLUENCE_API_TOKEN }}" }, - "variables": { "CONFLUENCE_SITE": ${{ toJSON(vars.CONFLUENCE_SITE) }}, - "CONFLUENCE_USERNAME": ${{ toJSON(vars.CONFLUENCE_USERNAME) }}, - "CONFLUENCE_SPACE_KEY": ${{ toJSON(vars.CONFLUENCE_SPACE_KEY) }} } } -``` - -Each entry becomes an environment variable in the test jobs, so the module's Pester tests read the -values directly: - -```powershell -$env:CONFLUENCE_API_TOKEN # from the "secrets" map (masked in logs) -$env:CONFLUENCE_SITE # from the "variables" map (not masked) -``` - -The same `TestData` keys are exported before every module-local phase runs: - -- `BeforeAll-ModuleLocal` runs root `tests/BeforeAll.ps1` before the module-local test matrix. -- `Test-ModuleLocal` discovers and runs module-local Pester tests recursively. -- `AfterAll-ModuleLocal` runs root `tests/AfterAll.ps1` after the module-local test matrix, including cleanup paths. - -Setup and teardown detection is not recursive. These root scripts and the discovered tests should use the same environment variable names. -If `$env:` is available in one phase but missing in another, treat that as a Process-PSModule -propagation bug rather than a caller contract difference. - -Notes: - -- The names are caller-defined; no secret or variable names are hard-coded in the shared workflow. - Names must match `^[A-Za-z_][A-Za-z0-9_]*$` and must not override reserved variables such as `PATH`, - `CI`, `GITHUB_*`, `RUNNER_*` or `ACTIONS_*`. -- The `TestData` validation, masking and environment export logic is shared by the ModuleLocal workflows - through the [`PSModule/Install-PSModuleHelpers`](https://github.com/PSModule/Install-PSModuleHelpers) - action, which installs the `Import-TestData` command each workflow runs to expose the values. -- Reference secrets as `"${{ secrets. }}"` (quoted, directly) rather than - `toJSON(secrets.)`. The direct form keeps CodeQL's *excessive secrets exposure* check happy and - works for single-line secret values. It cannot carry values that contain `"`, `\` or newlines, so - base64-encode a multi-line or special-character secret and decode it in the test (for example - `[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($env:MY_KEY_B64))`). -- Variables use `toJSON(vars.)` so any characters are JSON-encoded safely; they are never masked. - You can use the same quoted direct form as secrets (`"${{ vars. }}"`) only for simple values - that do not contain `"`, `\` or newlines. -- Provide `TestData` as a single-line value (the folded `>-` block above does this). Avoid a literal - `|` block: GitHub registers every line of a multi-line secret as its own mask, which over-masks - unrelated log output. -- Do not pretty-print `TestData` with nested indentation. YAML preserves more-indented lines inside a - folded scalar, so a fully formatted JSON object can still become a multi-line secret. That makes - GitHub register each line as its own mask, including brace-only lines such as `{`, `}` or `},`, which - can turn unrelated log output into `***`. Keep the compact form above, or keep every JSON content - line at the same indentation level. -- Omit `TestData` entirely when the module needs no secrets or variables. Include only the map you - need (just `secrets`, just `variables`, or both). -- Because `secrets: inherit` is not used, only the values you list are ever exposed. -- If using `secrets: inherit` in a caller workflow, remember that GitHub only forwards secrets that - already exist by name. It does not assemble a `TestData` JSON payload from individual secrets such as - `TEST_USER_PAT`; the caller must still create and pass the `TestData` value explicitly. -- Organization, repository and GitHub *Environment* secrets and variables are supported when they are - visible to the calling job. For environment-scoped values, set `environment:` on the calling job and - explicitly include those values in `TestData`; they are not exposed automatically. - -## Permissions - -The following permissions are needed for the workflow to be able to perform all tasks. - -```yaml -permissions: - contents: write # to checkout the repo and create releases on the repo - pull-requests: write # to write comments to PRs - statuses: write # to update the status of the workflow from linter - pages: write # to deploy to Pages - id-token: write # to verify the Pages deployment originates from an appropriate source -``` - -For more info, see [Deploy GitHub Pages site](https://github.com/marketplace/actions/deploy-github-pages-site). - -## Scenario Matrix - -This table shows when each job runs based on the trigger scenario: - -| Job | Open/Updated PR | Merged PR | Abandoned PR | Manual Run | -| ------------------------- | --------------- | ---------- | ------------ | ---------- | -| **Plan** | ✅ Always | ✅ Always | ✅ Always | ✅ Always | -| **Lint-Repository** | ✅ Yes | ❌ No | ❌ No | ❌ No | -| **Build-Module** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Build-Docs** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Build-Site** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Test-SourceCode** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Lint-SourceCode** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Test-Module** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **BeforeAll-ModuleLocal** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Test-ModuleLocal** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **AfterAll-ModuleLocal** | ✅ Yes | ✅ Yes | ✅ Yes* | ✅ Yes | -| **Get-TestResults** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Get-CodeCoverage** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Publish-Site** | ❌ No | ✅ Yes | ❌ No | ❌ No | -| **Publish-Module** | ✅ Yes** | ✅ Yes** | ✅ Yes*** | ✅ Yes** | - -- \* Runs for cleanup if tests were started -- \*\* Only when all tests/coverage/build succeed -- \*\*\* Cleans up prerelease versions and tags created for the abandoned PR (when `Publish.Module.AutoCleanup` is - enabled) - -## Important file change detection - -The workflow automatically detects whether a pull request contains changes to "important" files that should enter the -build, test, and publish path. This prevents unnecessary work and releases when only files outside the configured -patterns are modified. - -### Files that trigger the important-change path - -By default, the following regular expression patterns identify important files: - -| Pattern | Description | -| :--- | :---------- | -| `^src/` | Module source code | -| `^README\.md$` | Module documentation | - -### Customizing important file patterns - -To override the default patterns, set `ImportantFilePatterns` in your settings file (`.github/PSModule.yml`): - -```yaml -ImportantFilePatterns: - - '^src/' - - '^README\.md$' - - '^tests/' - - '^\.github/PSModule\.yml$' - - '^\.github/workflows/' -``` - -When configured, the provided list fully replaces the defaults. Include the default patterns in your list if you still -want them to trigger the build, test, and publish path. - -Recursive [module-local test discovery](pipeline-stages.md#module-local-test-discovery) does not change this trigger. -With the defaults, a test-only change does not run the important-change build, test, and publish stages because -`^tests/` is not matched. Add `^tests/` when those changes must exercise the path, plus each settings, workflow, or -other automation path whose changes need the same validation. Include only paths that should trigger all three stages. - -To disable file-change triggering entirely (so that no file changes ever trigger a release), set an empty list in the -settings file: - -```yaml -ImportantFilePatterns: [] -``` - -You can also pass patterns via the workflow input: - -```yaml -jobs: - Process: - uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 - with: - ImportantFilePatterns: | - ^src/ - ^README\.md$ - ^examples/ -``` - -To disable triggering via the workflow input, pass an explicit empty string: - -```yaml -jobs: - process: - uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 - with: - ImportantFilePatterns: '' -``` - -Note that omitting the `ImportantFilePatterns` key entirely causes the workflow's default patterns (`^src/` and -`^README\.md$`) to be used. The settings file takes priority over the workflow input, so set -`ImportantFilePatterns: []` in `.github/PSModule.yml` to disable triggering regardless of the workflow input. - -Resolution order: settings file → workflow input → workflow input default values. - -### Behavior when no important files are changed - -When a pull request does not contain changes to important files: - -1. A comment is automatically added to the PR listing the configured patterns and explaining why build/test stages are - skipped -2. `Settings.Publish.Module.Resolution.ReleaseType` is `None` (and `Settings.Publish.Module.Resolution.CreateRelease` is `false`) -3. Build, test, and publish stages are skipped -4. The PR can still be merged for non-release changes (documentation updates, CI improvements, etc.) - -This behavior ensures that maintenance PRs (such as updating GitHub Actions versions or fixing typos in comments) -don't create unnecessary releases in the PowerShell Gallery. diff --git a/src/docs/Coding-Standards/PowerShell/Testing.md b/src/docs/Coding-Standards/PowerShell/Testing.md index fb20b6f..d50dfc2 100644 --- a/src/docs/Coding-Standards/PowerShell/Testing.md +++ b/src/docs/Coding-Standards/PowerShell/Testing.md @@ -55,4 +55,4 @@ tests/ └── Windows.Container.ps1 ``` -Different directories may use different forms. Process-PSModule recursively applies its [per-directory discovery precedence](../../Capabilities/process-psmodule/pipeline-stages.md#module-local-test-discovery), including sibling suppression, unique test-name requirements, and root-only workflow phases. +Different directories may use different forms. Process-PSModule recursively applies its [per-directory discovery precedence](https://psmodule.io/docs/Modules/Process-PSModule/), including sibling suppression, unique test-name requirements, and root-only workflow phases. diff --git a/src/docs/Initiatives/PSModule.md b/src/docs/Initiatives/PSModule.md index 04c06b1..1537f46 100644 --- a/src/docs/Initiatives/PSModule.md +++ b/src/docs/Initiatives/PSModule.md @@ -12,7 +12,7 @@ It is two things at once: - **A module-building workflow** — GitHub Actions and reusable workflows that automate the whole PowerShell delivery lifecycle: build, test, version, and publish. - **The modules themselves** — a growing collection of reusable PowerShell modules built with that workflow. -PSModule inherits the [Coding Standards](../Coding-Standards/index.md) and [Ways of Working](../Ways-of-Working/index.md) from this site and adds only what is specific to the framework. The end-to-end workflow that ships every module — Process-PSModule — is documented under [Capabilities](../Capabilities/process-psmodule/index.md), and its module reference lives at [psmodule.io](https://psmodule.io). +PSModule inherits the [Coding Standards](../Coding-Standards/index.md) and [Ways of Working](../Ways-of-Working/index.md) from this site and adds only what is specific to the framework. The end-to-end workflow that ships every module — [Process-PSModule](https://psmodule.io/docs/Modules/Process-PSModule/) — is documented at its canonical site. ## Canonical boundary diff --git a/src/zensical.toml b/src/zensical.toml index d068328..cd17916 100644 --- a/src/zensical.toml +++ b/src/zensical.toml @@ -148,17 +148,6 @@ nav = [ {"Spec" = "Capabilities/powershell-on-github/spec.md"}, {"Design" = "Capabilities/powershell-on-github/design.md"}, ]}, - {"Process-PSModule" = [ - "Capabilities/process-psmodule/index.md", - {"Spec" = "Capabilities/process-psmodule/spec.md"}, - {"Design" = "Capabilities/process-psmodule/design.md"}, - {"Pipeline Stages" = "Capabilities/process-psmodule/pipeline-stages.md"}, - {"Usage" = "Capabilities/process-psmodule/usage.md"}, - {"Configuration" = "Capabilities/process-psmodule/configuration.md"}, - {"Skipping Framework Tests" = "Capabilities/process-psmodule/skipping-framework-tests.md"}, - {"Repository Structure" = "Capabilities/process-psmodule/repository-structure.md"}, - {"Principles and Practices" = "Capabilities/process-psmodule/principles-and-practices.md"}, - ]}, {"Agentic Development" = [ "Capabilities/agentic-development/index.md", {"Spec" = "Capabilities/agentic-development/spec.md"},