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
19 changes: 15 additions & 4 deletions .github/workflows/desktop-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,29 @@
# When it runs:
# - an official release is published (v1.13.0, …) → build both, smoke-test
# them, attach the .dmg and the Setup.exe to that release;
# - a development build is tagged (dev-build.yml calls this with its tag) →
# the same, attached to that pre-release, for app users who opted into
# development builds (the app's update check only offers a build once its
# files are attached);
# - by hand (Actions → Desktop app → Run workflow) → build both, keep them as
# downloadable workflow artifacts;
# - a pull request that touches the packaging → build and smoke-test, so a
# broken build is found before the release that needs it.
# Not on every merge: development builds are hundreds of MB each, and the
# dev-build workflow tags with GITHUB_TOKEN, which starts no other workflow.
# The dev-build workflow is a caller rather than a trigger because it tags with
# GITHUB_TOKEN, whose releases start no other workflow.

name: Desktop app

on:
release:
types: [published]
workflow_dispatch:
workflow_call:
inputs:
tag:
description: The development build's tag, to attach the apps to
required: true
type: string
pull_request:
paths:
- "packaging/**"
Expand Down Expand Up @@ -156,7 +166,8 @@ jobs:
retention-days: 14

- name: Attach to the release
if: github.event_name == 'release'
if: github.event_name == 'release' || inputs.tag != ''
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload "${{ github.event.release.tag_name }}" "$ASSET" --clobber
TAG: ${{ inputs.tag || github.event.release.tag_name }}
run: gh release upload "$TAG" "$ASSET" --clobber
49 changes: 43 additions & 6 deletions .github/workflows/dev-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@ on:
permissions:
contents: write

concurrency:
# One at a time, in order: two merges in quick succession must not race for
# the same number.
group: dev-build
cancel-in-progress: false

jobs:
tag:
runs-on: ubuntu-latest
concurrency:
# One at a time, in order: two merges in quick succession must not race
# for the same number. (The tagging only: the app builds below take ~20
# minutes and need not hold up the next merge's tag.)
group: dev-build
cancel-in-progress: false
outputs:
tag: ${{ steps.name.outputs.tag }}
skip: ${{ steps.name.outputs.skip }}
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -80,3 +83,37 @@ jobs:
--generate-notes \
--notes-start-tag "$PREV" \
--notes "Automatic development build of main since $BASE. Not an official release: it has not been through release testing, and its changes are listed below as pull requests rather than written up. Official releases are the ones marked Latest."

# The desktop apps, for app users who opted into development builds.
apps:
needs: tag
if: needs.tag.outputs.skip == 'false'
uses: ./.github/workflows/desktop-app.yml
with:
tag: ${{ needs.tag.outputs.tag }}

prune-apps:
# Each build's apps are ~500 MB, one set per merge. Only the newest are
# ever offered to update to, so older development builds lose theirs (the
# tag, notes and source stay). Official releases are never touched.
needs: apps
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ github.token }}
KEEP: 5
steps:
- name: Remove the apps of older development builds
run: |
set -euo pipefail
gh release list -R "$GITHUB_REPOSITORY" --limit 100 \
--json tagName,isPrerelease,createdAt \
--jq '[.[] | select(.isPrerelease and (.tagName | test("-dev\\.[0-9]+$")))]
| sort_by(.createdAt) | reverse | .[env.KEEP | tonumber:] | .[].tagName' |
while read -r tag; do
gh release view "$tag" -R "$GITHUB_REPOSITORY" --json assets \
--jq '.assets[].name | select(startswith("MEA-NAP-"))' |
while read -r name; do
echo "$tag: removing $name"
gh release delete-asset "$tag" "$name" -R "$GITHUB_REPOSITORY" --yes
done
done
23 changes: 17 additions & 6 deletions docs/python/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ what makes it safe to click through.
need administrator rights. Tick **Create a desktop shortcut** if you want one.
4. Start MEA-NAP from the Start menu (or the desktop shortcut).

