mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-21 06:24:32 +00:00
ci: build and release the Windows menubar
windows-menubar-ci.yml runs on windows/** changes: tsc, clippy with -D warnings, and cargo test on both windows-latest and ubuntu-latest, plus a release-profile `tauri build --no-bundle` on Windows. The Linux leg exists because most of the crate's cfg(windows) code cannot be compiled anywhere else, so the reverse - keeping the ksni paths and every shared helper clean off Windows - has to be checked somewhere too. release-menubar-windows.yml mirrors release-menubar.yml: a `windows-v*` tag (or a manual dispatch) builds the MSI and publishes it, with a sha256, to a "Windows Menubar vX" release. The two release-desktop-*.yml files on the source branch are deliberately not imported: their tag names and "Desktop" release titles would collide with the Electron app in app/, which already owns `desktop-v*`.
This commit is contained in:
parent
7e57fb8d4f
commit
120747d2fa
3 changed files with 200 additions and 11 deletions
99
.github/workflows/release-menubar-windows.yml
vendored
Normal file
99
.github/workflows/release-menubar-windows.yml
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
name: Release Windows Menubar
|
||||
|
||||
# Triggers on a `windows-v*` tag push (e.g. `git tag windows-v0.9.20 && git push origin
|
||||
# windows-v0.9.20`), or manually via the Actions tab. Mirrors release-menubar.yml, which
|
||||
# does the same job for the macOS menubar under the `mac-v*` tags. The produced `.msi` is
|
||||
# unsigned; users see a SmartScreen prompt on first run until we add signing.
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'windows-v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version label for the bundle (e.g. v0.9.20 or dev-preview)'
|
||||
required: true
|
||||
default: 'dev-preview'
|
||||
|
||||
permissions:
|
||||
contents: write # Needed to create the release + upload assets.
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Resolve version label
|
||||
id: version
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${GITHUB_REF}" == refs/tags/windows-v* ]]; then
|
||||
echo "value=${GITHUB_REF#refs/tags/windows-}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "value=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22.13.0
|
||||
cache: npm
|
||||
cache-dependency-path: windows/package-lock.json
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: x86_64-pc-windows-msvc
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: windows/src-tauri
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: windows
|
||||
run: npm ci
|
||||
|
||||
- name: Build MSI bundle
|
||||
working-directory: windows
|
||||
run: npm run tauri build
|
||||
|
||||
- name: Collect artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p release-artifacts
|
||||
find windows/src-tauri/target/release/bundle -type f -name '*.msi' \
|
||||
-exec cp -v {} release-artifacts/ \;
|
||||
(cd release-artifacts && for f in *.msi; do sha256sum "$f" > "$f.sha256"; done)
|
||||
ls -la release-artifacts
|
||||
|
||||
- name: Upload artifact (for manual runs)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: CodeBurnMenubar-Windows-${{ steps.version.outputs.value }}
|
||||
path: release-artifacts/*
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Create / update GitHub Release
|
||||
if: startsWith(github.ref, 'refs/tags/windows-v')
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
tag_name: ${{ github.ref_name }}
|
||||
name: Windows Menubar ${{ steps.version.outputs.value }}
|
||||
body: |
|
||||
Download the `.msi` below and run it. The tray app reads everything through the
|
||||
CodeBurn CLI, so install that first:
|
||||
|
||||
```
|
||||
npm install -g codeburn
|
||||
```
|
||||
|
||||
Requires codeburn 0.9.9 or newer and the WebView2 Runtime (preinstalled on
|
||||
Windows 11 and recent Windows 10 updates; installed on demand otherwise).
|
||||
|
||||
The bundle is unsigned, so Windows SmartScreen warns on first run: click
|
||||
"More info", then "Run anyway". Signing is planned.
|
||||
files: release-artifacts/*
|
||||
fail_on_unmatched_files: true
|
||||
83
.github/workflows/windows-menubar-ci.yml
vendored
Normal file
83
.github/workflows/windows-menubar-ci.yml
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
name: Windows Menubar CI
|
||||
|
||||
# The Windows menubar (windows/) is a Tauri app: a React frontend plus a Rust binary whose
|
||||
# interesting code is `#[cfg(windows)]` and therefore only ever compiled on a Windows runner.
|
||||
# ubuntu-latest is in the matrix because the same crate has to stay clean on the ksni/Linux
|
||||
# paths and because contributors develop it on non-Windows machines.
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- .github/workflows/windows-menubar-ci.yml
|
||||
- windows/**
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/windows-menubar-ci.yml
|
||||
- windows/**
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
# webkit2gtk + libayatana are what the Tauri and ksni crates link against; without
|
||||
# them the Linux leg cannot even typecheck the Rust side.
|
||||
- name: Install Linux system dependencies
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
libwebkit2gtk-4.1-dev \
|
||||
libayatana-appindicator3-dev \
|
||||
librsvg2-dev \
|
||||
libssl-dev \
|
||||
libxdo-dev \
|
||||
libgtk-3-dev \
|
||||
build-essential
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22.13.0
|
||||
cache: npm
|
||||
cache-dependency-path: windows/package-lock.json
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: clippy
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: windows/src-tauri
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: windows
|
||||
run: npm ci
|
||||
|
||||
- name: Typecheck frontend
|
||||
working-directory: windows
|
||||
run: npx tsc --noEmit
|
||||
|
||||
- name: Clippy
|
||||
working-directory: windows/src-tauri
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
|
||||
- name: Rust tests
|
||||
working-directory: windows/src-tauri
|
||||
run: cargo test
|
||||
|
||||
# Release-profile compile of the real Windows binary. `--no-bundle` skips the WiX
|
||||
# download and MSI packaging, which belong to the release workflow, not to every PR.
|
||||
- name: Release build smoke
|
||||
if: runner.os == 'Windows'
|
||||
working-directory: windows
|
||||
run: npm run tauri build -- --no-bundle
|
||||
|
|
@ -112,15 +112,21 @@ process, so the cadence follows popover visibility.
|
|||
|
||||
The Plan pill (visible on the Claude tab, or when Claude is the only detected provider) reads
|
||||
Claude Code's OAuth credentials from `~/.claude/.credentials.json`, calls
|
||||
`https://api.anthropic.com/api/oauth/usage`, refreshes the token once on 401, and stores one
|
||||
snapshot per window under `~/.cache/codeburn/subscription-snapshots.json` (`CODEBURN_CACHE_DIR`
|
||||
override) so a freshly reset window can still show last cycle's final. This is the same file
|
||||
format the macOS app writes. Nothing is logged: the credential blob never leaves the Rust side.
|
||||
`https://api.anthropic.com/api/oauth/usage`, and stores one snapshot per window under
|
||||
`~/.cache/codeburn/subscription-snapshots.json` (`CODEBURN_CACHE_DIR` override) so a freshly
|
||||
reset window can still show last cycle's final. This is the same file format the macOS app
|
||||
writes. Nothing is logged: the credential blob never leaves the Rust side.
|
||||
|
||||
On a 401 we do **not** call the token refresh endpoint. Claude's refresh token is single-use
|
||||
and rotates, so spending it would invalidate the token Claude Code itself is holding and break
|
||||
the user's login. Like `ClaudeCredentialStore.refreshAfter401` on macOS, we re-read Claude's
|
||||
own credential file for a token it has already rotated, and report a transient failure when
|
||||
there isn't one yet.
|
||||
|
||||
## Build a production package
|
||||
|
||||
```bash
|
||||
# Windows (.msi + NSIS .exe): run from a Windows host
|
||||
# Windows (.msi): run from a Windows host
|
||||
npm run tauri build
|
||||
|
||||
# Linux (experimental): produces .deb, .rpm, .AppImage under src-tauri/target/release/bundle/
|
||||
|
|
@ -139,13 +145,14 @@ npm run tauri build
|
|||
- **Config writes**: `~/.config/codeburn/config.json` writes run under a POSIX `flock` on
|
||||
`~/.config/codeburn/.config.lock`. On Windows the same path uses a create-new lock file. Note
|
||||
that this lock is advisory *between instances of this app only* - the codeburn CLI does not
|
||||
take it - so it narrows, but does not eliminate, a concurrent-write race. A lock left behind
|
||||
by a crash is never deleted by another process; it expires after 30 s of inactivity and the
|
||||
next writer retries.
|
||||
take it - so it narrows, but does not eliminate, a concurrent-write race. A live holder keeps
|
||||
its file handle open and Windows will not unlink an open file, so the staleness sweep can only
|
||||
ever reclaim a lock whose owner is gone (after 30 s).
|
||||
- **Snapshot writes**: `subscription-snapshots.json` refuses a symlinked target and is written
|
||||
0600 on unix, mirroring `mac/Sources/CodeBurnMenubar/Security/SafeFile.swift`.
|
||||
- **Credentials**: the Plan view reads `~/.claude/.credentials.json` with a 64 KB cap and refuses
|
||||
symlinks; tokens are only ever sent to the Anthropic usage and token endpoints over TLS.
|
||||
symlinks; the access token is only ever sent to the Anthropic usage endpoint over TLS, and the
|
||||
refresh token is never read or sent at all.
|
||||
- **FX fetches**: Frankfurter response is parsed as JSON and the rate is clamped to
|
||||
`[0.0001, 1_000_000]` before it touches displayed numbers. Stale cache preferred over poisoned
|
||||
fresh data.
|
||||
|
|
@ -158,8 +165,8 @@ npm run tauri build
|
|||
`cargo clippy -D warnings` and `cargo test` on windows-latest + ubuntu-latest, plus a release
|
||||
build smoke on Windows.
|
||||
- `windows-v*` tag (e.g. `windows-v0.9.20`) triggers
|
||||
`.github/workflows/release-menubar-windows.yml`; publishes the `.msi` and NSIS `.exe` to a
|
||||
"Windows Menubar vX" release. Unsigned for now, so Windows SmartScreen prompts on first run
|
||||
`.github/workflows/release-menubar-windows.yml`; publishes the `.msi` (plus its sha256) to
|
||||
a "Windows Menubar vX" release. Unsigned for now, so Windows SmartScreen prompts on first run
|
||||
until a signing cert is in place.
|
||||
|
||||
## Pending work
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue