Files
inkwatch/.gitea/workflows/design-system-guard.yml
T
PMon Dev 71efe04e32
Design System Guard / guard (push) Successful in 5m33s
fix(ci): 补上干净 clone 缺的两块——pg 依赖与 Rust 核心库
run 9 已跑通环境,暴露两处真实缺口:
① schema-consistency-test.js → server/shared/repository.js → require('pg'),
   干净 clone 无 node_modules,报 Cannot find module 'pg'。
   补 npm ci(server,走 npmmirror)。
② clock_test / host_ffi_test 在 loading 阶段要 libinkwatch_core.so,
   找不到即整份失败。补 rustup(rsproxy 镜像)+ cargo build --release,
   产物落在 rust-core/target/release,正是 core_lib.dart 的候选路径。
2026-11-09 22:17:46 +08:00

153 lines
8.3 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 墨观 InkWatch V4.0 · 设计系统双向护栏 CI 入口
#
# 前提:本 workflow 只有在 Gitea 实例「启用 Actions」时才会真正运行;
# 未启用时该文件仅作声明,不会触发任何检查。
# 本地复现(无需 Actions、无需 Gitea):cd <repo> && bash tests/run-guards.sh
# 不在本文件里引 CDN、不写任何凭据;Flutter 用官方 flutter-action 安装。
#
# Flutter / Dart 段说明:
# client/scripts/test.sh 默认找 $HOME/development/flutter/bin/flutter,
# 下面把 flutter 装到同一位置并把绝对路径经 FLUTTER_BIN 显式传给 test.sh,
# 以保证默认跑全量 Dart(含 token_parity_test.dart 的 CSS ↔ Dart 双向护栏)。
# SDK 取自 storage.flutter-io.cn 的 stable 归档(非 git clone),版本钉死。
# 若 runner 无法安装 Flutter:设 SKIP_FLUTTER_TESTS=1 降级 —— Dart 段会在
# 汇总表里显式标 SKIPPED (explicit),绝不静默通过。
#
# 管理台 axe 段(第 6 套件,默认不跑):
# run-guards.sh 只在 RUN_AXE=1 时执行 node tests/admin-axe-audit.mjs
# (3 视口 × 2 皮肤 × 6 页 + E-Ink 6 格 = 42 格,单跑约 45s)。
# **runner 必须自带 Chromium 系浏览器(google-chrome / microsoft-edge /
# chromium)并能联网安装 axe-core,否则保持默认不跑**;若强行启用而浏览器缺失,
# 该套件以退出码 2 失败(汇总表 FAIL,不会伪造成 PASS)。
# 两种启用方式(任选其一,均不硬编码任何凭据):
# ① 手动触发:Actions 里 Run workflow → run_axe 勾选 true;
# ② 仓库变量:Gitea 仓库 Settings → Actions → Variables 设 IW_RUN_AXE=1,
# 之后 push / pull_request 也会带上该套件。
# 若所在 Gitea 版本不支持 vars 上下文,删掉下面 job 级 env 里
# IW_RUN_AXE 那一行即可(其余逻辑不变,退回「默认不跑」)。
name: Design System Guard
on:
push:
pull_request:
workflow_dispatch:
inputs:
run_axe:
# 用字符串而非 type: boolean —— 兼容不支持 inputs.type 的旧版 Gitea
description: '启用管理台 axe 42 格矩阵(填 true 启用;需 runner 自带 Chromium/Edge)'
default: 'false'
jobs:
guard:
runs-on: ubuntu-latest
# 2026-11-09:历史上 6 次运行全红,根因两处,均已在此固化:
# ① subosito/flutter-action@v2 的 setup.sh 依赖 jq,而 runner 的
# node:20-bookworm 容器没有 jq → 首行即 "jq not found" 退出。
# 故本文件不再使用该 action,改为直取官方镜像的 tar.xz(无需 jq)。
# ② 该 runner 到 github.com 与 nodejs.org 的直连极慢/超时
# (实测 setup-node 重试 3 轮烧掉 8 分钟才靠 fallback 成功;
# flutter-action 默认 `git clone github.com/flutter/flutter` 必挂)。
# 故 Flutter 全程改走国内镜像。
# setup-node 也已删除:其 `mirror` 参数只影响 dist 下载,解析版本清单
# 时仍打 github.com/actions/node-versions,实测照样 ETIMEDOUT。
# 本 job 只用 fs/path/crypto 三个内置模块,容器自带的 node 20 足够
# (runner 的 ubuntu-latest 映射到 node:20-bookworm,见运行日志)。
timeout-minutes: 30
env:
# 仓库变量(可选);未设置时为空串,等价于「默认不跑 axe」
IW_RUN_AXE: ${{ vars.IW_RUN_AXE }}
# Flutter/Dart 官方中国镜像(下载 SDK 与 pub 包均走它,避开 github/pub.dev)
FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn
PUB_HOSTED_URL: https://pub.flutter-io.cn
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Report toolchain
run: |
# 不使用 setup-node:容器自带 Node,版本随镜像走,此处只记录以便追溯。
command -v node >/dev/null 2>&1 || { echo "容器内无 node,无法跑护栏脚本" >&2; exit 1; }
echo "node $(node --version) / npm $(npm --version 2>/dev/null || echo n/a)"
# schema-consistency-test.js 会 require server/shared/repository.js,
# 后者 require('pg')。本地能过是因为 node_modules 已装;干净 clone 没有。
- name: Install Node deps (pg, for schema guard)
run: |
set -euo pipefail
cd server
npm ci --omit=dev --no-audit --no-fund --registry=https://registry.npmmirror.com
node -e "require('pg'); console.log('pg ok')"
# 不用 subosito/flutter-action:它硬依赖 jq,且默认 git clone github。
# 直接取官方镜像归档,1.58GB,走 storage.flutter-io.cn。
# node:20-bookworm 自带 curl/tar/xz/git,故本步骤无需 apt。
- name: Setup Flutter (mirror archive, no jq)
run: |
set -euo pipefail
FLUTTER_VERSION="3.47.9" # Dart 3.13.7,满足 pubspec 的 sdk: ^3.13.3
ARCHIVE="flutter_linux_${FLUTTER_VERSION}-stable.tar.xz"
URL="${FLUTTER_STORAGE_BASE_URL}/flutter_infra_release/releases/stable/linux/${ARCHIVE}"
mkdir -p "$HOME/development"
echo "下载 $URL"
curl -fsSL --retry 3 --retry-delay 5 --connect-timeout 20 -o /tmp/flutter.tar.xz "$URL"
# --no-same-owner:归档内的 uid 不是 0,按原 uid 解压会让
# /root/development/flutter 属主≠root,git 2.35+ 随即报
# "fatal: detected dubious ownership",而 flutter 工具链启动时
# 会调用 git 取版本 → 直接 exit 128。run 8 就死在这里。
tar --no-same-owner -xf /tmp/flutter.tar.xz -C "$HOME/development"
rm -f /tmp/flutter.tar.xz
echo "$HOME/development/flutter/bin" >> "$GITHUB_PATH"
echo "FLUTTER_BIN=$HOME/development/flutter/bin/flutter" >> "$GITHUB_ENV"
# 双保险:即便属主仍有偏差,也让 git 认这个目录。
git config --global --add safe.directory "$HOME/development/flutter"
"$HOME/development/flutter/bin/flutter" --version
# clock_test / host_ffi_test 会 NativeLibrary.open 找 libinkwatch_core.so,
# 找不到就在 loading 阶段整份失败(Bad state: 未找到 libinkwatch_core.so)。
# 该 crate 只依赖 sysinfo/serde,跨平台可编;Linux 编出 .so 后
# core_lib.dart 的「仓库内构建产物」候选路径正好命中 rust-core/target/release。
- name: Build Rust core (for clock/host_ffi tests)
env:
RUSTUP_DIST_SERVER: https://rsproxy.cn
RUSTUP_UPDATE_ROOT: https://rsproxy.cn/rustup
run: |
set -euo pipefail
mkdir -p "$HOME/.cargo"
# 用 printf 而非 heredoc:YAML 的 block scalar 会带上缩进,
# 写进 config.toml 虽仍合法(TOML 忽略行首空白),但看着脏。
printf '%s\n' \
'[source.crates-io]' \
'replace-with = "rsproxy-sparse"' \
'' \
'[source.rsproxy-sparse]' \
'registry = "sparse+https://rsproxy.cn/index/"' \
> "$HOME/.cargo/config.toml"
curl -fsSL --retry 3 --retry-delay 5 -o /tmp/rustup-init.sh https://rsproxy.cn/rustup-init.sh
sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain stable
. "$HOME/.cargo/env"
rustc --version
cargo build --release --manifest-path rust-core/Cargo.toml
ls -la rust-core/target/release/libinkwatch_core.so
- name: Run design system guards
run: |
# FLUTTER_BIN 由 Setup Flutter 步骤写入 GITHUB_ENV,此处优先采用
if [ -n "${FLUTTER_BIN:-}" ] && [ -x "$FLUTTER_BIN" ]; then
:
elif [ -n "${FLUTTER_ROOT:-}" ] && [ -x "$FLUTTER_ROOT/bin/flutter" ]; then
export FLUTTER_BIN="$FLUTTER_ROOT/bin/flutter"
elif command -v flutter >/dev/null 2>&1; then
export FLUTTER_BIN="$(command -v flutter)"
fi
# 管理台 axe 段:默认 0;手动触发时取 run_axe 输入;否则看仓库变量 IW_RUN_AXE
RUN_AXE="${IW_RUN_AXE:-0}"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
if [ "${{ inputs.run_axe }}" = "true" ]; then RUN_AXE=1; else RUN_AXE=0; fi
fi
export RUN_AXE
echo "RUN_AXE=$RUN_AXE(0=跳过管理台 axe 42 格矩阵,1=执行)"
bash tests/run-guards.sh