To update, download the newer installer and run it: it replaces the old
version and keeps your settings. To uninstall: **Settings → Apps → Installed
To update, use **Update** in MEA-NAP itself (see [Updates](#good-to-know)
below), or download the newer installer and run it: either way it replaces
the old version and keeps your settings. To uninstall: **Settings → Apps → Installed
apps → MEA-NAP → Uninstall**.

### Installing on a Mac
Expand All @@ -79,8 +80,10 @@ apps → MEA-NAP → Uninstall**.
again.
4. From then on MEA-NAP opens normally.

To update, download the newer `.dmg` and drag MEA-NAP into Applications
again, replacing the old one. To uninstall, drag MEA-NAP from Applications to
To update, use **Update** in MEA-NAP itself (see [Updates](#good-to-know)
below; this needs MEA-NAP to be in Applications), or download the newer
`.dmg` and drag MEA-NAP into Applications again, replacing the old one. To
uninstall, drag MEA-NAP from Applications to
the Bin.

If macOS instead says MEA-NAP **"is damaged and can't be opened"**, the
Expand All @@ -100,8 +103,16 @@ time. On Windows, antivirus software may also scan the app the first time it
starts, so the window can take a minute to appear.

**Updates.** The version number in the toolbar, beside the **Mode**
selector, shows **⬆ update** when a newer release is out. Click it, then
**Download**.
selector, shows **⬆ update** when a newer version is out. Click it, then
**Update to …**: MEA-NAP downloads the new version, closes, installs it and
opens again, about a minute in all, with no browser and none of the warnings
above. Your settings and results are kept. (Version 1.13.0 doesn't have this
button yet: update from it once by downloading, as above.)

Tick **Also offer development builds** in the same window to get every fix as
soon as it is made (usually within half an hour), rather than waiting for the
next official release. These haven't been through release testing; untick
the box to go back to official releases from the next one on.

**What the app doesn't include.** Running MATLAB or switching between
MEA-NAP versions from inside the GUI, CAT-NAP's cell tracking across days
Expand Down
9 changes: 9 additions & 0 deletions packaging/windows/meanap.iss
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,12 @@ Name: "{autodesktop}\MEA-NAP"; Filename: "{app}\MEA-NAP.exe"; Tasks: desktopicon

[Run]
Filename: "{app}\MEA-NAP.exe"; Description: "{cm:LaunchProgram,MEA-NAP}"; Flags: nowait postinstall skipifsilent
; The app updating itself runs this installer with /SILENT /RELAUNCH=1
; (meanap.app_update), and the tick box above is skipped when silent.
Filename: "{app}\MEA-NAP.exe"; Flags: nowait runasoriginaluser; Check: RelaunchAfterUpdate

[Code]
function RelaunchAfterUpdate: Boolean;
begin
Result := WizardSilent and (ExpandConstant('{param:relaunch|0}') = '1');
end;
7 changes: 6 additions & 1 deletion python/DESKTOP_APP_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ it, and gets the MEA-NAP GUI. Today's route — git clone, `uv sync`,
| Left out | CAT-NAP **cell tracking** (needs `roicat` → PyTorch, not a declared dependency); **Kilosort**; **launching MATLAB / old MATLAB-only releases**; switching between versions in place. |
| Distribution | `.dmg` (macOS) and a setup `.exe` (Windows, Inno Setup), built by GitHub Actions on each **official** release tag (and on demand) and attached to the GitHub release. Not on every dev build: hundreds of MB per merge. |
| Download links | Asset names carry **no version** (`MEA-NAP-Windows-x64-Setup.exe`, `MEA-NAP-macOS-AppleSilicon.dmg`, `MEA-NAP-macOS-Intel.dmg`) so the install page can link to `releases/latest/download/<name>`, one click, always the newest. README → the docs site's install page (MyST doesn't render on GitHub). |
| Updates | The app checks GitHub's releases (public repo, no git, no login) and offers a link to download the newer one. |
| Updates | The app checks GitHub's releases (public repo, no git, no login) and **updates itself in place** (1.14.0, `meanap.app_update`): downloads this computer's file (size + SHA-256 checked), quits, and the Windows installer (`/SILENT /RELAUNCH=1`) or a macOS shell script swaps it in and reopens it. Fetched by the app, not a browser, so no Chrome / Gatekeeper warnings. Falls back to the download page when it can't (Mac app not in Applications / translocated / folder not writable; files not built yet). The next start reports success or failure (`pending-update.json`). |
| Update channels | Official releases by default; a tick box **"Also offer development builds"** adds the per-merge pre-releases. `dev-build.yml` calls `desktop-app.yml` (`workflow_call`) to attach apps to each one (~20 min after the merge; a build is only offered once its file is there), and prunes the apps of all but the newest 5 dev builds. |

## What has to change in the code

Expand Down Expand Up @@ -88,6 +89,10 @@ the package and, on Windows, no console. Each of these breaks something today:
- Source-only extensions (isosplit6; OASIS on Intel) are compiled in CI with
`MACOSX_DEPLOYMENT_TARGET=12.0`, or they'd only load on the runner's macOS.
- No macOS/Windows machine locally: real-device testing depends on the user.
- **Self-update untested on real machines.** The macOS script is tested on
Linux with stand-ins for hdiutil/ditto/open; the Windows silent install not
at all. First real test: install 1.14.0 by hand, tick development builds,
update to the next dev build. Users on 1.13.0 must download once by hand.

## Status

Expand Down
Loading
Loading