Repository navigation
[4.0.0-beta desktop] PyInstaller CI ships macOS/Windows apps without Couchbase Lite #247
Description
PROBLEM
The public v4.0.0-beta GitHub Release includes:
QueryAnalyzer-4.0.0-beta-macos.dmgQueryAnalyzer-4.0.0-beta-windows.zip
Those jobs are green, but the binaries do not contain Couchbase Lite (libcblite.dylib / cblite.dll or the CouchbaseLite Python bindings).
The Server Edition's only persistence layer is embedded CBL. Without it, the desktop app is a Flask static-file server: Settings → storage, save/load analyzer, preferences, and AI history all fail.
README claims the opposite:
Both bundle
libcblite.dylib/cblite.dll— no external Couchbase Server is needed.
Docker does bundle CBL (app/Dockerfile, CBL 3.2.1). Desktop CI does not copy that recipe.
Suggested RCA
.github/workflows/release-4.0.0-beta.yml (and the copies in liquid-dryrun.yml / qa-build.yml / release.yml) generate a throwaway spec / pyinstaller --onefile line that:
pip install -r requirements.txt— CBL is explicitly not on PyPI- never runs
scripts/fetch_libcblite_macos.sh/fetch_libcblite_windows.ps1 - never clones/builds
couchbaselabs/couchbase-lite-python - never adds the dylib/DLL to
binaries= - does not use the committed
app/build_mac.spec/app/build_win.spec
CI success only means "PyInstaller produced a binary", not "the Server Edition is inside it".
Suggested FIX
Make the desktop jobs do what Docker already does, then feed the result into PyInstaller.
# .github/workflows/release-4.0.0-beta.yml (build-macos, sketch)
- name: Fetch libcblite + build Python bindings
working-directory: ./app
run: |
./scripts/fetch_libcblite_macos.sh
python -m pip install cffi setuptools
git clone --depth 1 https://github.com/couchbaselabs/couchbase-lite-python.git /tmp/cbl-py
python /tmp/cbl-py/build.py \
--include "$(pwd)/vendor/macos/include" \
--library "$(pwd)/vendor/macos/libcblite.3.dylib"
pip install /tmp/cbl-py
pip install pyinstaller rumps
- name: Build with committed spec
working-directory: ./app
env:
CBL_MACOS_DYLIB: ${{ github.workspace }}/app/vendor/macos/libcblite.3.dylib
run: pyinstaller build_mac.spec --clean --noconfirmStop generating an inline spec. Add a runtime hook so the frozen process can dlopen the dylib (see BUILD_INFRASTRUCTURE.md):
# app/build/hooks/rt_set_cbl_path.py
import os, sys
if getattr(sys, "frozen", False):
base = sys._MEIPASS
if sys.platform == "darwin":
os.environ["DYLD_LIBRARY_PATH"] = base + os.pathsep + os.environ.get("DYLD_LIBRARY_PATH", "")
elif sys.platform == "win32":
try:
os.add_dll_directory(base)
except (OSError, AttributeError):
os.environ["PATH"] = base + os.pathsep + os.environ.get("PATH", "")Also add cbl_store.py, blob_storage.py, logging_config.py, app_base.py to hiddenimports / let Analysis collect them.
Depends on the fetch-URL fix and the spec-file fix in the sibling [4.0.0-beta desktop] issues.
Unit tests
Extract the "what must be in a desktop bundle" contract to a small helper so tests do not regex YAML forever.
# app/packaging_manifest.py
REQUIRED_PY_MODULES = (
"cbl_store", "blob_storage", "app_base", "logging_config",
"ai_analyzer", "tray", "CouchbaseLite",
)
REQUIRED_NATIVE = {
"darwin": "libcblite.3.dylib",
"win32": "cblite.dll",
}
def desktop_hiddenimports():
return list(REQUIRED_PY_MODULES)# tests/python/test_packaging_manifest.py
from packaging_manifest import REQUIRED_PY_MODULES, REQUIRED_NATIVE, desktop_hiddenimports
def test_cbl_is_a_required_desktop_module():
assert "CouchbaseLite" in desktop_hiddenimports()
assert "cbl_store" in REQUIRED_PY_MODULES
def test_native_lib_names_match_fetch_scripts():
assert REQUIRED_NATIVE["darwin"] == "libcblite.3.dylib"
assert REQUIRED_NATIVE["win32"] == "cblite.dll"Workflow contract (this is the behavior we care about):
from pathlib import Path
def test_beta_release_workflow_builds_cbl_bindings():
text = Path(".github/workflows/release-4.0.0-beta.yml").read_text()
assert "fetch_libcblite_macos.sh" in text
assert "couchbase-lite-python" in text
assert "build_mac.spec" in text
assert "build_win.spec" in text
assert "cat > QueryAnalyzer.spec" not in text # no more throwaway specContext: found on branch release-4.0.0-beta while reviewing standalone macOS .app / Windows .exe packaging. Issues in this batch share the title prefix [4.0.0-beta desktop].
Activity
Fujio-Turner commentedon Sep 10, 2026
Packaging review index (milestone 4.x)
All
[4.0.0-beta desktop]issues from the standalone macOS.app/ Windows.exereview. Suggested implementation order:P0 — app does not actually work as Server Edition
fetch_libcblite_*.sh/ps1URLs return HTTP 403build_mac.spec/build_win.speccannot buildCBL_AVAILABLEis True even when bindings are missingP1 — ships but misleads / breaks on the edges
config.jsonvia__file__not_MEIPASSapp.pyvsapp_base.py)STORAGE_BACKEND=serverfallbackP2 — hygiene so the next release is not a repeat
release.yml/qa-build.yml/liquid-dryrun.ymlduplicate the CBL-less recipenode_modules,.coverage,.DS_Store,app/config.jsoncommittedEach ticket has PROBLEM / Suggested RCA / Suggested FIX (with code) / Unit tests.
Merge pull request #263 from Fujio-Turner/fix/4.0.0-beta-desktop-issues
Fujio-Turner commentedon Sep 15, 2026
Fixed on
release-4.0.0-betavia #263