Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
- name: Ensure taskboard resource dirs exist
run: mkdir -p vendor/dashi-taskboard/dist/web
- name: Install vendored taskboard dependencies
run: npm --prefix vendor/dashi-taskboard install
run: npm --prefix vendor/dashi-taskboard ci
- name: Clippy
run: cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings
- name: Test
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "codex-pro-max",
"private": true,
"version": "1.22.2",
"version": "1.22.3",
"license": "MIT",
"type": "module",
"scripts": {
Expand All @@ -11,7 +11,7 @@
"preview": "vite preview",
"tauri": "node scripts/tauri.mjs",
"build:updater": "node scripts/build-updater.mjs",
"build:taskboard": "npm --prefix vendor/dashi-taskboard install && npm --prefix vendor/dashi-taskboard run build:web",
"build:taskboard": "npm --prefix vendor/dashi-taskboard ci && npm --prefix vendor/dashi-taskboard run build:web",
"ensure:taskboard": "node -e \"require('fs').mkdirSync('vendor/dashi-taskboard/dist/web',{recursive:true})\"",
"check:craft": "node scripts/check-craft.mjs",
"check:release": "node scripts/check-release.mjs",
Expand Down
6 changes: 6 additions & 0 deletions release-notes/v1.22.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Changes

- Repackage the bundled `dashi-taskboard` at `c9fb80c` (`v1.1.23`) after reviewing the current upstream runtime changes. New runtime files remain covered by the existing `server` / `shared` / `scripts` / `cli` / `inject` resource roots, so the bundle whitelist is not widened unnecessarily.
- Switch vendored Taskboard dependency installation from `npm install` to `npm ci` in release builds and CI, making the packaged web UI and runtime dependencies follow the submodule lockfile exactly.
- Strengthen release preflight: initialize the pinned Taskboard submodule when needed, verify the required Taskboard resource contract, and validate the `dashi-taskboard` Node engine requirement before packaging.
- Sync the release version to `1.22.3` across `package.json`, Tauri config, `Cargo.toml`, and the root package entry in `Cargo.lock`; release validation now checks all four locations.
98 changes: 68 additions & 30 deletions scripts/check-release.mjs
Original file line number Diff line number Diff line change
@@ -1,65 +1,103 @@
#!/usr/bin/env node
// 发布前置校验(本地打 tag 前与 CI validate job 共用):
// 必查:package.json / tauri.conf.json / Cargo.toml 三处版本号一致
// 必查:tauri.conf.json bundle.resources 中被 git 跟踪的源路径真实存在
// (v1.3.2 曾漏打包 skills/ 导致安装技能失败,见 AGENTS.md。
// dist/web 等构建产物被 gitignore,CI validate 阶段尚未构建,
// 只对 git 已跟踪的路径做存在性校验)
// 必查:package.json / tauri.conf.json / Cargo.toml / Cargo.lock 四处版本一致
// 必查:Taskboard 运行时资源白名单完整,且固定 submodule 中预构建阶段应存在的资源真实存在
// dist/web 与 node_modules 由 build:taskboard 在后续构建阶段生成,因此预检仅校验其映射存在
// --tag <vX.Y.Z>:追加校验 tag 与版本一致 + release-notes/<tag>.md 存在
// 用法:node scripts/check-release.mjs [--tag v0.12.2]
import { readFileSync, existsSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { execFileSync } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";

const read = (p) => readFileSync(p, "utf8");
const taskboardPackagePath = "vendor/dashi-taskboard/package.json";
if (!existsSync(taskboardPackagePath)) {
try {
execFileSync(
"git",
["submodule", "update", "--init", "--recursive", "vendor/dashi-taskboard"],
{ stdio: "inherit" },
);
} catch (error) {
console.error("✗ 无法初始化 vendor/dashi-taskboard submodule");
process.exit(1);
}
}

const pkgVersion = JSON.parse(read("package.json")).version;
const tauriConfPath = "src-tauri/tauri.conf.json";
const tauriConf = JSON.parse(read(tauriConfPath));
const tauriVersion = tauriConf.version;
const cargoVersion = read("src-tauri/Cargo.toml").match(/^version = "([^"]+)"$/m)?.[1];
const cargoLockVersion = read("src-tauri/Cargo.lock").match(
/\[\[package\]\]\nname = "codex-pro-max"\nversion = "([^"]+)"/,
)?.[1];

