mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-07-10 00:14:16 +00:00
210 lines
5 KiB
PowerShell
210 lines
5 KiB
PowerShell
param(
|
|
[string[]] $Only = @(),
|
|
[string[]] $Skip = @(),
|
|
[switch] $DryRun,
|
|
[switch] $Help,
|
|
[Parameter(ValueFromRemainingArguments = $true)]
|
|
[object[]] $RemainingArgs = @()
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$CheckOrder = @(
|
|
"suppressions",
|
|
"ruff-format",
|
|
"ruff-check",
|
|
"ty",
|
|
"pytest"
|
|
)
|
|
|
|
function Show-Usage {
|
|
@"
|
|
Usage: ci.ps1 [options]
|
|
|
|
Runs the local sequence for the same check IDs enforced by GitHub CI.
|
|
Requires uv on PATH when running ruff, ty, or pytest checks.
|
|
Local ruff checks repair formatting and autofixable lint before later checks.
|
|
|
|
Checks (in order):
|
|
suppressions Ban # type: ignore / # ty: ignore suppressions
|
|
ruff-format uv run ruff format
|
|
ruff-check uv run ruff check --fix
|
|
ty uv run ty check
|
|
pytest uv run pytest -v --tb=short
|
|
|
|
Options:
|
|
-Only ID Run only the given check (repeatable)
|
|
-Skip ID Skip the given check (repeatable)
|
|
-DryRun Print commands without running them.
|
|
-Help Show this help text.
|
|
"@
|
|
}
|
|
|
|
function Write-Step {
|
|
param([string] $Message)
|
|
|
|
Write-Host ""
|
|
Write-Host "==> $Message"
|
|
}
|
|
|
|
function Format-Argument {
|
|
param([string] $Value)
|
|
|
|
if ($Value -match '^[A-Za-z0-9_./:@%+=,\[\]-]+$') {
|
|
return $Value
|
|
}
|
|
|
|
return "'" + ($Value -replace "'", "''") + "'"
|
|
}
|
|
|
|
function Invoke-CiCommand {
|
|
param(
|
|
[string] $FilePath,
|
|
[string[]] $Arguments = @()
|
|
)
|
|
|
|
$parts = @($FilePath) + $Arguments
|
|
$commandText = ($parts | ForEach-Object { Format-Argument ([string] $_) }) -join " "
|
|
Write-Host "+ $commandText"
|
|
|
|
if (-not $DryRun) {
|
|
& $FilePath @Arguments
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Command failed with exit code ${LASTEXITCODE}: $commandText"
|
|
}
|
|
}
|
|
}
|
|
|
|
function Test-ValidCheckId {
|
|
param([string] $CheckId)
|
|
|
|
return $CheckOrder -contains $CheckId
|
|
}
|
|
|
|
function Assert-ValidCheckId {
|
|
param([string] $CheckId)
|
|
|
|
if (-not (Test-ValidCheckId $CheckId)) {
|
|
throw "unknown check id: $CheckId (expected one of: $($CheckOrder -join ', '))"
|
|
}
|
|
}
|
|
|
|
function Test-ShouldRunCheck {
|
|
param([string] $CheckId)
|
|
|
|
if ($Only.Count -gt 0 -and ($Only -notcontains $CheckId)) {
|
|
return $false
|
|
}
|
|
|
|
if ($Skip -contains $CheckId) {
|
|
return $false
|
|
}
|
|
|
|
return $true
|
|
}
|
|
|
|
function Assert-UvAvailable {
|
|
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
|
|
throw "uv is required but was not found on PATH. Install uv first (see README or scripts/install.ps1)."
|
|
}
|
|
}
|
|
|
|
function Test-SelectedChecksNeedUv {
|
|
if ($DryRun) {
|
|
return $false
|
|
}
|
|
|
|
foreach ($checkId in $CheckOrder) {
|
|
if ((Test-ShouldRunCheck $checkId) -and $checkId -ne "suppressions") {
|
|
return $true
|
|
}
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
function Invoke-SuppressionsCheck {
|
|
Write-Step "Ban type ignore suppressions"
|
|
$pattern = '# type: ignore|# ty: ignore'
|
|
Write-Host "+ Get-ChildItem -Recurse -Filter *.py (excluding .venv, .git) | Select-String '$pattern'"
|
|
|
|
if (-not $DryRun) {
|
|
$matches = Get-ChildItem -Path . -Recurse -Filter *.py -File |
|
|
Where-Object {
|
|
$full = $_.FullName
|
|
$full -notmatch '[\\/]\.venv[\\/]' -and
|
|
$full -notmatch '[\\/]\.git[\\/]'
|
|
} |
|
|
Select-String -Pattern $pattern
|
|
|
|
if ($matches) {
|
|
$matches | ForEach-Object { Write-Host $_.Line }
|
|
throw "type: ignore / ty: ignore comments are not allowed. Fix the underlying type errors instead."
|
|
}
|
|
}
|
|
}
|
|
|
|
function Invoke-RuffFormatCheck {
|
|
Write-Step "ruff format"
|
|
Invoke-CiCommand -FilePath "uv" -Arguments @("run", "ruff", "format")
|
|
}
|
|
|
|
function Invoke-RuffLintCheck {
|
|
Write-Step "ruff check --fix"
|
|
Invoke-CiCommand -FilePath "uv" -Arguments @("run", "ruff", "check", "--fix")
|
|
}
|
|
|
|
function Invoke-TyCheck {
|
|
Write-Step "ty check"
|
|
Invoke-CiCommand -FilePath "uv" -Arguments @("run", "ty", "check")
|
|
}
|
|
|
|
function Invoke-PytestCheck {
|
|
Write-Step "pytest"
|
|
Invoke-CiCommand -FilePath "uv" -Arguments @("run", "pytest", "-v", "--tb=short")
|
|
}
|
|
|
|
function Invoke-Check {
|
|
param([string] $CheckId)
|
|
|
|
switch ($CheckId) {
|
|
"suppressions" { Invoke-SuppressionsCheck }
|
|
"ruff-format" { Invoke-RuffFormatCheck }
|
|
"ruff-check" { Invoke-RuffLintCheck }
|
|
"ty" { Invoke-TyCheck }
|
|
"pytest" { Invoke-PytestCheck }
|
|
default { throw "unknown check id: $CheckId" }
|
|
}
|
|
}
|
|
|
|
if ($Help) {
|
|
Show-Usage
|
|
return
|
|
}
|
|
|
|
if ($RemainingArgs.Count -gt 0) {
|
|
Show-Usage
|
|
throw "Unknown option: $($RemainingArgs -join ' ')"
|
|
}
|
|
|
|
foreach ($checkId in $Only) {
|
|
Assert-ValidCheckId $checkId
|
|
}
|
|
|
|
foreach ($checkId in $Skip) {
|
|
Assert-ValidCheckId $checkId
|
|
}
|
|
|
|
if (Test-SelectedChecksNeedUv) {
|
|
Assert-UvAvailable
|
|
}
|
|
|
|
foreach ($checkId in $CheckOrder) {
|
|
if (Test-ShouldRunCheck $checkId) {
|
|
Invoke-Check $checkId
|
|
}
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "All selected CI checks passed."
|