From c6415a110ca40b9a20418e0f8590e7d93fb7d0e3 Mon Sep 17 00:00:00 2001 From: VAIO Date: Mon, 27 Jul 2026 20:55:11 +0000 Subject: [PATCH] chore: clean up release tooling --- scripts/bump-version.ps1 | 72 ------------------ scripts/check-docs.ps1 | 157 +++++++++++++++++++++++++++------------ 2 files changed, 109 insertions(+), 120 deletions(-) delete mode 100644 scripts/bump-version.ps1 diff --git a/scripts/bump-version.ps1 b/scripts/bump-version.ps1 deleted file mode 100644 index 006bc14..0000000 --- a/scripts/bump-version.ps1 +++ /dev/null @@ -1,72 +0,0 @@ -<# -.SYNOPSIS - Bumps the plugin version in plugin.json and writes it back. - -.DESCRIPTION - Reads the current Version from plugin.json, applies the requested - bump (patch / minor / major), writes the result back to plugin.json, - and outputs the new version string on stdout. - - plugin.json is the single source of truth for the plugin version. - -.PARAMETER Bump - The bump type: patch, minor, or major. - -.EXAMPLE - ./scripts/bump-version.ps1 -Bump patch - Reads "3.0.0" from plugin.json, writes "3.0.1", outputs "3.0.1". -#> - -param( - [Parameter(Mandatory = $true)] - [ValidateSet("patch", "minor", "major")] - [string]$Bump -) - -$ErrorActionPreference = "Stop" - -$manifestPath = Join-Path $PSScriptRoot "..\plugin.json" -$manifestPath = [System.IO.Path]::GetFullPath($manifestPath) - -if (-not (Test-Path $manifestPath)) { - Write-Error "plugin.json not found at: $manifestPath" - exit 1 -} - -$content = [System.IO.File]::ReadAllText($manifestPath) - -if ($content -notmatch '"Version"\s*:\s*"(\d+\.\d+\.\d+)"') { - Write-Error "Cannot find a valid semver Version field in plugin.json" - exit 1 -} - -$currentVersion = $Matches[1] - -if ($currentVersion -notmatch '^(\d+)\.(\d+)\.(\d+)$') { - Write-Error "Cannot parse version '$currentVersion' from plugin.json" - exit 1 -} - -$major = [int]$Matches[1] -$minor = [int]$Matches[2] -$patch = [int]$Matches[3] - -switch ($Bump) { - "major" { $major++; $minor = 0; $patch = 0 } - "minor" { $minor++; $patch = 0 } - "patch" { $patch++ } -} - -$newVersion = "$major.$minor.$patch" - -$newContent = $content -replace '"Version"\s*:\s*"[^"]*"', ('"Version": "' + $newVersion + '"') - -if ($newContent -eq $content) { - Write-Error "Version replacement had no effect — check plugin.json formatting" - exit 1 -} - -[System.IO.File]::WriteAllText($manifestPath, $newContent, [System.Text.Encoding]::UTF8) - -Write-Host "Bumped $currentVersion -> $newVersion ($Bump)" -Write-Output $newVersion diff --git a/scripts/check-docs.ps1 b/scripts/check-docs.ps1 index de1e0a7..71a98d8 100644 --- a/scripts/check-docs.ps1 +++ b/scripts/check-docs.ps1 @@ -1,25 +1,81 @@ $ErrorActionPreference = "Stop" +Set-StrictMode -Version Latest + +function Invoke-Git { + param( + [Parameter(Mandatory = $true)] + [string[]]$Arguments + ) + + $output = @(& git @Arguments 2>&1) + if ($LASTEXITCODE -ne 0) { + $details = ($output | Out-String).Trim() + throw "git $($Arguments -join ' ') failed with exit code $LASTEXITCODE.`n$details" + } + + return $output +} + +function Get-PluginManifest { + param( + [Parameter(Mandatory = $true)] + [string]$Revision + ) + + $json = (Invoke-Git -Arguments @("show", "${Revision}:plugin.json")) -join [Environment]::NewLine + return $json | ConvertFrom-Json +} + +function Get-ManifestFingerprint { + param( + [Parameter(Mandatory = $true)] + [object]$Manifest + ) + + $rows = @( + $Manifest.PSObject.Properties | + Where-Object { $_.Name -ne "Version" } | + Sort-Object Name | + ForEach-Object { + $value = $_.Value | ConvertTo-Json -Compress -Depth 20 + "$($_.Name)=$value" + } + ) + + return $rows -join "`n" +} if ($env:GITHUB_EVENT_NAME -ne "pull_request") { Write-Host "Docs check skipped: not a pull_request event." exit 0 } -$event = Get-Content $env:GITHUB_EVENT_PATH | ConvertFrom-Json -$baseSha = $event.pull_request.base.sha -$headSha = $event.pull_request.head.sha +if ([string]::IsNullOrWhiteSpace($env:GITHUB_EVENT_PATH) -or -not (Test-Path $env:GITHUB_EVENT_PATH)) { + throw "GITHUB_EVENT_PATH is missing or does not exist." +} + +$event = Get-Content $env:GITHUB_EVENT_PATH -Raw | ConvertFrom-Json +$baseSha = [string]$event.pull_request.base.sha +$headSha = [string]$event.pull_request.head.sha -if ([string]::IsNullOrWhiteSpace($baseSha) -or [string]::IsNullOrWhiteSpace($headSha)) { - Write-Error "Could not determine base/head SHA from pull request event." - exit 1 +if ($baseSha -notmatch '^[0-9a-fA-F]{40}$' -or $headSha -notmatch '^[0-9a-fA-F]{40}$') { + throw "Could not determine valid base/head SHA values from the pull request event." } -git fetch --no-tags origin $baseSha $headSha | Out-Null +Invoke-Git -Arguments @("fetch", "--no-tags", "origin", $baseSha, $headSha) | Out-Null -$changedFiles = @(git diff --name-only $baseSha $headSha) +$changedFiles = @( + Invoke-Git -Arguments @( + "diff", + "--name-only", + "--diff-filter=ACMR", + $baseSha, + $headSha + ) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } +) if ($changedFiles.Count -eq 0) { - Write-Host "No changed files detected." + Write-Host "Docs check passed: no changed files detected." exit 0 } @@ -29,59 +85,60 @@ $changedFiles | ForEach-Object { Write-Host " - $_" } $readmeChanged = $changedFiles -contains "README.md" $userFacingPatterns = @( - '^Main\.cs$', + '^ActionCommandBuilder\.cs$', '^AutoCompleter\.cs$', - '^SshConfigParser\.cs$', - '^SshCommandBuilder\.cs$', + '^CommandInputGuard\.cs$', + '^CommandProfile\.cs$', + '^Flow\.Launcher\.Plugin\.QuickSSH\.csproj$', + '^Main\.cs$', '^Profile\.cs$', + '^ProfileImportService\.cs$', + '^ProfileSerializer\.cs$', + '^ProfileStorage\.cs$', + '^ProfileWizard\.cs$', + '^RemoteKeyInstallBuilder\.cs$', + '^SearchMatcher\.cs$', + '^ShellLaunchPlan\.cs$', + '^SshCommandBuilder\.cs$', + '^SshConfigParser\.cs$', + '^SshKeyEntry\.cs$', + '^SshProfile\.cs$', + '^Utils\.cs$', + '^Images\/', '^Languages\/', '^plugin\.json$' ) -$userFacingChangedFiles = @() - -foreach ($file in $changedFiles) { - foreach ($pattern in $userFacingPatterns) { - if ($file -match $pattern) { - $userFacingChangedFiles += $file - break - } - } -} - -$userFacingChangedFiles = $userFacingChangedFiles | Sort-Object -Unique - -# Exempt plugin.json when only the Version field changed (version-only release bump) -if ($userFacingChangedFiles -contains "plugin.json") { - $pluginBase = git show "${baseSha}:plugin.json" 2>$null | ConvertFrom-Json - $pluginHead = git show "${headSha}:plugin.json" 2>$null | ConvertFrom-Json - - if ($null -ne $pluginBase -and $null -ne $pluginHead) { - $baseHash = @{} - $pluginBase.PSObject.Properties | Where-Object { $_.Name -ne "Version" } | ForEach-Object { $baseHash[$_.Name] = $_.Value } - - $headHash = @{} - $pluginHead.PSObject.Properties | Where-Object { $_.Name -ne "Version" } | ForEach-Object { $headHash[$_.Name] = $_.Value } - - $isVersionOnly = ($baseHash.Count -eq $headHash.Count) - if ($isVersionOnly) { - foreach ($key in $baseHash.Keys) { - if (-not $headHash.ContainsKey($key) -or "$($headHash[$key])" -ne "$($baseHash[$key])") { - $isVersionOnly = $false +$userFacingChangedFiles = @( + @( + foreach ($file in $changedFiles) { + foreach ($pattern in $userFacingPatterns) { + if ($file -match $pattern) { + $file break } } } + ) | Sort-Object -Unique +) - if ($isVersionOnly) { - Write-Host "plugin.json change is version-only bump — exempted from docs gate." - $userFacingChangedFiles = @($userFacingChangedFiles | Where-Object { $_ -ne "plugin.json" }) - } +# A plugin.json change that modifies only Version does not require README changes. +if ($userFacingChangedFiles -contains "plugin.json") { + $pluginBase = Get-PluginManifest -Revision $baseSha + $pluginHead = Get-PluginManifest -Revision $headSha + + if ((Get-ManifestFingerprint -Manifest $pluginBase) -eq + (Get-ManifestFingerprint -Manifest $pluginHead)) { + Write-Host "plugin.json change is version-only — exempted from the docs gate." + $userFacingChangedFiles = @( + $userFacingChangedFiles | Where-Object { $_ -ne "plugin.json" } + ) } } if ($userFacingChangedFiles.Count -eq 0) { Write-Host "Docs check passed: no tracked user-facing files changed." + Write-Host "README_REQUIRED=NO" exit 0 } @@ -89,9 +146,13 @@ Write-Host "Tracked user-facing files changed:" $userFacingChangedFiles | ForEach-Object { Write-Host " - $_" } if (-not $readmeChanged) { - Write-Error "README.md was not updated even though tracked user-facing files changed." - exit 1 + throw "README.md was not updated even though tracked user-facing files changed." } +Invoke-Git -Arguments @("cat-file", "-e", "${headSha}:README.md") | Out-Null + Write-Host "Docs check passed: README.md was updated." +Write-Host "README_REQUIRED=YES" +Write-Host "README_CHANGED=YES" +Write-Host "USER_FACING_FILE_COUNT=$($userFacingChangedFiles.Count)" exit 0