From fc86f855b27e98921cad3eb1fdda2d4b6b99331a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 15:33:43 +0000 Subject: [PATCH 1/6] Initial plan From 0f9c85cf20ce5da15376f1436f789998aadf2c4e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 15:35:35 +0000 Subject: [PATCH 2/6] docs: add documentation for declaring module dependencies using #Requires statements Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com> --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9fb9ce8e..4b964e2c 100644 --- a/README.md +++ b/README.md @@ -919,7 +919,7 @@ How the module is built. │ ├── 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 +│ ├── functions/ # Function scripts exported by the module; #Requires -Modules statements here are compiled into RequiredModules │ │ ├── private/ # Helper functions scoped to the module │ │ │ ├── Get-InternalPSModule.ps1 # Sample internal helper │ │ │ └── Set-InternalPSModule.ps1 # Sample internal helper @@ -949,10 +949,58 @@ How the module is built. │ │ └── 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 +│ ├── manifest.psd1 (optional) # Source manifest reused when present; RequiredModules is not propagated — use #Requires -Modules in function files instead (see "Declaring module dependencies" below) │ └── README.md # Module-level docs ingested by Document-PSModule ``` +### Declaring module dependencies + +Module dependencies are declared using [`#Requires -Modules`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires) +statements at the top of individual PowerShell function files under `src/functions/public/` and `src/functions/private/`. +The build system ([Build-PSModule](https://github.com/PSModule/Build-PSModule)) collects all `#Requires -Modules` +declarations across every source file, de-duplicates them, and writes the merged result into the `RequiredModules` field +of the compiled module manifest. + +> [!IMPORTANT] +> Adding `RequiredModules` to `src/manifest.psd1` is **not** supported for this purpose. Those entries are silently +> ignored by the build — they will not appear in the built manifest. Use `#Requires -Modules` in function files instead. + +#### Supported syntax variants + +```powershell +# Bare module name — any version is acceptable +#Requires -Modules Microsoft.Graph.Authentication + +# Minimum version constraint +#Requires -Modules @{ ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '2.28.0' } + +# Exact version constraint +#Requires -Modules @{ ModuleName = 'PSSemVer'; RequiredVersion = '1.1.4' } +``` + +#### Example + +A function that calls into `Microsoft.Graph.Authentication` declares its dependency at the top of the file: + +```powershell +#Requires -Modules @{ ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '2.28.0' } + +function Get-GraphToken { + ... +} +``` + +When the module is built, the compiled manifest automatically includes: + +```powershell +RequiredModules = @( + @{ ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '2.28.0' } +) +``` + +This co-location approach keeps dependency declarations next to the functions that need them, making it immediately +clear which commands drive each external dependency. + ## Principles and practices 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 From 88c2bf59bf1cb6f20246d06c9ce32b474e7a220d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 15:52:44 +0000 Subject: [PATCH 3/6] docs: simplify folder tree annotations, revise dependency docs, add maintainability principle Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com> --- README.md | 58 ++++++++++++++----------------------------------------- 1 file changed, 14 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 4b964e2c..22da9ac0 100644 --- a/README.md +++ b/README.md @@ -919,7 +919,7 @@ How the module is built. │ ├── 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; #Requires -Modules statements here are compiled into RequiredModules +│ ├── 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 @@ -949,57 +949,24 @@ How the module is built. │ │ └── 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; RequiredModules is not propagated — use #Requires -Modules in function files instead (see "Declaring module dependencies" below) +│ ├── manifest.psd1 (optional) # Source manifest reused when present │ └── README.md # Module-level docs ingested by Document-PSModule ``` ### Declaring module dependencies -Module dependencies are declared using [`#Requires -Modules`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires) -statements at the top of individual PowerShell function files under `src/functions/public/` and `src/functions/private/`. -The build system ([Build-PSModule](https://github.com/PSModule/Build-PSModule)) collects all `#Requires -Modules` -declarations across every source file, de-duplicates them, and writes the merged result into the `RequiredModules` field -of the compiled module manifest. +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 require external modules. +[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 — they will not appear in the built manifest. Use `#Requires -Modules` in function files instead. - -#### Supported syntax variants - -```powershell -# Bare module name — any version is acceptable -#Requires -Modules Microsoft.Graph.Authentication - -# Minimum version constraint -#Requires -Modules @{ ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '2.28.0' } - -# Exact version constraint -#Requires -Modules @{ ModuleName = 'PSSemVer'; RequiredVersion = '1.1.4' } -``` - -#### Example - -A function that calls into `Microsoft.Graph.Authentication` declares its dependency at the top of the file: - -```powershell -#Requires -Modules @{ ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '2.28.0' } - -function Get-GraphToken { - ... -} -``` - -When the module is built, the compiled manifest automatically includes: - -```powershell -RequiredModules = @( - @{ ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '2.28.0' } -) -``` - -This co-location approach keeps dependency declarations next to the functions that need them, making it immediately -clear which commands drive each external dependency. +> ignored by the build and will not appear in the compiled manifest. Use `#Requires -Modules` in function files instead. ## Principles and practices @@ -1013,6 +980,9 @@ For each topic or feature to add to the release, open a new branch representing 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. +Co-locate 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. The process is compatible with: From f898cf0cef132a9d6f979ca75617e60a26fa5cd4 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 17 Mar 2026 22:52:05 +0100 Subject: [PATCH 4/6] docs: enhance documentation on #Requires statements and parameter descriptions for better maintainability --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 22da9ac0..d6e64d9b 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,11 @@ Depending on the labels in the pull requests, the [workflow will result in diffe - [Example - `BeforeAll.ps1`](#example---beforeallps1) - [Teardown - `AfterAll.ps1`](#teardown---afterallps1) - [Example - `AfterAll.ps1`](#example---afterallps1) + - [Best practices for shared test infrastructure](#best-practices-for-shared-test-infrastructure) + - [Use deterministic naming with `$env:GITHUB_RUN_ID`](#use-deterministic-naming-with-envgithub_run_id) + - [Clean up stale resources from previous failed runs](#clean-up-stale-resources-from-previous-failed-runs) + - [Tests reference shared resources — they do not create them](#tests-reference-shared-resources--they-do-not-create-them) + - [Naming conventions](#naming-conventions) - [Module tests](#module-tests) - [Get test results](#get-test-results) - [Get code coverage](#get-code-coverage) @@ -94,7 +99,12 @@ Depending on the labels in the pull requests, the [workflow will result in diffe - [Related Configuration](#related-configuration) - [Repository structure](#repository-structure) - [Module source code structure](#module-source-code-structure) + - [Declaring module dependencies](#declaring-module-dependencies) - [Principles and practices](#principles-and-practices) + - [Linear versioning](#linear-versioning) + - [Release and feature branches](#release-and-feature-branches) + - [Co-location of concerns](#co-location-of-concerns) + - [Compatibility](#compatibility) ### Get-Settings @@ -970,19 +980,28 @@ documentation. ## 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. +### Co-location of concerns + Co-locate 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. +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: From e32908ea144efa2e8c2dfa43d38c3fac1ec6abb0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 17 Mar 2026 23:55:44 +0100 Subject: [PATCH 5/6] docs: correct spelling of "Co-location" to "Colocation" for consistency in documentation --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d6e64d9b..c8d41ad9 100644 --- a/README.md +++ b/README.md @@ -994,9 +994,9 @@ For each topic or feature to add to the release, open a new branch representing 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. -### Co-location of concerns +### Colocation of concerns -Co-locate concerns for long-term maintainability. For example, `#Requires -Modules` statements belong in the function files that use them, not in a +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. From f682c29e3983350cf7a015a817faa25ff9cf86eb Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 18 Mar 2026 01:02:48 +0100 Subject: [PATCH 6/6] docs: correct spelling of "Co-location" to "Colocation" for consistency in documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8d41ad9..24f22c6b 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ Depending on the labels in the pull requests, the [workflow will result in diffe - [Principles and practices](#principles-and-practices) - [Linear versioning](#linear-versioning) - [Release and feature branches](#release-and-feature-branches) - - [Co-location of concerns](#co-location-of-concerns) + - [Colocation of concerns](#colocation-of-concerns) - [Compatibility](#compatibility) ### Get-Settings