Skip to content

Copyright header check missing Write-CIAnnotation per file and Write-CIStepSummary in GitHub Actions #630

@WilliamBerryiii

Description

@WilliamBerryiii

Bug Description

Test-CopyrightHeaders.ps1 produces good per-file console output via Write-Host (✅/❌ indicators with file paths), but it is missing two CI integration features that the gold-standard Invoke-PSScriptAnalyzer.ps1 already uses:

  1. No Write-CIAnnotation per failing file — The only Write-CIAnnotation call fires inside the catch block (line 214) for fatal script errors, not for individual header violations. GitHub Actions users see no inline annotations on PRs indicating which files are missing headers.

  2. No Write-CIStepSummary — After the summary block (📋 Summary: on line 196), the script never calls Write-CIStepSummary. The GitHub Actions job summary panel remains empty — users must expand the log or download artifacts to see results.

Current Behavior

  • Per-file Write-Host output shows ✅/❌ with file paths (this works correctly).
  • Write-CIAnnotation only fires on fatal errors (catch block), not per failing file.
  • No Write-CIStepSummary call, so the Actions summary tab is empty for this job.
  • Users must manually download copyright-header-results.json from artifacts to see details.

Expected Behavior

  • Each file missing headers produces a Write-CIAnnotation (level Warning) so GitHub renders inline PR annotations showing the exact files.
  • A Write-CIStepSummary generates a markdown table in the Actions summary tab with file paths, missing header type (copyright/SPDX/both), and overall compliance percentage.

Reference Implementation

Invoke-PSScriptAnalyzer.ps1 (lines 91–127) demonstrates the pattern:

  • Per-file headers (📄 Analyzing: $filePath)
  • Per-issue detail lines with color-coded severity (⚠️ [Severity] Rule: Message)
  • Write-CIAnnotation per violation
  • Write-CIStepSummary with a formatted results table

Affected Files

File What to Change
scripts/linting/Test-CopyrightHeaders.ps1 Add Write-CIAnnotation per failing file inside the foreach loop (after the Write-Host "❌" line ~177). Add Write-CIStepSummary after the summary block (~line 203).
scripts/tests/linting/Test-CopyrightHeaders.Tests.ps1 Add tests verifying Write-CIAnnotation is called per failing file and Write-CIStepSummary is called with expected content.

Additional Notes

  • Write-Host is safe to use — PSAvoidUsingWriteHost is explicitly excluded in scripts/linting/PSScriptAnalyzer.psd1.
  • The CIHelpers module (scripts/lib/Modules/CIHelpers.psm1) is already imported by the script — no new imports needed.
  • The workflow file (.github/workflows/copyright-headers.yml) does not need changes.
  • Validate changes with npm run lint:ps (PSScriptAnalyzer) and npm run test:ps (Pester tests).

Unit Testing and Code Coverage Requirements

Codecov Configuration

The repository enforces an auto-incrementing project coverage threshold (+1% over base) and an 80% patch target (codecov.yml). All new or modified lines in scripts/linting/Test-CopyrightHeaders.ps1 must meet the patch coverage gate.

Pester Coverage

  • Config: scripts/tests/pester.config.ps1 — JaCoCo format, CoveragePercentTarget = 80
  • Coverage path: scripts/linting/ is already in the coverage scan scope
  • Run: npm run test:ps

Current Test Gap

The existing test file scripts/tests/linting/Test-CopyrightHeaders.Tests.ps1 has no mocks for Write-CIAnnotation or Write-CIStepSummary. When adding per-file Write-CIAnnotation calls and a Write-CIStepSummary block, entirely new mock infrastructure is needed:

  1. Mock Write-CIAnnotation — currently only called in catch blocks. New per-file annotation calls require mocks with -ParameterFilter to assert correct -File, -Level, and -Message for each missing/invalid header.
  2. Mock Write-CIStepSummary — does not exist in the script today. Add mock and Should -Invoke assertion verifying the markdown summary includes file counts, pass/fail status per file, and overall compliance score.
  3. Verify Write-Host call content — the script already emits per-file ✅/❌ output via Write-Host. Existing tests should verify message content matches expected patterns, not just that Write-Host was called.

