Files
UmbraEdit/UMBRAEDIT_UPDATE_PLAN.md
B.D. Murphy a04eaaa779 house: add multi-platform build infrastructure
- Add MANIFEST.in to include utils/ and setup/ in source distributions
- Add utils/build_all.py - unified multi-platform build orchestrator
  (Linux amd64/arm64, macOS amd64/arm64, Windows amd64/arm64)
- Add BUILD_LINUX.md - Linux build guide with .deb and AppImage options
- Add RELEASE.md - complete release process with versioning (YYYY/MM.####),
  platform support matrix, and release workflow
- Fix .gitignore to exclude UmbraEdit_Projects/, Inner_Demon_1.2a.docm,
  UmbraEdit_deb_Build_Script.txt, requirements.txt, .DS_Store
- All source distributions now include build scripts for Linux packages
2026-11-06 08:03:35 -08:00

246 lines
8.4 KiB
Markdown

# UmbraEdit — Toolchain & Dependency Update Plan
Copyright (C) 2026 B.D. Murphy and novelWriter contributors.
Plan for upgrading UmbraEdit (Python/PyQt6) toolchain and dependencies.
**Goal:** Bring UmbraEdit (Python/PyQt6) up to the latest stable versions of its tools and dependencies, starting from the current baseline.
**Baseline (as of 2026-11-05):**
- System Python: 3.9.6 (`/usr/bin/python3`) — **below** the project's `requires-python >=3.11`
- Available runtimes: Python 3.11.15, 3.12.13 (via `uv` in `~/.local/bin`)
- `uv`: 0.11.7 (2026-04-15) — outdated
- PyQt6: not yet installed in the 3.11 environment
- `pyproject.toml` deps: `pyqt6>=6.4`, `pyenchant>=3.3.0`, `pyobjc-framework-Cocoa` (darwin)
- Lockfile: `uv.lock` (references `novelwriter` package name — will need regen)
---
## 1. Target Versions
| Tool | Current | Target | Source |
|---|---|---|---|
| Python runtime | 3.9.6 (system) | 3.12.x (latest 3.12) or 3.13.x | `uv` / python.org |
| PyQt6 | not installed | latest 6.x | PyPI |
| pyenchant | >=3.3.0 | latest 3.x | PyPI |
| pyobjc-framework-Cocoa | pinned by pyproject | latest (macOS only) | PyPI |
| uv | 0.11.7 | latest | github.com/astral-sh/uv |
| ruff | (in `uv.lock`) | latest | PyPI |
| pyright | (in `uv.lock`) | latest | npm/PyPI |
| pytest | (in `uv.lock`) | latest 8.x | PyPI |
| pytest-qt | (in `uv.lock`) | latest | PyPI |
| coverage | (in `uv.lock`) | latest | PyPI |
| Sphinx + theme | (in `uv.lock`) | latest | PyPI |
| setuptools | 82.0.1 | latest | PyPI |
| pip | 26.0.1 | latest | ensure via `uv` |
> Prefer Python **3.12** as the primary target (mature, PyQt6 wheels widely available). Keep **3.11** as a secondary CI matrix entry since `requires-python` is `>=3.11`.
---
## 2. Phased Execution
### Phase 0 — Preparation & Safety
1. Ensure working tree is clean and all changes committed on `main` (already done).
2. Tag the current state as a rollback point:
```bash
git tag umbraedit/pre-toolchain-update
git push origin umbraedit/pre-toolchain-update
```
3. Record current working commands (`python3 UmbraEdit.py`, test runner) so you can compare before/after.
4. Back up `uv.lock` and `pyproject.toml`.
### Phase 1 — Upgrade `uv` and Python runtimes
1. Upgrade `uv` itself:
```bash
uv self upgrade
# or: curl -LsSf https://astral.sh/uv/install.sh | sh
```
2. Install the target Python(s) via `uv` (so they are isolated and reproducible):
```bash
uv python install 3.12
uv python install 3.11 # keep for CI matrix
uv python list
uv python pin 3.12 # sets default for this project (writes .python-version)
```
3. Verify:
```bash
uv run python --version # should report 3.12.x
```
### Phase 2 — Upgrade core runtime dependencies
Create a fresh virtual environment with the target Python and install the project's runtime deps at their latest compatible versions:
```bash
cd /Volumes/1TB_APL_Storage/UmbraEdit
uv venv --python 3.12
uv pip install "pyqt6>=6.4" "pyenchant>=3.3.0"
# macOS only:
uv pip install "pyobjc-framework-Cocoa"
```
Then:
1. Run the app to confirm it starts:
```bash
uv run python UmbraEdit.py
# or, after venv activation:
python UmbraEdit.py
```
2. If `pyqt6` wheels fail on the target Python, fall back to 3.11 or file an issue.
### Phase 3 — Upgrade build / lint / test tooling
Update the dependency groups in `pyproject.toml` (`build`, `docs`, `test`, `lint`) to latest, then sync:
```toml
[dependency-groups]
dev = [
{ include-group = "build" },
{ include-group = "docs" },
{ include-group = "test" },
{ include-group = "lint" },
]
build = ["pyyaml", "tzdata; sys_platform == 'win32'"]
docs = [
"docutils>=0.17.1",
"pygments>=2.7",
"sphinx-book-theme",
"sphinx-copybutton",
"sphinx-design",
"sphinx-favicon",
"sphinx-intl",
"sphinx>=5.0",
]
test = [
"coverage>=7.16.0",
"pytest-qt",
"pytest-timeout",
"pytest>=6.0.0",
"tzdata; sys_platform == 'win32'",
]
lint = ["pyright", "ruff"]
```
Suggested edits:
- Bump `pytest>=6.0.0` → `pytest>=8.0` (check PyPI for latest 8.x)
- Bump `coverage>=7.16.0` → latest
- Bump `sphinx>=5.0` → latest 7.x/8.x
- Keep `ruff` and `pyright` unpinned or with generous lower bounds so `uv lock` resolves latest
Then sync:
```bash
uv lock --upgrade # resolve all groups to latest
uv sync --all-groups # create .venv with everything
```
### Phase 4 — Regenerate `uv.lock`
`uv.lock` currently references the old `novelwriter` package name and is stale.
```bash
uv lock --upgrade
git diff uv.lock # review before committing
```
Commit the regenerated lockfile with the toolchain update.
### Phase 5 — Update `requires-python` and classifiers (optional)
If you want to drop 3.11 and standardize on 3.12+:
```toml
requires-python = ">=3.12"
```
And update classifiers accordingly. Otherwise keep `>=3.11` and test both 3.11 and 3.12 in CI.
### Phase 6 — Update Gitea CI workflows
The `.github/workflows/*.yml` files reference Python setup steps. Update them to:
- Use `actions/setup-python` with `python-version: ["3.11", "3.12"]` (or your Gitea Actions equivalent)
- Install via `uv sync --all-groups` instead of `pip install -e .`
- Run `uv run ruff check`, `uv run pyright`, `uv run pytest`
If your Gitea instance uses Gitea Actions, mirror the same matrix. If not, update the workflows to call `uv` explicitly.
### Phase 7 — Packaging scripts review
The `utils/` build scripts (`build_appimage.py`, `build_debian.py`, `build_flatpak.py`, `build_pypi.py`, `build_windows.py`) and `setup/` packaging may pin Python/Qt versions. Check each for:
- Hardcoded `python3` → should target the new runtime
- `qt_version = "6.11"` in `[tool.novelwriter.build] flatpak` → verify against latest Qt6
- `pyqt6>=6.4` lower bound → keep or raise
### Phase 8 — Validation
1. **Syntax/compile:** `uv run python -m py_compile umbraedit/ tests/ utils/`
2. **Import smoke:** `uv run python -c "import umbraedit; umbraedit.main(['--help'])"`
3. **Lint:** `uv run ruff check .` and `uv run pyright`
4. **Tests:** `uv run pytest` (or `uv run python run_tests.py`)
5. **App launch:** `uv run python UmbraEdit.py` — confirm main window opens
6. **Export formats:** exercise DOCX/EPUB/HTML/ODT export paths if sample data exists
### Phase 9 — Commit & publish
```bash
git add -A
git commit -m "chore: upgrade toolchain to Python 3.12 and latest deps
- Upgrade uv and pin Python 3.12 via .python-version
- Refresh pyproject.toml dependency groups to latest compatible versions
- Regenerate uv.lock
- Update Gitea CI workflows for uv + Python 3.11/3.12 matrix
- Review packaging scripts for hardcoded python/qt versions"
git push origin main
```
---
## 3. Rollback Plan
If anything breaks after the update:
```bash
# Restore previous state
git checkout umbraedit/pre-toolchain-update .
# or reset hard to the tag
git reset --hard umbraedit/pre-toolchain-update
git push origin main --force # only if already pushed and you need to undo
```
Also keep the old system Python 3.9.6 available (do not remove `/usr/bin/python3`), and keep the `upstream` remote pointing at the original novelWriter for reference.
---
## 4. Recommended Command Sequence (copy-paste ready)
```bash
cd /Volumes/1TB_APL_Storage/UmbraEdit
# 0. Tag rollback point
git tag umbraedit/pre-toolchain-update
git push origin umbraedit/pre-toolchain-update
# 1. Upgrade uv and pin Python 3.12
uv self upgrade
uv python install 3.12
uv python pin 3.12
uv run python --version
# 2. Create venv and install runtime deps at latest
uv venv --python 3.12
uv pip install "pyqt6>=6.4" "pyenchant>=3.3.0"
# 3. Smoke-test the app
uv run python UmbraEdit.py
# 4. Sync dev toolchains (lint/test/docs)
uv sync --all-groups
# 5. Regenerate lockfile
uv lock --upgrade
git diff uv.lock | head -100
# 6. Validate
uv run python -m py_compile umbraedit/ tests/ utils/
uv run ruff check .
uv run pytest
```
---
## 5. Notes & Risks
- **PyQt6 on Python 3.13:** Wheels may lag; if 3.13 is required, verify PyQt6 availability first. 3.12 is the safer target.
- **`pyobjc-framework-Cocoa`:** macOS-only; only install/test on darwin.
- **`uv.lock` diff:** Expect a large diff since the lockfile is stale; review that no unexpected major-version jumps occur (especially PyQt6 6.x → 7.x, which would be breaking).
- **CI:** Gitea Actions runners must have `uv` installed, or the workflows must install it as a step.
- **Application still runs on Python 3.9.6?** No — `match`/`case` syntax requires 3.10+, and `requires-python` is `>=3.11`. The system 3.9.6 must not be used to run UmbraEdit.