diff --git a/README.md b/README.md index 9fb9ce8e..24f22c6b 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) + - [Colocation of concerns](#colocation-of-concerns) + - [Compatibility](#compatibility) ### Get-Settings @@ -953,18 +963,45 @@ How the module is built. │ └── 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 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 and will not appear in the compiled manifest. Use `#Requires -Modules` in function files instead. + ## 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: