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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This project follows semantic versioning once public releases begin.
- Recognized driver-provided `OpenCL.dll` as a Windows system dependency while retaining checks for bundled compute libraries.
- Prevented analysis controls from overlapping the teacher panel in narrow windows and scaled the board to the space available below the wrapping header.
- Included the NVIDIA NVRTC dependency fix and the startup timeout, analysis rendering, navigation, and retry improvements merged since v0.4.21.
- Backported electron-builder's keychain password fix to the pinned packaging dependency so macOS signing can complete without changing certificate credentials.

### Changed

Expand Down
7 changes: 7 additions & 0 deletions docs/RELEASE_NOTES_v0.4.22.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The bundled engines remain KataGo 1.17.1 with the official Transformer 10B Balan

## 中文

- 回移打包工具的临时钥匙串密码修复,恢复 macOS 正式签名流程,保留签名和公证校验。
- 修复 Windows 开发启动和老师冒烟测试中的盘符、文件 URL 与 `.cmd` 启动问题,支持带空格、中文的路径。
- 修复 iKataGo 参数中的 Windows 反斜杠被吞掉的问题;老师的本机命令工具使用 Windows PowerShell,并正确报告进程启动失败。
- 将 Python 复盘脚本和依赖清单从 `app.asar` 提取到应用运行目录,修复打包应用无法执行复盘脚本及依赖启动目录的问题。
Expand All @@ -29,6 +30,7 @@ The bundled engines remain KataGo 1.17.1 with the official Transformer 10B Balan

## 繁體中文

- 回移打包工具的暫存鑰匙圈密碼修正,恢復 macOS 正式簽署流程,保留簽署與公證驗證。
- 修正 Windows 開發啟動、老師測試與包含空格或中文的路徑處理。
- 保留 iKataGo 參數中的 Windows 反斜線;本機命令工具使用 PowerShell 並正確回報啟動錯誤。
- 將 Python 複盤腳本與相依套件清單從 `app.asar` 提取至應用程式執行目錄,修正打包應用程式無法執行複盤腳本及依賴啟動目錄的問題。
Expand All @@ -40,6 +42,7 @@ The bundled engines remain KataGo 1.17.1 with the official Transformer 10B Balan

## English

- Backports the packaging tool's temporary keychain password fix so macOS signing works while preserving signing and notarization checks.
- Fixes Windows development and teacher smoke startup, including file URLs and paths containing spaces or Chinese characters.
- Preserves backslashes in iKataGo arguments and uses PowerShell for Windows teacher commands, with explicit process startup failure reporting.
- Extracts the Python review script and requirements from `app.asar` into the app's runtime directory so packaged reviews can run independently of the launch directory.
Expand All @@ -51,6 +54,7 @@ The bundled engines remain KataGo 1.17.1 with the official Transformer 10B Balan

## 日本語

- パッケージツールの一時キーチェーンのパスワード修正を適用し、署名と公証の検証を維持したまま macOS の正式な署名処理を修復しました。
- Windows の開発起動と先生機能のテストを修正し、空白や中国語を含むパスに対応しました。
- iKataGo の引数内のバックスラッシュを保持し、Windows のローカルコマンドには PowerShell を使用して起動エラーを報告します。
- Python の棋譜検討スクリプトと依存関係リストを `app.asar` からアプリの実行用ディレクトリへ展開し、パッケージ版でも起動ディレクトリに依存せず検討を実行できるようにしました。
Expand All @@ -62,6 +66,7 @@ The bundled engines remain KataGo 1.17.1 with the official Transformer 10B Balan

## 한국어

- 패키징 도구의 임시 키체인 암호 수정을 적용하여 서명 및 공증 검증을 유지하면서 macOS 서명 절차를 복구합니다.
- Windows 개발 실행과 교사 기능 테스트를 수정하고 공백이나 중국어가 포함된 경로를 처리합니다.
- iKataGo 인수의 역슬래시를 보존하고 Windows 명령에 PowerShell을 사용하며 실행 오류를 보고합니다.
- Python 복기 스크립트와 의존성 목록을 `app.asar`에서 앱의 런타임 디렉터리로 추출하여 패키지 앱에서도 시작 디렉터리와 관계없이 복기를 실행할 수 있도록 수정했습니다.
Expand All @@ -73,6 +78,7 @@ The bundled engines remain KataGo 1.17.1 with the official Transformer 10B Balan

## ภาษาไทย

