diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 6779ff4..6ba21d7 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -12,6 +12,8 @@ jobs: shell: bash env: ELY_RELEASE_TOKEN: ${{ secrets.GITEA_TOKEN }} + # The dev clone's engines: LibreOffice from scratch outlasts the runner. + ELY_SHARE: /Users/zacharyzhang/Documents/GitHub/ElyOfficeSuite ELY_PATH: /Users/zacharyzhang/.cargo/bin:/opt/homebrew/bin run: | dir=$HOME/ely-ci/ElyOffice diff --git a/agents.md b/agents.md index fdea0eb..6776ed2 100644 --- a/agents.md +++ b/agents.md @@ -137,6 +137,7 @@ packaging/linux/container.sh 命令 在 Ubuntu 26.04 镜像里运行(引擎 tests/scripts/linux-glibc.sh Linux 的应用、worker 与引擎要求的 glibc 不高于 2.43 packaging/linux/package.sh 应用 出该应用的 AppImage、deb、rpm 与 Arch 包到 dist/(在容器里运行) packaging/source.sh dist 本提交的源码包与随包的 copyleft 上游源码(打过补丁的 MuPDF、Git),文件名带提交号;工作区有未提交改动即拒绝(macOS 的 release.sh 与 CI 的 Windows、Linux 调用) +tests/scripts/ci-share.sh ci.sh 只经指向 ELY_SHARE 的链接用共享引擎:自建目录、指向别处或目标带换行的链接即拒绝 tests/scripts/linux-packages.sh deb、rpm、Arch 包在干净的 Ubuntu 26.04、Fedora 44、Arch 容器里装上,每个 ELF 都找得到库 tests/scripts/linux-pins.sh Linux 打包工具(appimagetool、linuxdeploy、运行时、nfpm)的下载与钉的散列相符 tests/scripts/linux-installed.sh installed|appimage Hyprland 上装好的六个应用或 AppImage:一个窗口、随 Omarchy(Catppuccin)、读出页面文字(PDF、Markdown 经各自引擎),ElyTree 随换主题到 Latte(grim 按窗口截取) @@ -294,7 +295,7 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely - 2026-10-09:每个应用只跑一份(缺陷清单 X-03)。`ely_ui::run` 在写日志之前取应用数据目录的 `instance.lock`(`ely_platform::instance::hold`;Unix 为 fcntl 记录锁,进程结束即放,被拒时以 `F_GETLK` 向系统问出持锁的进程号,不另存进程号文件,同时启动的几份也报得准;Windows 为 LockFileEx,不报进程号);已有一份在跑时第二份不启动,报“已在运行(进程号)”。原先第二份启动即清空第一份的工作目录、把它的恢复点当作干净结束删掉、改写崩溃锁。macOS 经访达打开文件本就交给运行中的那份;`open -n` 与 Linux 每文件一个进程时第二份被拒,文件须在已开的窗口里打开(未做转交)。`tests/scripts/one-instance.sh` 核对。 - 2026-10-10:ElyMark 的链接(M-05,我定,同常见编辑器):可视模式单击链接是编辑,Cmd 单击(Windows、Linux 为 Ctrl)交应用;预览单击即交应用;应用照 ElyPDF:http、https、mailto 交系统打开,其余提示拒绝。 - 2026-10-10:Windows 与 Linux 的构建环境(E-01)。Windows:MSVC(VS 2022,v143);MuPDF 由 `build-mupdf.sh` 以 MSBuild 编上游 `platform/win32` 的 `libmupdf`(静态运行库 /MT,同 Rust 的 `crt-static`;`HAVE_LIBCRYPTO`,`libmupdf.lib` 内含第三方、Tesseract 与 PKCS#7);静态 OpenSSL 取自钉在 2026.07.29 的 vcpkg(`engines/vcpkg`,`openssl:x64-windows-static`);Git 为 Git for Windows 的 MinGit 2.56.0(钉散列,`engines/git/cmd/git.exe`,LFS 在 `ucrt64/libexec/git-core`);CEF 照 cef-dll-sys 放在可执行文件旁(Windows、Linux 都是),不另载入;`%TEMP%` 下的程序被系统的应用控制拦下,构建与探针都不放那里;cmake 与 ninja 须在 PATH;LibreOffice 的 configure 只认 VS 自带的 CMake(组件 `VC.CMake.Project`)。仓库与 `reference/` 一律 LF(`core.autocrlf false`、`core.eol lf`;`fetch-references.sh` 对每个上游照设)。Linux:WSL 的 Ubuntu 26.04;静态 libcrypto 另需其 pkg-config 列出的库(jitterentropy、zstd、z)。LibreOffice 在 Linux 照 Collabora 的 LOKit 配置构建(无图形后端、cairo RGBA、自带各库)。 -- 2026-10-10:Windows 与 Linux 的内核与 worker(W-01、K-01,用户定:0.1.3 先三端发布)。内核只认合并库(`ffi::KERNEL`:`libmergedlo.dylib`、`libmergedlo.so`、`mergedlo.dll`;`sofficeapp` 在合并构建里是文本占位);Windows 载入时一并搜索该 DLL 所在的 `program/`。查找次序照旧,Windows 与 Linux 的包内位置是应用旁的 `libreoffice/program`,开发构建为 `engines/lo-src/instdir/program`。worker 的主循环:macOS 照旧以 GCD;Linux 以 unipoll,`runLoop` 的轮询回调里每次答一个请求,内核的唤醒回调往同一队列放信号(`worker/unipoll.rs`;回调的数据指针须非空,VCL 见空即不调用);Windows 也以 unipoll:LOK 不另起主线程,worker 的主线程跑 `runLoop`(Windows 的消息循环),请求经只收消息的窗口投到这条线程上执行(`worker/messages.rs`),同 macOS 的 GCD;原先 LOK 自起主线程、worker 在另一线程作答,载入表格即死锁。Windows 的循环不调轮询回调,但须传非空的回调,`isUnipoll` 只看它。补丁 `0043-lok-callbacks-flush-inline-everywhere.patch`:回调队列在各平台都即时冲出(原只 macOS),否则请求里等的命令结果与状态要等下一轮主循环才到。`0042-svx-boost-json-needs-no-library.patch`:svxcore 与 sd 定义 `BOOST_ALL_NO_LIB`,MSVC 不再按 Boost 的自动链接索要 `libboost_json`、`libboost_container`。Linux 的内核以 cairo 画图块(worker 设 `SAL_DISABLESKIA`;构建去掉 `--enable-cairo-rgba`,自带的 cairo 要清掉重建),字节为 BGRA,同 macOS 与 Windows;`getTileMode` 只看 cairo 开关,不可信。worker 启动核对在三端都画一段红字,按 BGRA 找不到红色即拒绝。`scripts/apply-lo-patches.sh` 的临时库设 `core.autocrlf false`(Windows 默认转换使任何前缀都对不上)。Windows 的 LibreOffice 在 Cygwin 下构建(`build-libreoffice.sh` 的 CYGWIN 分支:去掉 Unix 专用开关,加 VS 2022,用 `/opt/lo/bin` 的 make,清掉 Git Bash 带进来的 `MSYSTEM`);构建目录与 Cygwin 排除在 Defender 扫描之外(否则并行 configure 删不掉 `conftest.dir`)。英文词典扩展里的 Lightproof(Python 写的语法检查)在构建后删去:macOS 与 Linux 的内核不带 Python,它本不生效;Windows 必带内置 Python(Cygwin 下 configure 不许去掉),第二次用同一配置启动时初始化它,worker 挂起。worker 以 `SAL_NOLOCK_PROFILE` 运行,`ely.xcd` 关掉 LibreOffice 的文档锁(`Common/Misc/UseLocking`):被强杀的 worker 留下的锁会让下次启动或载入弹出交互而挂起;每个应用只有一个 worker 用自己的配置,冲突由 Ely 自己核对。三端发布(CI-01):`.gitea/workflows/release.yml` 在打标签时于三台运行器上执行 `scripts/ci.sh`:macOS 在 Mac mini 的常驻克隆里按需从零构建引擎,Windows 在本机运行器上把 `engines` 与 `reference` 接到开发克隆,Linux 由同一台 Windows 运行器经 WSL 构建(服务器上的 Linux 运行器是一次性容器,建不了内核);各自打包后上传到该标签的发布。Windows 为 NSIS 安装程序,Linux 为 AppImage、deb、rpm 与 Arch 包(引擎构建与打包都经 `packaging/linux/container.sh` 进 Ubuntu 26.04 容器,WSL 里须有 docker;`ELY_SHARE` 的目录一并挂进容器),都由 `packaging/stage.sh` 分装引擎;每个平台都上传本提交的源码包(`packaging/source.sh`);更新清单只含 macOS(Windows 与 Linux 的自动安装未做)。 +- 2026-10-10:Windows 与 Linux 的内核与 worker(W-01、K-01,用户定:0.1.3 先三端发布)。内核只认合并库(`ffi::KERNEL`:`libmergedlo.dylib`、`libmergedlo.so`、`mergedlo.dll`;`sofficeapp` 在合并构建里是文本占位);Windows 载入时一并搜索该 DLL 所在的 `program/`。查找次序照旧,Windows 与 Linux 的包内位置是应用旁的 `libreoffice/program`,开发构建为 `engines/lo-src/instdir/program`。worker 的主循环:macOS 照旧以 GCD;Linux 以 unipoll,`runLoop` 的轮询回调里每次答一个请求,内核的唤醒回调往同一队列放信号(`worker/unipoll.rs`;回调的数据指针须非空,VCL 见空即不调用);Windows 也以 unipoll:LOK 不另起主线程,worker 的主线程跑 `runLoop`(Windows 的消息循环),请求经只收消息的窗口投到这条线程上执行(`worker/messages.rs`),同 macOS 的 GCD;原先 LOK 自起主线程、worker 在另一线程作答,载入表格即死锁。Windows 的循环不调轮询回调,但须传非空的回调,`isUnipoll` 只看它。补丁 `0043-lok-callbacks-flush-inline-everywhere.patch`:回调队列在各平台都即时冲出(原只 macOS),否则请求里等的命令结果与状态要等下一轮主循环才到。`0042-svx-boost-json-needs-no-library.patch`:svxcore 与 sd 定义 `BOOST_ALL_NO_LIB`,MSVC 不再按 Boost 的自动链接索要 `libboost_json`、`libboost_container`。Linux 的内核以 cairo 画图块(worker 设 `SAL_DISABLESKIA`;构建去掉 `--enable-cairo-rgba`,自带的 cairo 要清掉重建),字节为 BGRA,同 macOS 与 Windows;`getTileMode` 只看 cairo 开关,不可信。worker 启动核对在三端都画一段红字,按 BGRA 找不到红色即拒绝。`scripts/apply-lo-patches.sh` 的临时库设 `core.autocrlf false`(Windows 默认转换使任何前缀都对不上)。Windows 的 LibreOffice 在 Cygwin 下构建(`build-libreoffice.sh` 的 CYGWIN 分支:去掉 Unix 专用开关,加 VS 2022,用 `/opt/lo/bin` 的 make,清掉 Git Bash 带进来的 `MSYSTEM`);构建目录与 Cygwin 排除在 Defender 扫描之外(否则并行 configure 删不掉 `conftest.dir`)。英文词典扩展里的 Lightproof(Python 写的语法检查)在构建后删去:macOS 与 Linux 的内核不带 Python,它本不生效;Windows 必带内置 Python(Cygwin 下 configure 不许去掉),第二次用同一配置启动时初始化它,worker 挂起。worker 以 `SAL_NOLOCK_PROFILE` 运行,`ely.xcd` 关掉 LibreOffice 的文档锁(`Common/Misc/UseLocking`):被强杀的 worker 留下的锁会让下次启动或载入弹出交互而挂起;每个应用只有一个 worker 用自己的配置,冲突由 Ely 自己核对。三端发布(CI-01):`.gitea/workflows/release.yml` 在打标签时于三台运行器上执行 `scripts/ci.sh`:macOS 在 Mac mini 的常驻克隆里借用开发克隆 `~/Documents/GitHub/ElyOfficeSuite` 的引擎(`ELY_SHARE`;2026-10-11 起:从零构建 LibreOffice 超过 act_runner 默认的 3 小时,v0.1.3 的 Mac 任务被杀、无 dmg),Windows 在本机运行器上把 `engines` 与 `reference` 接到开发克隆,Linux 由同一台 Windows 运行器经 WSL 构建(服务器上的 Linux 运行器是一次性容器,建不了内核);各自打包后上传到该标签的发布。Windows 为 NSIS 安装程序,Linux 为 AppImage、deb、rpm 与 Arch 包(引擎构建与打包都经 `packaging/linux/container.sh` 进 Ubuntu 26.04 容器,WSL 里须有 docker;`ELY_SHARE` 的目录一并挂进容器),都由 `packaging/stage.sh` 分装引擎;每个平台都上传本提交的源码包(`packaging/source.sh`);更新清单只含 macOS(Windows 与 Linux 的自动安装未做)。 - 2026-10-11:gpui 的 Windows 窗口关闭(W-03 冒烟查出)。`gpui-pre-windows` 0.3.8 在窗口关闭时报三条错:系统已销毁窗口(ElyTree 的关窗交给系统)后 Drop 仍对旧句柄 `RevokeDragDrop` 与 `DestroyWindow`(拖放处理器因此不释放,连带窗口状态);销毁时的失活回报排在异步任务里,执行时窗口已移除(“window not found”);退出后后台任务向已销毁的平台窗口投递(`Invalid window handle`)。修复在 `vendor/gpui-pre-windows`:`WM_DESTROY` 时记下已销毁、在句柄仍有效时撤销拖放、去掉失活回调,Drop 见已销毁即不再动句柄;平台窗口已不在时投递失败只记 debug(应用已退出),其余投递失败照报。三个应用关窗与退出的日志无错。 - 2026-10-11(用户报:Windows 启动带黑色命令行窗口、“打开方式”里无图标、点 X 不退出、表格全黑无网格线):四处根因。命令行窗口:应用是控制台子系统;发行构建改为 `windows_subsystem = "windows"`(开发构建照旧有控制台看日志),子进程(两个 worker、Git、`cmd start`)一律经 `ely_ipc::windowless` 以 `CREATE_NO_WINDOW` 启动。图标:exe 里只有 gpui 的清单资源;各应用共用构建脚本 `packaging/windows/icon.rs`,把 `assets/icons/<应用>.ico` 编成资源 1(gpui 的窗口图标也取资源 1)。点 X 不退出:窗口其实弹了“保存更改”询问。`ely.xcd` 深色方案的 `CalcNotesBackground` 与浅色不同,Calc 在配色变化时改写批注样式并记一步撤销(`ScDetectiveFunc::UpdateAllComments`),未动的表格切到深色即算已修改;两套方案的批注底色改为同一值(LibreOffice 默认的浅黄),切换主题不再改文档,三端同此(`sheet.rs` 的 `a_theme_switch_is_no_edit`)。全黑:Win32 的虚拟设备没有 `SetSizeUsingBuffer`(基类默认返回假,断言在发行构建里不在),给客户缓冲区的设备停在 1×1 像素,Calc 图块只画了一个像素,放映图层同空;补丁 `0044-lok-win32-paints-then-copies.patch` 让 Windows 走 macOS 的路:按全尺寸画进设备,再拷进客户缓冲区(`doc_paintTile` 与 `SlideshowLayerRenderer`)。Writer 自设设备尺寸,原本不受影响。`tests/scripts/lo-patches.sh` 的临时库也设 `core.autocrlf false`(原先在 Windows 上恒失败)。 - 2026-10-11(用户报:Windows 上标题栏的最小化、最大化、关闭三个按钮都按不动):gpui 回答系统的命中测试(`WM_NCHITTEST`)时按绘制次序取第一个含指针的窗口控制区,标题栏的拖动区先于其中的按钮画出,按钮上一律答“标题栏”,系统把按下当作拖动窗口的开始,点击到不了按钮。修复在 `vendor/gpui-pre`(原样一个提交,其后是修复):按命中测试的次序取最上层的控制区,且只看未被遮挡的部分(同 `is_hovered`,盖在标题栏上的对话框挡住其下的按钮)。实测(发行构建,DPI 感知的探针移动真实指针):自右向左依次答关闭、最大化、最小化、拖动;按下最小化即最小化,最大化即最大化,关闭即退出、worker 随之结束;v0.1.3 的安装版同一探针处处答拖动。该回调只有 Windows 平台调用。 @@ -309,3 +310,4 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely - 2026-10-11(用户要求:Linux 不只 AppImage):`packaging/linux/package.sh` 由同一个 AppDir 出四种包:AppImage,以及经 nfpm v2.47.0(钉散列)的 deb、rpm、Arch 包。包把 AppDir 的 `usr` 装到 `/opt/ely-office/<应用>`,`/usr/bin/<应用>` 为链接,桌面项与 512 像素图标在 `/usr/share`。依赖由 AppDir 里每个 ELF 所需而未随包的库,加 gpui 按名载入的 Vulkan 与 Wayland 客户端库得出:deb 与 Arch 按 `packaging/linux/depends.tsv` 换成包名(表里没有即打包失败),rpm 直接依赖库名(`libxcb.so.1()(64bit)`)。同级应用多找一处 `/opt/ely-office/<应用>/bin`(ElyMark 打开 ElyTree)。LibreOffice 的 cairo 由 meson 构建,内核直接拷其构建目录的产物,RUNPATH 仍指向构建树里的 pixman 与 fontconfig(别的机器上找不到);`build-libreoffice.sh` 在 Linux 上把指向源码树的 RUNPATH 改为 `$ORIGIN`(patchelf)。 - 2026-10-11:Linux 包的实测(L1.6)。本机(Omarchy,Hyprland 0.56)装上六个 Arch 包与六个 AppImage,`linux-installed.sh` 两种都过;deb、rpm、Arch 包在 Ubuntu 26.04、Fedora 44、Arch 容器里装上、全部 ELF 找得到库;deb 与 rpm 的六个应用在各自容器的 Xvfb 下画出窗口(`linux-distros.sh`)。截图按窗口(`grim -T` 加 Hyprland 的 `stableId`):按区域截时用户切换工作区或别的窗口盖住即截错。ElyMark 的文件监视略去读取后不会自激:重读前先比指纹(长度与修改时间),不打开文件。 - 2026-10-11(用户定:替换 v0.1.3 的 Linux 包):v0.1.3 发布里原有的六个 AppImage(无头,打不开窗口)已删去,换成本机容器里建出的六个应用各四种包(共 24 个),出自 L1.7 的提交(晚于该标签);上传后逐个核对大小,ElyTree 的 AppImage 下载回来散列相同。`package.sh` 把每个 RUNPATH 按所在 ELF 解析(`$ORIGIN` 或 `${ORIGIN}` 开头,规范化后须在 AppDir 内),否则拒绝(如未修正的 cairo):CI 用的是别处建好的引擎,旧构建会在这里报错而不是带进包里。替换的 Linux 包对应的源码随之上传到同一发布(`source.sh`,文件名带构建提交号),发布说明写明 Linux 包出自哪个提交。 +- 2026-10-11:`ci.sh` 用 `ELY_SHARE` 时,CI 克隆里的 `engines`、`reference` 须是指向共享克隆的链接(Windows 为目录联接,不查);是本克隆自建的目录或指向别处即报错,不混用。`.gitignore` 的 `/engines`、`/reference` 不带斜杠,链接也被忽略(`source.sh` 要求工作区干净)。 diff --git a/scripts/ci.sh b/scripts/ci.sh index 0008334..20d5ef8 100755 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -20,6 +20,16 @@ inside=() # Engines another clone on this host built; else built here. if [ -n "${ELY_SHARE:-}" ]; then for part in engines reference; do + # Never mix this clone's own build with shared engines. + if [ "$os" != windows ] && { [ -e "$part" ] || [ -L "$part" ]; }; then + # A sentinel keeps a trailing newline in the target. + target=$( (readlink "$part" || true) && printf x) + target=${target%x} + [ "$target" = "$ELY_SHARE/$part"$'\n' ] || { + echo "ci.sh: $root/$part is not a link to $ELY_SHARE/$part; remove it" >&2 + exit 1 + } + fi if [ ! -e "$part" ]; then case $os in windows) powershell -NoProfile -Command "New-Item -ItemType Junction -Path '$part' -Target '$(cygpath -w "$ELY_SHARE/$part")' | Out-Null" ;; diff --git a/tasks/TASKS.md b/tasks/TASKS.md index 006be6c..560972b 100644 --- a/tasks/TASKS.md +++ b/tasks/TASKS.md @@ -208,4 +208,4 @@ - [x] L1.5 Linux 包:deb、rpm、Arch(pkg.tar.zst)、AppImage 出自同一份分装,装到 `/opt/ely-office/<应用>`,带桌面项、图标与文件类型;依赖按 `packaging/linux/depends.tsv`;LibreOffice 的 cairo RUNPATH 改为 `$ORIGIN`;`tests/scripts/linux-packages.sh` — R1 列举与读错被吞、坏入口照过、无执行位;R2 坏 git-lfs 照过;R3 PASS - [x] L1.6 本机出六个应用的四种包;Omarchy 上装 Arch 包与 AppImage 出窗口;deb、rpm 在各自发行版的容器里装上并冒烟;`linux-installed.sh`、`linux-distros.sh`、`linux-mark-idle.sh` — R1 deb/rpm 未运行、外部改动未核对显示;R2 内核未出图也过、OCR 大小写、清理竞态;R3 公式栏冒充网格、OCR 与 pgrep 错误被吞;R4 取色、存活、截图错误被吞;R5 hyprctl 查询失败被当作未出窗口(第五轮后修正并以注入失败核对) - [x] L1.7 v0.1.3:删去旧 AppImage,上传新包;`ci.sh` 的 Linux 产出四种包;agents.md 与官网随之(官网只链到发布页,无需改);`package.sh` 拒绝指向包外的 RUNPATH;Linux CI 进容器;`packaging/source.sh` 随发布上传本提交的源码 — R1 前缀检查可越出、读错被吞、CI 未进容器、无对应源码;R2 空项、拆分错误、未跟踪文件;R3 换行、git 配置;R4 `]` 加换行;R5 末尾换行(第五轮后修正并以编译的 ELF 核对) -- [ ] L1.8 macOS 发布:CI 从零编 LibreOffice 超过 act_runner 的 3 小时被杀(v0.1.3 无 dmg);Mac 任务以 `ELY_SHARE` 借用 Mac mini 开发克隆 `ElyOfficeSuite` 的引擎,CI 克隆里自建的残留引擎即报错而非混用 +- [x] L1.8 macOS 发布:CI 从零编 LibreOffice 超过 act_runner 的 3 小时被杀(v0.1.3 无 dmg);Mac 任务以 `ELY_SHARE` 借用 Mac mini 开发克隆 `ElyOfficeSuite` 的引擎,CI 克隆里自建的残留引擎即报错而非混用;`tests/scripts/ci-share.sh` — R1 链接目标末尾换行;R2 测试只看文字;R3 目标仍截换行、reference 未测;R4 未按 macOS 跑;R5 PASS diff --git a/tasks/reviews/L1.8-r1.md b/tasks/reviews/L1.8-r1.md new file mode 100644 index 0000000..45f75c7 --- /dev/null +++ b/tasks/reviews/L1.8-r1.md @@ -0,0 +1,3 @@ +FAIL + +scripts/ci.sh:24 — Command substitution strips trailing newlines from `readlink` output, allowing a link to the wrong directory through the ELY_SHARE guard. If `engines` points to the existing directory `"$ELY_SHARE/engines"$'\n'`, its target compares equal to `$ELY_SHARE/engines`, and packaging proceeds using that other directory. The same bypass affects `reference`. Both isolated probes reached packaging instead of rejecting the link; evidence: `.work/L1.8-r1-probes.log`. Preserve the complete link target when comparing it, and add regression tests covering this case alongside correct links, local directories, and ordinary wrong links. diff --git a/tasks/reviews/L1.8-r2.md b/tasks/reviews/L1.8-r2.md new file mode 100644 index 0000000..be8542f --- /dev/null +++ b/tasks/reviews/L1.8-r2.md @@ -0,0 +1,3 @@ +FAIL + +tests/scripts/ci-share.sh:25 — The helpers check diagnostic text rather than the required outcomes, and `attempt` discards CI's exit status. In disposable copies, removing the guard's `exit 1` leaves all five tests green although a local `engines` directory reaches packaging; replacing link creation with a no-op also leaves them green although neither required link exists. Both failures were reproduced using a local packaging stub; evidence: `.work/L1.8-r2-probes.log`. Preserve the exit status, assert rejected layouts stop before packaging, and check that the absent-directory case creates both links with the exact requested targets. diff --git a/tasks/reviews/L1.8-r3.md b/tasks/reviews/L1.8-r3.md new file mode 100644 index 0000000..9aef5ca --- /dev/null +++ b/tasks/reviews/L1.8-r3.md @@ -0,0 +1,7 @@ +FAIL + +tests/scripts/ci-share.sh:33 — The exact-target assertion still strips trailing newlines: `$(target ...)` removes them after the helper preserves them. In a disposable copy, changing link creation to append a newline to each target leaves the entire suite green, although both links point elsewhere and CI reaches the local packaging stub. The two round 2 mutations now correctly fail, but this target assertion remains incomplete. Preserve a sentinel through the comparison and check the complete stored target. Evidence: `.work/L1.8-r3-probes.log`. + +tests/scripts/ci-share.sh:44 — All rejection cases exercise only `engines`, leaving rejection of a local or misdirected `reference` untested. Restricting the guard to `engines` leaves the suite green; a separate macOS probe then reaches packaging with a local `reference` directory. Exercise rejected layouts for both entries and assert that each stops before packaging. Evidence: `.work/L1.8-r3-probes.log`. + +tests/scripts/ci-share.sh:29 — The new inline comment has eleven words: “name, setup; the check lets it through to the release step”. This violates the ten-word comment limit; the existing comment checker misses inline shell comments and passes. Shorten the comment to ten words or fewer. Evidence: `.work/L1.8-r3-tests.log`. diff --git a/tasks/reviews/L1.8-r4.md b/tasks/reviews/L1.8-r4.md new file mode 100644 index 0000000..8f5b873 --- /dev/null +++ b/tasks/reviews/L1.8-r4.md @@ -0,0 +1,3 @@ +FAIL + +tests/scripts/ci-share.sh:24 — Every case runs the fictitious `probe` platform, leaving macOS rejection untested. In a disposable copy, changing the guard from `[ "$os" != windows ]` to `[ "$os" != macos ]` leaves the suite green; running that copy with `macos` and a local `engines` directory reaches the packaging stub (exit 71), violating L1.8. Exercise `macos` with a local packaging stub, asserting that valid links reach it and rejected layouts stop before it. Evidence: `.work/L1.8-r4-probes.log`. diff --git a/tasks/reviews/L1.8-r5.md b/tasks/reviews/L1.8-r5.md new file mode 100644 index 0000000..7ef22e9 --- /dev/null +++ b/tasks/reviews/L1.8-r5.md @@ -0,0 +1 @@ +PASS diff --git a/tests/scripts/ci-share.sh b/tests/scripts/ci-share.sh new file mode 100755 index 0000000..41e805b --- /dev/null +++ b/tests/scripts/ci-share.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# ci.sh uses shared engines only through links to them. +set -euo pipefail + +root=$(cd "$(dirname "$0")/../.." && pwd) +fail() { + echo "FAIL: $*" >&2 + exit 1 +} +work=$(mktemp -d) +trap 'rm -rf "$work"' EXIT +share=$work/share +mkdir -p "$share/engines" "$share/reference" "$share/engines"$'\n' "$share/reference"$'\n' "$work/elsewhere" +version=$(awk -F'"' '/^version = / { print $2; exit }' "$root/Cargo.toml") +# A macOS clone whose packaging stub stops before any upload. +attempt() { # name, setup; sets status, writes the output + local clone=$work/$1 + mkdir -p "$clone/scripts" "$clone/packaging/macos" + cp "$root/scripts/ci.sh" "$clone/scripts/" + printf '#!/usr/bin/env bash\necho "packaging reached"\nexit 1\n' >"$clone/packaging/macos/release.sh" + chmod +x "$clone/packaging/macos/release.sh" + cp "$root/Cargo.toml" "$clone/" + cp "$root/packaging/apps.tsv" "$clone/packaging/" + (cd "$clone" && eval "$2") + status=0 + ELY_SHARE=$share ELY_RELEASE_TOKEN=unused "$clone/scripts/ci.sh" macos "v$version" >"$work/$1.out" 2>&1 || + status=$? +} +# The target as stored plus a newline and x. +target() { readlink "$1" && printf x; } +passes() { # name, setup; reaches the release step + attempt "$1" "$2" + grep -q 'packaging reached' "$work/$1.out" || fail "$1 was refused: $(cat "$work/$1.out")" + for part in engines reference; do + [ "$(target "$work/$1/$part")" = "$share/$part"$'\n'x ] || fail "$1 has no $part link to $share/$part" + done +} +refused() { # name, setup; stopped before the release step + attempt "$1" "$2" + [ "$status" -ne 0 ] || fail "$1 exited 0" + grep -q 'is not a link to' "$work/$1.out" || fail "$1 was let through: $(cat "$work/$1.out")" + ! grep -q 'packaging reached' "$work/$1.out" || fail "$1 reached the release step" +} +passes absent ':' +passes linked 'ln -s "$share/engines" engines && ln -s "$share/reference" reference' +for part in engines reference; do + refused "built-$part" "mkdir $part" + refused "elsewhere-$part" "ln -s \"\$work/elsewhere\" $part" + refused "newline-$part" "ln -s \"\$share/$part\"\$'\\n' $part" + refused "dangling-$part" "ln -s \"\$work/gone\" $part" +done +echo "ci-share: links pass; own builds, other and newline targets refused"