const failures = [];
if (!cargoVersion) {
failures.push("src-tauri/Cargo.toml 找不到 version 字段");
}
if (pkgVersion !== tauriVersion || tauriVersion !== cargoVersion) {
if (!cargoVersion) failures.push("src-tauri/Cargo.toml 找不到 version 字段");
if (!cargoLockVersion) failures.push("src-tauri/Cargo.lock 找不到 codex-pro-max 根包版本");
if (
pkgVersion !== tauriVersion ||
tauriVersion !== cargoVersion ||
cargoVersion !== cargoLockVersion
) {
failures.push(
`版本号三处不一致:package.json=${pkgVersion} tauri.conf.json=${tauriVersion} Cargo.toml=${cargoVersion}`,
`版本号四处不一致:package.json=${pkgVersion} tauri.conf.json=${tauriVersion} Cargo.toml=${cargoVersion} Cargo.lock=${cargoLockVersion}`,
);
}

// bundle.resources 的源路径(map 的 key)必须存在。../vendor/... 相对 tauri.conf.json 所在目录解析。
// dist/web 等构建产物被 gitignore,CI validate job 在构建前运行、产物尚不存在,
// 因此只对 git 已跟踪的路径做存在性校验(能拦下 skills/ 这种仓库内资源漏打包)。
const isGitTracked = (abs) => {
try {
execFileSync("git", ["ls-files", "--error-unmatch", abs], { stdio: "pipe" });
return true;
} catch {
return false;
}
};
const tauriDir = dirname(tauriConfPath);
const resources = tauriConf.bundle?.resources ?? {};
const resourceEntries =
typeof resources === "object" && !Array.isArray(resources) ? Object.keys(resources) : resources;
const requiredTaskboardResources = [
"../vendor/dashi-taskboard/server",
"../vendor/dashi-taskboard/shared",
"../vendor/dashi-taskboard/scripts",
"../vendor/dashi-taskboard/cli",
"../vendor/dashi-taskboard/inject",
"../vendor/dashi-taskboard/skills",
"../vendor/dashi-taskboard/dist/web",
"../vendor/dashi-taskboard/package.json",
"../vendor/dashi-taskboard/node_modules/smol-toml",
"../vendor/dashi-taskboard/node_modules/ws",
"../vendor/dashi-taskboard/integrations/deepseek-harness",
];
for (const required of requiredTaskboardResources) {
if (!resourceEntries.includes(required)) {
failures.push(`bundle.resources 缺少 Taskboard 运行时资源:${required}`);
}
}

const tauriDir = dirname(tauriConfPath);
const generatedBeforeBuild = new Set([
resolve(tauriDir, "../vendor/dashi-taskboard/dist/web"),
resolve(tauriDir, "../vendor/dashi-taskboard/node_modules/smol-toml"),
resolve(tauriDir, "../vendor/dashi-taskboard/node_modules/ws"),
]);
for (const src of resourceEntries) {
const abs = resolve(tauriDir, src);
if (isGitTracked(abs) && !existsSync(abs)) {
failures.push(`bundle.resources 源路径不存在(git 已跟踪):${src}(解析为 ${abs})`);
if (generatedBeforeBuild.has(abs)) continue;
if (!existsSync(abs)) {
failures.push(`bundle.resources 源路径不存在:${src}(解析为 ${abs})`);
}
}

if (existsSync(taskboardPackagePath)) {
const taskboardPkg = JSON.parse(read(taskboardPackagePath));
if (taskboardPkg.engines?.node !== ">=22.5") {
failures.push(
`dashi-taskboard Node 引擎要求发生变化:当前=${taskboardPkg.engines?.node ?? "未声明"},请同步 launcher 前置条件`,
);
}
}

const tagIdx = process.argv.indexOf("--tag");
const tag = tagIdx !== -1 ? process.argv[tagIdx + 1] : null;
if (tag) {
if (tag !== `v${pkgVersion}`) {
failures.push(`tag ${tag} 与版本号 v${pkgVersion} 不一致`);
}
if (tag !== `v${pkgVersion}`) failures.push(`tag ${tag} 与版本号 v${pkgVersion} 不一致`);
const notesPath = `release-notes/${tag}.md`;
if (!existsSync(notesPath)) {
failures.push(`缺少 release notes:${notesPath}(build-release.yml 强制要求,见 AGENTS.md)`);
failures.push(`缺少 release notes:${notesPath}(build-release.yml 强制要求)`);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "codex-pro-max"
version = "1.22.2"
version = "1.22.3"
description = "One-click launcher for dashi-taskboard integrated with Codex"
authors = ["codex-pro-max"]
edition = "2021"
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json",
"productName": "Codex Pro Max",
"version": "1.22.2",
"version": "1.22.3",
"identifier": "com.codex.pro.max",
"build": {
"beforeDevCommand": "pnpm run ensure:taskboard && pnpm run dev",
Expand Down