microsoft/hve-core

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fix/1000-standardize-timestamp-security-helpers

Branches

Tags

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

Clone

HTTPS

Download ZIP

scripts/linting/Invoke-PythonLint.ps1

152lines · modecode

1#!/usr/bin/env pwsh
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4#
5# Invoke-PythonLint.ps1
6#
7# Purpose: Dynamically discovers and lints Python skills using ruff
8# Author: HVE Core Team
9
10#Requires -Version 7.0
11
12[CmdletBinding()]
13param(
14 [Parameter(Mandatory = $false)]
15 [string]$RepoRoot = (Get-Location).Path,
16
17 [Parameter(Mandatory = $false)]
18 [string]$OutputPath
19)
20
21$ErrorActionPreference = 'Stop'
22
23#region Functions
24
25function Invoke-PythonLint {
26 [CmdletBinding()]
27 param(
28 [Parameter(Mandatory = $true)]
29 [string]$RepoRoot,
30
31 [Parameter(Mandatory = $false)]
32 [string]$OutputPath
33 )
34
35 Push-Location $RepoRoot
36 try {
37 # Find all directories with pyproject.toml
38 $pythonSkills = Get-ChildItem -Path . -Filter 'pyproject.toml' -Recurse -Force -File |
39 Where-Object { $_.FullName -notmatch 'node_modules' } |
40 ForEach-Object { $_.Directory.FullName }
41
42 if (-not $pythonSkills) {
43 Write-Host 'No Python skills found (no pyproject.toml files detected)' -ForegroundColor Yellow
44 return @{ success = $true; skillsChecked = 0; errors = @() }
45 }
46
47 Write-Host "Found $($pythonSkills.Count) Python skill(s):" -ForegroundColor Cyan
48 $pythonSkills | ForEach-Object { Write-Host " - $_" -ForegroundColor Gray }
49
50 # Check if ruff is globally available (used as fallback when skill has no venv)
51 $globalRuff = Get-Command ruff -ErrorAction SilentlyContinue
52
53 $results = @{
54 success = $true
55 skillsChecked = 0
56 errors = @()
57 details = @()
58 }
59
60 foreach ($skillPath in $pythonSkills) {
61 Write-Host "`nRunning ruff in $skillPath..." -ForegroundColor Cyan
62
63 Push-Location $skillPath
64 try {
65 # Resolve ruff: prefer skill venv, fall back to global
66 $ruffCmd = $null
67 $venvRuff = Join-Path $skillPath '.venv/bin/ruff'
68 $venvRuffWin = Join-Path $skillPath '.venv/Scripts/ruff.exe'
69 if (Test-Path $venvRuff) {
70 $ruffCmd = $venvRuff
71 Write-Host ' Using venv ruff' -ForegroundColor Gray
72 } elseif (Test-Path $venvRuffWin) {
73 $ruffCmd = $venvRuffWin
74 Write-Host ' Using venv ruff' -ForegroundColor Gray
75 } elseif ($globalRuff) {
76 $ruffCmd = 'ruff'
77 }
78
79 if (-not $ruffCmd) {
80 Write-Host '❌ ruff not available (no .venv and not installed globally)' -ForegroundColor Red
81 $results.success = $false
82 $results.errors += $skillPath
83 continue
84 }
85
86 $output = & $ruffCmd check . 2>&1
87 $exitCode = $LASTEXITCODE
88
89 $result = @{
90 path = $skillPath
91 passed = ($exitCode -eq 0)
92 output = $output | Out-String
93 }
94
95 $results.details += $result
96 $results.skillsChecked++
97
98 if ($exitCode -ne 0) {
99 Write-Host "$output" -ForegroundColor Red
100 Write-Host '❌ Linting issues found' -ForegroundColor Red
101 $results.success = $false
102 $results.errors += $skillPath
103 } else {
104 if ($output) {
105 Write-Host "$output"
106 }
107 Write-Host '✓ No linting issues' -ForegroundColor Green
108 }
109 } catch {
110 Write-Host "Error running ruff: $_" -ForegroundColor Red
111 $results.success = $false
112 $results.errors += "$skillPath - error: $_"
113 } finally {
114 Pop-Location
115 }
116 }
117
118 # Default to logs directory when no OutputPath specified
119 if (-not $OutputPath) {
120 $logsDir = Join-Path -Path $RepoRoot -ChildPath 'logs'
121 if (-not (Test-Path $logsDir)) {
122 New-Item -ItemType Directory -Path $logsDir -Force | Out-Null
123 }
124 $OutputPath = Join-Path -Path $logsDir -ChildPath 'python-lint-results.json'
125 }
126 $results | ConvertTo-Json -Depth 3 | Out-File $OutputPath -Encoding UTF8
127 Write-Host "📊 Results written to: $OutputPath" -ForegroundColor Cyan
128
129 return $results
130 } finally {
131 Pop-Location
132 }
133}
134
135#endregion
136
137#region Main Execution
138
139# Don't run main logic if dot-sourced for testing
140if ($MyInvocation.InvocationName -ne '.') {
141 $result = Invoke-PythonLint -RepoRoot $RepoRoot -OutputPath $OutputPath
142
143 if ($result.success) {
144 Write-Host "`n✅ All Python skills passed linting" -ForegroundColor Green
145 exit 0
146 } else {
147 Write-Host "`n❌ Linting completed with errors" -ForegroundColor Red
148 exit 1
149 }
150}
151
152#endregion
153