Skip to content

Commit beedab3

Browse files
Release v1.1.12 with usage-meter pace fix and auto-release workflow
- Home.tsx: replace ambiguous "X% ahead of pace" with end-of-window projection ("35% headroom" / "caps in 27m" / "at limit"); suppress pace readout below 10 min elapsed or 0.5% used to kill rate-noise. - .github/workflows/auto-release.yml: when tauri.conf.json's version changes on main, create a GitHub release with tag v<version>. release.yml then builds, signs, and uploads the updater artifacts so the in-app UpdateChecker surfaces the update within 30 min. Idempotent via gh release view; manual workflow_dispatch supported. - tauri.conf.json: bump to 1.1.12. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 02e4760 commit beedab3

3 files changed

Lines changed: 107 additions & 15 deletions

File tree

.github/workflows/auto-release.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: Auto-publish release
2+
3+
# When tauri.conf.json's version changes on main, create a GitHub release
4+
# with tag v<version>. That `release: created` event triggers release.yml,
5+
# which builds and uploads the signed updater artifacts. The in-app
6+
# UpdateChecker (polls every 30 min) then surfaces the update to users.
7+
#
8+
# Idempotent: if a release with that tag already exists, this no-ops.
9+
10+
on:
11+
push:
12+
branches: [main]
13+
paths:
14+
- "apps/desktop/src-tauri/tauri.conf.json"
15+
workflow_dispatch:
16+
17+
permissions:
18+
contents: write
19+
20+
concurrency:
21+
group: auto-release-${{ github.ref }}
22+
cancel-in-progress: false
23+
24+
jobs:
25+
publish:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@v6
29+
with:
30+
fetch-depth: 0
31+
32+
- name: Read version from tauri.conf.json
33+
id: ver
34+
run: |
35+
set -euo pipefail
36+
VERSION=$(jq -r '.version' apps/desktop/src-tauri/tauri.conf.json)
37+
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
38+
echo "::error::No version field in apps/desktop/src-tauri/tauri.conf.json"
39+
exit 1
40+
fi
41+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
42+
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
43+
44+
- name: Check if release already exists
45+
id: check
46+
env:
47+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48+
run: |
49+
set -euo pipefail
50+
if gh release view "${{ steps.ver.outputs.tag }}" \
51+
--repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
52+
echo "exists=true" >> "$GITHUB_OUTPUT"
53+
echo "Release ${{ steps.ver.outputs.tag }} already exists — skipping."
54+
else
55+
echo "exists=false" >> "$GITHUB_OUTPUT"
56+
fi
57+
58+
- name: Create GitHub release
59+
if: steps.check.outputs.exists != 'true'
60+
env:
61+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
62+
run: |
63+
set -euo pipefail
64+
gh release create "${{ steps.ver.outputs.tag }}" \
65+
--repo "$GITHUB_REPOSITORY" \
66+
--target "$GITHUB_SHA" \
67+
--title "CodeVetter ${{ steps.ver.outputs.tag }}" \
68+
--generate-notes

apps/desktop/src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-utils/schema.json",
33
"identifier": "com.codevetter.desktop",
44
"productName": "CodeVetter",
5-
"version": "1.1.11",
5+
"version": "1.1.12",
66
"build": {
77
"beforeDevCommand": "npm run dev",
88
"beforeBuildCommand": "npm run build",

apps/desktop/src/pages/Home.tsx

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,47 @@ function UsageBar({
9494
};
9595
const c = colorMap[color];
9696

97-
// Reserve / deplete calculation
98-
// on-track % = (elapsed / total) * 100 — if actual < on-track → in reserve
97+
// Pace projection: at the current burn rate, where does usage land when
98+
// the window resets? Replaces a confusing "X% ahead of pace" readout —
99+
// that delta only made sense if you mentally extrapolated. Show projected
100+
// end-of-window headroom when safe, and a concrete countdown when on
101+
// track to hit the cap.
99102
let paceLabel: string | null = null;
100103
let paceColor = "text-slate-500";
101-
if (windowTotalSecs && resetsInSecs != null && resetsInSecs > 0) {
104+
if (
105+
windowTotalSecs &&
106+
windowTotalSecs > 0 &&
107+
resetsInSecs != null &&
108+
resetsInSecs > 0 &&
109+
resetsInSecs <= windowTotalSecs
110+
) {
102111
const elapsed = windowTotalSecs - resetsInSecs;
103-
const onTrackPct = (elapsed / windowTotalSecs) * 100;
104-
const delta = Math.abs(onTrackPct - pct);
105-
if (pct < onTrackPct - 0.5) {
106-
paceLabel = `${Math.round(delta)}% in reserve`;
107-
paceColor = "text-emerald-400/80";
108-
} else if (pct > onTrackPct + 0.5) {
109-
paceLabel = `${Math.round(delta)}% ahead of pace`;
110-
paceColor = "text-[#ff725f]/90";
111-
} else {
112-
paceLabel = "on pace";
113-
paceColor = "text-slate-500";
112+
// Suppress until ≥10 min elapsed AND ≥0.5% used — rate is noisy below
113+
// that and used to flicker between "ahead/behind pace" states.
114+
if (elapsed >= 10 * 60 && pct >= 0.5) {
115+
const projectedEndPct = pct * (windowTotalSecs / elapsed);
116+
if (projectedEndPct >= 100) {
117+
// Burn rate projects to hit the cap. When?
118+
// rate = pct/elapsed per second → secs to reach 100% = (100-pct)/rate
119+
const secsToCap = ((100 - pct) * elapsed) / pct;
120+
if (secsToCap <= 0) {
121+
paceLabel = "at limit";
122+
paceColor = "text-[#ff725f]";
123+
} else if (secsToCap < resetsInSecs) {
124+
paceLabel = `caps in ${formatDuration(secsToCap)}`;
125+
paceColor = "text-[#ff725f]/90";
126+
} else {
127+
// Tipped just over but slow enough to coast to reset
128+
paceLabel = "on pace";
129+
paceColor = "text-slate-500";
130+
}
131+
} else if (projectedEndPct >= 95) {
132+
paceLabel = "on pace";
133+
paceColor = "text-slate-500";
134+
} else {
135+
paceLabel = `${Math.round(100 - projectedEndPct)}% headroom`;
136+
paceColor = "text-emerald-400/80";
137+
}
114138
}
115139
}
116140

0 commit comments

Comments
 (0)