Skip to content
Closed
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
49 changes: 40 additions & 9 deletions .github/workflows/deploy-dmg.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,59 @@
name: Build macOS .dmg
name: Deploy macOS .dmg

on:
workflow_call:
workflow_dispatch:
pull_request:

jobs:
build-macos-dmg:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install py2app
run: pip install py2app
python-version: '3.10'

- name: Install tomli for version extraction
run: python -m pip install tomli

- name: Extract version from pyproject.toml
id: get_version
run: |
VERSION=$(python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Building version: $VERSION"

- name: Create virtual environment
run: python -m venv .venv

- name: Install dependencies and package
run: |
source .venv/bin/activate
pip install -U pip wheel setuptools
pip install py2app
# Install PyTorch CPU version (lighter for macOS)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
# Install other dependencies
pip install clip-anytorch numpy scikit-learn pillow
# Install your package
pip install .

- name: Build .app bundle
run: |
source .venv/bin/activate
cd macos
python setup.py py2app
- name: Create .dmg

- name: Create .dmg with version
run: |
hdiutil create -volname "PhotoMapAI" -srcfolder macos/dist/PhotoMapAI.app -ov -format UDZO PhotoMapAI.dmg
DMG_NAME="PhotoMapAI-v${{ steps.get_version.outputs.version }}.dmg"
hdiutil create -volname "PhotoMapAI" -srcfolder macos/dist/PhotoMapAI.app -ov -format UDZO "$DMG_NAME"

- name: Upload .dmg
uses: actions/upload-artifact@v4
with:
name: PhotoMapAI.dmg
path: PhotoMapAI.dmg

name: PhotoMapAI-v${{ steps.get_version.outputs.version }}
path: PhotoMapAI-v${{ steps.get_version.outputs.version }}.dmg
70 changes: 46 additions & 24 deletions .github/workflows/deploy-pyinstaller.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ name: Deploy PyInstaller Executables
on:
workflow_call:
workflow_dispatch:
pull_request:

jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
torch_variant: [cpu, cu128]
torch_variant: [cpu, cu129]
include:
- os: ubuntu-latest
platform: linux-x64
Expand All @@ -25,7 +26,7 @@ jobs:
executable_ext: ".exe"
exclude:
- os: macos-latest
torch_variant: cu128
torch_variant: cu129
runs-on: ${{ matrix.os }}

steps:
Expand All @@ -37,6 +38,25 @@ jobs:
with:
python-version: '3.12'

- name: Free up disk space (Linux/macOS)
if: matrix.torch_variant != 'cpu' && runner.os != 'Windows'
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf /usr/local/share/boost
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
df -h
shell: bash

- name: Free up disk space (Windows)
if: matrix.torch_variant != 'cpu' && runner.os == 'Windows'
run: |
Get-PSDrive C
Remove-Item -Recurse -Force $env:TEMP\* -ErrorAction SilentlyContinue
pip cache purge
Get-PSDrive C
shell: pwsh

- name: Install tomli for version extraction (Linux/macOS)
if: runner.os != 'Windows'
run: python -m pip install tomli
Expand Down Expand Up @@ -77,6 +97,7 @@ jobs:
if: runner.os != 'Windows'
run: |
source .venv/bin/activate
chmod +x ${{ matrix.build_script }}
${{ matrix.build_script }} ${{ matrix.torch_variant }}
shell: bash

Expand All @@ -87,35 +108,36 @@ jobs:
& ${{ matrix.build_script }} ${{ matrix.torch_variant }}
shell: pwsh

- name: Rename executable
run: |
mv dist/photomap${{ matrix.executable_ext }} dist/photomap-${{ matrix.torch_variant }}${{ matrix.executable_ext }}
shell: bash
if: runner.os != 'Windows'

- name: Rename executable (Windows)
run: |
Rename-Item -Path dist\photomap${{ matrix.executable_ext }} -NewName photomap-${{ matrix.torch_variant }}${{ matrix.executable_ext }}
shell: pwsh
if: runner.os == 'Windows'

- name: Create zip archive with version (Linux/macOS)
- name: Rename and zip executable or directory (Linux/macOS)
if: runner.os != 'Windows'
run: |
cd dist
ARCHIVE_NAME="photomap-${{ matrix.platform }}-${{ matrix.torch_variant }}-v${{ steps.get_version_unix.outputs.version || steps.get_version_win.outputs.version }}.zip"
zip -j "$ARCHIVE_NAME" "photomap-${{ matrix.torch_variant }}${{ matrix.executable_ext }}"
BASE="photomap-${{ matrix.torch_variant }}"
EXT="${{ matrix.executable_ext }}"
VERSION="${{ steps.get_version_unix.outputs.version || steps.get_version_win.outputs.version }}"
ARCHIVE_NAME="photomap-${{ matrix.platform }}-${{ matrix.torch_variant }}-v$VERSION.zip"
if [ -f "photomap$EXT" ]; then
mv "photomap$EXT" "$BASE$EXT"
zip "$ARCHIVE_NAME" "$BASE$EXT"
elif [ -d "photomap" ]; then
mv "photomap" "$BASE"
zip -r "$ARCHIVE_NAME" "$BASE"
else
echo "Neither photomap$EXT nor photomap directory found!"
exit 1
fi
ls -la *.zip
shell: bash

- name: Create zip archive with version (Windows)
if: runner.os == 'Windows'
run: |
cd dist
$archiveName = "photomap-${{ matrix.platform }}-${{ matrix.torch_variant }}-v${{ steps.get_version_unix.outputs.version || steps.get_version_win.outputs.version }}.zip"
Compress-Archive -Path "photomap-${{ matrix.torch_variant }}${{ matrix.executable_ext }}" -DestinationPath $archiveName
Get-ChildItem *.zip
- name: Debug - List dist contents
run: ls -la dist/
shell: bash
if: runner.os != 'Windows'

- name: Debug - List dist contents (Windows)
run: Get-ChildItem dist/
shell: pwsh
if: runner.os == 'Windows'

- name: Upload artifact
uses: actions/upload-artifact@v4
Expand Down
6 changes: 1 addition & 5 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,8 @@ jobs:
needs: deploy-dockerhub
uses: ./.github/workflows/deploy-pyinstaller.yml

deploy-make-dmg:
needs: deploy-pyinstaller
uses: ./.github/workflows/deploy-dmg.yml

upload-release:
needs: [deploy-pypi, deploy-dockerhub, deploy-pyinstaller, deploy-make-dmg]
needs: [deploy-pypi, deploy-dockerhub, deploy-pyinstaller]
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Run Pytest

on:
push:
branches: [ master, main ]
pull_request:
branches: [ master, main ]

Expand Down
12 changes: 11 additions & 1 deletion INSTALL/pyinstaller/make_pyinstaller_image.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ if ($IsWindows) {
$sep = ":"
}

# After installing PyTorch
pip cache purge

# Before running PyInstaller
Write-Host "Disk space before PyInstaller:"
Get-PSDrive C

# Run PyInstaller
pyinstaller `
--hidden-import clip `
Expand Down Expand Up @@ -90,4 +97,7 @@ pyinstaller `
$pyinstallerMode `
--name photomap `
-y `
photomap/backend/photomap_server.py
photomap/backend/photomap_server.py

# After PyInstaller
Remove-Item -Recurse -Force build/ -ErrorAction SilentlyContinue
13 changes: 12 additions & 1 deletion INSTALL/pyinstaller/make_pyinstaller_image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ case "$TORCH_VARIANT" in
;;
esac

# After installing PyTorch
pip cache purge
python -c "import torch; print(f'PyTorch cache cleared')"

# Make sure build tools and hooks are up to date
python -m pip install -U pip wheel setuptools
python -m pip install -U pyinstaller pyinstaller-hooks-contrib
Expand Down Expand Up @@ -82,4 +86,11 @@ pyinstaller \
--argv-emulation \
--name photomap \
-y \
photomap/backend/photomap_server.py
photomap/backend/photomap_server.py

# Before running PyInstaller
echo "Disk space before PyInstaller:"
df -h

# After PyInstaller
rm -rf build/ # Remove PyInstaller temp files
48 changes: 24 additions & 24 deletions macos/setup.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
from setuptools import find_packages, setup

APP = ["../photomap/backend/photomap_outer_loop.py"]
APP = ["./main.py"]
DATA_FILES = []
OPTIONS = {
"argv_emulation": True,
"packages": ["photomap"],
# "argv_emulation": True,
# "packages": ["photomap"],
"includes": [
"fastapi",
"uvicorn",
"jinja2",
"numpy",
"pandas",
"networkx",
"pillow_heif",
"platformdirs",
"pydantic",
"python_multipart",
"PyYAML",
"requests",
"scikit_learn",
"torch",
"tqdm",
"umap_learn",
"psutil",
"packaging",
"dash",
"clip_anytorch",
"colorama",
# "fastapi",
# "uvicorn",
# "jinja2",
# "numpy",
# "pandas",
# "networkx",
# "pillow_heif",
# "platformdirs",
# "pydantic",
# "python_multipart",
# "PyYAML",
# "requests",
# "scikit_learn",
# "torch",
# "tqdm",
# "umap_learn",
# "psutil",
# "packaging",
# "dash",
# "clip_anytorch",
# "colorama",
],
"iconfile": "../photomap/frontend/static/icons/icon.icns",
}
Expand Down
2 changes: 1 addition & 1 deletion photomap/backend/embeddings.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def _process_images_batch(
progress_callback: Optional callback function(index, total, message) for progress updates
"""
device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load("ViT-B/32", device=device, download_root=self._clip_root())
model, preprocess = clip.load("ViT-B/32", device=device, download_root=self._clip_root()) # type: ignore

embeddings = []
filenames = []
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "photomapai"
version = "0.9.3"
version = "0.9.4"
description = "AI-based image clustering and exploration tool"
authors = [
{ name = "Lincoln Stein", email = "[email protected]" }
Expand Down
Loading