|
| 1 | +--- |
| 2 | +title: Design |
| 3 | +description: How Process-PSModule delivers the spec — a single reusable GitHub Actions workflow composing sub-workflows, a settings file contract, and the scenario matrix. |
| 4 | +--- |
| 5 | + |
| 6 | +# Process-PSModule — Design |
| 7 | + |
| 8 | +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. |
| 9 | + |
| 10 | +## Workflow architecture |
| 11 | + |
| 12 | +### Single entry point |
| 13 | + |
| 14 | +The reusable workflow accepts a caller workflow and minimal caller configuration: |
| 15 | + |
| 16 | +```yaml |
| 17 | +# .github/workflows/Process-PSModule.yml in the module repository |
| 18 | +name: Process-PSModule |
| 19 | + |
| 20 | +on: |
| 21 | + workflow_dispatch: |
| 22 | + schedule: |
| 23 | + - cron: '0 0 * * *' |
| 24 | + pull_request: |
| 25 | + branches: |
| 26 | + - main |
| 27 | + types: |
| 28 | + - closed |
| 29 | + - opened |
| 30 | + - reopened |
| 31 | + - synchronize |
| 32 | + - labeled |
| 33 | + |
| 34 | +concurrency: |
| 35 | + group: ${{ github.workflow }}-${{ github.ref }} |
| 36 | + cancel-in-progress: true |
| 37 | + |
| 38 | +permissions: |
| 39 | + contents: write |
| 40 | + pull-requests: write |
| 41 | + statuses: write |
| 42 | + pages: write |
| 43 | + id-token: write |
| 44 | + |
| 45 | +jobs: |
| 46 | + Process-PSModule: |
| 47 | + uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 |
| 48 | + secrets: |
| 49 | + APIKey: ${{ secrets.APIKey }} |
| 50 | +``` |
| 51 | +
|
| 52 | +### Composed reusable workflows |
| 53 | +
|
| 54 | +The main workflow composes work across specialized reusable workflows, each owning a pipeline stage: |
| 55 | +
|
| 56 | +- **Plan** — reads the settings file and event context, decides what runs, computes the next version |
| 57 | +- **Lint-Repository** — validates repository structure and configuration |
| 58 | +- **Build-Module** — compiles the module source and versions the manifest |
| 59 | +- **Test-SourceCode** — validates source-code style and standards (PSScriptAnalyzer, framework tests) |
| 60 | +- **Lint-SourceCode** — runs static analysis on source |
| 61 | +- **Test-Module** — runs framework tests and module-local Pester tests in parallel per platform |
| 62 | +- **Get-TestResults** — aggregates test results and enforces pass/fail |
| 63 | +- **Get-CodeCoverage** — collects coverage from tests and enforces thresholds |
| 64 | +- **Publish-Module** — publishes the module to the PowerShell Gallery |
| 65 | +- **Publish-Site** — generates and publishes documentation to GitHub Pages |
| 66 | +
|
| 67 | +Each workflow is reusable so it can be tested and versioned independently, invoked by name in the main orchestration workflow. |
| 68 | +
|
| 69 | +## Settings file contract |
| 70 | +
|
| 71 | +The caller provides `.github/PSModule.yml`: |
| 72 | + |
| 73 | +```yaml |
| 74 | +# Minimal example — defaults apply for everything not specified |
| 75 | +Linter: |
| 76 | + Repository: |
| 77 | + Enabled: true |
| 78 | +
|
| 79 | +Build: |
| 80 | + Module: |
| 81 | + Enabled: true |
| 82 | +
|
| 83 | +Test: |
| 84 | + SourceCode: |
| 85 | + Enabled: true |
| 86 | + PSModule: |
| 87 | + Enabled: true |
| 88 | + Module: |
| 89 | + Enabled: true |
| 90 | + CodeCoverage: |
| 91 | + Enabled: true |
| 92 | + Threshold: 80 |
| 93 | +
|
| 94 | +Publish: |
| 95 | + Module: |
| 96 | + Enabled: true |
| 97 | + Site: |
| 98 | + Enabled: true |
| 99 | +``` |
| 100 | + |
| 101 | +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. |
| 102 | + |
| 103 | +### Runtime settings contract |
| 104 | + |
| 105 | +| Path | Meaning | |
| 106 | +| --- | --- | |
| 107 | +| `Settings.Linter.Repository.Enabled` | Whether repository linting runs. | |
| 108 | +| `Settings.Build.Module.Enabled` | Whether module build runs. | |
| 109 | +| `Settings.Test.SourceCode.Enabled` | Whether source-code tests run. | |
| 110 | +| `Settings.Test.PSModule.Enabled` | Whether framework tests run. | |
| 111 | +| `Settings.Test.Module.Enabled` | Whether module-local tests run. | |
| 112 | +| `Settings.Test.TestResults.Enabled` | Whether test-results aggregation runs. | |
| 113 | +| `Settings.Test.CodeCoverage.Enabled` | Whether code-coverage gates run. | |
| 114 | +| `Settings.Publish.Module.Enabled` | Whether module publication runs. | |
| 115 | +| `Settings.Publish.Site.Enabled` | Whether documentation publication runs. | |
| 116 | +| `Settings.Test.SourceCode.Suites` | Computed source-code test matrix (platform × test suite). | |
| 117 | +| `Settings.Test.PSModule.Suites` | Computed framework test matrix (platform × test suite). | |
| 118 | +| `Settings.Test.Module.Suites` | Computed module-local test matrix (platform × test suite). | |
| 119 | +| `Settings.Publish.Module.Resolution.Version` | Resolved semantic version (e.g., `v1.2.3`). | |
| 120 | +| `Settings.Publish.Module.Resolution.Prerelease` | Whether the version is prerelease. | |
| 121 | +| `Settings.Publish.Module.Resolution.FullVersion` | Full version string (e.g., `v1.2.3-pr.1.5`). | |
| 122 | +| `Settings.Publish.Module.Resolution.ReleaseType` | `stable`, `prerelease`, or `none`. | |
| 123 | +| `Settings.Publish.Module.Resolution.CreateRelease` | Whether to create a GitHub Release. | |
| 124 | + |
| 125 | +## Scenario matrix |
| 126 | + |
| 127 | +### Version labeling |
| 128 | + |
| 129 | +- **Major** — breaking change; bump `MAJOR` in SemVer |
| 130 | +- **Minor** — new feature; bump `MINOR` |
| 131 | +- **Patch** — bugfix; bump `PATCH` (default if no label) |
| 132 | +- **Prerelease** — publish as prerelease, not promoted to latest |
| 133 | +- **NoRelease** — run pipeline, skip publication |
| 134 | + |
| 135 | +Multiple SemVer labels or conflicting labels (e.g., `Major` + `NoRelease`) are rejected and block the merge. |
| 136 | + |
| 137 | +### Branch types |
| 138 | + |
| 139 | +- **Main (stable)** — publishes stable releases. A prerelease label publishes a prerelease from `main`. |
| 140 | +- **Development** — optional prerelease branch (e.g., `dev`). Each push publishes a prerelease. |
| 141 | +- **Feature branch** — optional feature branch. A prerelease label publishes a prerelease for testing. |
| 142 | + |
| 143 | +### Platform matrix |
| 144 | + |
| 145 | +Tests run on: |
| 146 | + |
| 147 | +- **Windows** (latest) |
| 148 | +- **Linux** (Ubuntu latest) |
| 149 | +- **macOS** (latest) |
| 150 | + |
| 151 | +Failures on any platform block the build. |
| 152 | + |
| 153 | +### Test suites |
| 154 | + |
| 155 | +Each platform runs in parallel: |
| 156 | + |
| 157 | +- **Source-code tests** — style, naming, structure (PSModule framework) |
| 158 | +- **Framework tests** — module structure, common issues (PSModule framework) |
| 159 | +- **Module-local tests** — Pester tests written by the module author |
| 160 | +- **Linting** — PSScriptAnalyzer rules |
| 161 | + |
| 162 | +Test results are aggregated into a single pass/fail and reported to the PR. |
| 163 | + |
| 164 | +## Alternatives considered |
| 165 | + |
| 166 | +### Monolithic workflow vs. composable reusable workflows |
| 167 | + |
| 168 | +**Chosen: Composable reusable workflows** |
| 169 | + |
| 170 | +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. |
| 171 | + |
| 172 | +**Alternative: Single monolithic workflow** |
| 173 | + |
| 174 | +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. |
| 175 | + |
| 176 | +### Settings file format |
| 177 | + |
| 178 | +**Chosen: YAML with runtime enrichment** |
| 179 | + |
| 180 | +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. |
| 181 | + |
| 182 | +**Alternative: JSON in workflow outputs** |
| 183 | + |
| 184 | +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. |
| 185 | + |
| 186 | +### Version computation |
| 187 | + |
| 188 | +**Chosen: PR label + current version** |
| 189 | + |
| 190 | +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. |
| 191 | + |
| 192 | +**Alternative: Conventional Commits** |
| 193 | + |
| 194 | +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. |
| 195 | + |
| 196 | +## External dependencies |
| 197 | + |
| 198 | +The workflow relies on: |
| 199 | + |
| 200 | +- **[PSModule/Build-PSModule](https://github.com/PSModule/Build-PSModule)** — compiles and versions the module |
| 201 | +- **[PSModule/Test-PSModule](https://github.com/PSModule/Test-PSModule)** — runs framework tests and style validation |
| 202 | +- **[PSModule/Invoke-ScriptAnalyzer](https://github.com/PSModule/Invoke-ScriptAnalyzer)** — runs PSScriptAnalyzer linting |
| 203 | +- **[Pester](https://pester.dev/)** — runs module tests |
| 204 | +- **[GitHub Actions](https://github.com/features/actions)** — workflow engine |
| 205 | +- **PowerShell Gallery API** — publishes module packages |
| 206 | +- **GitHub Pages** — hosts documentation |
| 207 | +- **Zensical** — generates documentation from source |
| 208 | + |
| 209 | +Each is versioned independently; the main workflow pins versions explicitly. |
| 210 | + |
| 211 | +## Where this connects |
| 212 | + |
| 213 | +- [Spec](spec.md) — the requirements this design delivers. |
| 214 | +- [Pipeline stages](pipeline-stages.md) — detailed breakdown of each job. |
| 215 | +- [Usage](usage.md) — how to invoke and configure. |
| 216 | +- [Configuration](configuration.md) — the settings file reference. |
| 217 | +- [Principles and practices](principles-and-practices.md) — the principles guiding this design. |
| 218 | +- [Repository structure](repository-structure.md) — the repo layout the workflow expects. |
0 commit comments