Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,37 @@ permissions:
jobs:
check:
name: Lint, Type-check, Build, Test
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install Rust toolchain
uses: dtolnay/rust-action@stable

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 CI workflow uses non-existent GitHub Action dtolnay/rust-action

The CI workflow references dtolnay/rust-action@stable which does not exist. The correct action name is dtolnay/rust-toolchain@stable, as correctly used in the publish workflow at .github/workflows/publish.yml:37.

Impact

The CI workflow will fail on every PR for both ubuntu-latest and windows-latest matrix entries because the Install Rust toolchain step will fail to find the action. This blocks all CI checks.

Suggested change
uses: dtolnay/rust-action@stable
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


- name: Install dependencies (Ubuntu only)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

- run: bun install

- name: Type-check and build
run: bun run build

- name: Run tests
run: bun run test

- name: Build Tauri (Windows only)
if: matrix.os == 'windows-latest'
run: bun run tauri build
env:
CI: true
50 changes: 48 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ jobs:
args: "--target aarch64-apple-darwin"
- platform: macos-latest
args: "--target x86_64-apple-darwin"
- platform: windows-latest
args: "--target x86_64-pc-windows-msvc"
runs-on: ${{ matrix.platform }}
env:
RELEASE_TAG: ${{ github.ref_type == 'tag' && github.ref_name || inputs.tag }}
Expand All @@ -34,7 +36,7 @@ jobs:

- uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-apple-darwin,x86_64-apple-darwin
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || 'x86_64-pc-windows-msvc' }}
- uses: swatinem/rust-cache@v2
with:
workspaces: "./src-tauri -> target"
Expand All @@ -46,14 +48,20 @@ jobs:
- name: Bundle plugins
run: bun run bundle:plugins
- name: Verify bundled plugins
shell: bash
run: |
COUNT=$(find src-tauri/resources/bundled_plugins -maxdepth 2 -name plugin.json | wc -l | tr -d ' ')
if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then
COUNT=$(find src-tauri/resources/bundled_plugins -maxdepth 2 -name plugin.json | wc -l | tr -d ' \r')
else
COUNT=$(find src-tauri/resources/bundled_plugins -maxdepth 2 -name plugin.json | wc -l | tr -d ' ')
fi
if [[ "$COUNT" -lt 1 ]]; then
echo "No bundled plugins found under src-tauri/resources/bundled_plugins."
exit 1
fi

- name: Validate release tag
shell: bash
run: |
if [[ -z "$RELEASE_TAG" ]]; then
echo "Missing RELEASE_TAG (push a v* tag, or provide workflow_dispatch input 'tag')."
Expand All @@ -65,6 +73,7 @@ jobs:
fi

- name: Validate app version matches tag
shell: bash
run: |
TAG_VERSION="${RELEASE_TAG#v}"

Expand All @@ -86,6 +95,7 @@ jobs:
fi

- name: Import Apple Developer Certificate
if: matrix.platform == 'macos-latest'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
Expand All @@ -100,6 +110,38 @@ jobs:
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
rm certificate.p12

- name: Validate Windows signing secrets
if: matrix.platform == 'windows-latest'
shell: pwsh
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
if ([string]::IsNullOrWhiteSpace($env:WINDOWS_CERTIFICATE)) {
Write-Error "Missing WINDOWS_CERTIFICATE secret for Windows release signing."
exit 1
}
if ([string]::IsNullOrWhiteSpace($env:WINDOWS_CERTIFICATE_PASSWORD)) {
Write-Error "Missing WINDOWS_CERTIFICATE_PASSWORD secret for Windows release signing."
exit 1
}

- name: Import Windows signing certificate
if: matrix.platform == 'windows-latest'
shell: pwsh
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
$certDir = Join-Path $env:RUNNER_TEMP "windows-cert"
New-Item -ItemType Directory -Path $certDir | Out-Null
$certBase64 = Join-Path $certDir "cert.base64"
$certPfx = Join-Path $certDir "cert.pfx"
Set-Content -Path $certBase64 -Value $env:WINDOWS_CERTIFICATE -NoNewline
certutil -decode $certBase64 $certPfx | Out-Null
$securePassword = ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -AsPlainText -Force
Import-PfxCertificate -FilePath $certPfx -CertStoreLocation Cert:\CurrentUser\My -Password $securePassword | Out-Null

- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -114,6 +156,9 @@ jobs:

APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}

WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
with:
tagName: ${{ env.RELEASE_TAG }}
releaseName: ${{ env.RELEASE_TAG }}
Expand All @@ -123,6 +168,7 @@ jobs:
args: ${{ matrix.args }}

- name: Verify updater assets uploaded
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
Expand Down
134 changes: 134 additions & 0 deletions OWNER_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Owner Guide: Windows Release Setup

Generate Windows certificate from your Mac, add GitHub secrets, push a tag.

## 1. Generate Windows Certificate

