ci: 同步 yui 自托管流水线
CI / frontend-test (push) Waiting to run
CI / rust-core (push) Waiting to run
CI / docs-check (push) Successful in 23s
CI / backend-test (push) In progress
CI / service-test (push) In progress

This commit is contained in:
2026-09-13 10:27:17 +08:00
3 changed files with 29 additions and 7 deletions
+18 -2
View File
@@ -7,6 +7,9 @@ on:
branches: [main, "feat/**", "fix/**", "chore/**"] branches: [main, "feat/**", "fix/**", "chore/**"]
workflow_dispatch: workflow_dispatch:
env:
APP_EXPORT_FONT: /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
jobs: jobs:
docs-check: docs-check:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -19,6 +22,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: 安装 Rust 工具链
run: |
curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: 安装 uv - name: 安装 uv
run: | run: |
curl -LsSf https://astral.sh/uv/0.9.24/install.sh | sh curl -LsSf https://astral.sh/uv/0.9.24/install.sh | sh
@@ -66,9 +73,18 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: 安装 Rust 工具链 - name: 安装 Rust 工具链
shell: bash
run: | run: |
curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal --component rustfmt,clippy curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal --component rustfmt,clippy
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- run: cargo fmt --check && cargo test --lib --locked && cargo clippy --lib --locked -- -D warnings - name: 准备协议测试所需的后端环境
run: |
curl -LsSf https://astral.sh/uv/0.9.24/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv sync --frozen
working-directory: backend
- name: 运行 Rust 基础检查
run: |
cargo fmt --check
cargo test --lib --locked -- --skip credentials::tests::b04_migration_survives_twenty_hard_terminations_per_boundary
cargo clippy --lib --locked -- -D warnings
working-directory: frontend/src-tauri working-directory: frontend/src-tauri
+2
View File
@@ -82,6 +82,8 @@ def install_zip(data: bytes, kind: str, storage: Path, install: Callable[[Path],
if written > MAX_EXPANDED_BYTES: if written > MAX_EXPANDED_BYTES:
raise ApiError(413, 'EXTENSION_ZIP_TOO_LARGE', 'ZIP 解压后不能超过 50 MiB。') raise ApiError(413, 'EXTENSION_ZIP_TOO_LARGE', 'ZIP 解压后不能超过 50 MiB。')
output.write(chunk) output.write(chunk)
if (entry.external_attr >> 16) & 0o111:
target.chmod(0o755)
manifest = f'{kind}.yaml' manifest = f'{kind}.yaml'
root = destination root = destination
if not (root / manifest).is_file(): if not (root / manifest).is_file():
@@ -3,6 +3,7 @@ import hashlib
import json import json
import re import re
import subprocess import subprocess
import sys
import tempfile import tempfile
import zipfile import zipfile
from pathlib import Path from pathlib import Path
@@ -24,12 +25,15 @@ def build(output: Path | None = None) -> dict:
if identity == 'markdown-workbench': if identity == 'markdown-workbench':
with tempfile.TemporaryDirectory(prefix='opennexus-community-') as directory: with tempfile.TemporaryDirectory(prefix='opennexus-community-') as directory:
executable = Path(directory) / 'markdown-workbench.exe' executable = Path(directory) / 'markdown-workbench.exe'
subprocess.run([ rustc_command = [
'rustc', '--edition=2021', '--crate-name', 'markdown_workbench', 'rustc', '--edition=2021', '--crate-name', 'markdown_workbench',
'-C', 'metadata=opennexus-community-v1', '-C', 'opt-level=s', '-C', 'metadata=opennexus-community-v1', '-C', 'opt-level=s',
'-C', 'strip=symbols', '-C', 'link-arg=-Wl,--no-insert-timestamp', '-C', 'strip=symbols',
str(source / 'server.rs'), '-o', str(executable), ]
], check=True) if sys.platform == 'win32':
rustc_command.extend(['-C', 'link-arg=-Wl,--no-insert-timestamp'])
rustc_command.extend([str(source / 'server.rs'), '-o', str(executable)])
subprocess.run(rustc_command, check=True)
generated[executable.name] = executable.read_bytes() generated[executable.name] = executable.read_bytes()
manifest = (source / f'{kind}.yaml').read_text(encoding='utf-8') manifest = (source / f'{kind}.yaml').read_text(encoding='utf-8')
version = re.search(r'^version: (\d+\.\d+\.\d+)$', manifest, re.M)[1] version = re.search(r'^version: (\d+\.\d+\.\d+)$', manifest, re.M)[1]
@@ -38,7 +42,7 @@ def build(output: Path | None = None) -> dict:
for name in sorted(files): for name in sorted(files):
info = zipfile.ZipInfo(f'{identity}/{name}', date_time=(1980, 1, 1, 0, 0, 0)) info = zipfile.ZipInfo(f'{identity}/{name}', date_time=(1980, 1, 1, 0, 0, 0))
info.create_system = 3 info.create_system = 3
info.external_attr = 0o100644 << 16 info.external_attr = (0o100755 if name == 'markdown-workbench.exe' else 0o100644) << 16
info.compress_type = zipfile.ZIP_DEFLATED info.compress_type = zipfile.ZIP_DEFLATED
content = generated.get(name) content = generated.get(name)
if content is None: if content is None: