microsoft/hve-core

Public

mirrored from https://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
hve-core-v3.1.44

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

scripts/linting/README.md

639lines · modecode

1---
2title: Linting Scripts
3description: PowerShell scripts for code quality validation and documentation checks
4author: HVE Core Team
5ms.date: 2025-11-05
6ms.topic: reference
7keywords:
8 - powershell
9 - linting
10 - validation
11 - code quality
12 - markdown
13estimated_reading_time: 10
14---
15
16This directory contains PowerShell scripts for validating code quality and documentation standards in the `hve-core` repository.
17
18## Architecture
19
20The linting scripts follow a **modular architecture** with shared helper functions:
21
22| Component | Description |
23|---------------------------------------------------|---------------------------------------------------------------------------------------------|
24| Wrapper Scripts (`Invoke-*.ps1`) | Entry points that orchestrate validation logic |
25| Core Scripts | Existing validation logic (e.g., `Link-Lang-Check.ps1`, `Validate-MarkdownFrontmatter.ps1`) |
26| Shared Module (`Modules/LintingHelpers.psm1`) | Common functions for file discovery and git operations |
27| CI Helpers (`scripts/lib/Modules/CIHelpers.psm1`) | CI annotations, outputs, env flags, and step summaries |
28| Configuration Files | Tool-specific settings (e.g., `PSScriptAnalyzer.psd1`, `markdown-link-check.config.json`) |
29
30## Scripts
31
32### PowerShell Linting
33
34#### `Invoke-PSScriptAnalyzer.ps1`
35
36Static analysis for PowerShell scripts using PSScriptAnalyzer.
37
38**Purpose**: Enforce PowerShell best practices and detect common issues.
39
40**Features**:
41
42* Detects changed PowerShell files via Git
43* Supports analyzing all files or changed files only
44* Creates CI annotations for violations
45* Exports JSON results and markdown summary
46* Configurable via `PSScriptAnalyzer.psd1`
47
48**Parameters**:
49
50* `-ChangedFilesOnly` (switch) - Analyze only files changed in current branch
51
52**Usage**:
53
54```powershell
55# Analyze all PowerShell files
56./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -Verbose
57
58# Analyze only changed files
59./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -ChangedFilesOnly
60
61# View detailed output
62./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -Verbose -Debug
63```
64
65**GitHub Actions Integration**:
66
67* Workflow: `.github/workflows/ps-script-analyzer.yml`
68* Artifacts: `psscriptanalyzer-results` (JSON + markdown)
69* Exit Code: Non-zero if violations found
70
71#### `PSScriptAnalyzer.psd1`
72
73Configuration file for PSScriptAnalyzer rules.
74
75**Enforced Rules**:
76
77| Rule Category | Description |
78|----------------|---------------------------------------------------|
79| Severity | Error and Warning levels |
80| Best Practices | Avoid aliases, use approved verbs, singular nouns |
81| Help | Require comment-based help |
82| Security | Check for credentials in code |
83| Performance | Identify inefficient patterns |
84
85**Excluded Rules**:
86
87* `PSAvoidUsingWriteHost` - Allowed for script output
88
89### YAML Linting
90
91#### `Invoke-YamlLint.ps1`
92
93Static analysis for GitHub Actions workflow files using actionlint.
94
95**Purpose**: Validate GitHub Actions workflow YAML syntax and best practices.
96
97**Features**:
98
99* Validates `.github/workflows/*.yml` and `.yaml` files
100* Detects changed workflow files via Git
101* Supports analyzing all files or changed files only
102* Creates CI annotations for violations
103* Exports JSON results and markdown summary
104* Configurable via `.github/actionlint.yaml`
105
106**Parameters**:
107
108* `-ChangedFilesOnly` (switch) - Analyze only files changed in current branch
109* `-BaseBranch` (string) - Base branch for comparison (default: `origin/main`)
110* `-OutputPath` (string) - Output path for JSON results (default: `logs/yaml-lint-results.json`)
111
112**Usage**:
113
114```powershell
115# Analyze all workflow files
116./scripts/linting/Invoke-YamlLint.ps1 -Verbose
117
118# Analyze only changed files
119./scripts/linting/Invoke-YamlLint.ps1 -ChangedFilesOnly
120
121# View detailed output
122./scripts/linting/Invoke-YamlLint.ps1 -Verbose -Debug
123```
124
125**GitHub Actions Integration**:
126
127* Workflow: `.github/workflows/yaml-lint.yml`
128* Configuration: `.github/actionlint.yaml`
129* Artifacts: `yaml-lint-results` (JSON)
130* Exit Code: Non-zero if violations found
131
132### Markdown Validation
133
134#### `Validate-MarkdownFrontmatter.ps1`
135
136Validates YAML frontmatter and footer format in markdown files.
137
138**Purpose**: Ensure consistent metadata across documentation.
139
140**Features**:
141
142* Validates required frontmatter fields
143* Checks footer format and copyright notice
144* Supports changed files only mode
145* Configurable warnings-as-errors
146* Creates CI annotations for all issues
147* Exports JSON results with detailed statistics
148* Generates comprehensive step summary
149
150**Parameters**:
151
152* `-ChangedFilesOnly` (switch) - Validate only changed markdown files
153* `-SkipFooterValidation` (switch) - Skip footer checks
154* `-WarningsAsErrors` (switch) - Treat warnings as errors
155* `-EnableSchemaValidation` (switch) - Enable JSON Schema validation (advisory only)
156
157**Artifacts Generated**:
158
159* `logs/frontmatter-validation-results.json` - Complete validation results including:
160 * Timestamp and script name
161 * Summary statistics (total files, error/warning counts)
162 * Lists of all errors and warnings
163
164**Usage**:
165
166```powershell
167# Validate all markdown files
168./scripts/linting/Validate-MarkdownFrontmatter.ps1
169
170# Validate only changed files
171./scripts/linting/Validate-MarkdownFrontmatter.ps1 -ChangedFilesOnly
172
173# Skip footer validation
174./scripts/linting/Validate-MarkdownFrontmatter.ps1 -SkipFooterValidation
175```
176
177**GitHub Actions Integration**:
178
179* Workflow: `.github/workflows/frontmatter-validation.yml`
180* Artifacts: `frontmatter-validation-results` (JSON)
181* Annotations: Errors and warnings with file paths
182* Exit Code: Non-zero if validation fails
183
184#### `Invoke-LinkLanguageCheck.ps1`
185
186Detects URLs with language paths (e.g., `/en-us/`) that should be removed.
187
188**Purpose**: Ensure language-agnostic URLs for better internationalization.
189
190**Features**:
191
192* Scans all markdown files recursively
193* Calls `Link-Lang-Check.ps1` for detection logic
194* Creates CI warning annotations
195* Provides fix instructions in summary
196
197**Usage**:
198
199```powershell
200# Check all markdown files
201./scripts/linting/Invoke-LinkLanguageCheck.ps1 -Verbose
202
203# View detection details
204./scripts/linting/Invoke-LinkLanguageCheck.ps1 -Debug
205```
206
207**GitHub Actions Integration**:
208
209* Workflow: `.github/workflows/link-lang-check.yml`
210* Annotations: Warnings on files with language paths
211* Artifacts: `link-lang-check-results` (JSON + markdown)
212
213#### `Link-Lang-Check.ps1`
214
215Core logic for detecting language paths in URLs.
216
217**Detection Pattern**: Matches `/[a-z]{2}-[a-z]{2}/` patterns in Microsoft domain URLs.
218
219#### `Markdown-Link-Check.ps1`
220
221Validates all links in markdown files using markdown-link-check npm package.
222
223**Purpose**: Detect broken links before deployment.
224
225**Features**:
226
227* Checks internal and external links
228* Configurable via `markdown-link-check.config.json`
229* Retries failed links
230* Respects robots.txt
231* Creates CI annotations for broken links
232* Exports JSON results with link statistics
233* Generates detailed step summary
234
235**Artifacts Generated**:
236
237* `logs/markdown-link-check-results.json` - Complete validation results including:
238 * Timestamp and script name
239 * Summary statistics (total files, broken links count)
240 * List of all broken links with file paths
241
242**GitHub Actions Integration**:
243
244* Workflow: `.github/workflows/markdown-link-check.yml`
245* Configuration: `markdown-link-check.config.json`
246* Artifacts: `markdown-link-check-results` (JSON)
247* Annotations: Error for each broken link
248* Exit Code: Non-zero if broken links found
249
250### Skill Structure Validation
251
252#### `Validate-SkillStructure.ps1`
253
254Validates the structural integrity of skill directories under `.github/skills/`.
255
256**Purpose**: Ensure all skill packages comply with the agentskills.io specification and hve-core conventions.
257
258**Features**:
259
260* Validates SKILL.md presence in each skill directory
261* Checks frontmatter for required `name` and `description` fields
262* Verifies `name` matches directory name
263* When `scripts/` subdirectory exists, requires both `.ps1` and `.sh` files for cross-platform support
264* Warns on unrecognized directories
265* Supports changed-files-only mode via Git
266* Creates CI annotations for violations
267* Exports JSON results to `logs/skill-validation-results.json`
268
269**Parameters**:
270
271* `-SkillsPath` (string) - Root path containing skill directories (default: `.github/skills`)
272* `-WarningsAsErrors` (switch) - Treat warnings as errors
273* `-ChangedFilesOnly` (switch) - Validate only skills with changed files
274* `-BaseBranch` (string) - Git reference for changed file detection (default: `origin/main`)
275
276**Usage**:
277
278```powershell
279# Validate all skills
280./scripts/linting/Validate-SkillStructure.ps1
281
282# Validate with warnings as errors
283./scripts/linting/Validate-SkillStructure.ps1 -WarningsAsErrors
284
285# Validate only changed skills
286./scripts/linting/Validate-SkillStructure.ps1 -ChangedFilesOnly
287```
288
289**GitHub Actions Integration**:
290
291* Workflow: `.github/workflows/skill-validation.yml`
292* Artifacts: `skill-validation-results` (JSON)
293* Exit Code: Non-zero if validation fails
294
295### Copyright Header Validation
296
297#### `Test-CopyrightHeaders.ps1`
298
299Validates copyright and SPDX license headers in source files.
300
301**Purpose**: Ensure all PowerShell and shell scripts include the required Microsoft copyright notice and MIT SPDX license identifier in their first 15 lines.
302
303**Features**:
304
305* Scans `.ps1`, `.psm1`, `.psd1`, and `.sh` files recursively
306* Checks for `Copyright (c) Microsoft Corporation` header
307* Checks for `SPDX-License-Identifier: MIT` identifier
308* Configurable file extensions and exclude paths
309* Exports JSON results with per-file compliance details
310* Calculates compliance percentage across all scanned files
311
312**Parameters**:
313
314* `-Path` (string) - Root path to scan (default: repository root via `git rev-parse --show-toplevel`)
315* `-FileExtensions` (string[]) - File extensions to check (default: `@('*.ps1', '*.psm1', '*.psd1', '*.sh')`)
316* `-OutputPath` (string) - Path for JSON results (default: `logs/copyright-header-results.json`)
317* `-FailOnMissing` (switch) - Exit with code 1 if any files lack required headers
318* `-ExcludePaths` (string[]) - Directories to exclude (default: `@('node_modules', '.git', 'vendor', 'logs')`)
319
320**Usage**:
321
322```powershell
323# Check all source files (report only)
324./scripts/linting/Test-CopyrightHeaders.ps1
325
326# Check and fail on missing headers
327./scripts/linting/Test-CopyrightHeaders.ps1 -FailOnMissing
328
329# Check specific path with verbose output
330./scripts/linting/Test-CopyrightHeaders.ps1 -Path ./scripts -FailOnMissing -Verbose
331```
332
333**GitHub Actions Integration**:
334
335* Workflow: `.github/workflows/copyright-headers.yml`
336* Artifacts: `copyright-header-results` (JSON)
337* Exit Code: Non-zero if validation fails (with `-FailOnMissing`)
338
339## Shared Module
340
341### `Modules/LintingHelpers.psm1`
342
343Common helper functions for file discovery and git operations.
344
345**Exported Functions**:
346
347#### `Get-ChangedFilesFromGit`
348
349Detects files changed in current branch compared to main.
350
351**Parameters**:
352
353* `-BaseBranch` (string) - Base branch to compare against (default: `origin/main`)
354* `-FileExtensions` (string[]) - Array of file patterns to filter (e.g., `@('*.ps1', '*.md')`)
355
356**Returns**: Array of changed file paths
357
358**Fallbacks**:
359
3601. `git merge-base` with specified base branch
3612. `git diff HEAD~1` when merge-base fails
3623. `git diff HEAD` for staged/unstaged files
363
364#### `Get-FilesRecursive`
365
366Finds files matching patterns using `git ls-files` with a `Get-ChildItem` fallback.
367
368**Parameters**:
369
370* `-Path` (string, required) - Root directory to search from
371* `-Include` (string[], required) - File patterns to include (e.g., `@('*.ps1', '*.psm1')`)
372* `-GitIgnorePath` (string) - Path to `.gitignore` file for exclusion patterns (fallback path only)
373
374**Returns**: Array of FileInfo objects
375
376**Behavior**:
377
378* Inside a git repository, uses `git ls-files --cached --others --exclude-standard` scoped to the given path. Git natively handles `.gitignore` exclusions.
379* Outside a git repository (or when `git` is unavailable), falls back to `Get-ChildItem -Recurse` with optional `-GitIgnorePath` filtering.
380
381#### `Get-GitIgnorePatterns`
382
383Parses `.gitignore` into PowerShell wildcard patterns.
384
385**Parameters**:
386
387* `-GitIgnorePath` (string, required) - Path to `.gitignore` file
388
389**Returns**: Array of wildcard patterns using platform-appropriate separators
390
391### `scripts/lib/Modules/CIHelpers.psm1`
392
393CI helper functions for annotations, outputs, environment flags, and summaries.
394
395**Exported Functions**:
396
397#### `Write-CIAnnotation`
398
399Creates a CI annotation.
400
401**Parameters**:
402
403* `-Level` ('Error'|'Warning'|'Notice') - Annotation severity
404* `-Message` (string) - Annotation text
405* `-File` (string, optional) - File path
406* `-Line` (int, optional) - Line number
407* `-Column` (int, optional) - Column number
408
409**Output**: CI annotation command
410
411#### `Write-CIAnnotations`
412
413Writes CI annotations from a validation summary.
414
415**Parameters**:
416
417* `-Summary` (ValidationSummary) - Validation results to annotate
418
419#### `Set-CIOutput`
420
421Sets a CI output variable.
422
423**Parameters**:
424
425* `-Name` (string) - Variable name
426* `-Value` (string) - Variable value
427
428#### `Set-CIEnv`
429
430Sets a CI environment variable.
431
432**Parameters**:
433
434* `-Name` (string) - Variable name
435* `-Value` (string) - Variable value
436
437#### `Write-CIStepSummary`
438
439Appends content to the CI step summary.
440
441**Parameters**:
442
443* `-Content` (string) - Markdown content
444
445**Usage Example**:
446
447```powershell
448Import-Module ./Modules/LintingHelpers.psm1
449
450# Get changed PowerShell files
451$files = Get-ChangedFilesFromGit -FileExtension '.ps1'
452
453# Create error annotation
454Write-CIAnnotation -Level 'Error' -Message 'Syntax error' -File 'script.ps1' -Line 42
455
456# Set output variable
457Set-CIOutput -Name 'files-analyzed' -Value $files.Count
458
459# Add to step summary
460Write-CIStepSummary -Content "## Results`n`nAnalyzed $($files.Count) files"
461```
462
463## Configuration Files
464
465### Configuration: `PSScriptAnalyzer.psd1`
466
467PSScriptAnalyzer rule configuration.
468
469**Key Settings**:
470
471* Severity: Error, Warning
472* IncludeRules: Best practices, security, performance
473* ExcludeRules: `PSAvoidUsingWriteHost`
474
475### `markdown-link-check.config.json`
476
477Markdown link checker configuration.
478
479**Key Settings**:
480
481* Retry attempts: 3
482* Timeout: 10 seconds
483* Ignore patterns: Localhost, example.com
484
485## Testing
486
487All scripts support local testing before running in GitHub Actions:
488
489```powershell
490# Test PSScriptAnalyzer
491./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -Verbose
492
493# Test frontmatter validation
494./scripts/linting/Validate-MarkdownFrontmatter.ps1 -ChangedFilesOnly
495
496# Test link language check
497./scripts/linting/Invoke-LinkLanguageCheck.ps1
498
499# Test markdown links
500./scripts/linting/Markdown-Link-Check.ps1
501
502# Test shared module
503Import-Module ./scripts/linting/Modules/LintingHelpers.psm1
504Get-Command -Module LintingHelpers
505```
506
507## GitHub Actions Workflows
508
509All linting scripts are integrated into GitHub Actions workflows:
510
511| Script | Workflow |
512|------------------------|------------------------------------------------|
513| PSScriptAnalyzer | `.github/workflows/ps-script-analyzer.yml` |
514| YAML Lint | `.github/workflows/yaml-lint.yml` |
515| Frontmatter Validation | `.github/workflows/frontmatter-validation.yml` |
516| Link Language Check | `.github/workflows/link-lang-check.yml` |
517| Markdown Link Check | `.github/workflows/markdown-link-check.yml` |
518
519See [GitHub Workflows Documentation](../../.github/workflows/README.md) for details.
520
521## Adding New Linting Scripts
522
523To add a new linting script:
524
5251. **Create wrapper script** following `Invoke-*.ps1` naming convention
5262. **Import LintingHelpers and CIHelpers modules** for file discovery and CI integration
5273. **Implement core validation logic** with clear error reporting
5284. **Support common parameters**: `-Verbose`, `-Debug`, `-ChangedFilesOnly` (if applicable)
5295. **Create GitHub Actions workflow** in `.github/workflows/`
5306. **Add to PR validation** in `.github/workflows/pr-validation.yml`
5317. **Document** in this README and workflows README
5328. **Test locally** before creating PR
533
534**Template**:
535
536```powershell
537#!/usr/bin/env pwsh
538<#
539.SYNOPSIS
540 Brief description of validation.
541
542.DESCRIPTION
543 Detailed description.
544
545.PARAMETER ChangedFilesOnly
546 Validate only changed files.
547
548.EXAMPLE
549 ./scripts/linting/Invoke-MyValidator.ps1 -Verbose
550#>
551
552[CmdletBinding()]
553param(
554 [switch]$ChangedFilesOnly
555)
556
557$ErrorActionPreference = 'Stop'
558Import-Module (Join-Path $PSScriptRoot 'Modules/LintingHelpers.psm1') -Force
559Import-Module (Join-Path $PSScriptRoot '../lib/Modules/CIHelpers.psm1') -Force
560
561#region Functions
562
563function Invoke-MyValidatorCore {
564 [CmdletBinding()]
565 [OutputType([void])]
566 param(
567 [switch]$ChangedFilesOnly
568 )
569
570 Write-Host "🔍 Running MyValidator..."
571
572 if ($ChangedFilesOnly) {
573 $files = Get-ChangedFilesFromGit -FileExtension '.ext'
574 }
575 else {
576 $files = Get-FilesRecursive -Path (Get-Location) -Pattern '*.ext'
577 }
578
579 if ($files.Count -eq 0) {
580 Write-Host "✅ No files to validate"
581 return
582 }
583
584 # Perform validation
585 $issues = @()
586 foreach ($file in $files) {
587 # Validation logic here
588 if ($issue) {
589 $issues += $issue
590 Write-CIAnnotation -Level 'Error' -Message 'Issue found' -File $file
591 }
592 }
593
594 Write-CIStepSummary -Content "## Validation Results`n`nFound $($issues.Count) issues"
595
596 if ($issues.Count -gt 0) {
597 throw "Found $($issues.Count) issues"
598 }
599
600 Write-Host "✅ All files validated successfully"
601}
602
603#endregion Functions
604
605#region Main Execution
606if ($MyInvocation.InvocationName -ne '.') {
607 try {
608 Invoke-MyValidatorCore @PSBoundParameters
609 exit 0
610 }
611 catch {
612 Write-Error -ErrorAction Continue "Invoke-MyValidator failed: $($_.Exception.Message)"
613 Write-CIAnnotation -Message $_.Exception.Message -Level Error
614 exit 1
615 }
616}
617#endregion Main Execution
618```
619
620## Contributing
621
622When modifying linting scripts:
623
6241. Follow PowerShell best practices (PSScriptAnalyzer compliant)
6252. Maintain CI integration patterns
6263. Keep scripts testable locally without GitHub Actions
6274. Update documentation in README files
6285. Test thoroughly before creating PR
6296. Get CODEOWNERS approval
630
631## Related Documentation
632
633* [Scripts Documentation](../README.md)
634* [GitHub Workflows Documentation](../../.github/workflows/README.md)
635* [Contributing Guidelines](../../CONTRIBUTING.md)
636
637---
638
639🤖 Crafted with precision by ✨Copilot following brilliant human instruction, then carefully refined by our team of discerning human reviewers.
640