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