Skip to content

Commit 6998401

Browse files
committed
Docs: version lineage (1/2/3), release and installer guide; add build_installers workflow
- README: MotionMeerkat 1.0, DeepMeerkat 2.0, Meerkat 3 / 3.0; PyPI + tag release checklist - Optional [packaging] extra for PyInstaller - GHA: matrix PyInstaller GUI builds; attach artifacts to GitHub Release on v* tags Made-with: Cursor
1 parent ffef3b5 commit 6998401

3 files changed

Lines changed: 173 additions & 1 deletion

File tree

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Build PyInstaller GUI bundles (large: includes PyTorch + MegaDetector).
2+
# Runs on version tags and can be run manually from the Actions tab.
3+
4+
name: Build installers
5+
6+
on:
7+
workflow_dispatch:
8+
inputs:
9+
version_label:
10+
description: "Filename prefix (e.g. v3.0.0). Leave empty to read version from pyproject.toml."
11+
required: false
12+
default: ""
13+
push:
14+
tags:
15+
- "v*"
16+
17+
concurrency:
18+
group: build-installers-${{ github.ref }}
19+
cancel-in-progress: true
20+
21+
jobs:
22+
gui:
23+
name: GUI (${{ matrix.os }})
24+
runs-on: ${{ matrix.os }}
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
os: [ubuntu-latest, windows-latest, macos-latest]
29+
30+
steps:
31+
- uses: actions/checkout@v4
32+
33+
- name: Set up Python
34+
uses: actions/setup-python@v5
35+
with:
36+
python-version: "3.12"
37+
38+
- name: Install project and PyInstaller
39+
run: |
40+
python -m pip install --upgrade pip
41+
pip install -e ".[ui]" pyinstaller
42+
43+
- name: Build GUI (one-file)
44+
run: pyinstaller --noconfirm packaging/deepmeerkat-gui.spec
45+
46+
- name: Compute version label
47+
id: label
48+
shell: bash
49+
run: |
50+
if [ "${{ github.ref_type }}" = "tag" ]; then
51+
echo "v=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
52+
elif [ -n "${{ github.event.inputs.version_label }}" ]; then
53+
echo "v=${{ github.event.inputs.version_label }}" >> "$GITHUB_OUTPUT"
54+
else
55+
V=$(python -c "import tomllib; print('v'+tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
56+
echo "v=$V" >> "$GITHUB_OUTPUT"
57+
fi
58+
59+
- name: Stage artifact for upload
60+
shell: bash
61+
run: |
62+
set -euo pipefail
63+
V="${{ steps.label.outputs.v }}"
64+
mkdir -p staging
65+
case "${{ runner.os }}" in
66+
Windows)
67+
cp "dist/deepmeerkat-gui.exe" "staging/DeepMeerkat-${V}-Windows-x64.exe"
68+
;;
69+
macOS)
70+
cp "dist/deepmeerkat-gui" "staging/DeepMeerkat-${V}-macOS"
71+
chmod +x "staging/DeepMeerkat-${V}-macOS"
72+
;;
73+
Linux)
74+
tar -C dist -czvf "staging/DeepMeerkat-${V}-Linux-x64.tar.gz" deepmeerkat-gui
75+
;;
76+
esac
77+
78+
- name: Upload workflow artifact
79+
uses: actions/upload-artifact@v4
80+
with:
81+
name: deepmeerkat-gui-${{ runner.os }}-${{ steps.label.outputs.v }}
82+
path: staging/*
83+
84+
attach-to-release:
85+
name: Attach installers to GitHub Release
86+
needs: [gui]
87+
if: github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/v')
88+
runs-on: ubuntu-latest
89+
permissions:
90+
contents: write
91+
steps:
92+
- uses: actions/download-artifact@v4
93+
with:
94+
path: assets
95+
pattern: deepmeerkat-gui-*
96+
merge-multiple: true
97+
98+
- name: List assets
99+
run: find assets -type f -ls
100+
101+
- name: Upload to release
102+
uses: softprops/action-gh-release@v2
103+
with:
104+
tag_name: ${{ github.ref_name }}
105+
generate_release_notes: true
106+
files: |
107+
assets/**/*
108+
env:
109+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

README.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,21 @@ Desktop and CLI tooling for ecological camera video: **MegaDetector** (default)
66

77
Development uses the **`main`** branch (and CI runs on pushes/PRs to `main`).
88

9+
## Version history (why “3.0”?)
10+
11+
This codebase is released as **DeepMeerkat 3.0** and is the modern “**Meerkat 3**” line:
12+
13+
| Line | What it refers to |
14+
|------|-------------------|
15+
| **1.0** | **MotionMeerkat** — earlier motion-focused tooling in the same research lineage. |
16+
| **2.0** | **DeepMeerkat** — the previous desktop/codebase generation, preserved as Git tag **`v2.0.0`** and branch **`v2.0`**. |
17+
| **3.0** | **DeepMeerkat 3.0** (this repository) — MegaDetector-first PySide6 GUI and CLI, rewritten packaging and outputs. |
18+
19+
We **start numbering releases at 3.0** here so installers and PyPI stay aligned with that story (not with MotionMeerkat or legacy DeepMeerkat release tags).
20+
921
## DeepMeerkat 2.0 (legacy)
1022

11-
The previous **2.x** line is preserved as Git tag **`v2.0.0`** and branch **`v2.0`** (last state before 3.0). Use those if you need the older codebase.
23+
The **2.x** codebase is frozen at Git tag **`v2.0.0`** on branch **`v2.0`**. Use those only if you need the older application.
1224

1325
## Requirements
1426

@@ -43,6 +55,55 @@ deepmeerkat run /path/to/video.mp4 --output ./out --mode motion
4355

4456
Set `DEEPMEERKAT_TEST_VIDEO` to a clip on your machine for manual checks (not used in CI).
4557

58+
## PyPI and GitHub releases (maintainers)
59+
60+
### 1. Version bump
61+
62+
- Set `version` in `pyproject.toml` (for example `3.0.0`).
63+
- Commit on `main`.
64+
65+
### 2. Tag and push
66+
67+
Create an annotated tag (example for **3.0.0**):
68+
69+
```bash
70+
git tag -a v3.0.0 -m "DeepMeerkat 3.0.0"
71+
git push origin v3.0.0
72+
```
73+
74+
Pushing `v*` triggers:
75+
76+
- **`.github/workflows/publish.yml`** — sdist/wheel to **Test PyPI** then **PyPI** (requires repository secrets `TEST_PYPI_TOKEN` and `PYPI_TOKEN`).
77+
- **`.github/workflows/build_installers.yml`** — builds **GUI** PyInstaller bundles on **Linux, Windows, and macOS** and uploads them to the **GitHub Release** for that tag (uses `GITHUB_TOKEN`).
78+
79+
If installer jobs fail (timeouts, size limits, or missing system libs), fix the workflow or build locally (below) and attach assets by hand on the release page.
80+
81+
### 3. GitHub Release assets
82+
83+
After the tag build, the release **v3.0.0** should list downloadable files similar to:
84+
85+
- `DeepMeerkat-v3.0.0-Windows-x64.exe`
86+
- `DeepMeerkat-v3.0.0-macOS` (unsigned binary; see below)
87+
- `DeepMeerkat-v3.0.0-Linux-x64.tar.gz`
88+
89+
Names follow the staging step in `build_installers.yml`.
90+
91+
### 4. Manual installer build (optional)
92+
93+
From the repository root, with the same Python you use for development:
94+
95+
```bash
96+
pip install -e ".[ui]" pyinstaller
97+
# or: pip install -e ".[ui,packaging]"
98+
pyinstaller --noconfirm packaging/deepmeerkat-gui.spec
99+
```
100+
101+
Outputs live under **`dist/`** (`deepmeerkat-gui` or `deepmeerkat-gui.exe`). A **CLI** one-file build is available via `packaging/deepmeerkat-cli.spec` (also large, includes PyTorch).
102+
103+
**macOS distribution:** CI produces a raw binary, not a signed **`.app`** or **`.dmg`**. For public distribution outside the lab, plan for **codesigning** and optionally **notarization** (Apple Developer Program), or ship via **pip** / conda instead.
104+
105+
**Linux:** The tarball contains a single executable built on a recent glibc (GitHub’s `ubuntu-latest`). Very old distributions may need a build on that target or a **pip** install.
106+
46107
## License
47108

48109
See `LICENSE`. Third-party models (MegaDetector) have their own terms; see the MegaDetector project documentation.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ dev = [
2424
"pytest>=8.0",
2525
"ruff>=0.4",
2626
]
27+
# Local PyInstaller builds (see README — bundles are large).
28+
packaging = ["pyinstaller>=6.0"]
2729

2830
[project.scripts]
2931
deepmeerkat = "deepmeerkat.cli:app"

0 commit comments

Comments
 (0)