Skip to content

Commit f07a6a0

Browse files
authored
feat(hub): add self-hosted multi-user Hub with local and Docker runtimes (#7112)
1 parent e730e94 commit f07a6a0

112 files changed

Lines changed: 22690 additions & 351 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release-verify.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,29 @@ jobs:
173173
with:
174174
ref: ${{ inputs.ref }}
175175

176+
- name: Verify managed runtime boundary version
177+
shell: bash
178+
run: |
179+
python - <<'PY'
180+
import re
181+
from pathlib import Path
182+
183+
version_source = Path("src/qwenpaw/__version__.py").read_text()
184+
dockerfile = Path("deploy/Dockerfile").read_text()
185+
version = re.search(r'__version__ = "([^"]+)"', version_source)
186+
boundary = re.search(
187+
r'ARG QWENPAW_MANAGED_RUNTIME_BOUNDARY_VERSION="([^"]+)"',
188+
dockerfile,
189+
)
190+
if version is None or boundary is None:
191+
raise SystemExit("Unable to read runtime boundary versions")
192+
if version.group(1) != boundary.group(1):
193+
raise SystemExit(
194+
f"Runtime boundary version mismatch: "
195+
f"{boundary.group(1)} != {version.group(1)}",
196+
)
197+
PY
198+
176199
- name: Log in to Aliyun ACR (when credentials available)
177200
if: env.ACR_USERNAME != ''
178201
uses: docker/login-action@v3

.github/workflows/tests.yml

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
- 'tests/**'
99
- 'pyproject.toml'
1010
- 'setup.py'
11+
- 'deploy/Dockerfile'
1112
- '.github/workflows/tests.yml'
1213
pull_request:
1314
branches: [main, master, dev, develop]
@@ -16,6 +17,7 @@ on:
1617
- 'tests/**'
1718
- 'pyproject.toml'
1819
- 'setup.py'
20+
- 'deploy/Dockerfile'
1921
- '.github/workflows/tests.yml'
2022
workflow_dispatch:
2123
inputs:
@@ -77,6 +79,40 @@ jobs:
7779
steps:
7880
- uses: actions/checkout@v4
7981

82+
- name: Install Linux isolation dependency
83+
if: |
84+
runner.os == 'Linux' &&
85+
matrix.python-version == '3.11'
86+
shell: bash
87+
run: |
88+
sudo apt-get update
89+
sudo apt-get install -y bubblewrap
90+
if sysctl kernel.apparmor_restrict_unprivileged_userns \
91+
>/dev/null 2>&1; then
92+
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
93+
fi
94+
95+
- name: Set up Node.js (for console build)
96+
uses: actions/setup-node@v4
97+
with:
98+
node-version: '20'
99+
cache: 'npm'
100+
cache-dependency-path: console/package-lock.json
101+
102+
- name: Build console frontend
103+
shell: bash
104+
env:
105+
NODE_OPTIONS: "--max-old-space-size=8192"
106+
run: |
107+
cd console && npm ci && npm run build
108+
109+
- name: Copy console build into package
110+
shell: bash
111+
run: |
112+
rm -rf src/qwenpaw/console/*
113+
mkdir -p src/qwenpaw/console
114+
cp -R console/dist/* src/qwenpaw/console/
115+
80116
- name: Set up Python ${{ matrix.python-version }}
81117
uses: actions/setup-python@v5
82118
with:
@@ -86,14 +122,8 @@ jobs:
86122
- name: Install dependencies
87123
shell: bash
88124
run: |
89-
# Slim install for the unit tier: unit tests neither serve the
90-
# console frontend nor require the optional heavy extras
91-
# (whisper/torch, codex, qoder). Optional-dependency tests are
92-
# guarded with pytest.importorskip and still run in the nightly
93-
# full sweep, which keeps the full extra. Keeping this job lean
94-
# cuts the Windows matrix entry from tens of minutes to a few.
95125
python -m pip install --upgrade pip
96-
pip install -e ".[dev,test]"
126+
pip install -e ".[dev,test,full]"
97127
98128
- name: Run unit tests
99129
shell: bash
@@ -112,6 +142,15 @@ jobs:
112142
pytest tests/unit -v
113143
fi
114144
145+
- name: Run Hub Local runtime E2E
146+
if: matrix.python-version == '3.11'
147+
shell: bash
148+
env:
149+
QWENPAW_LOCAL_RUNTIME_E2E: '1'
150+
run: |
151+
python -m pip install --no-deps --force-reinstall .
152+
pytest tests/e2e/test_hub_local_runtime.py -v
153+
115154
- name: Upload unit coverage data
116155
if: |
117156
matrix.os == 'ubuntu-latest' &&

console/index.html

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,60 @@
88
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
99
/>
1010
<title>QwenPaw Console</title>
11+
<style>
12+
.qwenpaw-boot {
13+
align-items: center;
14+
background: #f7f7f5;
15+
color: #1f1f1f;
16+
display: flex;
17+
font-family:
18+
Inter,
19+
ui-sans-serif,
20+
-apple-system,
21+
BlinkMacSystemFont,
22+
"Segoe UI",
23+
sans-serif;
24+
inset: 0;
25+
justify-content: center;
26+
position: fixed;
27+
}
28+
.qwenpaw-boot__content {
29+
align-items: center;
30+
display: flex;
31+
flex-direction: column;
32+
gap: 18px;
33+
}
34+
.qwenpaw-boot__logo {
35+
height: 68px;
36+
object-fit: contain;
37+
width: 68px;
38+
}
39+
.qwenpaw-boot__label {
40+
color: #70706c;
41+
font-size: 13px;
42+
letter-spacing: 0.08em;
43+
text-transform: uppercase;
44+
}
45+
@media (prefers-color-scheme: dark) {
46+
.qwenpaw-boot {
47+
background: #141414;
48+
color: #f4f4f1;
49+
}
50+
.qwenpaw-boot__label {
51+
color: #a6a6a0;
52+
}
53+
}
54+
</style>
1155
</head>
1256
<body>
13-
<div id="root"></div>
57+
<div id="root">
58+
<div class="qwenpaw-boot" role="status" aria-live="polite">
59+
<div class="qwenpaw-boot__content">
60+
<img class="qwenpaw-boot__logo" src="/qwenpaw.png" alt="QwenPaw" />
61+
<span class="qwenpaw-boot__label">Loading Console</span>
62+
</div>
63+
</div>
64+
</div>
1465
<script type="module" src="/src/main.tsx"></script>
1566
</body>
1667
</html>

0 commit comments

Comments
 (0)