- นำการแก้ไขรหัสผ่านพวงกุญแจชั่วคราวของเครื่องมือแพ็กเกจมาใช้ เพื่อแก้ไขการลงนาม macOS โดยคงการตรวจสอบลายเซ็นและการรับรองไว้
- แก้ไขการเริ่มแอปและการทดสอบครูบน Windows รวมถึงพาธที่มีช่องว่างหรืออักษรจีน
- รักษาเครื่องหมายแบ็กสแลชในอาร์กิวเมนต์ iKataGo ใช้ PowerShell สำหรับคำสั่งบน Windows และรายงานข้อผิดพลาดในการเริ่มโปรเซส
- แยกสคริปต์ทบทวนเกม Python และรายการไลบรารีที่จำเป็นออกจาก `app.asar` ไปยังไดเรกทอรีรันไทม์ของแอป เพื่อให้แอปที่แพ็กแล้วทบทวนเกมได้โดยไม่ขึ้นกับไดเรกทอรีที่ใช้เริ่มแอป
Expand All @@ -84,6 +90,7 @@ The bundled engines remain KataGo 1.17.1 with the official Transformer 10B Balan

## Tiếng Việt

- Áp dụng bản sửa mật khẩu chuỗi khóa tạm thời của công cụ đóng gói để khôi phục ký macOS, đồng thời giữ nguyên kiểm tra chữ ký và công chứng.
- Sửa khởi chạy môi trường phát triển và kiểm thử giáo viên trên Windows, gồm đường dẫn có dấu cách hoặc chữ Trung Quốc.
- Giữ dấu gạch chéo ngược trong tham số iKataGo, dùng PowerShell cho lệnh Windows và báo lỗi khởi chạy tiến trình.
- Trích xuất tập lệnh phân tích ván đấu bằng Python và danh sách thư viện phụ thuộc từ `app.asar` vào thư mục chạy của ứng dụng, giúp bản đóng gói thực hiện phân tích mà không phụ thuộc vào thư mục khởi chạy.
Expand Down
26 changes: 26 additions & 0 deletions patches/app-builder-lib@26.8.1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
diff --git a/out/codeSign/macCodeSign.js b/out/codeSign/macCodeSign.js
index 17e0c1e7be271b7bce8a7671bfe9d0760a0c9f9a..f68f8d6c98ab71990e6dd88a533eca08e6eb647d 100644
--- a/out/codeSign/macCodeSign.js
+++ b/out/codeSign/macCodeSign.js
@@ -157,16 +157,18 @@ async function createKeychain({ tmpDir, cscLink, cscKeyPassword, cscILink, cscIK
if (cscIKeyPassword != null) {
cscPasswords.push(cscIKeyPassword);
}
- return await importCerts(keychainFile, certPaths, cscPasswords);
+ return await importCerts(keychainFile, certPaths, cscPasswords, keychainPassword);
}
-async function importCerts(keychainFile, paths, keyPasswords) {
+async function importCerts(keychainFile, paths, keyPasswords, keychainPassword) {
var _a;
for (let i = 0; i < paths.length; i++) {
const password = (_a = keyPasswords[i]) !== null && _a !== void 0 ? _a : "";
await (0, builder_util_1.exec)("/usr/bin/security", ["import", paths[i], "-k", keychainFile, "-T", "/usr/bin/codesign", "-T", "/usr/bin/productbuild", "-P", password]);
// https://stackoverflow.com/questions/39868578/security-codesign-in-sierra-keychain-ignores-access-control-settings-and-ui-p
// https://github.com/electron-userland/electron-packager/issues/701#issuecomment-322315996
- await (0, builder_util_1.exec)("/usr/bin/security", ["set-key-partition-list", "-S", "apple-tool:,apple:", "-s", "-k", password, keychainFile]);
+ // Backport https://github.com/electron-userland/electron-builder/pull/10101:
+ // -k authenticates the keychain itself; only import -P takes the certificate password.
+ await (0, builder_util_1.exec)("/usr/bin/security", ["set-key-partition-list", "-S", "apple-tool:,apple:", "-s", "-k", keychainPassword, keychainFile]);
}
return {
keychainFile,
13 changes: 9 additions & 4 deletions pnpm-lock.yaml

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

3 changes: 3 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ allowBuilds:
onnxruntime-node: true
protobufjs: true
sharp: true

patchedDependencies:
app-builder-lib@26.8.1: patches/app-builder-lib@26.8.1.patch
92 changes: 92 additions & 0 deletions tests/macos-keychain-password.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { createRequire } from 'node:module'
import { dirname } from 'node:path'
import test from 'node:test'
import { runInNewContext } from 'node:vm'

const require = createRequire(import.meta.url)
const builderRequire = createRequire(require.resolve('electron-builder/package.json'))
const signerPath = builderRequire.resolve('app-builder-lib/out/codeSign/macCodeSign.js')
const signerRequire = createRequire(signerPath)
const signerSource = readFileSync(signerPath, 'utf8')

// Exercise the installed, pnpm-patched module, not a copy of its implementation.
// Backport: https://github.com/electron-userland/electron-builder/pull/10101
// No real certificates, macOS keychains, filesystem writes or security processes.
function signerHarness(rejectCommand) {
const calls = []
const keychains = new Map()
const exec = async (file, rawArgs) => {
assert.equal(file, '/usr/bin/security')
const args = Array.from(rawArgs)
calls.push(args)
const command = args[0]
if (command === rejectCommand) throw new Error(`security ${command} rejected`)
const keychain = args.at(-1)
if (command === 'create-keychain') keychains.set(keychain, flag(args, '-p'))
if (command === 'unlock-keychain' || command === 'set-key-partition-list') {
const password = flag(args, command === 'unlock-keychain' ? '-p' : '-k')
if (!keychains.has(keychain) || password !== keychains.get(keychain)) {
throw new Error('security rejected the incorrect keychain password')
}
}
return ''
}
const mockRequire = name => {
if (name === 'builder-util') return { ...signerRequire(name), exec }
if (name === './codesign') return { importCertificate: async link => link }
return signerRequire(name)
}
const module = { exports: {} }
const evaluate = runInNewContext(`(function (exports, require, module, __filename, __dirname) {\n${signerSource}\n})`, {
// Skip the unrelated bundled root-certificate copy; all keychain commands
// still execute through the password-validating mock above.
process: { env: { TRAVIS: 'true' }, platform: 'darwin' }
}, { filename: signerPath, timeout: 1000 })
evaluate(module.exports, mockRequire, module, signerPath, dirname(signerPath))
return { createKeychain: module.exports.createKeychain, calls }
}

function flag(args, name) {
const index = args.indexOf(name)
assert.ok(index >= 0, `Missing ${name} in ${args[0]}`)
return args[index + 1]
}

function options(password, extra = {}) {
return { tmpDir: {}, cscLink: 'fixture-application.p12', cscKeyPassword: password, currentDir: dirname(signerPath), ...extra }
}

for (const certificatePassword of ['certificate-import-password', '']) {
test(`macOS signing uses its random keychain password with ${certificatePassword ? 'protected' : 'empty-password'} certificates`, async () => {
const { createKeychain, calls } = signerHarness()
const result = await createKeychain(options(certificatePassword))
const created = calls.find(args => args[0] === 'create-keychain')
const keychainPassword = flag(created, '-p')
assert.ok(keychainPassword.length > 0)
assert.notEqual(keychainPassword, certificatePassword)
assert.equal(flag(calls.find(args => args[0] === 'unlock-keychain'), '-p'), keychainPassword)
assert.equal(flag(calls.find(args => args[0] === 'import'), '-P'), certificatePassword)
assert.equal(flag(calls.find(args => args[0] === 'set-key-partition-list'), '-k'), keychainPassword)
assert.equal(result.keychainFile, created.at(-1))
})
}

test('application and installer certificates keep separate import passwords but share the keychain password', async () => {
const { createKeychain, calls } = signerHarness()
await createKeychain(options('app-password', { cscILink: 'fixture-installer.p12', cscIKeyPassword: 'installer-password' }))
const imports = calls.filter(args => args[0] === 'import')
assert.deepEqual(imports.map(args => flag(args, '-P')), ['app-password', 'installer-password'])
const partitions = calls.filter(args => args[0] === 'set-key-partition-list')
assert.equal(partitions.length, 2)
const keychainPassword = flag(calls.find(args => args[0] === 'create-keychain'), '-p')
for (const args of partitions) assert.equal(flag(args, '-k'), keychainPassword)
})

for (const command of ['import', 'set-key-partition-list']) {
test(`macOS signing propagates ${command} failures instead of bypassing signing`, async () => {
const { createKeychain } = signerHarness(command)
await assert.rejects(createKeychain(options('certificate-password')), new RegExp(`security ${command} rejected`))
})
}
Loading