Skip to content

Bump Vistumbler version to v10.9.7 (#29) #12

Bump Vistumbler version to v10.9.7 (#29)

Bump Vistumbler version to v10.9.7 (#29) #12

Workflow file for this run

name: Create Release
on:
push:
branches:
- main
- beta
workflow_dispatch:
concurrency:
group: create-release-${{ github.ref }}
cancel-in-progress: true
jobs:
check_release:
runs-on: ubuntu-latest
outputs:
proceed: ${{ steps.check.outputs.proceed }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check for existing release
id: check
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const content = fs.readFileSync('VistumblerMDB/Vistumbler.au3','utf8');
// Allow matching versions with hyphens (pre-releases) e.g. v10.9.5-pre.1
let verMatch = content.match(/\$version\s*=\s*'v?([^']+)'/);
let ver = verMatch ? verMatch[1] : null;
if (!ver) {
const m2 = content.match(/#AutoIt3Wrapper_Res_Fileversion\s*=\s*([0-9\.]+)/);
ver = m2 ? m2[1] : null;
}
if (!ver) { core.setOutput('proceed','true'); return; }
const tags = [`v${ver}`, `v${ver.replace(/[\.\-]/g,'-')}`];
for (const tag of tags) {
try {
const res = await github.rest.repos.getReleaseByTag({ owner: context.repo.owner, repo: context.repo.repo, tag });
if (res && res.data && res.data.draft === false) { core.setOutput('proceed','false'); return; }
} catch (e) {
if (e.status === 404) { continue; } else { throw e; }
}
}
core.setOutput('proceed','true');
package_and_release:
needs: check_release
if: needs.check_release.outputs.proceed == 'true'
runs-on: windows-latest
environment: signing
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Determine version and patch NSI
shell: pwsh
id: determine_version
run: |
$au3 = Join-Path $PWD 'VistumblerMDB\Vistumbler.au3'
if (-not (Test-Path $au3)) { Write-Error "Vistumbler.au3 not found"; exit 2 }
$content = Get-Content $au3 -Raw
$ver = ''
# Use single quotes to prevent PowerShell variable interpolation of $version
# Updated regex to support pre-release versions with hyphens (e.g. 10.9.5-pre.1)
if ($content -match '\$version\s*=\s*''v?([^'']+)''') { $ver = $matches[1] }
if (-not $ver) {
if ($content -match '#AutoIt3Wrapper_Res_Fileversion\s*=\s*([0-9\.]+)') { $ver = $matches[1] }
}
if (-not $ver) { Write-Error "Could not determine version"; exit 2 }
Write-Host "Detected version: $ver"
"version=$ver" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
if ($ver -match '-') {
Write-Host "Pre-release version detected"
"prerelease=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
} else {
"prerelease=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
}
# prepare NSI
$nsiTemplate = Join-Path $PWD 'Installer\Vistumbler.nsi.template'
$nsiTarget = Join-Path $PWD 'Installer\Vistumbler.nsi'
Copy-Item -Path $nsiTemplate -Destination $nsiTarget -Force
$verDash = $ver -replace '[\.\-]','-'
$outFileName = "OutFile `"Vistumbler_v$verDash.exe`""
$displayVer = "WriteRegStr HKLM `"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vistumbler`" `"DisplayVersion`" `"$ver`""
$content = Get-Content $nsiTarget
$content = $content -replace 'OutFile\s+"[^"]+"', $outFileName
$content = $content -replace 'WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vistumbler" "DisplayVersion" "[^"]+"', $displayVer
$content | Set-Content $nsiTarget
Write-Host "Patched NSI -> $nsiTarget"
- name: Create ZIP of `VistumblerMDB` (versioned)
shell: pwsh
run: |
$nsiTarget = Join-Path $PWD 'Installer\Vistumbler.nsi'
if (-not (Test-Path $nsiTarget)) { Write-Error "Patched NSI not found"; exit 2 }
$nsiText = Get-Content $nsiTarget -Raw
if ($nsiText -match 'OutFile\s+"Vistumbler_v([0-9\-]+)\.exe"') { $ver = ($matches[1] -replace '-', '.') } else { $ver = 'unknown' }
$zipOut = "builds\Vistumbler_v$ver.zip"
$zipPortable = "builds\Vistumbler_v${ver}_Portable.zip"
if (-not (Test-Path builds)) { New-Item -ItemType Directory -Path builds | Out-Null }
Write-Host "Creating zip $zipOut from VistumblerMDB"
Compress-Archive -Path 'VistumblerMDB\*' -DestinationPath $zipOut -Force
Write-Host "ZIP created: $zipOut"
# Create portable zip: copy tree, set PortableMode=1 in Settings\vistumbler_settings.ini, then zip
$portableTemp = Join-Path $PWD 'temp_portable'
if (Test-Path $portableTemp) { Remove-Item -Recurse -Force $portableTemp }
New-Item -ItemType Directory -Path $portableTemp -Force | Out-Null
Copy-Item -Path 'VistumblerMDB' -Destination $portableTemp -Recurse
$settingsPath = Join-Path $portableTemp 'VistumblerMDB\Settings\vistumbler_settings.ini'
if (Test-Path $settingsPath) {
$lines = @(Get-Content $settingsPath)
$newLines = @()
$inVistumbler = $false
$found = $false
$vistumblerFound = $false
foreach ($line in $lines) {
if ($line -match '^\s*\[Vistumbler\]') {
$inVistumbler = $true
$vistumblerFound = $true
$newLines += $line
continue
}
if ($line -match '^\s*\[') { $inVistumbler = $false }
if ($inVistumbler -and $line -match '^\s*PortableMode\s*=') {
$newLines += 'PortableMode=1'
$found = $true
} else {
$newLines += $line
}
}
if (-not $found) {
if ($vistumblerFound) {
$final = @()
foreach ($l in $newLines) {
$final += $l
if ($l -match '^\s*\[Vistumbler\]') { $final += 'PortableMode=1' }
}
$newLines = $final
} else {
$newLines += ''
$newLines += '[Vistumbler]'
$newLines += 'PortableMode=1'
}
}
$newLines | Set-Content -Path $settingsPath -Encoding UTF8
} else {
New-Item -ItemType Directory -Path (Split-Path $settingsPath -Parent) -Force | Out-Null
"[Vistumbler]`r`nPortableMode=1" | Out-File -FilePath $settingsPath -Encoding utf8
}
Write-Host "Creating portable zip $zipPortable from modified copy"
Compress-Archive -Path (Join-Path $portableTemp 'VistumblerMDB\*') -DestinationPath $zipPortable -Force
Write-Host "Portable ZIP created: $zipPortable"
Remove-Item -Recurse -Force $portableTemp
- name: Install NSIS (use repo installer if present)
shell: pwsh
run: |
$localInst = Join-Path $PWD 'Installer\nsis-3.04-setup.exe'
if (Test-Path $localInst) {
Write-Host "Found local NSIS installer: $localInst. Installing silently..."
Start-Process -FilePath $localInst -ArgumentList '/S' -Wait -NoNewWindow
} else {
Write-Host "Local NSIS installer not found; installing via Chocolatey"
choco install nsis -y
}
# Add NSIS to PATH for subsequent steps
$nsisPath = 'C:\Program Files (x86)\NSIS'
if (Test-Path $nsisPath) {
Write-Host "Adding NSIS to GITHUB_PATH: $nsisPath"
Add-Content -Path $env:GITHUB_PATH -Value $nsisPath
# Also update PATH for this session
$env:PATH = "$env:PATH;$nsisPath"
}
- name: Build NSIS installer
shell: pwsh
run: |
# Try to find makensis.exe
$makensis = Get-Command makensis.exe -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $makensis) {
# Search common NSIS installation paths
$nsisLocations = @(
'C:\Program Files (x86)\NSIS\makensis.exe',
'C:\Program Files\NSIS\makensis.exe'
)
foreach ($loc in $nsisLocations) {
if (Test-Path $loc) {
$makensis = Get-Item $loc
Write-Host "Found makensis at: $loc"
break
}
}
}
if (-not $makensis) { Write-Error 'makensis.exe not found'; exit 2 }
$nsi = 'Installer\Vistumbler.nsi'
if (-not (Test-Path $nsi)) { Write-Error "NSI script $nsi not found"; exit 2 }
Write-Host "Running makensis on $nsi"
& $makensis.Path /V2 $nsi
Write-Host "NSIS finished"
- name: Sign Installer
shell: pwsh
env:
SIG_PFX: ${{ secrets.SIG_PFX }}
SIG_PFX_PASS: ${{ secrets.SIG_PFX_PASS }}
run: |
if (-not $env:SIG_PFX) { Write-Warning "No SIG_PFX secret found, skipping signing."; exit 0 }
# Decode PFX
$pfxPath = Join-Path $PWD 'cert.pfx'
[IO.File]::WriteAllBytes($pfxPath, [Convert]::FromBase64String($env:SIG_PFX))
# Find Signtool
$signtoolPath = ""
$programFiles = ${env:ProgramFiles(x86)}
if (-not $programFiles) { $programFiles = $env:ProgramFiles }
# Search common paths
$candidates = Get-ChildItem -Path "$programFiles\Windows Kits" -Include signtool.exe -Recurse -ErrorAction SilentlyContinue
if ($candidates) {
# Prioritize x64/x86, avoid arm64 if not on arm machine
$best = $null
# 1. Try x64
$best = $candidates | Where-Object { $_.FullName -match 'x64' } | Select-Object -First 1
# 2. Try x86
if (-not $best) {
$best = $candidates | Where-Object { $_.FullName -match 'x86' } | Select-Object -First 1
}
# 3. Try any non-arm
if (-not $best) {
$best = $candidates | Where-Object { $_.FullName -notmatch 'arm' } | Select-Object -First 1
}
# 4. Final fallback
if (-not $best) { $best = $candidates | Select-Object -First 1 }
if ($best) {
$signtoolPath = $best.FullName
}
}
if (-not $signtoolPath) {
choco install windows-sdk-10.0 -y --no-progress
refreshenv || true
$cmd = Get-Command signtool.exe -ErrorAction SilentlyContinue
if ($cmd) { $signtoolPath = $cmd.Path }
}
if (-not $signtoolPath) { Write-Warning "Signtool not found, skipping signing"; exit 0 }
# Sign installer
$inst = Get-ChildItem -Path $PWD -include 'Vistumbler_v*.exe' -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if ($inst) {
Write-Host "Signing $($inst.FullName)"
& $signtoolPath sign /f $pfxPath /p $env:SIG_PFX_PASS /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 $inst.FullName
} else {
Write-Warning "No installer found to sign"
}
Remove-Item -Path $pfxPath -Force -ErrorAction SilentlyContinue
- name: Find built installer and prepare release assets
shell: pwsh
id: find_assets
env:
VERSION: ${{ steps.determine_version.outputs.version }}
run: |
$ver = $env:VERSION
if (-not $ver) { Write-Error "Version not found in environment variables"; exit 2 }
$verDash = $ver -replace '[\.\-]', '-'
Write-Host "Looking for assets for version: $ver (dash: $verDash)"
$out = @{ installer=''; zip=''; zip_portable=''; version=$ver; version_dash=$verDash }
# Look for the versioned installer (Vistumbler_v*.exe) specifically
$inst = Get-ChildItem -Path $PWD -include "Vistumbler_v$verDash.exe" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if ($inst) {
$out.installer = $inst.FullName
Write-Host "Found installer: $($inst.FullName)"
} else {
# Fallback to wildcard search if specific version search fails but regex safety check later will catch mismatch
$inst = Get-ChildItem -Path $PWD -include 'Vistumbler_v*.exe' -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if ($inst) {
$out.installer = $inst.FullName
Write-Host "Found installer (wildcard): $($inst.FullName)"
} else {
Write-Host "No versioned installer found!"
}
}
$zip = Get-ChildItem -Path (Join-Path $PWD 'builds') -Filter "Vistumbler_v$ver.zip" -ErrorAction SilentlyContinue | Where-Object { $_.Name -notmatch '_Portable' } | Select-Object -First 1
if ($zip) { $out.zip = $zip.FullName }
$zipp = Get-ChildItem -Path (Join-Path $PWD 'builds') -Filter "Vistumbler_v${ver}_Portable.zip" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($zipp) { $out.zip_portable = $zipp.FullName }
# Verify found assets match expected version
if ($out.installer -and ($out.installer -notmatch "Vistumbler_v$verDash.exe")) {
Write-Warning "Found installer name $($out.installer) does not match expected version $verDash"
}
Write-Host "Installer: $($out.installer)"
Write-Host "Zip: $($out.zip)"
Write-Host "Portable Zip: $($out.zip_portable)"
Write-Host "Version: $($out.version) (dash: $($out.version_dash))"
if (-not $out.installer -and -not $out.zip) {
Write-Error "Could not find expected assets for version $ver! Release will fail."
exit 1
}
# set outputs
"installer=$($out.installer)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"zip=$($out.zip)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"zip_portable=$($out.zip_portable)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"version=$($out.version)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"version_dash=$($out.version_dash)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
- name: Extract Release Notes
shell: pwsh
env:
VERSION: ${{ steps.find_assets.outputs.version }}
run: |
$ver = $env:VERSION
$changelog = Join-Path $PWD 'VistumblerMDB\CHANGELOG.md'
if (-not (Test-Path $changelog)) {
"No changelog found" | Set-Content release_notes.md
exit 0
}
$content = Get-Content $changelog -Raw
$verEsc = [Regex]::Escape($ver)
# Regex:
# (?sm) = Single-line (dot matches newline) + Multi-line (^ matches start of line)
# ^##\s+$verEsc = Line starting with "## " followed by version
# \s*$ = optional trailing whitespace to end of line
# (.*?) = Capture group 1: content (non-greedy)
# (?=^##|\Z) = Lookahead: stop at next "##" at start of line OR end of string
# Note: We use string concatenation to safe-guard regex interpretation
$pattern = '(?sm)^##\s+' + $verEsc + '\s*$(.*?)(?=^##|\Z)'
if ($content -match $pattern) {
$notes = $matches[1].Trim()
$notes | Set-Content release_notes.md -Encoding utf8
Write-Host "Extracted notes for v$ver"
} else {
Write-Host "No notes found for v$ver in changelog"
"Release v$ver" | Set-Content release_notes.md -Encoding utf8
}
- name: Create GitHub Release
uses: ncipollo/release-action@v1
with:
tag: v${{ steps.find_assets.outputs.version }}
name: Vistumbler v${{ steps.find_assets.outputs.version }}
bodyFile: release_notes.md
draft: false
prerelease: ${{ steps.determine_version.outputs.prerelease }}
token: ${{ secrets.GITHUB_TOKEN }}
allowUpdates: true
artifacts: "${{ steps.find_assets.outputs.installer }},${{ steps.find_assets.outputs.zip }},${{ steps.find_assets.outputs.zip_portable }}"