Skip to content

fix(ci): pin PowerShell-Yaml to 0.4.7 across all install sites#1378

Merged
WilliamBerryiii merged 11 commits intomainfrom
fix/pin-powershell-yaml-version
Apr 23, 2026
Merged

fix(ci): pin PowerShell-Yaml to 0.4.7 across all install sites#1378
WilliamBerryiii merged 11 commits intomainfrom
fix/pin-powershell-yaml-version

Conversation

@WilliamBerryiii
Copy link
Copy Markdown
Member

Pull Request

Description

Pin the PowerShell-Yaml PowerShell Gallery module to 0.4.7 at every install site across the repository so that workflows, the devcontainer, and contributor environments install a deterministic version instead of silently floating to whatever the gallery currently serves. A breaking upstream release would otherwise surface as red CI with no obvious cause.

The change applies the same pin pattern (Install-Module -Name PowerShell-Yaml -RequiredVersion 0.4.7 -Force -Scope CurrentUser) to:

Surfaced from PR #1287 review comment r3104011635.

Related Issue(s)

Closes #1377

Related: #1287 (RAI Planner alignment update — origin of the review feedback)

Type of Change

Code & Documentation:

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update

Infrastructure & Configuration:

  • GitHub Actions workflow
  • Linting configuration (markdown, PowerShell, etc.)
  • Security configuration
  • DevContainer configuration
  • Dependency update

AI Artifacts:

  • Reviewed contribution with prompt-builder agent and addressed all feedback
  • Copilot instructions (.github/instructions/*.instructions.md)
  • Copilot prompt (.github/prompts/*.prompt.md)
  • Copilot agent (.github/agents/*.agent.md)
  • Copilot skill (.github/skills/*/SKILL.md)

Other:

  • Script/automation (.ps1, .sh, .py)
  • Other (please describe):

Testing

  • Verified diff manually: every previously unpinned Install-Module PowerShell-Yaml site now passes -RequiredVersion 0.4.7, and idempotency guards (Get-Module -ListAvailable | Where-Object Version -eq '0.4.7' / if (-not (Get-Module ...))) were preserved or added so reruns stay fast.
  • Required automated checks listed below.

Checklist

Required Checks

  • Documentation is updated (if applicable)
  • Files follow existing naming conventions
  • Changes are backwards compatible (if applicable)
  • Tests added for new functionality (if applicable)

Required Automated Checks

  • Markdown linting: npm run lint:md
  • Spell checking: npm run spell-check
  • Frontmatter validation: npm run lint:frontmatter
  • Skill structure validation: npm run validate:skills
  • Link validation: npm run lint:md-links
  • PowerShell analysis: npm run lint:ps
  • Plugin freshness: npm run plugin:generate
  • Docusaurus tests: npm run docs:test

Security Considerations

  • This PR does not contain any sensitive or NDA information
  • Any new dependencies have been reviewed for security issues
  • Security-related scripts follow the principle of least privilege

Pinning a specific module version reduces supply-chain risk by removing implicit trust in whatever version the gallery serves at install time. No new dependencies are introduced; the pinned version (0.4.7) is already in active use.

Additional Notes

  • .github/workflows/ai-artifact-validation.yml is added back as part of this change so the pin can land at every install site uniformly. A merge conflict against main is anticipated for this file and will be resolved in a follow-up.
  • Renovate already monitors the powershell-galleryV2 ecosystem, so it can propose future bumps once a pinned version is in place. Dependabot does not yet have a PowerShell Gallery datasource.

- pin all workflows installing PowerShell-Yaml: ai-artifact-validation, copilot-setup-steps, extension-package, frontmatter-validation, msdate-freshness-check, pester-tests, plugin-package, plugin-validation, release-prerelease-pr, release-stable
- pin devcontainer setup: .devcontainer/scripts/on-create.sh
- pin docs and error messages: extension/PACKAGING.md, scripts/plugins/README.md, scripts/collections/README.md, Invoke-MsDateFreshnessCheck.ps1, FrontmatterValidation.psm1
- addresses PR #1287 review comment r3104011635

🔒 - Generated by Copilot
@WilliamBerryiii WilliamBerryiii requested a review from a team as a code owner April 18, 2026 02:50
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 18, 2026

Codecov Report

❌ Patch coverage is 89.74359% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.64%. Comparing base (50c1767) to head (699bbf4).

Files with missing lines Patch % Lines
scripts/security/Test-PSModulePins.ps1 92.10% 6 Missing ⚠️
scripts/linting/Invoke-MsDateFreshnessCheck.ps1 0.00% 1 Missing ⚠️
scripts/linting/Modules/FrontmatterValidation.psm1 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1378      +/-   ##
==========================================
+ Coverage   87.62%   87.64%   +0.02%     
==========================================
  Files          62       63       +1     
  Lines        9790     9866      +76     
==========================================
+ Hits         8578     8647      +69     
- Misses       1212     1219       +7     
Flag Coverage Δ
pester 84.92% <89.74%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
scripts/linting/Invoke-MsDateFreshnessCheck.ps1 91.96% <0.00%> (ø)
scripts/linting/Modules/FrontmatterValidation.psm1 96.05% <0.00%> (ø)
scripts/security/Test-PSModulePins.ps1 92.10% <92.10%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions Bot mentioned this pull request Apr 18, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory review, this PR is from a maintainer. Findings are informational only.


Review Summary

This is a well-scoped, clearly motivated dependency-pinning change. The PR comprehensively addresses all 16 sites identified in issue #1377 and the description is thorough.

✅ Issue Alignment

All files listed in issue #1377's scope are covered. The acceptance criteria are met:

  • No unpinned Install-Module -Name PowerShell-Yaml invocations remain.
  • Documentation and diagnostic strings now instruct contributors to use the pinned form.

✅ PR Template Compliance

The description, related issues, type-of-change checkboxes, testing notes, and security considerations are all filled out correctly. A few automated checks are left unchecked (lint:frontmatter, validate:skills, lint:md-links, plugin:generate, docs:test) — for a pure version-pinning change touching no frontmatter or plugins, these are reasonably not applicable.

✅ Coding Standards (Workflows)

ai-artifact-validation.yml meets all workflow conventions:

  • SHA-pinned third-party actions ✅
  • persist-credentials: false
  • Explicit permissions: contents: read at both workflow and job level ✅
  • runs-on: ubuntu-latest
  • Reusable workflow_call structure with documented inputs ✅

⚠️ Code Quality — Idempotency Guard Inconsistency (Advisory)

Four workflows (plugin-package.yml, plugin-validation.yml, release-prerelease-pr.yml, release-stable.yml) have pre-existing guards that test only for module presence, not for version 0.4.7. The new ai-artifact-validation.yml introduced in this PR correctly guards with Where-Object { $_.Version -eq '0.4.7' }.

For GitHub-hosted runners (fresh environment per run) this is low risk today, but the inconsistency is worth resolving — either in a follow-up or squashed into this PR — so that all install sites are semantically equivalent. Inline comments are attached to the relevant lines in each affected workflow.

i️ Process Note

The Additional Notes flag a likely merge conflict for ai-artifact-validation.yml against main. Since this is marked for follow-up resolution, no action is needed now, but it should be tracked to prevent the re-added file from diverging.

Generated by PR Review for issue #1378 · ● 1.2M

Comment thread .github/workflows/plugin-package.yml
Comment thread .github/workflows/plugin-validation.yml
Comment thread .github/workflows/release-prerelease-pr.yml
Comment thread .github/workflows/release-stable.yml
…ons.json

- add scripts/security/ps-module-versions.json as canonical source for required module versions
- add scripts/security/Test-PSModulePins.ps1 governance validator wired into lint:all
- update scripts/tests/Invoke-PesterTests.ps1 to load Pester version from JSON and import with -RequiredVersion
- add lint:ps-module-pins npm script chained between lint:dependency-pinning and lint:py

🔒 - Generated by Copilot
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 19, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
actions/actions/checkout de0fac2e4500dabe0009e67214ff5f5447ce83dd 🟢 5.7
Details
CheckScoreReason
Binary-Artifacts🟢 10no binaries found in the repo
Maintained⚠️ 00 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Code-Review🟢 10all changesets reviewed
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
Packaging⚠️ -1packaging workflow not detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Pinned-Dependencies🟢 3dependency not pinned by hash detected -- score normalized to 3
Security-Policy🟢 9security policy file detected
Branch-Protection🟢 5branch protection is not maximal on development and all release branches
SAST🟢 8SAST tool detected but not run on all commits
actions/actions/upload-artifact 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a 🟢 6
Details
CheckScoreReason
Maintained🟢 88 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 8
Binary-Artifacts🟢 10no binaries found in the repo
Code-Review🟢 10all changesets reviewed
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 1dependency not pinned by hash detected -- score normalized to 1
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST🟢 10SAST tool is run on all commits

Scanned Files

  • .github/workflows/ai-artifact-validation.yml

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory review, this PR is from a maintainer. Findings are informational only.


Review Summary

The second commit adds a purpose-built pin validator (Test-PSModulePins.ps1), a canonical version config (ps-module-versions.json), and wires Pester's version into the test runner from the same config. The overall direction is sound and valuable. Three advisory items are raised below for the new additions; the four prior advisory comments on idempotency guards in plugin-package.yml, plugin-validation.yml, release-prerelease-pr.yml, and release-stable.yml remain open from the previous review.

✅ Issue Alignment

All 16 install sites from issue #1377 are pinned. Acceptance criteria are fully met. The added enforcement tooling (validator + canonical config) goes beyond the issue scope in a useful way.

✅ PR Template Compliance

Description, linked issue, type-of-change selections, testing notes, and security section are complete. The unchecked automated checks (lint:frontmatter, validate:skills, lint:md-links, plugin:generate, docs:test) are reasonable to skip for a pure pin/tooling change.

⚠️ Coding Standards — Test-PSModulePins.ps1 (Advisory)

The new script omits two patterns required by .github/instructions/hve-core/powershell-script.instructions.md:

  1. Main invocation guard (if ($MyInvocation.InvocationName -ne '.')) — see inline comment at line 38.
  2. #region/#endregion blocks — the instructions require logical sections to be wrapped. The script is flat from $ErrorActionPreference through exit 0 with no region grouping.

⚠️ Missing Schema File (Advisory)

ps-module-versions.json declares "$schema": "./ps-module-versions.schema.json" but the schema file is not in the PR. See inline comment at line 2.

⚠️ PSScriptAnalyzer Entry Provides No Enforcement (Advisory)

ps-module-versions.json lists PSScriptAnalyzer with a canonical version, but no -RequiredVersion pins exist for it in the codebase. The validator will silently find zero matches and report success. See inline comment at line 19.

i️ Missing Pester Tests for Test-PSModulePins.ps1

The repo mirrors security script tests under scripts/tests/security/. Test-PSModulePins.ps1 has no corresponding Test-PSModulePins.Tests.ps1. The PR checklist item "Tests added for new functionality" is unchecked. Consider adding:

  • A test for the happy path (all pins match canonical).
  • A test for the violation path (a pin mismatches and the script exits 1).
  • A test for the allowedFiles skip logic.
  • A test for the missing config path error.

This is particularly important because the script is now part of lint:all and a regression would silently skip or fail all pinning checks.

Generated by PR Review for issue #1378 · ● 1.2M

Note

🔒 Integrity filter blocked 4 items

The following items were blocked because they don't meet the GitHub integrity level.

  • 5da19ac list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 893d9ef list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 29a2df1 list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 4adb608 list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Review for issue #1378 · ● 2.5M

Comment thread scripts/security/Test-PSModulePins.ps1
Comment thread scripts/security/ps-module-versions.json
Comment thread scripts/security/ps-module-versions.json Outdated
- Make PowerShell-Yaml install guards version-aware in plugin-package, plugin-validation, release-prerelease-pr, and release-stable workflows (matches ai-artifact-validation.yml pattern)

- Wrap Test-PSModulePins.ps1 body in Invoke-PSModulePinScan function with main-invocation guard so it can be dot-sourced for unit tests

- Remove dangling \\\ reference from ps-module-versions.json (schema file not yet authored; deferred to stashed follow-up PR)
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory review, this PR is from a maintainer. Findings are informational only.


Review Summary

This PR cleanly addresses #1377. Every tracked Install-Module -Name PowerShell-Yaml site now carries -RequiredVersion 0.4.7, the idempotency guards in the workflows with existing version checks have been correctly updated, and the new Test-PSModulePins.ps1 + ps-module-versions.json pair gives CI a durable enforcement mechanism going forward. The Invoke-PesterTests.ps1 change is a nice touch — it reads the pin config rather than hard-coding the Pester version a second time.


Issue Alignment ✅

The PR directly closes #1377. All locations listed in the issue scope are addressed. The additions (Test-PSModulePins.ps1, ps-module-versions.json, ai-artifact-validation.yml) go beyond the issue's minimum scope but are well-motivated. The note about an anticipated merge conflict for ai-artifact-validation.yml is clearly disclosed.


PR Template Compliance ✅

Description, related issue references, type-of-change checkboxes, and testing sections are all properly filled in. The unchecked automated checks (lint:frontmatter, validate:skills, lint:md-links, plugin:generate, docs:test) are appropriate N/As for a change scoped to module-pin strings and workflow steps.


Coding Standards ⚠️ (advisory)

Three minor observations — see inline comments for details:

  1. [OutputType([int])] missing on Invoke-PSModulePinScan (scripts/security/Test-PSModulePins.ps1:42) — PSScriptAnalyzer enforces PSUseOutputTypeCorrectly; adding it keeps npm run lint:ps green.

  2. Misaligned comment at $allowedFiles block (scripts/security/Test-PSModulePins.ps1:66) — the opening comment line lacks the 4-space function-body indent.

  3. PSScriptAnalyzer in ps-module-versions.json but never pinned (scripts/security/ps-module-versions.json:18) — the enforcedBy metadata implies enforcement that the validator doesn't actually provide for unpinned installs. Either pin it now (consistent with this PR's goal) or hold it for a follow-up.


Code Quality 💡 (advisory)

  • ai-artifact-validation.yml "Check results" step (line 57): when soft-fail is false, the job already fails at the validate step; the extra Write-Error/exit 1 adds no new signal. If surfacing the JSON violations in logs is the goal, replace it with a step that reads and prints logs/ai-artifact-results.json. See inline comment.

Follow-up Observations

  • Test-PSModulePins.ps1 has no corresponding scripts/tests/security/Test-PSModulePins.Tests.ps1. Following the pattern of Test-DependencyPinning.Tests.ps1, a test file covering the scan logic (valid pins, version mismatches, allowed-file exclusions) would complete the security test suite. Non-blocking for this PR but worth tracking.
  • Renovate support for powershell-galleryV2 means future version bumps to PowerShell-Yaml should flow through the standard dependency-update pipeline once a pinned entry is in place — no additional config needed beyond what's here.

Generated by PR Review for issue #1378 · ● 1.8M

Comment thread scripts/security/Test-PSModulePins.ps1 Outdated
Comment thread scripts/security/Test-PSModulePins.ps1
Comment thread scripts/security/ps-module-versions.json
Comment thread .github/workflows/ai-artifact-validation.yml
Copy link
Copy Markdown
Contributor

@katriendg katriendg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we not have a .Tests.ps1 file for Test-PSModulePins.ps1?

…et-Content handling

- add 10 Pester tests covering both regex patterns, all three verbs, multi-file violations, allowed list, untracked/extension filtering, results metadata, and error path

- wrap Get-Content with @() to force array iteration for single-line files

🔒 - Generated by Copilot
@WilliamBerryiii
Copy link
Copy Markdown
Member Author

Should we not have a .Tests.ps1 file for Test-PSModulePins.ps1?

Done ...

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory review, this PR is from a maintainer. Findings are informational only.


Review Overview

This PR does exactly what it says: it pins PowerShell-Yaml to 0.4.7 at every install site and adds a new validator (Test-PSModulePins.ps1) and canonical version config (ps-module-versions.json) to enforce consistency going forward. The approach is well-structured and the test coverage for the new script is thorough.

One bug requires attention before the new lint:ps-module-pins step will pass on the real repository.


Issue Alignment ✅

Closes #1377. All acceptance criteria are addressed:

  • Every Install-Module -Name PowerShell-Yaml call across .devcontainer/scripts/on-create.sh, all ten listed workflows, documentation, and diagnostic strings now includes -RequiredVersion 0.4.7.
  • Documentation and warning/error messages instruct contributors to use the pinned form.
  • The new Test-PSModulePins.ps1 + ps-module-versions.json provide the automation follow-up mentioned in the issue.

PR Template Compliance ⚠️

  • Tests added checkbox unchecked: scripts/tests/security/Test-PSModulePins.Tests.ps1 is included in the diff, but the "Tests added for new functionality (if applicable)" checkbox is unchecked. Minor inconsistency — worth ticking for accuracy.
  • Several required automated checks are unchecked: npm run lint:frontmatter, npm run lint:md-links, npm run plugin:generate, and npm run docs:test are not checked off. These should be verified before merge, especially since the new lint:ps-module-pins command is being added to lint:all.

Coding Standards ⚠️

See inline comments for specifics. Summary:

  1. [OutputType([int])] missing on Invoke-PSModulePinScan — required by PSUseOutputTypeCorrectly.
  2. Indentation bug at line 66 of Test-PSModulePins.ps1 — comment block starts at column 0 inside a 4-space-indented function body.
  3. checkout version comment mismatch in ai-artifact-validation.yml — same SHA labeled # v4.2.2 here vs # v6.0.2 in pester-tests.yml.

Code Quality ⚠️

🐛 Bug — new lint:ps-module-pins will immediately fail (see inline comment on line 73)

scripts/tests/security/Test-PSModulePins.Tests.ps1 contains deliberate non-canonical version literals (e.g. 9.9.9, 5.6.0, 0.4.6) as test-fixture strings. Because this file is tracked by Git and not in the $allowedFiles exemption list, npm run lint:ps-module-pins will report false-positive violations on every run against the real repository. Add 'scripts/tests/security/Test-PSModulePins.Tests.ps1' to the $allowedFiles array in Test-PSModulePins.ps1.

⚠️ upload-artifact version inconsistency in ai-artifact-validation.yml (see inline comment on line 44)

The new workflow uses v4.4.3 while pester-tests.yml uses v7. npm run lint:version-consistency will flag this divergence.

Informational: ai-artifact-validation.yml re-addition scope

The PR description correctly flags the anticipated merge conflict as a follow-up item. Reviewers should be aware that this file re-adds a previously removed workflow, which adds surface area beyond the pin-only change. Confirming the file's content is intentional before merge is advisable.


Action Items

  1. ⚠️ Required: Add 'scripts/tests/security/Test-PSModulePins.Tests.ps1' to $allowedFiles in Test-PSModulePins.ps1 (line 73).
  2. ⚠️ Recommended: Update upload-artifact in ai-artifact-validation.yml to match the v7 SHA used in the rest of the repo.
  3. 💡 Fix comment indentation at line 66 of Test-PSModulePins.ps1.
  4. 💡 Add [OutputType([int])] to Invoke-PSModulePinScan.
  5. 💡 Reconcile the checkout version comment (# v4.2.2 vs # v6.0.2) in ai-artifact-validation.yml.
  6. 💡 Check the "Tests added" checkbox and verify any unchecked automated checks before merge.

Generated by PR Review for issue #1378 · ● 2.2M

Comment thread .github/workflows/ai-artifact-validation.yml Outdated
Comment thread scripts/security/Test-PSModulePins.ps1
Comment thread scripts/security/Test-PSModulePins.ps1 Outdated
Comment thread .github/workflows/ai-artifact-validation.yml Outdated
Comment thread scripts/security/Test-PSModulePins.ps1
Copy link
Copy Markdown
Contributor

@katriendg katriendg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving but given a small conflict, and some PR notes on the tests, we can fix these before merging.

…in scanner

- Bump actions/upload-artifact in ai-artifact-validation.yml from v4.4.3 to v7 (043fb46d1a93c77aae656e7c1c64a875d1fc6a0a) to match the canonical pin
- Correct actions/checkout SHA-comment label from v4.2.2 to v6.0.2 in ai-artifact-validation.yml so all checkout pins agree
- Add scripts/tests/security/Test-PSModulePins.Tests.ps1 to $allowedFiles exemption list in Test-PSModulePins.ps1
- Add [OutputType([int])] to Invoke-PSModulePinScan to satisfy PSUseOutputTypeCorrectly
- Re-indent the $allowedFiles header comment to align with function body

Addresses PR #1378 review comments r3128508115, r3128508118, r3128508119, r3128508120, r3128508123.

🔒 - Generated by Copilot
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory review, this PR is from a maintainer. Findings are informational only.


Review Overview

This PR cleanly delivers on the scope of issue #1377 — every Install-Module -Name PowerShell-Yaml site is now pinned to 0.4.7, and the accompanying Test-PSModulePins.ps1 validator plus Pester test suite are solid additions that reduce future drift risk. The work is well-structured and the PR description is thorough.

Two items in the re-added ai-artifact-validation.yml workflow need attention before merging; the remainder are informational suggestions.


Issue Alignment

✅ PR directly addresses #1377. All listed install sites in the issue scope are covered. The bonus additions (canonical config JSON, pin validator, tests, lint:ps-module-pins script) go beyond the issue scope in a useful way.

One minor observation: the ps-module-versions.json now tracks PSScriptAnalyzer at 1.25.0, but on-create.sh and copilot-setup-steps.yml still install it without -RequiredVersion. The new validator only flags mismatched pins, not absent ones, so this creates a gap in enforcement. This is out of scope for the current issue but worth a follow-up.


PR Template Compliance

⚠️ "Documentation update" checkbox unchecked — three Markdown files (extension/PACKAGING.md, scripts/collections/README.md, scripts/plugins/README.md) were updated to use the pinned form. The "Documentation update" checkbox should be checked to accurately reflect the change set.

All other template sections are correctly filled.


Coding Standards

Two action SHA/version mismatches in .github/workflows/ai-artifact-validation.yml — see inline comments. These are the only blocking-quality items in the advisory sense.

Test-PSModulePins.ps1 is otherwise well-structured and follows conventions. The only gap is the missing .EXAMPLE and .NOTES sections in comment-based help and the # Author: line — see the inline comment on line 28.


Code Quality

The Invoke-PSModulePinScan function is straightforward and easy to follow. The regex patterns correctly cover the three install forms documented in the .SYNOPSIS. The test suite exercises edge cases (allowed-list, untracked files, extension filtering, multi-file violations) thoroughly.

💡 $allowedFiles is hardcoded in Test-PSModulePins.ps1 — adding new test fixtures in future work requires editing both the test file and the validator. Consider moving the allowedFiles array into ps-module-versions.json (e.g., under an "allowedFiles" key) so there is a single place to update when the test suite grows.


Action Items for the Author

  1. Fix action SHAs in ai-artifact-validation.yml (lines 23 and 44) — replace with the correct v4.2.2 / v4 SHAs used by all other workflows in this repo.
  2. Check "Documentation update" in the Type of Change section.
  3. (Optional) Add .EXAMPLE / .NOTES to Test-PSModulePins.ps1 help and remove the # Author: line.
  4. (Follow-up, out of scope) Pin PSScriptAnalyzer in on-create.sh and copilot-setup-steps.yml now that it has a canonical version in ps-module-versions.json.

Generated by PR Review for issue #1378 · ● 2.6M

Comment thread .github/workflows/ai-artifact-validation.yml
Comment thread .github/workflows/ai-artifact-validation.yml Outdated
Comment thread scripts/security/Test-PSModulePins.ps1
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory review, this PR is from a maintainer. Findings are informational only.


Review Summary

This PR cleanly delivers on the stated goal: every Install-Module -Name PowerShell-Yaml site across the repository now carries -RequiredVersion 0.4.7, and the new Test-PSModulePins.ps1 + ps-module-versions.json pair gives the repository a durable enforcement mechanism going forward. The test coverage (Test-PSModulePins.Tests.ps1) is thorough and the Invoke-PesterTests.ps1 change to drive Pester versioning from the config JSON is a solid consistency win.


Issue Alignment

✅ Closes #1377 — all install sites listed in the issue are covered, including both the direct Install-Module calls and the idempotency-guarded forms.

The addition of ai-artifact-validation.yml is minor scope creep beyond the issue, but the rationale (landing the pin at every install site uniformly) is clearly explained in Additional Notes. No concerns.


PR Template Compliance

The description is well-written and Type of Change checkboxes accurately reflect the diff.

⚠️ Several Required Automated Checks are unchecked. While many are N/A for this change (skill validation, docs:test, plugin:generate), these two are likely applicable given the markdown documentation edits:

  • npm run lint:frontmatter — the updated extension/PACKAGING.md and the two scripts/*/README.md files may be validated by this check.
  • npm run lint:md-links — the inline code references changed in the READMEs are worth a quick link-validity sweep.

Consider checking these off (or marking N/A with a note) before merge.


Coding Standards

Workflows (.github/workflows/*.yml)

✅ All SHA-pinned with matching version comments — consistent with existing workflow conventions.
✅ Top-level and job-level permissions: contents: read declared.
persist-credentials: false on every checkout.
ai-artifact-validation.yml reusable workflow structure is correct.

PowerShell (Test-PSModulePins.ps1)

Three minor convention observations are captured as inline comments:

  1. Line 5–9# Test-PSModulePins.ps1, # Purpose:, and # Author: should follow #Requires -Version 7.0 or live inside .NOTES, per the script structure convention (shebang → copyright → #Requires → comment-based help).
  2. Line 29 — Comment-based help is missing the required .EXAMPLE and .NOTES sections.
  3. Lines 88–90 — Design gap: the regex patterns detect wrong-version pins but silently pass over invocations where -RequiredVersion is entirely absent.

Code Quality

The Invoke-PSModulePinScan logic is clean: it reads tracked files only (avoiding untracked artifacts), builds a single-pass alternation regex, produces structured JSON output to logs/, and includes a well-designed allowlist for test fixtures. The @PSBoundParameters forwarding from the script param block to the inner function is idiomatic.

One forward-looking note: $allowedFiles is hardcoded inside the function. If a future contributor adds a new security test file that contains intentional mismatched versions (e.g., Test-SHANewFeature.Tests.ps1), they must remember to extend this list. A brief comment above the array noting this maintenance responsibility would help discoverability — the existing comment is good but could call out the "you must add here" implication more explicitly.


Action Items

# Severity Item
1 Minor Restructure Test-PSModulePins.ps1 script header — move Author to .NOTES, reorder #Requires above freestanding comments
2 Minor Add .EXAMPLE and .NOTES sections to comment-based help in Test-PSModulePins.ps1
3 Advisory Consider a follow-up (or within this PR) to detect missing -RequiredVersion pins, not just version mismatches
4 Info Check lint:frontmatter and lint:md-links against the markdown documentation changes

Generated by PR Review for issue #1378 · ● 3.9M

Comment thread scripts/security/Test-PSModulePins.ps1
Comment thread scripts/security/Test-PSModulePins.ps1
Comment thread scripts/security/Test-PSModulePins.ps1
@kgmwang1 kgmwang1 self-requested a review April 23, 2026 20:11
Comment thread .github/workflows/ai-artifact-validation.yml Outdated
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory review — this PR is from a maintainer. Findings are informational only.


Review Summary

This PR cleanly addresses #1377: every Install-Module -Name PowerShell-Yaml call now carries -RequiredVersion 0.4.7, and the new Test-PSModulePins.ps1 validator + ps-module-versions.json config give the repo a solid single source of truth that CI will enforce going forward. The test coverage in Test-PSModulePins.Tests.ps1 is thorough (9 named scenarios covering happy path, multi-file violations, allowed-list skipping, verb variants, untracked files, and metadata output). The Invoke-PesterTests.ps1 change to read the Pester version from the same config is an elegant consistency improvement.

Three advisory findings are raised as inline comments. A few additional observations below.


Issue Alignment ✅

PR fully covers all acceptance criteria from #1377. The scope expansion (centralized ps-module-versions.json, new validator, Pester version read from config) is a welcome architectural improvement beyond the minimum ask.


PR Template Compliance

⚠️ "Tests added for new functionality" is unchecked (scripts/tests/security/Test-PSModulePins.Tests.ps1 is a 317-line new test file). This checkbox should be checked.

The unchecked automated checks (lint:frontmatter, validate:skills, lint:md-links, plugin:generate, docs:test) are all reasonable N/A skips for this change type, but explicitly annotating them as N/A rather than leaving them blank would improve readability.


Coding Standards

⚠️ Test-PSModulePins.ps1 is missing .EXAMPLE and .NOTES sections in its comment-based help block. Per powershell-script.instructions.md, all five sections are required. See inline comment on line 13–31.


Code Quality Notes

💡 allowedFiles is hardcoded in the function body — The list at lines 70–75 of Test-PSModulePins.ps1 includes Test-SHAStaleness.Tests.ps1. This exemption is exercised by the "allowed list" test and is intentional, but a reader encountering it cold might be confused about why a SHA-staleness test file is exempt from a module-pin validator. A one-line comment next to that entry (e.g., # contains intentional fixture pins; see test at Test-PSModulePins.Tests.ps1 line 120) would aid future maintainers.

💡 OutputPath parameter pattern — Peer validators (Test-DependencyPinning.ps1, Test-WorkflowPermissions.ps1) expose an -OutputPath parameter so callers can override the results file location. Test-PSModulePins.ps1 hardcodes logs/ps-module-pins-results.json. This is a non-blocking inconsistency, but adding an optional -OutputPath parameter with the current path as a default would align the script with the established pattern and make the validator more composable.

💡 PSScriptAnalyzer declared but unpinned — See inline comment on ps-module-versions.json lines 19–22. The config creates a reader expectation of enforced pinning that is not yet met.

💡 Install-guard inconsistency — See inline comment on extension-package.yml line 52–54. Five workflows still install without the version-aware idempotency guard used by the other six.


Security Considerations ✅

Pinning to a specific SHA-addressable version reduces supply-chain exposure. No new external dependencies, no secrets, no privilege escalation. The validator correctly operates only on git ls-files output, avoiding scanning untracked files or generated artifacts.

Generated by PR Review for issue #1378 · ● 3.8M

Comment thread scripts/security/Test-PSModulePins.ps1
Comment thread scripts/security/ps-module-versions.json
Comment thread .github/workflows/extension-package.yml
WilliamBerryiii added a commit that referenced this pull request Apr 23, 2026
<!-- markdownlint-disable-file -->
## Description

Adds a PowerShell Gallery staleness validator to `Test-SHAStaleness.ps1`
and removes a stray UTF-8 BOM from collection-helper modules.

The new `Get-PSModuleStaleness` function queries the PSGallery v2 OData
API for every `psModules` entry in `dependency-pinning.config.json` and
returns whether each pinned version matches the latest published
version. The orchestrator (`Test-SHAStaleness`) now reports stale
PowerShell modules alongside GitHub Actions, including a per-module
`sha256ByArch` field for forward-compatible per-architecture checksum
tracking.

The BOM cleanup pass strips the leading `EF BB BF` byte sequence from
`CollectionHelpers.psm1` and `Find-CollectionManifests.ps1`. While
editing those files, the existing `#Requires -Modules PowerShell-Yaml`
directives were tightened to pin `RequiredVersion='0.4.7'` to match the
version installed by `copilot-setup-steps.yml` and the devcontainer.

## Related Issue(s)

No tracking issue. Implements the deferred review advisories from PR
#1378 (per-architecture checksum field + PSGallery staleness check) and
resolves BOM lint findings surfaced during that review.

## Type of Change

### Code & Documentation

- [x] New feature

### Infrastructure & Configuration

- [x] Security configuration update
- [x] Script/automation change

## Testing

- `npm run test:ps -- -TestPath
scripts/tests/security/Test-SHAStaleness.Tests.ps1` — 63/63 tests pass.
- Live validation: `Get-PSModuleStaleness` against PSGallery returned
the expected stale/current verdicts for every pinned module in
`dependency-pinning.config.json`.
- `npm run lint:ps` — clean.

## Checklist

### Required Checks

- [x] My code follows the project's coding standards
- [x] I have performed a self-review of my code
- [x] My changes generate no new warnings or errors
- [x] I have updated documentation as needed

### Required Automated Checks

- [x] `lint:ps` passes locally
- [x] `lint:md` passes locally
- [x] `lint:frontmatter` passes locally

## Security Considerations

- [x] No sensitive information (secrets, keys, tokens) is exposed
- [x] Dependencies have been reviewed for known vulnerabilities
- [x] Access controls follow least-privilege principle

## Additional Notes

**Out-of-scope changes documented for reviewers:**

- `CollectionHelpers.psm1` and `Find-CollectionManifests.ps1` had their
`#Requires -Modules PowerShell-Yaml` directives upgraded to pin
`RequiredVersion='0.4.7'`. This is a behavioral tightening (strict
version match at `Import-Module` time) made while touching the files for
BOM cleanup; the pinned version matches the version provisioned by
`copilot-setup-steps.yml` and the devcontainer setup.
- The new `sha256ByArch` field on PowerShell-module results is
forward-looking infrastructure. It is populated but not yet consumed by
downstream tooling; consumers will be added in a follow-up PR once the
multi-architecture checksum source is finalized.
- The `PSGallery OData response structure` concern raised by the
automated reviewer was investigated against a live PSGallery response:
`Invoke-RestMethod` returns the `<entry>` `XmlElement` directly for
single-package queries, so `$response.properties.Version` is the correct
access path. End-to-end runs of `Get-PSModuleStaleness` confirm correct
stale/current detection. No code change required.
…ml-version

# Conflicts:
#	.github/workflows/copilot-setup-steps.yml
#	.github/workflows/plugin-package.yml
#	.github/workflows/plugin-validation.yml
#	.github/workflows/release-prerelease-pr.yml
#	.github/workflows/release-stable.yml
- update reusable workflow to invoke Validate-PlannerArtifacts.ps1
- match rename from commit 406538c on feat/rai-planner-guide-alignment
- stale reference never failed CI because workflow has no caller

🔧 - Generated by Copilot
@WilliamBerryiii WilliamBerryiii merged commit ee3badf into main Apr 23, 2026
57 checks passed
WilliamBerryiii pushed a commit that referenced this pull request Apr 24, 2026
## Pre-Release 3.3.101

### ✨ Features

- add removed maturity tier and retire owasp-docker (#1444)
- add evaluation dataset creator (#1279)
- align RAI planner with guide, remove scoring, improve UX (#1287)
- add PSGallery staleness check and BOM cleanup (#1379)
- ISA-95 network planner agent (#1177)
- auto-generate collection.md with maturity filtering (#1316)
- add folder-consistency check and standardize WARN outp… (#1350)
- add synth-data-generate prompt to data-science collection (#1419)
- add canonical deck workflow and customer-card rendering for design
thinking (#1413)
- add Figma MCP integration for DT artifact export (#1222)
- introduce `owasp-docker` (#1245)
- replace hve-core-specific references with portable discovery-based
language (#1335)
- introduce `owasp-cicd` (#1246)
- add secure-by-design knowledge skill (#1223)
- introduce `owasp-infrastructure` (#1244)
- introduce `owasp-mcp` (#1207)
- add OutputPath parameter to Invoke-LinkLanguageCheck.ps1 (#1229)
- add -OutputPath parameter to Validate-SkillStructure.ps1 (#1225)
- add maintainer-only skip-review label guard (#1293)
- add extension collections overview and integrate into getting started
flow (#950)
- add agentic workflows for automated issue triage, implementation, PR
review, dependency review, and doc-staleness detection (#1219)
- consolidate package-lock.json version sync into
Update-VersionFiles.ps1 (#1240)
- add standards code review agent and full review orchestrator (#1174)
- standardize pytest-mock as Python mocking framework (#1170)
- add Jira backlog workflows and Jira/GitLab skills (#978)
- add centralized version bump script and supply-chain attestation
(#1183)

### 🐛 Bug Fixes

- pin PowerShell-Yaml to 0.4.7 across all install sites (#1378)
- close fork-PR/workflow-file-PR secret-strip gap and normalize
upload-artifact version (#1421)
- replace stream-based lookahead with array indexing in
list-changed-files.sh (#1376)
- centralize ISO 8601 timestamp regex in CIHelpers (#1343)
- update stale documentation date in release-process.md (#1363)
- pin basic-ftp to 5.3.0 to resolve GHSA-rp42-5vxx-qpwr (#1374)
- add bot filter to dependency PR review workflow (#1362)
- resolve pip-audit findings in powerpoint, gitlab, and jira skill lock
files (#1360)
- standardize Timestamp JSON key casing across all lint result files
(#1314)
- add synchronize trigger to PR Review workflow (#1323)
- standardize timestamp in Validate-SkillStructure.ps1 to use
Get-StandardTimestamp (#1280)
- add parallel subagent dispatch and structured JSON contracts to
code-review-full (#1304)
- standardize timestamp in SecurityHelpers.psm1 to use
Get-StandardTimestamp (#1284)
- standardize timestamps in Test-DependencyPinning.ps1 and
SecurityClasses.psm1 (#1282)
- derive collection artifact counts from YAML at build time (#1275)
- standardize timestamp in FrontmatterValidation.psm1 to use
Get-StandardTimestamp (#1285)
- standardize timestamp in Markdown-Link-Check.ps1 to use
Get-StandardTimestamp (#1283)
- escape hyphens in Mermaid diagram on Collections page (#1262)
- add summary timestamp to PSScriptAnalyzer output (#1211)
- fix plugin compatibility and robustness for coding-standards code
review agents (#1289)
- standardize timestamp in Test-CopyrightHeaders.ps1 to use
Get-StandardTimestamp (#1278)
- standardize timestamp in Invoke-YamlLint.ps1 to use
Get-StandardTimestamp (#1270)
- standardize timestamp in Invoke-LinkLanguageCheck.ps1 to use
Get-StandardTimestamp (#1264)
- fix dependency-review path filters and sparse-checkout cone mode
(#1259)
- replace invalid bare tool names with official tool identifiers (#1198)
- fix broken links and remove orphaned reference in code review docs
(#1257)
- exclude Python env dirs from skill validation warnings (#1255)
- pin happy-dom and serialize-javascript to resolve Dependabot
vulnerabilities (#1253)
- remove Mermaid diagram and add missing collection cards (#1247)
- disable MCP servers by default to prevent token limit errors (#1144)
- sync package-lock.json after pre-release version bump (#1236)
- separate mermaid node declarations and add dynamic diagram generation
with tests (#1215)
- replace anchor links in meeting-analyst with bold text references
(#1201)
- remove recursive symlinks in jira and gitlab skill directories (#1233)
- validate-installation scripts now check .github/skills directory
(#1010) (#1206)
- resolve npm audit vulnerabilities via dependency overrides (#1200)
- add post-release triggers to scorecard workflow (#1186)
- add missing .md extensions to relative links in agent documentation
(#1180)

### 📚 Documentation

- broaden Security Review description beyond OWASP (#1385)
- document maintainer advisory mode and skip-review label guard (#1386)
- document ExcludePaths/OutputPath for Invoke-LinkLanguageCheck (#1383)
- CLI getting-started: clarify plugin install commands as alternatives
(-all vs base) (#1251)

### ♻️ Refactoring

- align agent and prompt folder names to collection identifier (#1210)

### 🔧 Maintenance

- pin PSScriptAnalyzer to 1.25.0 and sync stale workflow version
comments (#1389)
- bump lxml from 6.0.2 to 6.1.0 in
/.github/skills/experimental/powerpoint (#1424)
- bump @vscode/vsce from 3.7.1 to 3.9.1 in the npm-dependencies group
(#1390)
- bump the github-actions group across 1 directory with 7 updates
(#1391)
- bump follow-redirects from 1.15.11 to 1.16.0 in /docs/docusaurus
(#1356)
- upgrade Node.js from 20 to 24 and bump cspell to v10 (#1353)
- bump basic-ftp from 5.2.0 to 5.2.1 (#1324)
- update github/gh-aw-actions requirement to
536ea1bad8c6715d098a9dc1afea8d403733acfe in the github-actions group
across 1 directory (#1298)
- update security instruction attributions and compliance (#1294)
- bump the npm-dependencies group with 2 updates (#1297)
- pre-release 3.3.41 (#1252)
- streamline RAI Planner phase structure and documentation (#1273)
- bump happy-dom from 20.8.8 to 20.8.9 in /docs/docusaurus (#1237)
- pre-release 3.3.27 (#1191)
- bump pygments from 2.19.2 to 2.20.0 in /.github/skills/gitlab/gitlab
(#1234)
- bump path-to-regexp from 0.1.12 to 0.1.13 in /docs/docusaurus (#1226)
- bump the github-actions group with 4 updates (#1231)
- add missing folders and alphabetize location lists (#1193)
- bump brace-expansion (#1224)
- bump handlebars from 4.7.8 to 4.7.9 in /docs/docusaurus (#1217)
- bump brace-expansion from 5.0.3 to 5.0.5 in /docs/docusaurus (#1213)
- pre-release 3.3.10 (#1187)
- bump markdownlint-cli2 from 0.21.0 to 0.22.0 in the npm-dependencies
group (#1175)
- bump the github-actions group with 3 updates (#1176)
- pre-release 3.3.1 (#1165)

---
*Managed automatically by pre-release workflow.*

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pin PowerShell-Yaml module version across all install sites

6 participants