diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 22f34aa..6122ad2 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -85,8 +85,8 @@ index and drill down to the right page. Three conventions make that work. - **The tables are generated from front matter.** `.github/scripts/Update-DocumentationIndex.ps1` reads each page's `title` and `description`, orders them to match the navigation in - `src/zensical.toml`, and fills every index in place. CI runs the same script with `-Check` - and fails if an index is out of date. + `src/zensical.toml`, and fills every index in place. CI regenerates the indexes before + building the site instead of rejecting index drift. Choose a page's home by subject first, then by the artifact that answers the reader's question. The [Documentation Model](https://msxorg.github.io/docs/Ways-of-Working/Documentation-Model/#architecture-and-classification) diff --git a/.github/scripts/Update-DocumentationIndex.ps1 b/.github/scripts/Update-DocumentationIndex.ps1 index 047fcd4..7e18df1 100644 --- a/.github/scripts/Update-DocumentationIndex.ps1 +++ b/.github/scripts/Update-DocumentationIndex.ps1 @@ -21,11 +21,12 @@ .EXAMPLE ./Update-DocumentationIndex.ps1 Updates every section index.md in place from the current front matter. + CI runs this mode before building the site. .EXAMPLE ./Update-DocumentationIndex.ps1 -Check Verifies the indexes are current without writing; exits non-zero on drift. - This is the mode the CI build job runs. + This is an optional local diagnostic, not a CI gate. #> [CmdletBinding()] param( diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml index 10d662c..de01a42 100644 --- a/.github/workflows/Docs.yml +++ b/.github/workflows/Docs.yml @@ -76,9 +76,9 @@ jobs: with: python-version: 3.x - - name: Verify documentation indexes + - name: Generate documentation indexes shell: pwsh - run: ./.github/scripts/Update-DocumentationIndex.ps1 -Check + run: ./.github/scripts/Update-DocumentationIndex.ps1 - name: Install Zensical run: pip install -r requirements.txt diff --git a/src/docs/Capabilities/release-management/design.md b/src/docs/Capabilities/release-management/design.md index 1466cc6..76b3857 100644 --- a/src/docs/Capabilities/release-management/design.md +++ b/src/docs/Capabilities/release-management/design.md @@ -8,7 +8,7 @@ description: How release management is built — effective defaults, owned overr The behavior in the [spec](spec.md) is delivered by shared release mechanics, through a reusable workflow or a native producer pipeline. A repository's effective release pipeline establishes which target routes are managed. The -optional `.github/release.config.yml` file refines those settings; it does not +release solution's optional `.github/release.settings.yml` file refines those settings; it does not create a release pipeline, and its absence does not opt a managed route out. Documented defaults make a managed route usable without per-PR bump labels; repository settings, supported caller inputs, and owned labels provide overrides. @@ -21,7 +21,7 @@ immutable output that another system consumes by version. - When a shared workflow or native producer pipeline delivers that release behavior, evaluate its release decision and require the pre-merge check. This - remains true when `.github/release.config.yml` is absent or the route does not + remains true when `.github/release.settings.yml` is absent or the route does not call a named shared workflow. - When the route has no versioned release behavior, Release Management does not apply. Omit the `Release decisions` block and every `release:*` label, @@ -57,7 +57,7 @@ A **release branch** is any branch configured as a release target, each with a a release branch produces **exactly one** release for all bundled changes. ```yaml -# .github/release.config.yml +# .github/release.settings.yml release-branches: - branch: main release-type: stable @@ -105,9 +105,15 @@ that supplied each decision before Build. ### Settings and caller overrides +The release solution uses `.github/release.settings.yml` under the [Naming standard](../../Coding-Standards/Naming.md#solution-settings-files). + +A filename convention does not implement a reader or rename its public input. Verify the immutable producer revision's declared settings input and default before adoption. `ConfigurationFile`, where exposed, remains the settings-path input; supported explicit custom paths follow that producer's contract. + +[Module settings](../../Initiatives/PSModule.md#module-settings) retain their supported initiative interface; the release-solution filename does not replace it. + Follow [Smart defaults, local overrides](../../Ways-of-Working/Principles/Software-Design.md#smart-defaults-local-overrides): shared defaults are overridden by repository settings in the optional -`.github/release.config.yml`, then by explicitly supplied supported caller +`.github/release.settings.yml`, then by explicitly supplied supported caller inputs for that invocation. Omitted caller inputs preserve repository settings; they do not overwrite them with an input's default. The implementing workflow or action documents its exact supported caller surface and validates it through @@ -121,13 +127,13 @@ even when a narrower override or bump label exists. | Setting | Shared default | Repository override | Supported caller override | | --- | --- | --- | --- | -| `DefaultBump` | `patch` | `DefaultBump` in `.github/release.config.yml` | Explicitly supplied caller override supported and documented by the invoked producer for this setting. | +| `DefaultBump` | `patch` | `DefaultBump` in `.github/release.settings.yml` | Explicitly supplied caller override supported and documented by the invoked producer for this setting. | For example, a repository can select minor as its normal level without requiring a minor label on every publishing PR: ```yaml -# .github/release.config.yml +# .github/release.settings.yml DefaultBump: minor ``` @@ -256,7 +262,7 @@ either: rerun the existing release with the same artifact and version under the ## Path filtering -When present, `.github/release.config.yml` declares `release-paths` as ordered +When present, `.github/release.settings.yml` declares `release-paths` as ordered include/exclude globs (excludes win). On an invoked route, the workflow **always runs** so validation executes on every merge; only the release step is skipped when no artifact-affecting path changed. @@ -494,12 +500,12 @@ release, and its runs are serialised like any other. | Surface | Where | | --- | --- | | Release Management applicability | effective target-route pipeline, including shared workflows and native producers | -| Release branches + type | optional `.github/release.config.yml`; the default branch is stable when omitted | +| Release branches + type | optional `.github/release.settings.yml`; the default branch is stable when omitted | | Default bump and overrides | documented shared `DefaultBump: patch`, repository settings, then supported caller inputs | | Explicit bump / prerelease / skip | `release:` PR label on an invoked route | | Pre-merge decision validation | named PR check required by the branch ruleset or protection | | Optional ad hoc release | `workflow_dispatch` inputs | -| Path filter | `.github/release.config.yml` | +| Path filter | `.github/release.settings.yml` | | Prerelease cleanup toggle | release config / workflow input | | Publishing targets | reusable-workflow input + GitHub environment; see [Publishing Targets](design-publishing-targets.md) | diff --git a/src/docs/Capabilities/release-management/spec.md b/src/docs/Capabilities/release-management/spec.md index 5ef9a80..1dcba21 100644 --- a/src/docs/Capabilities/release-management/spec.md +++ b/src/docs/Capabilities/release-management/spec.md @@ -16,7 +16,7 @@ release CLI, a hand-edited version file, or a tagging convention. A target route participates when its effective pipeline produces a versioned, immutable output consumed by version. This includes a shared Release Management workflow and a native producer pipeline; the contract is not conditional on one -implementation's name. The optional `.github/release.config.yml` file refines a +implementation's name. The release solution's optional `.github/release.settings.yml` file refines a managed route's settings but does not create a release pipeline, and its absence does not opt a managed route out. @@ -41,7 +41,7 @@ If no, there is nothing to release and the pull request carries neither the ## Requirements - **Semantic versioning.** Versions follow [SemVer 2.0.0](https://semver.org/) (`vMAJOR.MINOR.PATCH`), derived automatically — never written by hand. -- **Release behavior determines applicability.** Release Management MUST evaluate every pull request targeting a managed release route, including native producer routes and routes without `.github/release.config.yml`. A route without versioned release behavior MUST NOT require, apply, or report the `Release decisions` block or any `release:*` label. +- **Release behavior determines applicability.** Release Management MUST evaluate every pull request targeting a managed release route, including native producer routes and routes without `.github/release.settings.yml`. A route without versioned release behavior MUST NOT require, apply, or report the `Release decisions` block or any `release:*` label. - **Producer compatibility is verified, not inferred.** Authors MUST verify the effective producer revision's settings and owned-label mapping. A differing released interface MUST have a verified adapter or producer/configuration migration before the canonical signals are used. Unsupported signals MUST block finalization and required decision validation, not become ignored skip requests or an excuse to classify a managed route as unmanaged. The producer's PR/release record owns its exact adoption actions. - **Settings have documented defaults and supported overrides.** Release automation MUST document its setting names, accepted values, shared defaults, and supported caller overrides. Repository settings MUST override shared defaults; explicitly supplied supported caller inputs MUST override repository settings for that invocation. Unknown settings and invalid supplied values MUST fail even when a narrower override or explicit bump label exists. Omission MUST inherit a documented default rather than require configuration to become usable. - **A resolved PR release decision.** `DefaultBump` accepts exactly `patch`, `minor`, or `major` and has the shared default `patch`. Multiple owned bump labels, or `release:skip` combined with another owned release label, MUST fail. A valid `release:skip` MUST select no release without resolving a bump. For publishing decisions, one owned `release:patch`, `release:minor`, or `release:major` label MUST take precedence over the valid effective default; without a bump label, that default MUST supply the level without requiring a per-PR bump label. If neither source resolves a valid level, automation MUST fail with an actionable decision error; it MUST NOT recover from invalid input by selecting patch. `release:prerelease` MAY use either the explicit or default bump; the mode alone does not supply a level. Bare or unrelated labels MUST be ignored. Conventional commit messages are **not** required. @@ -88,7 +88,7 @@ Because versions are semantic, immutable, and published once, a consumer can ado ## Success criteria - Merging an eligible PR with an explicit or configured bump produces a GitHub Release, a git tag, and (where one exists) a published artifact, with no manual step. -- A pull request targeting a managed release route, including a native producer route, is evaluated even when `.github/release.config.yml` is absent; an unmanaged route carries no release decision block, label, or check. +- A pull request targeting a managed release route, including a native producer route, is evaluated even when `.github/release.settings.yml` is absent; an unmanaged route carries no release decision block, label, or check. - With no repository setting, caller override, or bump label, a publishing PR resolves the documented patch default. A repository default and supported caller override resolve in that order, and an explicit owned bump label overrides the valid effective default. - The resolver records the effective value and its source. Invalid supplied settings and conflicting owned labels block merge even when another input would supply a valid level; no success-shaped fallback occurs. - Removing a bump override re-evaluates the PR check against the effective default; changing source, settings, or route inputs also re-evaluates it. A prior result does not validate different inputs. diff --git a/src/docs/Capabilities/vscode-extension-framework/design.md b/src/docs/Capabilities/vscode-extension-framework/design.md index ab8e226..9e48cf1 100644 --- a/src/docs/Capabilities/vscode-extension-framework/design.md +++ b/src/docs/Capabilities/vscode-extension-framework/design.md @@ -197,6 +197,8 @@ Every external Action is pinned to a commit SHA; organization- or initiative-own ## Configuration surface +`.github/vscode-extension.yml` is the documented template settings interface and a [supported naming exception](../../Coding-Standards/Naming.md#solution-settings-files). The naming convention does not change this interface or its settings keys; a filename change requires a verified reader and a separate template/caller migration. + | Surface | Where | | --- | --- | | Adoption (opt-in) | a short caller workflow that calls the reusable workflow | @@ -204,7 +206,7 @@ Every external Action is pinned to a commit SHA; organization- or initiative-own | Explicit bump / prerelease / skip | owned pull-request label | | Default bump and overrides | shared `DefaultBump: patch`, repository settings, and supported caller inputs | | Pre-merge decision validation | version check required by the branch ruleset or protection | -| Release branches + path filter | `.github/release.config.yml` ([Release Management](../release-management/design.md)) | +| Release branches + path filter | `.github/release.settings.yml` ([Release Management](../release-management/design.md)) | | Marketplace publish tokens | a GitHub environment's secrets | | Extension manifest (`engines.vscode`, `contributes`, activation) | `package.json` | @@ -218,7 +220,7 @@ The template repository lays down the whole shape, mirroring `contributes`, `activationEvents`, and `main` pointing at the bundle. - the bundler config, `tsconfig.json`, and `.vscodeignore`. - `install/` — the hosted one-liner install scripts. -- `.github/` — the caller workflow, `vscode-extension.yml`, `release.config.yml`, +- `.github/` — the caller workflow, `vscode-extension.yml`, `release.settings.yml`, and `dependabot.yml`. ## Where this connects diff --git a/src/docs/Coding-Standards/Naming.md b/src/docs/Coding-Standards/Naming.md index 9a3db9e..a0a7b68 100644 --- a/src/docs/Coding-Standards/Naming.md +++ b/src/docs/Coding-Standards/Naming.md @@ -34,6 +34,18 @@ Follow the **idiom of the language**, and be consistent within a codebase: - Never fight the language's conventions to impose a personal preference. The least-surprising name is the right name. - Files and folders follow the repository's established pattern. When starting fresh, prefer `kebab-case` for cross-platform safety (no case-sensitivity surprises between Windows, macOS, and Linux). +## Solution settings files + +Solution-owned settings MUST use `.settings.yml` as their conventional filename, where `` identifies the owning solution. One naming shape makes both the owner and the file's purpose discoverable. + +Each solution documents its settings location. This standard does not impose a shared directory or change settings schemas, defaults, or precedence. + +Tool-mandated manifests, lockfiles, workflow filenames, and YAML files that are not solution-owned settings follow their tool's contract, not this settings-filename convention. + +A reader MAY expose a documented explicit path override. This convention does not remove that input or restrict otherwise supported custom paths. + +A supported naming exception MUST be documented by the owning solution. Verify the reader before changing a released conventional filename, and keep exact migration actions in its [release record](../Capabilities/release-management/design.md#release-notes). Review verifies adoption against the reader contract. + ## Scope and length Name length should track scope. A loop index living for three lines can be `i`. A module-level export read across the codebase earns a full, descriptive name. The wider the reach, the more the name has to carry on its own. diff --git a/src/docs/Coding-Standards/YAML.md b/src/docs/Coding-Standards/YAML.md index e0228b1..42091d5 100644 --- a/src/docs/Coding-Standards/YAML.md +++ b/src/docs/Coding-Standards/YAML.md @@ -27,6 +27,8 @@ One exception exists, and only because the tool allows no alternative: `.pre-commit-config.yaml`. Where a tool hard-codes the long form, follow the tool and note it; otherwise, `.yml`. +Solution-owned settings filenames follow the [Naming standard](Naming.md#solution-settings-files). + ## Lint every file `yamllint` MUST run against every YAML file in the repository — locally through diff --git a/src/docs/Initiatives/PSModule.md b/src/docs/Initiatives/PSModule.md index 1a237a4..b762be3 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](https://psmodule.io/docs/Modules/Process-PSModule/) — is documented at its canonical site. +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/Process-PSModule/) — is documented at its canonical site. ## Target audience @@ -23,6 +23,12 @@ PSModule inherits the [Coding Standards](../Coding-Standards/index.md) and [Ways In both cases, users are also integrators: these are roles of the same audience, not separate classes of customer. Repository READMEs [declare their audience](../Ways-of-Working/Readme-Driven-Context.md#target-audience) by adopting this definition or stating their specialization. +## Module settings + +The supported settings default is `.github/PSModule.yml`, through `SettingsPath`. It controls module-pipeline configuration, including module release settings. Module repositories do not need a separate `.github/release.settings.yml` file. + +This is a supported naming exception under the [Naming standard](../Coding-Standards/Naming.md#solution-settings-files), not a requirement to migrate module settings. The [workflow input reference](https://psmodule.io/Process-PSModule/reference/workflow-inputs/) owns supported `SettingsPath` controls; the [settings reference](https://psmodule.io/Process-PSModule/reference/settings/) owns the module settings keys and defaults. Changing this supported interface requires a separate reader and migration change. + ## Canonical boundary Cross-org standards and reusable architecture are canonical in MSXOrg/docs, including: diff --git a/src/docs/Ways-of-Working/Automation-Labels.md b/src/docs/Ways-of-Working/Automation-Labels.md index fd3b443..64f4b63 100644 --- a/src/docs/Ways-of-Working/Automation-Labels.md +++ b/src/docs/Ways-of-Working/Automation-Labels.md @@ -60,7 +60,7 @@ This set applies only when the pull request's target route invokes Release Management, including through a native producer pipeline. An unmanaged route does not apply or report any `release:*` label, including `release:skip`. The optional -`.github/release.config.yml` file refines an invocation; its absence alone does +`.github/release.settings.yml` file refines an invocation; its absence alone does not determine whether the route invokes the capability. These labels are read by diff --git a/src/docs/Ways-of-Working/PR-Format.md b/src/docs/Ways-of-Working/PR-Format.md index 556dd40..c741204 100644 --- a/src/docs/Ways-of-Working/PR-Format.md +++ b/src/docs/Ways-of-Working/PR-Format.md @@ -167,7 +167,7 @@ target route. Inspect the effective pipeline and its inputs, including native producer pipelines that publish versioned artifacts without calling a named shared workflow. The [applicability contract](../Capabilities/release-management/design.md#applicability) is about the route's release behavior, not one implementation. The optional -`.github/release.config.yml` file refines the route's settings; its absence alone +`.github/release.settings.yml` file refines the route's settings; its absence alone does not prove that release management is absent. Verify the immutable producer revision's supported settings and owned-label @@ -411,7 +411,7 @@ from the actual base. When the target route does not invoke Release Management, omit this block and all `release:*` labels. Do not add `release:skip` merely because the repository -has no `.github/release.config.yml`. +has no `.github/release.settings.yml`. ### Assemble the body diff --git a/src/docs/Ways-of-Working/Repository-Standard.md b/src/docs/Ways-of-Working/Repository-Standard.md index 35de7cc..fbf53e4 100644 --- a/src/docs/Ways-of-Working/Repository-Standard.md +++ b/src/docs/Ways-of-Working/Repository-Standard.md @@ -46,7 +46,9 @@ instead of carrying repository-specific baseline files that have no function there. Its own README, agent routes, text handling, and ignore rules remain local; only supported community defaults are inherited by other repositories. -Repository types may require additional files. For example, a PowerShell module may require `.github/PSModule.yml`, while a GitHub Action may require `action.yml`. +Repository types may require additional files. For example, a PowerShell module may require [`.github/PSModule.yml`](../Initiatives/PSModule.md#module-settings), while a GitHub Action may require `action.yml`. + +Solution-owned settings filenames follow the [Naming standard](../Coding-Standards/Naming.md#solution-settings-files). ### Required files by type diff --git a/tests/PR-Format.Tests.ps1 b/tests/PR-Format.Tests.ps1 deleted file mode 100644 index ccff1a2..0000000 --- a/tests/PR-Format.Tests.ps1 +++ /dev/null @@ -1,129 +0,0 @@ -#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '6.0.0'; MaximumVersion = '6.*' } - -Describe 'PR Format authoring contract' { - BeforeAll { - $ErrorActionPreference = 'Stop' - $repositoryRoot = Split-Path -Path $PSScriptRoot -Parent - $documentationRoot = [IO.Path]::Combine($repositoryRoot, 'src', 'docs', 'Ways-of-Working') - $script:format = [IO.File]::ReadAllText([IO.Path]::Combine($documentationRoot, 'PR-Format.md')) - $script:recordExample = [regex]::Match( - $format, - '(?s)````markdown\r?\n(?.*?)\r?\n````' - ) - } - - It 'resolves artifact publication coverage before inspecting the scoped PR diff' { - $coveragePosition = $format.IndexOf('### Resolve release coverage first', [StringComparison]::Ordinal) - $reviewerPosition = $format.IndexOf('### Read the whole change', [StringComparison]::Ordinal) - - $coveragePosition | Should -BeGreaterOrEqual 0 - $reviewerPosition | Should -BeGreaterThan $coveragePosition - } - - It 'requires published and candidate identities separately from the scoped PR comparison' { - $requiredEvidence = @( - '| Product scope |' - '| Published artifact |' - '| Published source |' - '| Candidate source |' - '| Scoped PR comparison |' - ) - - foreach ($field in $requiredEvidence) { - $format | Should -Match ([regex]::Escape($field)) - } - } - - It 'retains one complete description example with one boundary and five ordered classifiers' { - $recordExample.Success | Should -BeTrue - $body = $recordExample.Groups['body'].Value - $boundary = [regex]::Escape('') - - [regex]::Matches($body, $boundary).Count | Should -Be 1 - $classifiers = @( - [regex]::Matches($body, '(?m)^## (Breaking|Removed|New|Changed|Fixed):') | - ForEach-Object { $_.Groups[1].Value } - ) - $classifiers.Count | Should -Be 5 - $classifiers -join ',' | Should -BeExactly 'Breaking,Removed,New,Changed,Fixed' - } - - It 'prompts every classifier for publication-baseline evidence' { - $recordExample.Success | Should -BeTrue - $prompt = [regex]::Escape('{{ Publication-baseline evidence:') - - [regex]::Matches($recordExample.Groups['body'].Value, $prompt).Count | Should -Be 5 - } - - It 'focuses on the authored record instead of repository file policy' { - $format | Should -Match '### Complete description example' - $format | Should -Not -Match 'PR-template|pull_request_template|GitHub PR template|inherited GitHub scaffold' - } - - It 'retains five affected-product integration-evidence prompts' { - $prompt = [regex]::Escape('For an affected integration template, identify its') - - [regex]::Matches($format, $prompt).Count | Should -Be 5 - } -} - -Describe 'Repository PR-template-file policy' { - BeforeAll { - $ErrorActionPreference = 'Stop' - $script:repositoryRoot = Split-Path -Path $PSScriptRoot -Parent - $policyPath = [IO.Path]::Combine( - $repositoryRoot, 'src', 'docs', 'Ways-of-Working', 'Repository-Standard.md' - ) - $script:repositoryStandard = [IO.File]::ReadAllText($policyPath) - $script:templatePathPattern = '(^|/)pull_request_template([./]|$)' - $script:trackedFiles = @(& git --no-pager -C $repositoryRoot ls-files) - if ($LASTEXITCODE -ne 0 -or $trackedFiles.Count -eq 0) { - throw 'Could not inspect tracked source files for the repository file policy.' - } - } - - It 'keeps the authoritative no-file rule in Repository Standard' { - $repositoryStandard | Should -Match '### No PR-template files' - $repositoryStandard | Should -Match 'GitHub PR-template files MUST NOT' - } - - It 'links the file policy from ' -ForEach @( - @{ Directory = @('Ways-of-Working'); File = 'Organization-Standard.md' } - @{ Directory = @('Capabilities', 'repository-governance'); File = 'design.md' } - ) { - $segments = [string[]] (@($repositoryRoot, 'src', 'docs') + $Directory + @($File)) - $path = [IO.Path]::Combine($segments) - $guidance = [IO.File]::ReadAllText($path) - - $guidance | Should -Match 'Repository-Standard\.md#no-pr-template-files' - $guidance | Should -Not -Match '(?im)^\|\s*`\.github/pull_request_template\.md`\s*\|' - } - - It 'keeps repository-specific contribution instructions and canonical record guidance' { - $path = [IO.Path]::Combine($repositoryRoot, '.github', 'CONTRIBUTING.md') - $contribution = [IO.File]::ReadAllText($path) - - $contribution | Should -Match 'PR-Format/#complete-description-example' - $contribution | Should -Not -Match 'pull_request_template\.md' - $contribution | Should -Match 'Invoke-PesterSuite\.ps1' - $contribution | Should -Match 'Test-DocumentationLink\.ps1' - } - - It 'contains no tracked PR-template file or file-set directory' { - $templateFiles = @( - $trackedFiles | Where-Object { $_ -match $templatePathPattern } - ) - - $templateFiles.Count | Should -Be 0 - } - - It 'distinguishes the source path from unaffected guidance' -ForEach @( - @{ Path = 'PULL_REQUEST_TEMPLATE.md'; IsPrTemplate = $true } - @{ Path = '.github/pull_request_template.txt'; IsPrTemplate = $true } - @{ Path = '.github/PULL_REQUEST_TEMPLATE/change.md'; IsPrTemplate = $true } - @{ Path = '.github/ISSUE_TEMPLATE/feature.yml'; IsPrTemplate = $false } - @{ Path = 'src/docs/Ways-of-Working/PR-Format.md'; IsPrTemplate = $false } - ) { - ($Path -match $templatePathPattern) | Should -Be $IsPrTemplate - } -}