-
Notifications
You must be signed in to change notification settings - Fork 1
225 lines (193 loc) · 7.8 KB
/
deploy-docs.yml
File metadata and controls
225 lines (193 loc) · 7.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
name: Deploy Documentation
on:
push:
branches: [main]
paths:
- 'docs/**'
- 'src/**'
- 'assets/**'
- '.github/workflows/deploy-docs.yml'
workflow_dispatch:
permissions:
contents: write
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.13'
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install .[test]
pip install Pillow
- name: Run Tests (I18n Integrity)
run: python -m pytest tests/test_i18n_integrity.py
- name: Pre-install Addons (Web)
run: |
# Helper to unzip addons into source tree so they are bundled as python packages
# Must ensure destination exists
mkdir -p src/switchcraft/addons
python -c "import zipfile, os, glob; from pathlib import Path; [zipfile.ZipFile(z).extractall(Path('src/switchcraft/addons') / Path(z).stem.replace('switchcraft_', '')) for z in glob.glob('src/switchcraft/assets/addons/*.zip')]"
- name: Build Web Demo
run: |
# Bake translations for WASM
python scripts/prepare_web_dist.py --bake
# Create an isolated build directory
mkdir -p build_web
cp -r src/switchcraft build_web/
# Create entry point inside build_web
cat > build_web/web_entry.py <<EOF
import os
import sys
print("DEBUG: WEB ENTRY RELOADED")
print(f"BUILD_TIME: $(date)")
# ============================================================
# CRITICAL: Patch ssl module BEFORE any urllib3 import
# Pyodide injects a MagicMock for ssl, breaking urllib3's version check
# ============================================================
if sys.platform == "emscripten":
import types
# Force patch if 'ssl' is a MagicMock or missing version info
should_patch_ssl = "ssl" not in sys.modules
if not should_patch_ssl:
ssl_mod = sys.modules["ssl"]
# Check if it's a MagicMock
if "Mock" in str(type(ssl_mod)) or not hasattr(ssl_mod, "OPENSSL_VERSION_INFO"):
should_patch_ssl = True
else:
try:
if not isinstance(ssl_mod.OPENSSL_VERSION_INFO, tuple):
should_patch_ssl = True
except (AttributeError, TypeError):
should_patch_ssl = True
if should_patch_ssl:
ssl_mock = types.ModuleType("ssl")
ssl_mock.SSLContext = type("SSLContext", (), {"__init__": lambda *a, **kw: None})
ssl_mock.PROTOCOL_TLS = 2
ssl_mock.PROTOCOL_TLS_CLIENT = 16
ssl_mock.create_default_context = lambda *a, **kw: None
ssl_mock.HAS_SNI = True
ssl_mock.CERT_NONE = 0
ssl_mock.CERT_OPTIONAL = 1
ssl_mock.CERT_REQUIRED = 2
ssl_mock.OPENSSL_VERSION_NUMBER = 0x101010CF
ssl_mock.OPENSSL_VERSION = "OpenSSL 1.1.1 (Pyodide Mock)"
ssl_mock.OPENSSL_VERSION_INFO = (1, 1, 1, 15, 15)
ssl_mock.HAS_NEVER_CHECK_COMMON_NAME = True
sys.modules["ssl"] = ssl_mock
print("DEBUG: SSL module patched successfully")
# Now safe to patch pyodide_http
try:
import pyodide_http
pyodide_http.patch_all()
print("DEBUG: pyodide_http patched successfully")
except ImportError:
pass
# ============================================================
# GLOBAL THREADING MONKEYPATCH FOR WASM
# ============================================================
import threading
import asyncio
class WASMThread(threading.Thread):
"""Bridge between standard threading and WASM-friendly asyncio tasks."""
def start(self):
async def _bridge():
try:
self.run()
except Exception as e:
print(f"ERROR in WASM background thread '{self.name}': {e}")
try:
asyncio.create_task(_bridge())
except RuntimeError:
self.run()
threading.Thread = WASMThread
print("DEBUG: Global threading monkeypatch applied")
# ============================================================
# Normal imports AFTER ssl patching
# ============================================================
import flet as ft
# Ensure current dir is in path
sys.path.insert(0, os.getcwd())
import switchcraft
switchcraft.IS_DEMO = True
import switchcraft.main
if __name__ == "__main__":
# Use ft.run for modern Flet (0.80.0+)
ft.run(switchcraft.main.main, assets_dir="assets")
EOF
# Generate dynamic splash screen
VERSION=$(python -c "import src.switchcraft as s; print(s.__version__)")
echo "Generating Splash for Version: $VERSION"
python scripts/generate_splash.py --version "$VERSION" --output "build_web/switchcraft/assets/splash.png"
# Manually create requirements.txt
cat > build_web/requirements.txt <<EOF
flet==0.80.3
pyodide-http
pefile
olefile
requests
click
rich
PyYAML
defusedxml
PyJWT
anyio>=4.12.1
EOF
# Publish
cd build_web
cp web_entry.py ../web_entry.py.patched
flet publish web_entry.py --app-name "SwitchCraft Demo" --app-short-name "SwitchCraft" --app-description "SwitchCraft Web Demo" --base-url "/demo/" --distpath ../dist --assets switchcraft/assets
# Overwrite with patched entry
cd ..
cp web_entry.py.patched dist/web_entry.py
# Customize Flet loading screen and Overwrite Icons
python scripts/prepare_web_dist.py --patch dist
cp src/switchcraft/assets/icon-192.png dist/icons/icon-192.png
cp src/switchcraft/assets/icon-512.png dist/icons/icon-512.png
cp src/switchcraft/assets/favicon.png dist/favicon.png
cp src/switchcraft/assets/apple-touch-icon.png dist/apple-touch-icon.png || true
# Deploy to docs public
rm -rf docs/public/demo
mkdir -p docs/public/demo
cp -r dist/* docs/public/demo/
# Clean up
rm -rf dist
rm -rf build_web
rm -f web_entry.py.patched
shell: bash
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24.13.0
- name: Install dependencies
run: |
cd docs
if [ -f package-lock.json ]; then
npm ci
else
npm install vitepress vue
fi
- name: Build with VitePress
run: |
cd docs
npx vitepress build
env:
BASE_URL: /
- name: Upload to gh-pages
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: docs/.vitepress/dist
branch: gh-pages
clean: true
# Preserve the pr-preview directory
clean-exclude: |
pr-preview/