Skip to content

Release 2.1.0 — Quill meetings, notifications, quality digests, audit fixes #64

Release 2.1.0 — Quill meetings, notifications, quality digests, audit fixes

Release 2.1.0 — Quill meetings, notifications, quality digests, audit fixes #64

Workflow file for this run

name: ci
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
permissions:
contents: read
jobs:
python:
name: Python ${{ matrix.python }}
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python }}
- name: Install package and dev tools
shell: pwsh
run: python -m pip install -e ".[dev]"
- name: AST validate Python scripts
shell: pwsh
run: |
$files = Get-ChildItem -Path scripts -Filter *.py -File
foreach ($f in $files) {
python -c "import ast; ast.parse(open(r'$($f.FullName)', encoding='utf-8').read()); print('OK $($f.Name)')"
}
- name: Validate JSON configs
shell: pwsh
run: |
$files = Get-ChildItem -Path config -Filter *.json -File
foreach ($f in $files) {
python -c "import json; json.load(open(r'$($f.FullName)', encoding='utf-8')); print('OK $($f.Name)')"
}
- name: Ruff
shell: pwsh
run: ruff check scripts tests
- name: Pytest
shell: pwsh
run: python -m pytest tests -q
ahk:
name: AutoHotkey syntax check
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- name: Install AutoHotkey v2
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
# Don't let choco's non-zero exit throw (pwsh 7.4+ default) — we want to
# inspect $LASTEXITCODE ourselves and retry / fall back, not abort here.
$PSNativeCommandUseErrorActionPreference = $false
$installed = $false
# Primary: Chocolatey, retried — the community feed has transient 503s
# that would otherwise red-flag PRs that touch no AHK code at all.
for ($i = 1; $i -le 3; $i++) {
choco install autohotkey --version=2.0.26 -y --no-progress
if ($LASTEXITCODE -eq 0) { $installed = $true; break }
Write-Host "choco attempt $i failed (exit $LASTEXITCODE); retrying in 15s..."
Start-Sleep -Seconds 15
}
if (-not $installed) {
# Fallback: the official AutoHotkey v2 release zip (AutoHotkey64.exe at
# its root), so a full Chocolatey outage can't block the syntax check.
Write-Host "Chocolatey unavailable; falling back to the GitHub release zip."
$zip = Join-Path $env:RUNNER_TEMP "ahk2.zip"
$dest = "C:\Program Files\AutoHotkey"
Invoke-WebRequest -UseBasicParsing -OutFile $zip `
-Uri "https://github.com/AutoHotkey/AutoHotkey/releases/download/v2.0.26/AutoHotkey_2.0.26.zip"
New-Item -ItemType Directory -Force -Path $dest | Out-Null
Expand-Archive -Path $zip -DestinationPath $dest -Force
}
# Fail fast if neither path produced the interpreter — the parse-check
# steps below skip silently when it is missing, which must not pass green.
$ahk = Get-ChildItem -Path "C:\Program Files\AutoHotkey" -Recurse -Filter AutoHotkey64.exe -File -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $ahk) { Write-Error "AutoHotkey64.exe not found after install"; exit 1 }
Write-Host "AutoHotkey64.exe at $($ahk.FullName)"
# A failed-then-recovered choco attempt leaves $LASTEXITCODE non-zero;
# exit explicitly so GitHub's wrapper doesn't fail this successful step.
exit 0
- name: Validate AutoHotkey scripts (brace balance, all .ahk)
shell: pwsh
run: |
$files = Get-ChildItem -Path scripts -Recurse -Filter *.ahk -File
$failed = $false
foreach ($f in $files) {
$script = Get-Content -Raw $f.FullName
$noComments = ($script -split "`n" | ForEach-Object { $_ -replace ';.*$','' }) -join "`n"
$noStrings = $noComments -replace '"[^"\n]*"','' -replace "'[^'\n]*'", ''
$opens = ($noStrings.ToCharArray() | Where-Object { $_ -eq '{' }).Count
$closes = ($noStrings.ToCharArray() | Where-Object { $_ -eq '}' }).Count
if ($opens -ne $closes) { Write-Host "FAIL $($f.Name): braces $opens / $closes"; $failed = $true }
else { Write-Host "OK $($f.Name): braces $opens / $closes" }
}
if ($failed) { Write-Error "Brace mismatch in one or more .ahk files"; exit 1 }
- name: Parse-check whole include tree
shell: pwsh
run: |
$ahk = Get-ChildItem -Path "C:\Program Files\AutoHotkey" -Recurse -Filter AutoHotkey64.exe -File -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $ahk) { Write-Host "AutoHotkey64.exe not found; skipping parse-check"; exit 0 }
$stub = Join-Path $env:RUNNER_TEMP "_ci_syntaxcheck.ahk"
# ExitApp(0) runs before any hotkey binds; #Include pulls the whole tree.
$main = (Resolve-Path -LiteralPath "scripts\grammarFix.ahk").Path
Set-Content -LiteralPath $stub -Encoding UTF8 -Value "ExitApp(0)`n#Include `"$main`"`n"
$errFile = Join-Path $env:RUNNER_TEMP "_ci_syntaxcheck.err"
$p = Start-Process -FilePath $ahk.FullName -ArgumentList @('/ErrorStdOut', "`"$stub`"") -WorkingDirectory "scripts" -RedirectStandardError $errFile -PassThru -Wait
$e = Get-Content -Raw -LiteralPath $errFile -ErrorAction SilentlyContinue
if ($e -and $e.Trim()) { Write-Error "AHK parse errors:`n$e"; exit 1 }
Write-Host "AHK parse-check clean (exit $($p.ExitCode))"
- name: AHK unit tests
shell: pwsh
run: |
$ahk = Get-ChildItem -Path "C:\Program Files\AutoHotkey" -Recurse -Filter AutoHotkey64.exe -File -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $ahk) { Write-Host "AutoHotkey64.exe not found; skipping AHK unit tests"; exit 0 }
foreach ($test in @("tests/test_classify_clipboard.ahk", "tests/test_parse_mode.ahk")) {
$errFile = Join-Path $env:RUNNER_TEMP "_ahk_test.err"
$p = Start-Process -FilePath $ahk.FullName -ArgumentList @('/ErrorStdOut', $test) -RedirectStandardError $errFile -PassThru -Wait
$e = Get-Content -Raw -LiteralPath $errFile -ErrorAction SilentlyContinue
if ($p.ExitCode -ne 0) { Write-Error "AHK unit test failed ($test, exit $($p.ExitCode)):`n$e"; exit 1 }
Write-Host "AHK unit test passed: $test"
}
web:
name: Web dashboard JS syntax
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
# ubuntu-latest ships Node, so no setup-node step (and no extra Node-20
# action). --check validates syntax without executing browser globals.
- name: node --check app.js
run: node --check scripts/ui/web/app.js