RPI Phase Testing Guidance

  • Research: Audit existing test coverage for CI output paths in Test-CopyrightHeaders.Tests.ps1; confirm no existing mocks for CI helpers.
  • Plan: Design test cases for per-file Write-CIAnnotation, Write-CIStepSummary markdown output, and enhanced Write-Host content verification.
  • Implement: Add mock infrastructure for all CI helper functions; verify npm run test:ps passes with patch coverage ≥ 80%.
  • Review: Confirm no coverage regressions in the pester flag on Codecov; verify the reference implementation pattern from Invoke-PSScriptAnalyzer.ps1 is followed.

RPI Starter Prompts

Research Phase

Research the CI output gap in Test-CopyrightHeaders.ps1. Compare its Invoke-CopyrightHeaderCheck function with the per-issue output loop in Invoke-PSScriptAnalyzer.ps1 (lines 91–127). Document: (1) where per-file Write-CIAnnotation calls should be inserted inside the foreach loop after the Write-Host "❌" block (~line 177), (2) what a Write-CIStepSummary markdown table should contain (file path, missing header types, compliance percentage), (3) which Pester tests in Test-CopyrightHeaders.Tests.ps1 need updating, and (4) the current test gap — no mocks exist for Write-CIAnnotation or Write-CIStepSummary — and what mock infrastructure is needed to maintain codecov patch coverage ≥ 80%. Reference the CIHelpers module exports in scripts/lib/Modules/CIHelpers.psm1 for exact function signatures. Review codecov.yml and scripts/tests/pester.config.ps1 for coverage configuration.

Plan Phase

Plan the changes to add CI annotations and step summary to Test-CopyrightHeaders.ps1. The plan should cover: (1) inserting Write-CIAnnotation -Message "..." -Level Warning -File $file inside the foreach failing-file branch after the Write-Host "❌" line, (2) building a markdown summary table from $results and passing it to Write-CIStepSummary after the summary block, and (3) adding Pester tests that mock Write-CIAnnotation and Write-CIStepSummary to verify call count and arguments, with sufficient coverage to meet the 80% codecov patch target. Follow the pattern established in Invoke-PSScriptAnalyzer.ps1.

Implement Phase

Implement the CI output improvements for Test-CopyrightHeaders.ps1. In Invoke-CopyrightHeaderCheck: (1) after the Write-Host " ❌ ..." line inside the foreach loop, add a Write-CIAnnotation call with level Warning, the file path, and a message stating which headers are missing, (2) after the summary block ending at Write-Host " Compliance: ...", build a markdown table from $results (columns: File, Copyright, SPDX, Status) and call Write-CIStepSummary. In Test-CopyrightHeaders.Tests.ps1: add tests that mock Write-CIAnnotation and Write-CIStepSummary to verify they are called with correct arguments when files are missing headers. Ensure all new code paths have test coverage to meet the 80% codecov patch target. Run npm run lint:ps and npm run test:ps to validate.

Review Phase

Review the changes to Test-CopyrightHeaders.ps1 and Test-CopyrightHeaders.Tests.ps1. Verify: (1) Write-CIAnnotation is called exactly once per failing file with appropriate message and Warning level, (2) Write-CIStepSummary produces a well-formed markdown table, (3) no regressions in existing Pester tests, (4) npm run lint:ps passes without PSScriptAnalyzer violations, (5) the CI workflow file is unchanged, (6) the output pattern aligns with Invoke-PSScriptAnalyzer.ps1 for user consistency, (7) patch coverage meets the 80% codecov gate for modified files, and (8) no coverage regressions in the pester flag on Codecov.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggithub-actionsGitHub Actions workflowsgood first issueGood for newcomerslintingLinting rules and validationscriptsPowerShell, Bash, or Python scripts

    Type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions