Skip to content

Add Oh My Pi (omp) integration: client entry + extension for deterministic read/write paths #163

Add Oh My Pi (omp) integration: client entry + extension for deterministic read/write paths

Add Oh My Pi (omp) integration: client entry + extension for deterministic read/write paths #163

Workflow file for this run

name: CI
on:
push:
pull_request:
jobs:
test-offline:
# The full suite - including init, seed-pack install, selftest, store,
# search, shred, lock, unlock - runs with the runtime offline guard
# active: any attempt to create a network socket aborts the process.
# This is the executable proof of the zero-network claim.
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python: ["3.11", "3.12"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Install (network allowed for dependency download only)
run: pip install -e .[dev]
- name: Test suite with offline guard active
env:
COMPARTMENT_ASSERT_OFFLINE: "1"
run: pytest tests/ -q
- name: Dashboard tests (loopback socket; offline guard intentionally off)
# `compartment dash` binds 127.0.0.1 by design and is never run under the
# offline guard, so its tests run here with the guard off.
run: pytest tests/test_dash.py -q
linux-panel:
# Linux has no notification area worth relying on, so it draws the same
# panel as an ordinary window. "It opens and stays open" is the failure
# unit tests cannot see, and this is a real Linux box, so it is checked
# here on a virtual display.
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: The Tk package, which pip cannot install
run: sudo apt-get update && sudo apt-get install -y python3-tk xvfb
- name: Install
run: pip install -e .[dev]
- name: A vault to look at
run: |
compartment init --passphrase ci-only-not-a-secret --no-app
compartment store --source "from chat" "Deploys go out Tuesday and Thursday mornings."
compartment store --source "from chat" "Staging runs Postgres 16 behind pgbouncer."
- name: The panel, without a display (what it would say)
run: compartment panel --self-check
- name: It opens and stays open
run: |
xvfb-run -a --server-args="-screen 0 1280x1024x24" \
compartment panel --show >/dev/null 2>&1 &
PID=$!
sleep 18
if ! kill -0 $PID 2>/dev/null; then
echo "the panel exited on its own"; exit 1
fi
echo "still running after 18s"
kill $PID 2>/dev/null || true
pkill -f "compartment.*panel" || true
sleep 2
- name: A second copy stands down instead of opening a second window
run: |
# Detached from the step's stdout, or the runner waits on it.
xvfb-run -a --server-args="-screen 0 1280x1024x24" \
compartment panel --show >/dev/null 2>&1 &
sleep 12
set +e
out=$(timeout 30 xvfb-run -a compartment panel --show 2>&1)
rc=$?
set -e
echo "second copy rc=$rc said: $out"
pkill -f "compartment.*panel" || true
if [ "$rc" -ne 0 ]; then
echo "the second copy did not exit; it opened a window of its own"
exit 1
fi
echo "$out" | grep -q "already open" || {
echo "the second copy exited without saying why"; exit 1; }
- name: It puts itself in the applications menu
run: |
compartment panel --login on
test -f "$HOME/.local/share/applications/compartment.desktop" \
|| { echo "no desktop entry"; exit 1; }
cat "$HOME/.local/share/applications/compartment.desktop"
grep -q "^Type=Application" "$HOME/.local/share/applications/compartment.desktop"
grep -q "^Exec=" "$HOME/.local/share/applications/compartment.desktop"
desktop-file-validate "$HOME/.local/share/applications/compartment.desktop" \
|| echo "note: desktop-file-validate not installed or reported style warnings"
compartment panel --login off
test ! -f "$HOME/.local/share/applications/compartment.desktop"
windows-tray:
# The tray app has to actually start on Windows, and "it starts" is the
# failure the unit tests cannot see: the macOS app once launched, ran, and
# showed nothing at all. The runner has a desktop session, so the app can
# really be drawn here - the screenshot is uploaded so a human can look at
# the panel without owning a Windows machine.
runs-on: windows-latest
# Nothing here should take twenty minutes. Without a cap, one command
# waiting on a passphrase prompt that no one can answer held a runner
# for 2h40m: init crashed on a non-ASCII character, left the vault
# locked, and the next command sat asking for input.
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install with the tray extra
run: pip install -e .[tray]
- name: A vault to look at
# Five ordinary-looking memories, so the screenshot shows the panel
# doing its job instead of an empty list.
run: |
compartment init --passphrase ci-only-not-a-secret
compartment store --source "from chat" "Deploys go out Tuesday and Thursday mornings, never on a Friday."
compartment store --source "from chat" "Approved (answered OK): send the release notes to the team now?"
compartment store --source "from chat" "Staging runs Postgres 16 behind pgbouncer on port 6432."
compartment store --source "from chat" "Prefers spaces over tabs everywhere except Go."
compartment store --source "from chat" "This laptop has 16 GB, so keep parallel jobs at 4."
python -c "from compartment import menubar as m; m.set_setting(m.default_vault(), 'capture_hook', True)"
- name: The panel, without a window (what it would say)
run: compartment tray --self-check
- name: Changing the passphrase has to work here too
# The apps grew a Change password button, and Windows is the side
# with no one sitting in front of it. Prove the whole round trip:
# the new passphrase opens the vault and the old one does not.
shell: pwsh
run: |
"Locksmith-ci-only" | compartment rekey --new-passphrase-stdin
if ($LASTEXITCODE -ne 0) { Write-Error "rekey failed"; exit 1 }
compartment lock
$old = "ci-only-not-a-secret" | compartment unlock --passphrase-stdin 2>&1
if ($LASTEXITCODE -eq 0) { Write-Error "the OLD passphrase still opens it"; exit 1 }
Write-Host "old passphrase correctly rejected"
"Locksmith-ci-only" | compartment unlock --passphrase-stdin
if ($LASTEXITCODE -ne 0) { Write-Error "the NEW passphrase does not open it"; exit 1 }
Write-Host "new passphrase accepted"
- name: A bigger screen than the 1024x768 default
shell: pwsh
continue-on-error: true
run: |
Set-DisplayResolution -Width 1920 -Height 1080 -Force
Start-Sleep -Seconds 3
- name: A second copy stands down instead of adding another icon
# `compartment init` above already started the tray app, which is the
# whole point of it. So a launch now must hand off and exit 0, and
# the copy that was already there must still be running afterwards.
shell: pwsh
run: |
$before = @(Get-Process compartment -ErrorAction SilentlyContinue).Count
if ($before -lt 1) { Write-Error "init did not start the tray app"; exit 1 }
compartment tray --show
if ($LASTEXITCODE -ne 0) { Write-Error "the second copy failed instead of standing down"; exit 1 }
$after = @(Get-Process compartment -ErrorAction SilentlyContinue).Count
if ($after -ne $before) { Write-Error "second copy changed the count: $before -> $after"; exit 1 }
Write-Host "one copy before, one copy after"
Get-Process compartment -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Sleep -Seconds 2
- name: Start the tray app and prove it is still alive
# At the DEFAULT scale, which is what nearly everyone runs. The
# high-DPI path below must not be the only one exercised.
shell: pwsh
run: |
$p = Start-Process -PassThru -FilePath compartment -ArgumentList 'tray','--show'
Start-Sleep -Seconds 25
if ($p.HasExited) {
Write-Error "the tray app exited on its own with $($p.ExitCode)"
exit 1
}
Write-Host "still running after 25s (pid $($p.Id))"
Stop-Process -Id $p.Id -Force
Start-Sleep -Seconds 2
- name: Start it again at 2x, the way a high-DPI laptop draws it
# The runner's display is 96 DPI, so this is the only way to see the
# scaled path render here - and it is what produces a screenshot
# sharp enough to sit beside the Retina macOS one.
shell: pwsh
env:
COMPARTMENT_UI_SCALE: "2"
run: |
$p = Start-Process -PassThru -FilePath compartment -ArgumentList 'tray','--show'
Start-Sleep -Seconds 25
if ($p.HasExited) {
Write-Error "the tray app exited at 2x scale with $($p.ExitCode)"
exit 1
}
Write-Host "still running at 2x after 25s (pid $($p.Id))"
- name: Screenshot the panel, cropped by Windows itself
shell: pwsh
run: |
Add-Type -AssemblyName System.Windows.Forms,System.Drawing
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class NativeWin {
[DllImport("user32.dll", CharSet=CharSet.Unicode)]
public static extern IntPtr FindWindow(string cls, string name);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr h);
[StructLayout(LayoutKind.Sequential)]
public struct RECT { public int Left, Top, Right, Bottom; }
[DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute(
IntPtr h, int attr, out RECT r, int size);
}
"@
# The whole desktop first, so this step always produces something
# even if the precise capture below cannot find the window.
$b = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
Write-Host "desktop: $($b.Width)x$($b.Height)"
$full = New-Object System.Drawing.Bitmap $b.Width, $b.Height
$g2 = [System.Drawing.Graphics]::FromImage($full)
$g2.CopyFromScreen($b.Location, [System.Drawing.Point]::Empty, $b.Size)
$full.Save("$PWD\tray.png", [System.Drawing.Imaging.ImageFormat]::Png)
# Ask the process for its own window rather than FindWindow: passing
# $null for a string parameter through P/Invoke marshals as "" in
# PowerShell, which then matches a window class literally named
# empty and finds nothing.
Write-Host "windows with a title:"
Get-Process | Where-Object { $_.MainWindowHandle -ne 0 } |
ForEach-Object { Write-Host " $($_.ProcessName): '$($_.MainWindowTitle)'" }
$proc = Get-Process |
Where-Object { $_.MainWindowHandle -ne 0 -and
($_.ProcessName -like "*compartment*" -or
$_.MainWindowTitle -eq "Compartment") } |
Select-Object -First 1
if (-not $proc) {
Write-Warning "no Compartment window found; desktop shot only"
exit 0
}
$h = $proc.MainWindowHandle
[void][NativeWin]::SetForegroundWindow($h)
Start-Sleep -Milliseconds 900
$r = New-Object NativeWin+RECT
# 9 = DWMWA_EXTENDED_FRAME_BOUNDS: the real frame, without the
# invisible resize border a plain GetWindowRect includes.
[void][NativeWin]::DwmGetWindowAttribute($h, 9, [ref]$r, 16)
$w = $r.Right - $r.Left; $ht = $r.Bottom - $r.Top
if ($w -lt 50 -or $ht -lt 50) {
Write-Warning "implausible window rect ${w}x${ht}; desktop shot only"
exit 0
}
$bmp = New-Object System.Drawing.Bitmap $w, $ht
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.CopyFromScreen($r.Left, $r.Top, 0, 0,
(New-Object System.Drawing.Size $w, $ht))
$bmp.Save("$PWD\compartment-windows-panel.png",
[System.Drawing.Imaging.ImageFormat]::Png)
Write-Host "panel: ${w}x${ht}"
- uses: actions/upload-artifact@v4
with:
name: windows-tray-screenshot
path: |
compartment-windows-panel.png
tray.png