microsoft/hve-core

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
hve-core-v2.0.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

scripts/linting/Invoke-YamlLint.ps1

184lines · modecode

1#!/usr/bin/env pwsh
2<#
3.SYNOPSIS
4 Validates YAML files using actionlint for GitHub Actions workflows.
5
6.DESCRIPTION
7 Runs actionlint to validate GitHub Actions workflow files. Supports changed-files-only
8 mode for PR validation and exports JSON results for CI integration.
9
10.PARAMETER ChangedFilesOnly
11 Validate only changed YAML files.
12
13.PARAMETER BaseBranch
14 Base branch for detecting changed files (default: origin/main).
15
16.PARAMETER OutputPath
17 Path for JSON results output (default: logs/yaml-lint-results.json).
18
19.EXAMPLE
20 ./scripts/linting/Invoke-YamlLint.ps1 -Verbose
21
22.EXAMPLE
23 ./scripts/linting/Invoke-YamlLint.ps1 -ChangedFilesOnly
24
25.NOTES
26 Requires actionlint to be installed. Install via:
27 - Windows: choco install actionlint -or- scoop install actionlint -or- winget install actionlint
28 - macOS: brew install actionlint
29 - Linux: go install github.com/rhysd/actionlint/cmd/actionlint@latest
30#>
31#Requires -Version 7.0
32
33[CmdletBinding()]
34param(
35 [Parameter(Mandatory = $false)]
36 [switch]$ChangedFilesOnly,
37
38 [Parameter(Mandatory = $false)]
39 [string]$BaseBranch = "origin/main",
40
41 [Parameter(Mandatory = $false)]
42 [string]$OutputPath = "logs/yaml-lint-results.json"
43)
44
45# Import shared helpers
46Import-Module (Join-Path $PSScriptRoot "Modules/LintingHelpers.psm1") -Force
47
48Write-Host "🔍 Running YAML Lint (actionlint)..." -ForegroundColor Cyan
49
50# Check if actionlint is available
51$actionlintPath = Get-Command actionlint -ErrorAction SilentlyContinue
52if (-not $actionlintPath) {
53 Write-Error "actionlint is not installed. See script help for installation instructions."
54 exit 1
55}
56
57Write-Verbose "Using actionlint: $($actionlintPath.Source)"
58
59# Get files to analyze
60$workflowPath = ".github/workflows"
61$filesToAnalyze = @()
62
63if ($ChangedFilesOnly) {
64 Write-Host "Detecting changed workflow files..." -ForegroundColor Cyan
65 $changedFiles = Get-ChangedFilesFromGit -BaseBranch $BaseBranch -FileExtensions @('*.yml', '*.yaml')
66 $filesToAnalyze = $changedFiles | Where-Object { $_ -like "$workflowPath/*" }
67}
68else {
69 Write-Host "Analyzing all workflow files..." -ForegroundColor Cyan
70 if (Test-Path $workflowPath) {
71 $filesToAnalyze = Get-ChildItem -Path $workflowPath -File | Where-Object { $_.Extension -in '.yml', '.yaml' } | ForEach-Object { $_.FullName }
72 }
73}
74
75if ($filesToAnalyze.Count -eq 0) {
76 Write-Host "✅ No workflow files to analyze" -ForegroundColor Green
77 Set-GitHubOutput -Name "count" -Value "0"
78 Set-GitHubOutput -Name "issues" -Value "0"
79 exit 0
80}
81
82Write-Host "Analyzing $($filesToAnalyze.Count) workflow files..." -ForegroundColor Cyan
83Set-GitHubOutput -Name "count" -Value $filesToAnalyze.Count
84
85#region Main Execution
86try {
87 # Run actionlint with JSON output
88 $actionlintArgs = @('-format', '{{json .}}')
89 if ($ChangedFilesOnly -and $filesToAnalyze.Count -gt 0) {
90 $actionlintArgs += $filesToAnalyze
91 }
92
93 $rawOutput = & actionlint @actionlintArgs 2>&1
94 # actionlint exit code is not used; errors are parsed from JSON output
95
96 # Parse JSON output
97 $issues = @()
98 if ($rawOutput -and $rawOutput -ne "null") {
99 try {
100 $issues = $rawOutput | ConvertFrom-Json -ErrorAction Stop
101 if ($null -eq $issues) { $issues = @() }
102 if ($issues -isnot [array]) { $issues = @($issues) }
103 }
104 catch {
105 Write-Warning "Failed to parse actionlint output: $($_.Exception.Message)"
106 Write-Verbose "Raw output: $rawOutput"
107 }
108 }
109
110 # Process issues and create annotations
111 $hasErrors = $false
112 foreach ($issue in $issues) {
113 $hasErrors = $true
114
115 # Create GitHub annotation
116 Write-GitHubAnnotation `
117 -Type 'error' `
118 -Message $issue.message `
119 -File $issue.filepath `
120 -Line $issue.line `
121 -Column $issue.column
122
123 Write-Host " ❌ $($issue.filepath):$($issue.line):$($issue.column): $($issue.message)" -ForegroundColor Red
124 }
125
126 # Export results
127 $summary = @{
128 TotalFiles = $filesToAnalyze.Count
129 TotalIssues = $issues.Count
130 Errors = $issues.Count
131 Warnings = 0
132 HasErrors = $hasErrors
133 Timestamp = (Get-Date -Format "o")
134 Tool = "actionlint"
135 }
136
137 # Ensure logs directory exists
138 $logsDir = Split-Path $OutputPath -Parent
139 if (-not (Test-Path $logsDir)) {
140 New-Item -ItemType Directory -Force -Path $logsDir | Out-Null
141 }
142
143 $issues | ConvertTo-Json -Depth 5 | Out-File $OutputPath
144 $summary | ConvertTo-Json | Out-File "logs/yaml-lint-summary.json"
145
146 # Set outputs
147 Set-GitHubOutput -Name "issues" -Value $summary.TotalIssues
148 Set-GitHubOutput -Name "errors" -Value $summary.Errors
149
150 if ($hasErrors) {
151 Set-GitHubEnv -Name "YAML_LINT_FAILED" -Value "true"
152 }
153
154 # Write summary
155 Write-GitHubStepSummary -Content "## YAML Lint Results`n"
156
157 if ($summary.TotalIssues -eq 0) {
158 Write-GitHubStepSummary -Content "✅ **Status**: Passed`n`nAll $($summary.TotalFiles) workflow files passed validation."
159 Write-Host "`n✅ All workflow files passed YAML linting!" -ForegroundColor Green
160 exit 0
161 }
162 else {
163 Write-GitHubStepSummary -Content @"
164❌ **Status**: Failed
165
166| Metric | Count |
167|--------|-------|
168| Files Analyzed | $($summary.TotalFiles) |
169| Total Issues | $($summary.TotalIssues) |
170| Errors | $($summary.Errors) |
171"@
172
173 Write-Host "`n❌ YAML Lint found $($summary.TotalIssues) issue(s)" -ForegroundColor Red
174 exit 1
175 }
176}
177catch {
178 Write-Host "YAML Lint failed: $($_.Exception.Message)"
179 if ($env:GITHUB_ACTIONS -eq 'true') {
180 Write-Output "::error::$($_.Exception.Message)"
181 }
182 exit 1
183}
184#endregion