Skip to content

refactor(scripts): extract frontmatter validation to testable module#293

Merged
WilliamBerryiii merged 16 commits intomainfrom
feat/issue-266-frontmatter-testability
Jan 26, 2026
Merged

refactor(scripts): extract frontmatter validation to testable module#293
WilliamBerryiii merged 16 commits intomainfrom
feat/issue-266-frontmatter-testability

Conversation

@WilliamBerryiii
Copy link
Copy Markdown
Member

refactor(scripts): extract frontmatter validation to testable module

Description

Extract frontmatter validation logic from Validate-MarkdownFrontmatter.ps1 into a dedicated testable module (FrontmatterValidation.psm1), addressing the testability concerns raised in issue #266.

Key changes:

  • New module: FrontmatterValidation.psm1 (1,039 lines) containing:

    • Classes: ValidationIssue, FileTypeInfo, FileValidationResult, ValidationSummary
    • Shared validators: Test-RequiredField, Test-DateFormat, Test-SuggestedFields, Test-TopicValue
    • Content-type validators for root community, devcontainer, VS Code readme, GitHub resources, and docs files
    • Orchestration: Test-CommonFields, Test-MarkdownFooter, Test-SingleFileFrontmatter, Invoke-FrontmatterValidation
    • Output formatters: Write-ValidationConsoleOutput, Write-GitHubAnnotations
  • New test suite: FrontmatterValidation.Tests.ps1 (1,553 lines) with comprehensive coverage

  • Refactored main script: Validate-MarkdownFrontmatter.ps1 is now a thin orchestration wrapper

  • Removed ~550 lines of duplicate code from main script

Related Issue(s)

Closes #266

Type of Change

Select all that apply:

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)

Other:

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

Sample Prompts (for AI Artifact Contributions)

Testing

  • 226 tests pass (110 new module tests + existing integration tests)
  • 96.33% code coverage (exceeds 80% target)
  • All linting checks pass
Test Category Tests Coverage
ValidationIssue class 8 Full
FileValidationResult class 12 Full
ValidationSummary class 14 Full
Shared validators 20+ Full
Content-type validators 25+ Full
Orchestration functions 18+ Full
Output functions 6 Full
Error handling 10+ Full
Git fallback strategies 12 Full

Checklist

Required Checks

  • Documentation is updated (if applicable)
  • Files follow existing naming conventions
  • Changes are backwards compatible (if applicable)

AI Artifact Contributions

Required Automated Checks

The following validation commands must pass before merging:

  • Markdown linting: npm run lint:md
  • Spell checking: npm run spell-check
  • Frontmatter validation: npm run lint:frontmatter
  • Link validation: npm run lint:md-links
  • PowerShell analysis: npm run lint:ps

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

No security concerns. Internal refactoring of development tooling with no changes to authentication, data handling, external dependencies, or network communication.

Additional Notes

Architecture Benefits

  1. Testability: Pure functions with explicit dependencies enable comprehensive unit testing
  2. Maintainability: Clear separation between validation logic and orchestration
  3. Reusability: Module can be imported independently for programmatic validation
  4. Consistency: Structured result types replace ad-hoc hashtables

API Changes

Internal API surface changed (ValidationResultValidationSummary), but external behavior remains compatible. Integration tests updated for new type names.

🔧 - Generated by Copilot

- Create FrontmatterValidation.psm1 with ValidationIssue and FileTypeInfo classes
- Extract 6 content-type validators and 4 shared helper functions
- Add comprehensive unit tests (67+ test cases for module)
- Remove ~550 lines of duplicated code from main script

🧪 - Generated by Copilot
…n module

- Extract parsing, validation, and output functions into new FrontmatterValidation.psm1 module
- Replace 500+ line god function with thin wrapper delegating to module
- Add ValidationSummary return type with GetExitCode method for cleaner API
- Update integration tests for ValidationSummary interface (TotalFiles, TotalErrors, TotalWarnings)

