Skip to content

Commit aa85b93

Browse files
ci: enforce tag version match and pywebview bundle checks
1 parent ae0c38b commit aa85b93

3 files changed

Lines changed: 78 additions & 11 deletions

File tree

.github/workflows/release.yml

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ name: Release
88
# cppa_cursor_browser-<version>.tar.gz (~225 KiB at 0.2.0)
99
# CursorChatBrowser-windows.zip
1010
#
11-
# Fork check: push v0.0.0-test and confirm all three files on the Release.
11+
# Fork rehearsal: push v0.2.0 (pyproject is already 0.2.0) and confirm all three assets on the Release.
1212

1313
on:
1414
push:
@@ -37,6 +37,19 @@ jobs:
3737
with:
3838
python-version: "3.12"
3939

40+
- name: Tag must match pyproject version
41+
if: github.ref_type == 'tag'
42+
env:
43+
RELEASE_TAG: ${{ github.ref_name }}
44+
run: |
45+
set -euo pipefail
46+
tag_version="${RELEASE_TAG#v}"
47+
pyproject_version="$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")"
48+
if [ "$tag_version" != "$pyproject_version" ]; then
49+
echo "Release tag is $tag_version but pyproject.toml [project].version is $pyproject_version"
50+
exit 1
51+
fi
52+
4053
- name: Build hatchling distributables
4154
run: |
4255
python -m pip install --upgrade pip
@@ -65,20 +78,28 @@ jobs:
6578
python-version: "3.12"
6679

6780
- name: Install runtime dependencies
68-
# requirements-lock.txt for runtime; pywebview for the desktop window.
81+
# Runtime from requirements-lock.txt; pywebview pin from pyproject [desktop].
82+
shell: pwsh
6983
run: |
7084
python -m pip install --upgrade pip
7185
python -m pip install -r requirements-lock.txt
72-
python -m pip install 'pywebview>=5.0,<7'
86+
$spec = python scripts/read_desktop_pywebview_spec.py
87+
python -m pip install $spec
7388
7489
- name: Install PyInstaller
7590
run: python -m pip install 'pyinstaller>=6,<7'
7691

7792
- name: Build PyInstaller bundle
7893
run: pyinstaller cursor-browser.spec --noconfirm
7994

80-
- name: Smoke-test PyInstaller exe (--help)
81-
run: dist\CursorChatBrowser\CursorChatBrowser.exe --help
95+
- name: Check webview/lib in bundle
96+
shell: pwsh
97+
run: |
98+
$lib = 'dist\CursorChatBrowser\_internal\webview\lib'
99+
if (-not (Test-Path $lib)) {
100+
Write-Error "pywebview bundle missing: $lib"
101+
exit 1
102+
}
82103
83104
- name: Zip onedir bundle
84105
shell: pwsh

.github/workflows/tests.yml

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,24 @@ jobs:
5454
sys.exit(1)
5555
PY
5656
57+
- name: Check pywebview pin is single-sourced
58+
run: |
59+
python scripts/read_desktop_pywebview_spec.py
60+
python <<'PY'
61+
import sys
62+
from pathlib import Path
63+
64+
for path in sorted(Path(".github/workflows").glob("*.yml")):
65+
text = path.read_text()
66+
if "pywebview>=" in text or "pywebview<" in text:
67+
print(f"{path} hardcodes a pywebview version; use scripts/read_desktop_pywebview_spec.py", file=sys.stderr)
68+
sys.exit(1)
69+
if "read_desktop_pywebview_spec.py" not in text and "pywebview" in text.lower():
70+
if path.name in ("release.yml", "tests.yml"):
71+
print(f"{path} installs pywebview but does not read the pin from pyproject", file=sys.stderr)
72+
sys.exit(1)
73+
PY
74+
5775
- name: Install pip-tools
5876
# Pin matches update-lock.yml so lock verification uses the same resolver.
5977
run: python -m pip install 'pip-tools==7.5.3'
@@ -118,12 +136,13 @@ jobs:
118136
run: python -m pytest tests/test_api_search.py tests/test_api_workspaces.py tests/test_api_export.py tests/test_pdf_export.py tests/test_search_helpers.py tests/test_check_benchmark_regression.py tests/test_reduce_baselines.py -v --tb=short -o addopts=
119137

120138
# ── PyInstaller desktop build (Windows only, once per workflow) ────────
121-
# Closes #44. Builds the onedir bundle and smoke-tests --help so the
122-
# desktop entry point is verified without launching the GUI window.
123-
# pywebview matches release.yml so the Windows bundle matches what we ship.
139+
# Closes #44. Check webview/lib after build; --help returns before import webview.
124140
- name: Install pywebview for PyInstaller bundle
125141
if: matrix.os == 'windows-latest' && matrix.python-version == '3.12'
126-
run: python -m pip install 'pywebview>=5.0,<7'
142+
shell: pwsh
143+
run: |
144+
$spec = python scripts/read_desktop_pywebview_spec.py
145+
python -m pip install $spec
127146
128147
- name: Install PyInstaller
129148
if: matrix.os == 'windows-latest' && matrix.python-version == '3.12'
@@ -133,9 +152,15 @@ jobs:
133152
if: matrix.os == 'windows-latest' && matrix.python-version == '3.12'
134153
run: pyinstaller cursor-browser.spec --noconfirm
135154

136-
- name: Smoke-test PyInstaller exe (--help)
155+
- name: Check webview/lib in bundle
137156
if: matrix.os == 'windows-latest' && matrix.python-version == '3.12'
138-
run: dist\CursorChatBrowser\CursorChatBrowser.exe --help
157+
shell: pwsh
158+
run: |
159+
$lib = 'dist\CursorChatBrowser\_internal\webview\lib'
160+
if (-not (Test-Path $lib)) {
161+
Write-Error "pywebview bundle missing: $lib"
162+
exit 1
163+
}
139164
140165
# ── Browser XSS: Playwright (sprint item #3) ─────────────────────────────
141166
browser-xss:
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""Stdout the pywebview pin from pyproject.toml [desktop]."""
2+
3+
from __future__ import annotations
4+
5+
import sys
6+
import tomllib
7+
8+
9+
def main() -> None:
10+
deps = tomllib.load(open("pyproject.toml", "rb"))["project"]["optional-dependencies"]["desktop"]
11+
if len(deps) != 1 or not deps[0].startswith("pywebview"):
12+
print(
13+
"need exactly one pywebview dep in [project.optional-dependencies].desktop",
14+
file=sys.stderr,
15+
)
16+
raise SystemExit(1)
17+
print(deps[0])
18+
19+
20+
if __name__ == "__main__":
21+
main()

0 commit comments

Comments
 (0)