Skip to content
Draft
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
30 changes: 30 additions & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,36 @@ jobs:
working-directory: app
run: npm ci

- name: Inject build-time secrets
# Writes app/build-config.js (gitignored) from GitHub Actions
# secrets so electron-builder packages the credentials into the
# asar at build time. Local dev fills its own build-config.js
# from build-config.example.js.
#
# Fail loudly if either secret is missing — without this guard, a
# release built before the secrets were added would silently ship
# with empty OAuth credentials and every user's calendar would
# fail to authenticate.
working-directory: app
env:
GOOGLE_OAUTH_CLIENT_ID: ${{ secrets.GOOGLE_OAUTH_CLIENT_ID }}
GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}
run: |
if [ -z "${GOOGLE_OAUTH_CLIENT_ID}" ] || [ -z "${GOOGLE_OAUTH_CLIENT_SECRET}" ]; then
echo "::error::GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET must be set in repo Settings → Secrets and variables → Actions before releasing." >&2
exit 1
fi
# Generate via node so JSON.stringify handles all escaping (quotes,
# backslashes, unicode) — safer than shell string substitution.
node -e '
const fs = require("fs");
const cfg = {
GOOGLE_OAUTH_CLIENT_ID: process.env.GOOGLE_OAUTH_CLIENT_ID,
GOOGLE_OAUTH_CLIENT_SECRET: process.env.GOOGLE_OAUTH_CLIENT_SECRET,
};
fs.writeFileSync("build-config.js", "module.exports = " + JSON.stringify(cfg, null, 2) + ";\n");
'

- name: Import code signing certificate
uses: apple-actions/import-codesign-certs@v2
with:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ celerybeat.pid
# Environments
.env
.venv
# Build-time OAuth credentials — written by CI from GitHub Actions secrets,
# or by contributors locally from build-config.example.js. Never commit.
app/build-config.js
env/
venv/
ENV/
Expand Down
22 changes: 21 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,27 @@ Thank you for your interest in contributing to StenoAI! This guide will help you
npm start
```

5. **Test the setup**
5. **(Optional) Configure Google Calendar OAuth for local dev**

Calendar integration reads its OAuth credentials from
`app/build-config.js` at startup. CI builds write this file from
GitHub Actions secrets; local builds need your own.

```bash
cd app
cp build-config.example.js build-config.js
```

Then fill in `GOOGLE_OAUTH_CLIENT_ID` and `GOOGLE_OAUTH_CLIENT_SECRET`
from your own Google Cloud project (Create an OAuth 2.0 Client ID of
type **Desktop application** at
https://console.cloud.google.com → APIs & Services → Credentials).

If you skip this step the app launches normally — calendar
integration will surface "calendar not connected" and the rest of
the app (recording, transcription, summarization) works as usual.

6. **Test the setup**
```bash
# Test CLI
python simple_recorder.py --help
Expand Down
22 changes: 22 additions & 0 deletions app/build-config.example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Build-time configuration, read by app/main.js at startup.
//
// Copy this file to `build-config.js` and fill in your own values for
// local development. `build-config.js` is gitignored — never commit it.
//
// CI builds write this file directly from GitHub Actions secrets in
// .github/workflows/build-release.yml; this template is only for local
// dev runs (`npm start` / `npm run start:nobuild`).
//
// If you leave these blank, calendar integration is disabled but the
// rest of the app (recording, transcription, summarization) works
// normally.

module.exports = {
// Google Calendar OAuth credentials. Get your own from
// https://console.cloud.google.com → APIs & Services → Credentials.
// Create an OAuth 2.0 Client ID of type "Desktop application".
// Google treats Desktop-client secrets as public-by-policy; the
// production value is held in the repo's GitHub Actions secrets.
GOOGLE_OAUTH_CLIENT_ID: '',
GOOGLE_OAUTH_CLIENT_SECRET: '',
};
30 changes: 27 additions & 3 deletions app/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ const { PostHog } = require('posthog-node');
const { initMain } = require('electron-audio-loopback');
const { autoUpdater } = require('electron-updater');

// Build-time configuration. `build-config.js` is gitignored and written
// by CI from GitHub Actions secrets before electron-builder runs (see
// .github/workflows/build-release.yml). For local dev, copy
// `build-config.example.js` to `build-config.js` and fill in your own
// Google OAuth credentials — calendar integration is "not connected"
// without it but the rest of the app works.
//
// Plain require + try/catch (rather than dotenv) so we don't ship a
// runtime dependency just to read two constants.
let buildConfig = {};
try {
buildConfig = require('./build-config');
} catch (_) {
// Missing file in local dev → calendar surfaces as "not connected"
// rather than crashing.
}

// E2E test-harness hooks. Set via env vars; production sees none of these.
// STENOAI_USER_DATA_DIR — per-test temp userData dir (must be set before app.whenReady)
// STENOAI_E2E=1 — skip tray, auto-updater, PostHog telemetry
Expand Down Expand Up @@ -356,9 +373,16 @@ let anonymousId = null;
const POSTHOG_API_KEY = 'phc_U2cnTyIyKGNSVaK18FyBMltd8nmN7uHxhhm21fAHwqb';
const POSTHOG_HOST = 'https://us.i.posthog.com';

// Google Calendar OAuth2 configuration
const GOOGLE_CLIENT_ID = '281073275073-20da4u5t9luk2366vd5ai0a2r55d5pf5.apps.googleusercontent.com';
const GOOGLE_CLIENT_SECRET = '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';
// Google Calendar OAuth2 configuration.
//
// Both values come from `build-config.js` (see top of file). Empty
// strings in local dev with no `build-config.js` mean Google auth is
// disabled — the renderer surfaces this as "calendar not connected"
// rather than a crash. Rotate the secret in Google Cloud Console +
// update the `GOOGLE_OAUTH_CLIENT_*` GitHub Actions secrets to roll a
// new credential without a code change.
const GOOGLE_CLIENT_ID = buildConfig.GOOGLE_OAUTH_CLIENT_ID || '';
const GOOGLE_CLIENT_SECRET = buildConfig.GOOGLE_OAUTH_CLIENT_SECRET || '';
const GOOGLE_SCOPES = 'https://www.googleapis.com/auth/calendar.readonly';
const GOOGLE_AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth';
const GOOGLE_TOKEN_URL = 'https://oauth2.googleapis.com/token';
Expand Down
Loading