Skip to content
Merged
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
51 changes: 51 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Release

# Manual-only CD: build the macOS DMG and publish it as a GitHub release.
on:
workflow_dispatch:
inputs:
tag:
description: "Release tag (default: v<version> from app/package.json)"
required: false
default: ""

permissions:
contents: write # create releases + upload assets

jobs:
release:
runs-on: macos-latest # electron-builder needs macOS to produce a .dmg
defaults:
run:
working-directory: app
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: app/package-lock.json
- run: npm ci
- name: Build DMG (ad-hoc signed)
env:
CSC_IDENTITY_AUTO_DISCOVERY: "false" # no signing identity; match local ad-hoc build
run: npm run package
- name: Resolve release tag
id: meta
env:
INPUT_TAG: ${{ inputs.tag }}
run: |
VERSION=$(node -p "require('./package.json').version")
TAG="${INPUT_TAG:-v$VERSION}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Publish release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.meta.outputs.tag }}
run: |
NOTES="Automated release. macOS DMG is ad-hoc signed — on first launch, right-click the app → Open to bypass Gatekeeper."
if gh release view "$TAG" >/dev/null 2>&1; then
gh release upload "$TAG" dist/*.dmg --clobber
else
gh release create "$TAG" --target "$GITHUB_SHA" --title "Fish Notes $TAG" --notes "$NOTES" dist/*.dmg
fi
2 changes: 1 addition & 1 deletion app/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const createWindow = (token: string): void => {
// electron-vite emits the preload as .mjs (ESM); an ESM preload needs sandbox off.
preload: join(__dirname, '../preload/preload.mjs'),
sandbox: false,
additionalArguments: [`--engine-token=${token}`, `--engine-port=${PORT}`]
additionalArguments: [`--engine-token=${token}`, `--engine-port=${PORT}`, `--app-version=${app.getVersion()}`]
}
})
mainWindow = win
Expand Down
3 changes: 3 additions & 0 deletions app/electron/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ contextBridge.exposeInMainWorld('engine', {
token: arg('engine-token')
})

// App version (from package.json via app.getVersion() in main), shown in the sidebar.
contextBridge.exposeInMainWorld('appInfo', { version: arg('app-version') })

// Native screen-region capture (main runs macOS `screencapture`).
contextBridge.exposeInMainWorld('capture', {
region: () => ipcRenderer.invoke('capture-region'),
Expand Down
4 changes: 4 additions & 0 deletions app/renderer/canvas-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ export const CanvasList = (): React.ReactElement => {
<ListItemText primary="Settings" sx={{ ml: 1.5 }} />
</ListItemButton>

<Typography variant="caption" sx={{ textAlign: 'center', opacity: 0.4, mt: 0.5 }}>
v{window.appInfo.version}
</Typography>

<SettingsDialog open={settingsOpen} onClose={() => setSettingsOpen(false)} />

<Popover
Expand Down
1 change: 1 addition & 0 deletions app/renderer/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class ErrorBoundary extends React.Component<{ children: React.ReactNode }, { err
declare global {
interface Window {
engine: { baseUrl: string; token: string }
appInfo: { version: string }
capture: {
region: () => Promise<{ cancelled?: boolean; pngBase64?: string; error?: string; appName?: string; url?: string; windowTitle?: string }>
saveImage: (dataUrl: string, name: string) => Promise<{ saved?: boolean; path?: string; cancelled?: boolean }>
Expand Down
Loading