Compare commits

...
Author SHA1 Message Date
Jon Saad-FalconandClaude Opus 4.8 e7c46c1985 fix(frontend): make Supabase anon key optional to unblock PyPI publishing (#589)
PyPI publishing had been broken since v1.0.3.dev851: #587 made VITE_SUPABASE_ANON_KEY a hard build-time requirement, but no such secret exists, so the frontend build aborted every publish run before the PyPI upload. Decouple package buildability from the leaderboard credential: a missing anon key now disables the savings leaderboard at runtime instead of failing the build, and auto-enables when the secret is provided. Verified: npm run build with the key unset succeeds; tsc + vitest pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 13:15:06 -07:00
github-actions[bot] 00d1e39b6d chore: update clone traffic data [skip ci] 2026-06-24 07:14:44 +00:00
Elliot SluskyandClaude Opus 4.8 843375d6ef Fix Supabase frontend build env for release builds (#588)
Follow-up to #587. Pass VITE_SUPABASE_ANON_KEY into the frontend builds of both release paths: the PyPI publish workflow (wheel-bundled frontend) and the desktop tauri-action build (npm run build:tauri -> vite build). Kept strict: a missing/empty secret fails the release by design rather than shipping a placeholder key. Requires the VITE_SUPABASE_ANON_KEY repo secret to be set for releases to succeed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:32:13 -07:00
8 changed files with 31 additions and 25 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"label": "Git Clones",
"message": "129,427",
"message": "130,895",
"color": "green",
"namedLogo": "git"
}
+4 -3
View File
@@ -1,6 +1,6 @@
{
"total_clones": 129427,
"last_updated": "2026-06-23T07:18:12Z",
"total_clones": 130895,
"last_updated": "2026-06-24T07:14:43Z",
"daily": {
"2026-03-27": 2189,
"2026-03-28": 1874,
@@ -89,6 +89,7 @@
"2026-06-19": 1350,
"2026-06-20": 1437,
"2026-06-21": 1426,
"2026-06-22": 1350
"2026-06-22": 1350,
"2026-06-23": 1468
}
}
+4
View File
@@ -254,6 +254,10 @@ jobs:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
TAURI_CONFIG: '{"version":"${{ steps.release-info.outputs.tauri_version }}","bundle":{"externalBin":["binaries/ollama"]}}'
# tauri-action runs beforeBuildCommand (npm run build:tauri -> vite
# build), which requires this at build time (#587). Strict for
# releases: a missing/empty secret fails the build by design.
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
with:
projectPath: frontend
tauriScript: npx tauri
+4 -5
View File
@@ -36,8 +36,7 @@ jobs:
- run: npx tsc --noEmit
- run: npm run build
env:
# vite.config/supabase.ts require this at build time. The real value
# comes from the repo secret; CI falls back to a placeholder so the
# build check passes (the leaderboard is not exercised in CI builds).
# Release/docs builds MUST set the secret to the real anon key.
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY || 'ci-placeholder-anon-key' }}
# Optional: when the secret is unset the build still succeeds and the
# leaderboard is disabled (see src/lib/supabase.ts). No placeholder,
# so a keyless CI build doesn't bake in a bogus anon key.
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
+2
View File
@@ -55,6 +55,8 @@ jobs:
cache-dependency-path: frontend/package-lock.json
- name: Build frontend and bundle into package
env:
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
run: |
set -euo pipefail
cd frontend
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback } from 'react';
import type React from 'react';
import { invoke } from '@tauri-apps/api/core';
import { SUPABASE_ANON_KEY, SUPABASE_URL } from '../../lib/supabase';
import { LEADERBOARD_ENABLED, SUPABASE_ANON_KEY, SUPABASE_URL } from '../../lib/supabase';
// ---------------------------------------------------------------------------
// Types
@@ -316,9 +316,10 @@ export function SavingsDashboard({ apiUrl }: { apiUrl: string }) {
return () => clearInterval(timer);
}, [fetchData]);
// Share savings to Supabase when opted in and data changes
// Share savings to Supabase when opted in and data changes. Skipped entirely
// when no anon key was built in (leaderboard disabled).
useEffect(() => {
if (!optInEnabled || !displayName || !data) return;
if (!LEADERBOARD_ENABLED || !optInEnabled || !displayName || !data) return;
const dollarSavings = data.per_provider.reduce((s, p) => s + p.total_cost, 0);
const energySaved = data.per_provider.reduce((s, p) => s + (p.energy_wh || 0), 0);
const flopsSaved = data.per_provider.reduce((s, p) => s + (p.flops || 0), 0);
+7 -4
View File
@@ -1,8 +1,11 @@
export const SUPABASE_URL =
import.meta.env.VITE_SUPABASE_URL || 'https://mtbtgpwzrbostweaanpr.supabase.co';
export const SUPABASE_ANON_KEY = import.meta.env.VITE_SUPABASE_ANON_KEY;
// The Supabase anon key is optional at build time. When it is unset the public
// savings leaderboard is disabled rather than failing the build — this keeps
// the `openjarvis` package and desktop app buildable without coupling
// publishability to a leaderboard credential. Set VITE_SUPABASE_ANON_KEY at
// build time (from a repo secret) to enable the leaderboard.
export const SUPABASE_ANON_KEY = import.meta.env.VITE_SUPABASE_ANON_KEY ?? '';
if (!SUPABASE_ANON_KEY) {
throw new Error('VITE_SUPABASE_ANON_KEY is required');
}
export const LEADERBOARD_ENABLED = SUPABASE_ANON_KEY.length > 0;
+5 -9
View File
@@ -1,16 +1,13 @@
import path from 'path';
import { defineConfig, loadEnv } from 'vite';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, __dirname, '');
if (command === 'build' && !env.VITE_SUPABASE_ANON_KEY) {
throw new Error('VITE_SUPABASE_ANON_KEY is required');
}
return {
// VITE_SUPABASE_ANON_KEY is intentionally NOT required here: a missing key
// disables the savings leaderboard at runtime (see src/lib/supabase.ts) rather
// than failing the build, so the package/app stays publishable without it.
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
@@ -62,5 +59,4 @@ export default defineConfig(({ command, mode }) => {
'/api': process.env.VITE_API_URL || 'http://localhost:8000',
},
},
};
});