🧹 - Generated by Copilot
- extract ValidationIssue, FileValidationResult, ValidationSummary classes
- extract 18 public functions to FrontmatterValidation.psm1
- convert main script to thin orchestration wrapper
- achieve 96.33% test coverage (target: 80%)

🔧 - Generated by Copilot
… test coverage

- remove duplicate FrontmatterResult class, ConvertFrom-YamlFrontmatter, Get-MarkdownFrontmatter from main script
- update schema validation to use frontmatter from module's FileValidationResult
- add 11 tests for Initialize-JsonSchemaValidation, Get-SchemaForFile pattern matching, ChangedFilesOnly mode
- improve coverage from 78.41% to 82.58% (110 tests)

🧹 - Generated by Copilot
- Remove unused param declarations in FileReader scriptblocks
- Fix unused BaseBranch parameter and result variables
- Add UTF-8 BOM encoding to FrontmatterValidation.Tests.ps1
- Remove 10 obsolete tests for deleted functions

🧹 - Generated by Copilot
@WilliamBerryiii WilliamBerryiii requested a review from a team as a code owner January 25, 2026 23:23
Copilot AI review requested due to automatic review settings January 25, 2026 23:23
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 25, 2026

Dependency Review

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

Scanned Files

None

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors markdown frontmatter validation by extracting the core validation logic into a dedicated PowerShell module to improve testability and unit coverage.

Changes:

  • Introduces scripts/linting/Modules/FrontmatterValidation.psm1 containing validation types, validators, orchestration, and output helpers.
  • Refactors scripts/linting/Validate-MarkdownFrontmatter.ps1 into a thinner wrapper that delegates to the new module.
  • Updates and expands Pester coverage via a new module-focused test suite and updates to existing validation tests.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.

File Description
scripts/linting/Validate-MarkdownFrontmatter.ps1 Imports and delegates validation to the new module; updates result model and orchestration.
scripts/linting/Modules/FrontmatterValidation.psm1 New module implementing frontmatter parsing, file-type routing, validation rules, and output/export formatting.
scripts/tests/linting/FrontmatterValidation.Tests.ps1 Adds comprehensive unit tests for the new module and some wrapper-level behavior.
scripts/tests/linting/Validate-MarkdownFrontmatter.Tests.ps1 Updates existing tests to the new ValidationSummary result model and adds new scenarios.

- Replace hardcoded Windows paths (C:\test\repo) with TestDrive
- Use Join-Path instead of string interpolation with backslashes
- Add Push-Location/Pop-Location for Test-Path relative path resolution
- Use platform-specific directory separator in path assertions

