microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
79db525325e5e5bc087af12d0fc658c8db2d9458

Branches

Tags

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

Clone

HTTPS

Download ZIP

scripts/linting/Invoke-YamlLint.ps1

211lines Ā· modecode

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