Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions .github/workflows/mf12-native-qa.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: MF-12 Mac release

on:
push:
branches: [codex/mf-12-unified-workspace]
paths:
- serverbox/**
- scripts/native_acceptance.py
- scripts/test_pty_native.py
- scripts/package_unified_macos.py
- scripts/package_mac_preview.py
- .github/workflows/mf12-native-qa.yml
workflow_dispatch:

permissions:
contents: read

concurrency:
group: mf12-native-qa-${{ github.ref }}
cancel-in-progress: true

jobs:
mac-native:
runs-on: macos-15
permissions:
contents: write
timeout-minutes: 60
env:
RUSTUP_TOOLCHAIN: 1.98.1
CARGO_BUILD_JOBS: 3
steps:
- name: Check out the exact public candidate without stored credentials
env:
CANDIDATE_SHA: ${{ github.sha }}
run: |
git init source
git -C source remote add origin https://github.com/Ferryyer/gpu-queue.git
git -C source fetch --depth=1 origin "$CANDIDATE_SHA"
git -C source checkout --detach FETCH_HEAD
- name: Prepare the pinned Flutter SDK
run: |
git init flutter-sdk
git -C flutter-sdk remote add origin https://github.com/flutter/flutter.git
git -C flutter-sdk fetch --depth=1 origin tag 3.47.8
git -C flutter-sdk checkout --detach 737ba8f885dc774b53b442759999a312c9461e4e
./flutter-sdk/bin/flutter --version
printf '%s\n' "$GITHUB_WORKSPACE/flutter-sdk/bin" >> "$GITHUB_PATH"
- name: Prepare pinned Rust and IronRDP
working-directory: source
run: |
rustup toolchain install 1.98.1 --profile minimal --component rustfmt --component clippy
if [ "$(uname -m)" = arm64 ]; then target=aarch64-apple-darwin; else target=x86_64-apple-darwin; fi
rustup target add --toolchain 1.98.1 "$target"
git clone --no-checkout https://github.com/lollipopkit/IronRDP.git serverbox/third_party/ironrdp
git -C serverbox/third_party/ironrdp checkout --detach debc16c0039936bef2fb0ded046b171ecced3885
git -C serverbox/third_party/ironrdp submodule update --init --recursive
- name: Restore native compiler cache
id: native-cache
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
source/serverbox/.dart_tool/hooks_runner
key: mf12-macos15-arm64-flutter3478-rust1981-${{ hashFiles('source/serverbox/**/Cargo.lock', 'source/serverbox/**/pubspec.lock', 'source/serverbox/**/hook/*.dart', 'source/serverbox/**/rust_build_environment.dart') }}
- name: Generate Mac app without preflight or test gates
working-directory: source
run: python3 scripts/native_acceptance.py --stage build --package-only
- name: Package the installable Mac release
working-directory: source
run: python3 scripts/package_mac_preview.py
- name: Publish the Mac release
working-directory: source
env:
GH_TOKEN: ${{ github.token }}
CANDIDATE_SHA: ${{ github.sha }}
run: |
tag=v2.0.2002
gh release create "$tag" build/unified-release/* \
--repo Ferryyer/gpu-queue --target "$CANDIDATE_SHA" \
--latest --title 'GPU Queue 2.0.2002 · Mac 发布版' \
--notes-file build/unified-release/RELEASE-NOTES.md
- name: Upload native evidence and unsigned QA app
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: mf12-native-mac-qa-${{ github.sha }}
path: |
source/build/native-acceptance/
source/build/unified-release/
if-no-files-found: warn
retention-days: 7
- name: Save native compiler cache even if app compilation fails
if: always() && steps.native-cache.outputs.cache-hit != 'true' && steps.native-cache.outputs.cache-primary-key != ''
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
source/serverbox/.dart_tool/hooks_runner
key: ${{ steps.native-cache.outputs.cache-primary-key }}
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# GPU Queue

个人 GPU 任务台:网页、CPU 调度服务,以及 macOS 桌面小组件。
个人 GPU 任务台:网页、CPU 调度服务、ServerBox 原生统一工作台与兼容旧版的 macOS 小组件。

这是为 linlishuo 的 Markflow 环境编写的个人工具,包含用户身份、SSH 入口和平台适配,并非开箱即用的多用户产品。

## ServerBox 融合

`serverbox/` 为带 GPU 桥接、账号线程卡片和 Mac 自动重连的完整原生客户端源码。
网页新增逐实例 GPU 监控、页面内趋势、JSON 导出及账号线程面板;原生客户端新增任务台入口与暖纸色主题。
原生客户端提供总览、任务、服务器与设置,任务详情在应用内打开关联服务器的 SSH 终端和 SFTP 目录。复用已有安全连接配置;Edit/Auto 与重连不会批准任务。网页同步修复焦点、断线读数与任务入口布局。

当前工程候选尚未完成 Mac 实机验收与安装包发布。见 [MF-12 实现、验证和原生阻塞](docs/UNIFIED-WORKSPACE.md)。
关于页捐赠与产品推广已移除;源码中未发现内购或功能订阅锁。

详见 [融合范围与验证](docs/SERVER-MONITOR.md) 和 [原生构建说明](serverbox/README.gpu-console.md)。
Expand Down
113 changes: 113 additions & 0 deletions docs/MAC-NATIVE-HANDOFF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# MF-12 · Mac 原生验收接手包

维护仓库 `Ferryyer/gpu-queue`,分支 `codex/mf-12-unified-workspace`,PR #3;依赖 PR #1 的 `6a0b990`,不合并、不生产部署。UI 修正基线是 `5fc0e0afac822143f44fae0bcdd70a5a5c2acef1`。接手包的 `CHECKOUT.txt` 和任务本轮评论给出**包含本文件及 PTY 加载修正的完整提交 SHA**;在新目录检出该 SHA,不在已有安装或验收树覆盖文件。

## 已验证与责任边界

Linux 已用真实 Clang 编译 vendored PTY C 库,并运行真实生产 build hook 的本地终端测试:shell 输入/输出、环境/目录、resize、退出状态与信号。发现旧 `DynamicLibrary.open` 文件名不经过 code-asset 映射,已改用 `@Native` 精确指向 hook 输出的 `package:flutter_pty/flutter_pty`。这要求完整重建原生运行时,不能复用旧版 Mac 运行时只替换 AOT。

Linux 已进一步通过根应用真实 native hooks 的 19 项任务定向测试,但这不证明 Mac SSH/SFTP、安装或更新。Mac 构建在 GitHub macos-15 runner 执行;用户本机的交互验收仍由 Mac 执行者完成。

工程后续负责人:GPU 任务台设计开发负责构建错误和代码修复;MF-9 的产品设计师负责独立 UI 复验;Mac 本机操作由 linlishuo 或其指定的 Mac 验收执行者接手。Mac 人工验收任务为 MF-18。用户已授权先发布、再本机验收;发布结果以 GitHub Release 的实际资产为准。

## 准备固定依赖

1. macOS **13+**,原生架构为 arm64 或 x86_64;完整 Xcode(不仅 Command Line Tools)、已接受本机 Xcode 许可,`xcodebuild -version`、`xcrun --sdk macosx --show-sdk-path`、`clang --version`、`swift --version` 均应成功。不要降低部署目标 13.0。
2. Flutter **3.47.8 / Dart 3.13.7**。将这个 SDK 的 `bin` 加入本次终端 PATH;不要升级源码 lockfile。`flutter pub get --enforce-lockfile` 必须成功。
3. rustup 与 Rust **1.98.1**、本机 Apple target。三个 Rust crate 的 `rust-toolchain.toml` 均锁此版本。已有 rustup 时,在仓库根目录执行:

```sh
rustup toolchain install 1.98.1 --profile minimal --component rustfmt --component clippy
# Apple Silicon 用这一行;Intel 改为 x86_64-apple-darwin。
rustup target add --toolchain 1.98.1 aarch64-apple-darwin
export RUSTUP_TOOLCHAIN=1.98.1
```

`RUSTUP_TOOLCHAIN` 只影响本终端。Flutter hooks 会过滤自定义环境变量,因此验收脚本会额外生成本次构建专用的 rustup launcher:固定 1.98.1 并保留已配置的 RUSTUP_HOME/CARGO_HOME,避免 rustup 另行下载所有手机/桌面 target。不要更改项目的 toolchain 文件来绕过版本。

4. IronRDP 固定源码;以下命令仅在新的检出目录执行。若目录已存在,先核对 `git rev-parse HEAD` 和工作区,保留已有修改,不使用 reset/clean:

```sh
git clone --no-checkout https://github.com/lollipopkit/IronRDP.git serverbox/third_party/ironrdp
git -C serverbox/third_party/ironrdp checkout --detach debc16c0039936bef2fb0ded046b171ecced3885
git -C serverbox/third_party/ironrdp submodule update --init --recursive
```

macOS 不需要 ShellBox(仅 iOS Linux 引擎需要)。九个 Dart 依赖已 vendored。Rust crates.io 依赖由提交内 Cargo.lock 决定。不要运行上游发布、Homebrew 同步或隧道安装脚本作为构建前置操作。

## 一次性预检、测试和 QA 构建

从仓库根目录执行(可用 `--flutter /具体SDK/bin/flutter` 指定 SDK):

```sh
python3 scripts/native_acceptance.py --stage preflight
python3 scripts/native_acceptance.py --stage tests
python3 scripts/native_acceptance.py --stage build
```

预检缺任一项则退出 2,写 `build/native-acceptance/report.json`;tests/build 不会在缺依赖或非 Mac 时继续。每个真正执行的命令独立写日志并记录退出码,失败即停。tests 会运行实际 PTY hook 与应用原生 hooks,build 先通过测试再构建。

QA 构建先 `flutter build macos --config-only --release` 写配置,再以本机架构运行 Xcode build,命令行禁用签名(`CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= DEVELOPMENT_TEAM=`),避免使用源码中上游开发者团队。没有修改项目团队身份或 bundle ID。候选 app 位置:

`serverbox/build/macos-qa/Build/Products/Release/GPU Queue.app`

保留源码现有的 `SERVERBOX_DATA_NAME=ServerBoxH100`、`FL_LIB_MACOS_DATA_PROTECTION_KEYCHAIN=false`、`FL_LIB_MACOS_SECURE_ACCOUNT=local.ferry.serverbox.h100`。不要改 bundle ID 或钥匙串定义后宣称旧配置保留。首次验收在专门的 macOS 测试用户执行,保留已有安装与钥匙串;完成隔离验收后再在原用户下验证兼容性。

成功与否以对应源码提交的 Mac Actions 报告/日志为准。Mac 上打开 QA app 前用 `lipo -archs` 检查 `Contents/MacOS` 与框架架构,并查看 Info.plist 的 `2.0.2001 / 2001`。本地 QA app 没有 Developer ID 签名,不能当作稳定自动更新候选。

用户最新要求“不用构建检查直接上传”。PR 分支的 `.github/workflows/mf12-native-qa.yml` 已改为直接生成预览包:`native_acceptance.py --stage build --package-only` 跳过环境预检和全部测试,仅安装固定依赖、编译 Mac 应用;`package_mac_preview.py` 做 Apple Silicon 启动必需的 ad-hoc 签名和 DMG 打包,不运行签名复验、架构复验或启动冒烟。报告明确记录 checksSkippedByUser / testsSkippedByUser,macBuildVerified 和交互/安装项目仍为 false。上文完整 QA 命令供用户之后需要时自行执行,不作为这次上传前置条件。

生成成功后直接创建 `v2.0.2001-preview.2` 预发布,不设为 latest、不改变旧 Widget 稳定更新入口。流程只用本仓库短期 GITHUB_TOKEN,没有上游开发者签名、Apple Developer ID 或公证。生成可安装的 Mac 二进制仍必须执行一次编译,这不是额外验收检查。
用户安装入口(仅在 Release 实际存在并有资产后可用):
https://github.com/Ferryyer/gpu-queue/releases/tag/v2.0.2001-preview.2

预览仅支持 Apple Silicon、macOS 13+。下载 DMG 和 SHA256SUMS 校验后挂载,先备份已有应用,优先用独立测试用户验收。若 Gatekeeper 阻止打开,核实来源和 SHA-256 后在系统设置 → 隐私与安全性中选择“仍要打开”,不要全局禁用 Gatekeeper。退出预览后可恢复备份应用。原包名的 unsigned 表示没有正式 Developer ID 签名/公证,即使已经 ad-hoc 签名。不能将 CI 启动冒烟当作 SSH/SFTP、真实安装覆盖或旧配置兼容性通过。
## 实机交互清单(每项记录结果及证据)

- 在同一窗口添加两台已有测试 SSH 服务器。使用隔离的任务库和无 GPU 的结果 fixture,不连接或启动真实 GPU 队列。
- 任务 → 显式关联实例/服务器 A → SSH 终端核对 hostname/目录 → 返回同一任务 → SFTP 工作目录 → 返回已保存结果;对 B 重复。切换后终端、文件和 GPU 必须一致。无关联时不能猜机器;编辑 SSH 目的地后原关联应失效。
- 测试 SSH 可用但任务服务失败、无权限、空任务/空实例、断线/重连。旧 GPU 指标隐藏并标非实时;服务失败不能把 SSH 显示为离线。
- 未授权任务在 Auto、切模式、刷新和重连后都不获授权;Auto/断线禁用启动。停止先取消再确认,启动 digest 失败与回执不明不得重放。此处使用隔离 CPU fixture,不以真实 GPU 作业测试。
- 启动按钮前资源需求/固定版本可读;逐 GPU 指标、缺测、过期与中文步骤状态可读。连续两轮刷新保持焦点、选择、任务/日志滚动。
- 中文字体、浅/深色、全屏、窗口缩放、菜单栏摘要与入口、休眠/唤醒和网络恢复;Safari 网页缩放/全屏与 390/640/800px 键盘闭环。Swift 恢复模块使用本机编译和实机事件验证,不运行旧安装脚本替换现有隧道。
- 只在隔离用户中做 QA DMG 挂载/覆盖测试,保存 SHA-256;再验证旧用户配置和钥匙串保留。正式签名/公证和发布渠道更新仍需拥有者开发者环境,不能用未签名包替代。

报告中的 `interactiveSshSftpVerified` 和 `installationVerified` 默认永远为 false,脚本不会因构建通过自行把人工项目标绿。验收执行者另附带时间的清单/录像/截图;脱敏后回传 report.json、失败命令对应日志、架构与版本信息。

如需生成明确标识的 QA 包(不是正式版):

```sh
python3 scripts/package_unified_macos.py --app 'serverbox/build/macos-qa/Build/Products/Release/GPU Queue.app' --allow-unsigned
```

仅发布用户授权的验收预览;旧 Widget ZIP 不代表统一版,旧更新入口保持原状。

## Linux 继续验证 PTY 的实际配置

本任务下载 Ubuntu Clang 14 包至任务私有工具目录,复用本人既有 GCC 13 sysroot、头文件和链接器,不用 sudo、不改系统 PATH。Clang wrapper 明确传 `--sysroot`、`--gcc-toolchain` 与 `-B`。仅把任务 wrapper 目录加入当前命令 PATH,然后执行:

```sh
python3 scripts/test_pty_native.py --flutter /具体SDK/bin/flutter
```

未配置 Clang 时的旧错误为 `No compiler configured on host linux_x64`;配置后暴露并修复的错误为 `Failed to load dynamic library 'libflutter_pty.so'`。这两个问题与 SSH 登录故障、GPFS 存储故障分别处理。整应用后续 Rust/native 依赖错误及退出码见本轮交付的原生验证报告,不把独立 PTY 通过称为整应用通过。


## 已批准原生设计预览 2(MF-12)

版本 2.0.2001 / build 2001,基于 PR #3 的 f2b0de2;按 MF-9 最终设计重新实现工作区,没有直接合并 PR #4 草稿。208px 侧栏可收起,64px 工具栏,紧凑任务行,详情按需占用右侧 416px,概览/日志/结果保留列表上下文。浅深色使用批准的 token,仅展示标题用 Georgia / 宋体-简;正文使用系统字体 / 苹方,日志 Menlo,可复制、保留缩进并独立滚动。没有打包 Anthropic 字体。

新版本发布使用独立 tag 与 build,不覆盖 preview.1 或旧 Widget 稳定更新入口。沿用既有 bundle ID、数据名称、钥匙串账户和 SSH/SFTP 入口;切换服务重置详情选择,实例仍需明确绑定服务器。只有点击开始会授权当前版本,Auto 策略位于工具栏的「队列策略与连接状态」,停止仍需确认。

工程验证包含生产 Flutter 组件的浅深色、长标题、侧栏收起、416px 日志与复制、文本放大、刷新后焦点/滚动保持;这些 Linux CPU 渲染检查不能代替 Mac 安装和字体验收。下载后在 MF-18 验收 SSH/SFTP、双服务器、安装覆盖/配置保留、休眠、中文字体和全屏。


## 2.0.2002 发布交付

用户要求直接完成发布版。本次从 PR #3 的 8ec5920 创建新版本 2.0.2002 / build 2002,包含已批准界面和任务更新时间 P2 修复。工作流在 Apple Silicon Mac 上执行必要编译、ad-hoc 签名和 DMG 打包,发布独立 v2.0.2002 tag,为非预发布 GitHub Latest Release;旧 preview.1/preview.2 资产保留。

发布入口:https://github.com/Ferryyer/gpu-queue/releases/tag/v2.0.2002

下载 GPU-Queue-macos-arm64-2002-unsigned.dmg 与 SHA256SUMS,校验后挂载并将应用拖入 Applications;先退出旧应用并保留备份。沿用既有 bundle ID、数据目录及钥匙串定义。未申请 Apple Developer ID 或公证,unsigned/ad-hoc 状态继续在文件名、元数据和发布说明披露。非预发布渠道不等于 Mac 安装/配置/SSH/SFTP 人工验收通过;26 项 CPU 组件/队列检查与定向静态分析已通过,不重复空跑。

旧 Widget 更新入口不迁移;统一应用以新 DMG 手动更新,不向旧 Widget 推送不兼容的包。PR #3 保持未合并,本次不部署服务器或启动 GPU 作业。
Loading
Loading