🐛 - Generated by Copilot
- add SkipFooterValidation parameter (Fix #1)
- add agent.md classification with IsAgent property (Fix #3)
- use RelativePath in GitHub annotations (Fix #5)
- remove misleading 'pure' header claim (Fix #6)
- remove hardcoded creation date (Fix #7)
- fix regex for empty frontmatter (Fix #8)
- add workflow command escaping for security (Fix #10)
- remove type constraints for testability (PowerShell class identity)

🔧 - Generated by Copilot
- add exit code 2 when no files validated (Fix #2)
- add ConvertFrom-Yaml availability check with clear error (Fix #4)
- expand footer validation to all markdown except AI artifacts (Fix #9)
- update tests for new exit code behavior

🔧 - Generated by Copilot
- Change ConvertFrom-Yaml check from throw to error result
- Add SkipFooterValidation parameter chain to main execution
- Add YAML support skip checks to 17 tests requiring powershell-yaml

🔧 - Generated by Copilot
Copilot AI review requested due to automatic review settings January 26, 2026 01:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

- add YAML support detection to skip tests when powershell-yaml unavailable
- fix ChangedFilesOnly to return success when no markdown files changed
- fix IsAgent handling in Test-GitHubResourceFileFields
- add Test-CommonFields call for keywords and reading time validation
- fix footer severity routing for root community and config files
- implement full GitHub workflow command escaping

🔧 - Generated by Copilot
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jan 26, 2026

Codecov Report

❌ Patch coverage is 89.09574% with 41 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.21%. Comparing base (321aadf) to head (87efa6b).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
scripts/linting/Validate-MarkdownFrontmatter.ps1 53.22% 29 Missing ⚠️
scripts/linting/Modules/FrontmatterValidation.psm1 96.17% 12 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #293      +/-   ##
==========================================
+ Coverage   29.94%   38.21%   +8.27%     
==========================================
  Files          14       15       +1     
  Lines        2785     2805      +20     
==========================================
+ Hits          834     1072     +238     
+ Misses       1951     1733     -218     
Flag Coverage Δ
pester 38.21% <89.09%> (+8.27%) ⬆️

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

Files with missing lines Coverage Δ
scripts/linting/Modules/FrontmatterValidation.psm1 96.17% <96.17%> (ø)
scripts/linting/Validate-MarkdownFrontmatter.ps1 75.23% <53.22%> (+24.84%) ⬆️

... and 2 files with indirect coverage changes

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

…lesOnly exit code

- add 8 tests for ConvertTo-GitHubCommandMessage escaping (%, CR, LF, ::, null)
- add 8 tests for ConvertTo-GitHubCommandProperty escaping (%, CR, LF, :, ,, null)
- update ChangedFilesOnly test to expect TotalFiles=1 (success exit code)

🔧 - Generated by Copilot
Copilot AI review requested due to automatic review settings January 26, 2026 03:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

- make YAML parsing graceful with warning instead of hard error
- detect file type before missing frontmatter warning (skip AI artifacts)
- call Complete() on empty summary in ChangedFilesOnly mode
- show warning icon for files with warnings but no errors
- exclude strings from array type validation (IEnumerable fix)
- update test to expect error for string in array field

🔧 - Generated by Copilot
- add GetNewClosure() to FileReader scriptblocks in Test-SingleFileFrontmatter tests
- fixes variable capture across module boundaries on Linux/PowerShell Core
- ensures mockContent variable is available when invoked from module scope

🔧 - Generated by Copilot
Copilot AI review requested due to automatic review settings January 26, 2026 05:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

- add PowerShell-Yaml install step to pester-tests.yml workflow
- change FrontmatterValidation.psm1 to error (not warn) when YAML missing
- remove hasYamlSupport skip logic from 3 test files (~21 tests now run)

📦 - Generated by Copilot
- return accurate TotalFiles=0 for ChangedFilesOnly empty case
- replace hardcoded Windows paths with cross-platform $TestDrive
- add UTF-8 BOM encoding for non-ASCII test file

🔧 - Generated by Copilot
Copilot AI review requested due to automatic review settings January 26, 2026 06:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

@WilliamBerryiii WilliamBerryiii merged commit 4e8707e into main Jan 26, 2026
16 checks passed
@WilliamBerryiii WilliamBerryiii deleted the feat/issue-266-frontmatter-testability branch January 26, 2026 16:49
WilliamBerryiii pushed a commit that referenced this pull request Jan 28, 2026
🤖 I have created a release *beep* *boop*
---


##
[2.0.0](hve-core-v1.1.0...hve-core-v2.0.0)
(2026-01-28)


### ⚠ BREAKING CHANGES

* **agents:** add Task Reviewer and expand RPI to 4-phase workflow
([#277](#277))

### ✨ Features

* **agents:** add hve-core-installer agent to extension package
([#297](#297))
([c0e48c6](c0e48c6))
* **agents:** add Task Reviewer and expand RPI to 4-phase workflow
([#277](#277))
([ae76cab](ae76cab))
* **build:** add code coverage reporting to Pester workflow
([#230](#230))
([a34822a](a34822a))
* **docs:** add GOVERNANCE.md for OSSF Silver Badge compliance
([#235](#235))
([b0e752c](b0e752c))
* **docs:** add ROADMAP.md for OSSF Silver badge compliance
([#238](#238))
([4a41c16](4a41c16))
* **mcp:** add MCP server configuration guidance and installer
enhancements ([#225](#225))
([0bce418](0bce418))
* **scripts:** add YAML linting with actionlint
([#234](#234))
([d9301f9](d9301f9))
* **security:** add OpenSSF Scorecard workflow and badge
([#271](#271))
([7c6d788](7c6d788))
* **skills:** add video-to-gif conversion skill with FFmpeg two-pass
optimization ([#247](#247))
([8d65c42](8d65c42))
* **tests:** add Pester tests for LintingHelpers and
Validate-MarkdownFrontmatter
([#197](#197),
[#198](#198))
([#205](#205))
([51ae563](51ae563))


### 🐛 Bug Fixes

* **build:** detect table formatting changes via git diff
([#261](#261))
([985eee0](985eee0))
* **build:** disable MD024 lint rule in CHANGELOG for release-please
([#220](#220))
([971df94](971df94))
* **build:** quote shell variables and group redirects in workflow files
([#299](#299))
([3372509](3372509))
* **build:** resolve scorecard badge and workflow security issues
([#301](#301))
([aeaed13](aeaed13))
* **extension:** remove frontmatter from README and exclude from
markdown linting
([#223](#223))
([4272529](4272529))
* **instructions:** quote applyTo glob pattern for YAML compatibility
([#216](#216))
([085199c](085199c))
* **scripts:** add FooterExcludePaths parameter to frontmatter
validation ([#334](#334))
([64db98d](64db98d))
* **scripts:** add GHSA word and logs/ exclusion to cspell config
([#214](#214))
([5c99b3f](5c99b3f))
* **scripts:** correct type assertions in Invoke-YamlLint.Tests.ps1
([#332](#332))
([af7050d](af7050d))
* **scripts:** eliminate false positives in dependency pinning npm
pattern ([#273](#273))
([ccbdfa3](ccbdfa3))
* **security:** add artifact attestation for signed releases
([#257](#257))
([c52d6e2](c52d6e2))
* standardize markdown footers and complete frontmatter
([#217](#217))
([b4e7556](b4e7556))


### 📚 Documentation

* add OpenSSF Best Practices Passing badge to README
([#239](#239))
([91bc529](91bc529))
* **architecture:** add architecture documentation and value proposition
([#252](#252))
([0e4b02f](0e4b02f))
* **contributing:** add testing requirements for OSSF compliance
([#254](#254))
([4db1a18](4db1a18))
* **docs:** add enterprise status badges to README header
([#270](#270))
([ccb68a4](ccb68a4))
* **security:** add security assurance case and threat model for OSSF
Silver ([#259](#259))
([a390e26](a390e26))


### ♻️ Refactoring

* **application:** wrap execution with try blocks, ensure proper …
([#296](#296))
([35c4417](35c4417))
* **scripts:** extract frontmatter validation to testable module
([#293](#293))
([4e8707e](4e8707e))
* **scripts:** extract pure functions for Pester testability
([#221](#221))
([d40e742](d40e742))


### 🔧 Maintenance

* **deps-dev:** bump cspell from 9.4.0 to 9.6.0 in the npm-dependencies
group ([#208](#208))
([855914b](855914b))
* **deps-dev:** bump cspell from 9.6.0 to 9.6.1 in the npm-dependencies
group ([#294](#294))
([1e45ad6](1e45ad6))
* **deps:** bump actions/setup-node from 6.1.0 to 6.2.0 in the
github-actions group
([#209](#209))
([c4c69e2](c4c69e2))
* **deps:** bump the github-actions group with 4 updates
([#295](#295))
([d8337b8](d8337b8))
* remove step-security/harden-runner from workflows
([#246](#246))
([c5708d8](c5708d8))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor Validate-MarkdownFrontmatter.ps1 for improved modularity and testability

4 participants