diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml new file mode 100644 index 0000000..9f4dad0 --- /dev/null +++ b/.github/workflows/release-build.yml @@ -0,0 +1,55 @@ +name: Build & Release (PyInstaller) +on: + push: + tags: [ "v*.*.*" ] + workflow_dispatch: +jobs: + build: + strategy: + matrix: { os: [windows-latest, macos-latest, ubuntu-latest] } + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: { python-version: "3.11" } + - name: Install deps + run: | + python -m pip install --upgrade pip + if [ -f requirements_app.txt ]; then pip install -r requirements_app.txt; fi + pip install pyinstaller pillow pystray + - name: Build (PyInstaller) + run: pyinstaller packaging/app.spec --noconfirm + shell: bash + - name: Package artifacts + run: | + mkdir -p upload + if [ "${{ matrix.os }}" = "windows-latest" ]; then + 7z a upload/BongoCatMonitor-Windows.zip ./dist/BongoCatMonitor/* >/dev/null + elif [ "${{ matrix.os }}" = "macos-latest" ]; then + if [ -d dist/BongoCatMonitor.app ]; then + ditto -c -k --sequesterRsrc --keepParent dist/BongoCatMonitor.app upload/BongoCatMonitor-macOS.zip + fi + else + if [ -f dist/BongoCatMonitor ]; then + tar czf upload/BongoCatMonitor-Linux.tar.gz -C dist BongoCatMonitor + fi + fi + shell: bash + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.os }}-artifacts + path: upload/* + release: + needs: build + runs-on: ubuntu-latest + permissions: { contents: write } + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: { path: dist } + - uses: softprops/action-gh-release@v2 + with: + files: | + dist/**/BongoCatMonitor-*.zip + dist/**/BongoCatMonitor-*.tar.gz + generate_release_notes: true diff --git a/.github/workflows/test-protocol.yml b/.github/workflows/test-protocol.yml index 1bf6cc2..b3f0a50 100644 --- a/.github/workflows/test-protocol.yml +++ b/.github/workflows/test-protocol.yml @@ -1,27 +1,18 @@ name: Protocol tests - -on: - push: - pull_request: - +on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: "3.11" - - name: Install deps run: | python -m pip install --upgrade pip pip install pyserial pytest - - - name: Run protocol tests + - name: Run tests env: PYTHONPATH: ${{ github.workspace }} run: pytest -q tests/test_serial_proto_sim.py diff --git a/bongo_cat_app/__init__.py b/bongo_cat_app/__init__.py new file mode 100644 index 0000000..a9a2c5b --- /dev/null +++ b/bongo_cat_app/__init__.py @@ -0,0 +1 @@ +__all__ = [] diff --git a/packaging/app.spec b/packaging/app.spec new file mode 100644 index 0000000..2e26195 --- /dev/null +++ b/packaging/app.spec @@ -0,0 +1,27 @@ +import sys +from PyInstaller.utils.hooks import collect_submodules + +hidden = [] +hidden += collect_submodules('pystray') +hidden += collect_submodules('PIL') + +a = Analysis( + ['bongo_cat_app/main.py'], + pathex=['bongo_cat_app'], + binaries=[], + datas=[ + ('bongo_cat_app/assets', 'assets'), + ], + hiddenimports=hidden, + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) + +exe = EXE( + a.pure, a.scripts, a.binaries, a.zipfiles, a.datas, + name='BongoCatMonitor', + console=False, +) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c95b18d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,23 @@ +[build-system] +requires = ["setuptools>=68", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "bongo-cat-monitor" +version = "2.0.0" +description = "Bongo Cat Monitor - Python desktop app" +readme = "README.md" +requires-python = ">=3.9" +authors = [{ name = "Your Name" }] +license = { text = "MIT" } +dependencies = [ + "Pillow>=10.0", + "pystray>=0.19", +] + +[tool.setuptools] +packages = ["bongo_cat_app"] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "-q" diff --git a/tools/consolidate.sh b/tools/consolidate.sh new file mode 100755 index 0000000..7edd228 --- /dev/null +++ b/tools/consolidate.sh @@ -0,0 +1,192 @@ +#!/usr/bin/env bash +set -euo pipefail + +BRANCH="chore/consolidate-python-root" +ROOT="$(pwd)" + +echo "==> creating branch $BRANCH" +git fetch origin --prune +git checkout -b "$BRANCH" || git checkout "$BRANCH" + +# 1) Ensure package marker +if [ ! -f bongo_cat_app/__init__.py ]; then + echo "==> adding bongo_cat_app/__init__.py" + mkdir -p bongo_cat_app + printf "__all__ = []\n" > bongo_cat_app/__init__.py +fi + +# 2) pyproject.toml (backup if exists) +if [ -f pyproject.toml ]; then cp pyproject.toml pyproject.toml.bak; fi +cat > pyproject.toml <<'PYT' +[build-system] +requires = ["setuptools>=68", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "bongo-cat-monitor" +version = "2.0.0" +description = "Bongo Cat Monitor - Python desktop app" +readme = "README.md" +requires-python = ">=3.9" +authors = [{ name = "Your Name" }] +license = { text = "MIT" } +dependencies = [ + "Pillow>=10.0", + "pystray>=0.19", +] + +[tool.setuptools] +packages = ["bongo_cat_app"] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "-q" +PYT + +# 3) PyInstaller spec +mkdir -p packaging +cat > packaging/app.spec <<'SPEC' +import sys +from PyInstaller.utils.hooks import collect_submodules + +hidden = [] +hidden += collect_submodules('pystray') +hidden += collect_submodules('PIL') + +a = Analysis( + ['bongo_cat_app/main.py'], + pathex=['bongo_cat_app'], + binaries=[], + datas=[ + ('bongo_cat_app/assets', 'assets'), + ], + hiddenimports=hidden, + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) + +exe = EXE( + a.pure, a.scripts, a.binaries, a.zipfiles, a.datas, + name='BongoCatMonitor', + console=False, +) +SPEC + +# 4) Workflows +mkdir -p .github/workflows + +cat > .github/workflows/test-protocol.yml <<'Y1' +name: Protocol tests +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install deps + run: | + python -m pip install --upgrade pip + pip install pyserial pytest + - name: Run tests + env: + PYTHONPATH: ${{ github.workspace }} + run: pytest -q tests/test_serial_proto_sim.py +Y1 + +cat > .github/workflows/release-build.yml <<'Y2' +name: Build & Release (PyInstaller) +on: + push: + tags: [ "v*.*.*" ] + workflow_dispatch: +jobs: + build: + strategy: + matrix: { os: [windows-latest, macos-latest, ubuntu-latest] } + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: { python-version: "3.11" } + - name: Install deps + run: | + python -m pip install --upgrade pip + if [ -f requirements_app.txt ]; then pip install -r requirements_app.txt; fi + pip install pyinstaller pillow pystray + - name: Build (PyInstaller) + run: pyinstaller packaging/app.spec --noconfirm + shell: bash + - name: Package artifacts + run: | + mkdir -p upload + if [ "${{ matrix.os }}" = "windows-latest" ]; then + 7z a upload/BongoCatMonitor-Windows.zip ./dist/BongoCatMonitor/* >/dev/null + elif [ "${{ matrix.os }}" = "macos-latest" ]; then + if [ -d dist/BongoCatMonitor.app ]; then + ditto -c -k --sequesterRsrc --keepParent dist/BongoCatMonitor.app upload/BongoCatMonitor-macOS.zip + fi + else + if [ -f dist/BongoCatMonitor ]; then + tar czf upload/BongoCatMonitor-Linux.tar.gz -C dist BongoCatMonitor + fi + fi + shell: bash + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.os }}-artifacts + path: upload/* + release: + needs: build + runs-on: ubuntu-latest + permissions: { contents: write } + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: { path: dist } + - uses: softprops/action-gh-release@v2 + with: + files: | + dist/**/BongoCatMonitor-*.zip + dist/**/BongoCatMonitor-*.tar.gz + generate_release_notes: true +Y2 + +# 5) README nudge (non-destructive): show where to edit +echo +echo "==> Search for stale README references to 'app/' or 'cd app'" +git grep -nE '\bapp/|cd app\b' || true +echo " (Open README.md and update to use 'bongo_cat_app/' and the run commands.)" + +# Remind about resource_path helper presence +if ! grep -Rqs "def resource_path" bongo_cat_app 2>/dev/null; then + cat < Heads-up: +Add this helper where you load icons (e.g., bongo_cat_app/tray.py): + +import os, sys +def resource_path(rel_path: str) -> str: + base = getattr(sys, "_MEIPASS", os.path.abspath(os.path.dirname(__file__))) + return os.path.join(base, rel_path) + +And then use: resource_path(os.path.join("assets", "tray_icon.png")) + +NOTE +fi + +# 6) Commit & push +git add -A +git commit -m "chore: canonicalize Python app to bongo_cat_app; update CI/packaging; add pyproject.toml" +git push -u origin "$BRANCH" + +echo +echo "==> Open PR:" +REPO_URL="$(git config --get remote.origin.url | sed -E 's/\.git$//')" +REPO_URL="${REPO_URL/git@github.com:/https://github.com/}" +echo " $REPO_URL/compare/master...$BRANCH"