Install OpenSSL if not present:

```bash
brew install openssl
```

Create certificate:

```bash
# Create private key
openssl genrsa -out windows.key 4096

# Create certificate
openssl req -new -x509 -key windows.key -out windows.crt -days 365 \
-subj "/CN=Sunstory/O=Sunstory/C=US"

# Convert to PFX
openssl pkcs12 -export -out codesign.pfx -inkey windows.key -in windows.crt
# Enter password when prompted (save this!)
```

For production: Buy a certificate from DigiCert/Sectigo instead.

## 2. Encode for GitHub Secrets

```bash
# Base64 encode
cat codesign.pfx | base64 > cert_base64.txt

# Copy to clipboard (macOS)
cat cert_base64.txt | pbcopy

# Cleanup sensitive files
rm windows.key windows.crt codesign.pfx
```

## 3. Add GitHub Secrets

Go to: `https://github.com/robinebers/openusage/settings/secrets/actions`

Add:

| Secret | Value |
|--------|-------|
| `WINDOWS_CERTIFICATE` | Paste from clipboard (base64) |
| `WINDOWS_CERTIFICATE_PASSWORD` | Password from step 1 |

## 4. Update Versions

Set same version in all 3 files:

```bash
# Check current
grep '"version"' package.json src-tauri/tauri.conf.json
grep '^version' src-tauri/Cargo.toml

# Edit files (use your editor)
cursor src-tauri/tauri.conf.json # "version": "0.6.4"
cursor src-tauri/Cargo.toml # version = "0.6.4"
cursor package.json # "version": "0.6.4"
```

## 5. Create Release

```bash
# Commit
git add src-tauri/tauri.conf.json src-tauri/Cargo.toml package.json
git commit -m "chore: release v0.6.4"

# Push
git push origin main

# Tag
git tag v0.6.4
git push origin v0.6.4
```

## 6. Monitor Build

```bash
# Watch workflow
gh run watch

# Or open browser
open "https://github.com/robinebers/openusage/actions"
```

## 7. Verify

```bash
# Check release assets
gh release view v0.6.4
```

Should have:
- `OpenUsage_0.6.4_aarch64.dmg`
- `OpenUsage_0.6.4_x64.dmg`
- `OpenUsage_0.6.4_x64_en-US.msi` (Windows)
- `OpenUsage_0.6.4_x64-setup.exe` (Windows)
- `latest.json`

## Troubleshooting

**Missing WINDOWS_CERTIFICATE**
- Check secret exists in GitHub → Settings → Secrets

**Version mismatch**
- All 3 files must have same version number

**No Windows assets**
- Check workflow logs for Windows build errors
- Verify `WINDOWS_CERTIFICATE_PASSWORD` is correct

## Commands Reference

```bash
# Check versions
grep -h version package.json src-tauri/tauri.conf.json src-tauri/Cargo.toml

# List releases
gh release list

# View workflow runs
gh run list --workflow=publish.yml

# Check specific run
gh run view <run-id>
```
3 changes: 3 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions docs/breadcrumbs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Breadcrumbs

## 2026-02-09

- Windows dev: align AppState plugin/probe types with LoadedPlugin + PluginOutput, and persist arrow offset for tray alignment fallback.
- Arrow alignment: account for panel horizontal padding when positioning tray arrow.
- Side taskbar: compute arrow offset on Y axis and render left/right arrows.
- Side taskbar: use work area bounds to avoid overlapping the taskbar.
- Windows plugin scan: identified OS path/keychain blockers per plugin.
- Windows plugins: add Windows path candidates for Codex/Claude/Cursor/Windsurf and guard keychain usage to macOS.
- Windows OS gating: enable windows in plugin manifests and add actionable missing-path errors for testers.
- Cleanup: moved `WINDOWS_CHANGES.md` and reserved `nul` file to trash; kept `src/contexts/taskbar-context.tsx` for later wiring.
- Windows updater: documented that production updates require Authenticode signing; marked current state as test-only.
- Windows signing: added conditional PFX import step and owner follow-up checklist.
- Cleanup: removed unused `src/contexts/taskbar-context.tsx`.
- PR 77 fixes: re-enabled tray icon updates, restored Linux tray click handling, guarded window clamp, and replaced env-based Windows probes with `~`-based paths under a CODEX_HOME-only allowlist.

## 2026-02-10

- Switched plugin host sqlite to embedded `rusqlite` with bundled SQLite for cross-platform availability.
- Replaced Windows process discovery `wmic` with PowerShell CIM JSON parsing in `src-tauri/src/plugin_engine/host_api.rs`.
- Added Windows DPAPI-backed `host.vault` and updated Copilot auth to use it.
- Enforced Windows signing secrets in publish workflow to prevent unsigned releases.
- Adjusted dynamic tray icon rendering to stay visible on dark Windows taskbars.
- Restored Linux placeholders for tray positioning and plugin availability.
Loading
Loading