refactor: fix asar integration (#9753)

* refactor: replace afterPack script with beforePack and remove after-pack.js file

- Updated electron-builder configuration to use beforePack instead of afterPack.
- Removed the after-pack.js script as its functionality is no longer needed.

* refactor: streamline filter logic for architecture-specific packages in before-pack script

- Consolidated platform-specific filter conditions for arm64 and x64 architectures.
- Improved readability and maintainability by using arrays to manage filters for different architectures.
- Ensured that the correct filters are applied based on the architecture during the packaging process.

* chore: remove npm build commands from CI workflows

- Eliminated unnecessary `yarn build:npm` commands from the nightly build and release workflows for Linux, macOS, and Windows.
- Streamlined the build process by focusing on platform-specific build commands.

* delete build npm

* refactor: enhance architecture-specific package management in before-pack script

- Updated the before-pack script to include additional architecture-specific packages for arm64 and x64.
- Improved the organization of package filters and streamlined the logic for handling different architectures during the packaging process.
- Ensured that the correct filters are applied based on the architecture, enhancing the build process for various platforms.

* docs: clarify comment on prebuild binaries in before-pack script

* format code

* chore: add afterPack script to electron-builder configuration

- Included afterPack script in electron-builder.yml to enhance the packaging process.
- This addition allows for post-packaging tasks to be executed, improving build automation.

* chore: update macOS entitlements to disable library validation

- Added the key `com.apple.security.cs.disable-library-validation` to the entitlements file to enhance security settings for macOS builds.

* chore: remove unused package for win32 arm64 architecture

- Deleted the `@strongtz/win32-arm64-msvc` package from `package.json` and `yarn.lock` as it is no longer needed.
- Updated the `before-pack.js` script to improve architecture-specific package management by refining filter logic and ensuring correct package downloads based on architecture.
- Enhanced the `downloadNpmPackage` function to use Node.js streams for downloading and extracting packages, improving efficiency and error handling.
This commit is contained in:
beyondkmp
2025-09-01 19:48:24 +08:00
committed by GitHub
parent d258d9474a
commit 86d8e10dcb
10 changed files with 138 additions and 230 deletions

View File

@@ -94,7 +94,6 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
run: | run: |
sudo apt-get install -y rpm sudo apt-get install -y rpm
yarn build:npm linux
yarn build:linux yarn build:linux
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -107,7 +106,6 @@ jobs:
- name: Build Mac - name: Build Mac
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-latest'
run: | run: |
yarn build:npm mac
yarn build:mac yarn build:mac
env: env:
CSC_LINK: ${{ secrets.CSC_LINK }} CSC_LINK: ${{ secrets.CSC_LINK }}
@@ -125,7 +123,6 @@ jobs:
- name: Build Windows - name: Build Windows
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
run: | run: |
yarn build:npm windows
yarn build:win yarn build:win
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -80,7 +80,6 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
run: | run: |
sudo apt-get install -y rpm sudo apt-get install -y rpm
yarn build:npm linux
yarn build:linux yarn build:linux
env: env:
@@ -95,7 +94,6 @@ jobs:
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-latest'
run: | run: |
sudo -H pip install setuptools sudo -H pip install setuptools
yarn build:npm mac
yarn build:mac yarn build:mac
env: env:
CSC_LINK: ${{ secrets.CSC_LINK }} CSC_LINK: ${{ secrets.CSC_LINK }}
@@ -113,7 +111,6 @@ jobs:
- name: Build Windows - name: Build Windows
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
run: | run: |
yarn build:npm windows
yarn build:win yarn build:win
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -8,5 +8,7 @@
<true/> <true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key> <key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/> <true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@@ -114,6 +114,7 @@ publish:
url: https://releases.cherry-ai.com url: https://releases.cherry-ai.com
electronDownload: electronDownload:
mirror: https://npmmirror.com/mirrors/electron/ mirror: https://npmmirror.com/mirrors/electron/
beforePack: scripts/before-pack.js
afterPack: scripts/after-pack.js afterPack: scripts/after-pack.js
afterSign: scripts/notarize.js afterSign: scripts/notarize.js
artifactBuildCompleted: scripts/artifact-build-completed.js artifactBuildCompleted: scripts/artifact-build-completed.js

View File

@@ -40,7 +40,6 @@
"build:linux": "dotenv npm run build && electron-builder --linux --x64 --arm64", "build:linux": "dotenv npm run build && electron-builder --linux --x64 --arm64",
"build:linux:arm64": "dotenv npm run build && electron-builder --linux --arm64", "build:linux:arm64": "dotenv npm run build && electron-builder --linux --arm64",
"build:linux:x64": "dotenv npm run build && electron-builder --linux --x64", "build:linux:x64": "dotenv npm run build && electron-builder --linux --x64",
"build:npm": "node scripts/build-npm.js",
"release": "node scripts/version.js", "release": "node scripts/version.js",
"publish": "yarn build:check && yarn release patch push", "publish": "yarn build:check && yarn release patch push",
"pulish:artifacts": "cd packages/artifacts && npm publish && cd -", "pulish:artifacts": "cd packages/artifacts && npm publish && cd -",
@@ -74,7 +73,6 @@
"@libsql/client": "0.14.0", "@libsql/client": "0.14.0",
"@libsql/win32-x64-msvc": "^0.4.7", "@libsql/win32-x64-msvc": "^0.4.7",
"@napi-rs/system-ocr": "^1.0.2", "@napi-rs/system-ocr": "^1.0.2",
"@strongtz/win32-arm64-msvc": "^0.4.7",
"graceful-fs": "^4.2.11", "graceful-fs": "^4.2.11",
"jsdom": "26.1.0", "jsdom": "26.1.0",
"node-stream-zip": "^1.15.0", "node-stream-zip": "^1.15.0",

View File

@@ -1,104 +1,10 @@
const { Arch } = require('electron-builder')
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
exports.default = async function (context) { exports.default = async function (context) {
const platform = context.packager.platform.name const platform = context.packager.platform.name
const arch = context.arch
if (platform === 'mac') {
const node_modules_path = path.join(
context.appOutDir,
'Cherry Studio.app',
'Contents',
'Resources',
'app.asar.unpacked',
'node_modules'
)
keepPackageNodeFiles(node_modules_path, '@libsql', arch === Arch.arm64 ? ['darwin-arm64'] : ['darwin-x64'])
keepPackageNodeFiles(
node_modules_path,
'@img',
arch === Arch.arm64
? ['sharp-darwin-arm64', 'sharp-libvips-darwin-arm64']
: ['sharp-darwin-x64', 'sharp-libvips-darwin-x64']
)
keepPackageNodeFiles(
node_modules_path,
'@napi-rs',
arch === Arch.arm64 ? ['system-ocr-darwin-arm64'] : ['system-ocr-darwin-x64']
)
}
if (platform === 'linux') {
const node_modules_path = path.join(context.appOutDir, 'resources', 'app.asar.unpacked', 'node_modules')
const _arch = arch === Arch.arm64 ? ['linux-arm64-gnu', 'linux-arm64-musl'] : ['linux-x64-gnu', 'linux-x64-musl']
keepPackageNodeFiles(node_modules_path, '@libsql', _arch)
keepPackageNodeFiles(
node_modules_path,
'@img',
arch === Arch.arm64
? ['sharp-libvips-linux-arm64', 'sharp-linux-arm64']
: ['sharp-libvips-linux-x64', 'sharp-linux-x64']
)
}
if (platform === 'windows') {
const node_modules_path = path.join(context.appOutDir, 'resources', 'app.asar.unpacked', 'node_modules')
if (arch === Arch.arm64) {
keepPackageNodeFiles(node_modules_path, '@strongtz', ['win32-arm64-msvc'])
keepPackageNodeFiles(node_modules_path, '@libsql', ['win32-arm64-msvc'])
}
if (arch === Arch.x64) {
keepPackageNodeFiles(node_modules_path, '@strongtz', ['win32-x64-msvc'])
keepPackageNodeFiles(node_modules_path, '@libsql', ['win32-x64-msvc'])
}
keepPackageNodeFiles(
node_modules_path,
'@img',
arch === Arch.arm64
? ['sharp-win32-arm64', 'sharp-libvips-win32-arm64']
: ['sharp-win32-x64', 'sharp-libvips-win32-x64']
)
keepPackageNodeFiles(
node_modules_path,
'@napi-rs',
arch === Arch.arm64 ? ['system-ocr-win32-arm64-msvc'] : ['system-ocr-win32-x64-msvc']
)
}
if (platform === 'windows') { if (platform === 'windows') {
fs.rmSync(path.join(context.appOutDir, 'LICENSE.electron.txt'), { force: true }) fs.rmSync(path.join(context.appOutDir, 'LICENSE.electron.txt'), { force: true })
fs.rmSync(path.join(context.appOutDir, 'LICENSES.chromium.html'), { force: true }) fs.rmSync(path.join(context.appOutDir, 'LICENSES.chromium.html'), { force: true })
} }
} }
/**
* 使用指定架构的 node_modules 文件
* @param {*} nodeModulesPath
* @param {*} packageName
* @param {*} arch
* @returns
*/
function keepPackageNodeFiles(nodeModulesPath, packageName, arch) {
const modulePath = path.join(nodeModulesPath, packageName)
if (!fs.existsSync(modulePath)) {
console.log(`[After Pack] Directory does not exist: ${modulePath}`)
return
}
const dirs = fs.readdirSync(modulePath)
dirs
.filter((dir) => !arch.includes(dir))
.forEach((dir) => {
fs.rmSync(path.join(modulePath, dir), { recursive: true, force: true })
console.log(`[After Pack] Removed dir: ${dir}`, arch)
})
}

97
scripts/before-pack.js Normal file
View File

@@ -0,0 +1,97 @@
const { Arch } = require('electron-builder')
const { downloadNpmPackage } = require('./utils')
// if you want to add new prebuild binaries packages with different architectures, you can add them here
// please add to allX64 and allArm64 from yarn.lock
const allArm64 = {
'@img/sharp-darwin-arm64': '0.34.3',
'@img/sharp-win32-arm64': '0.34.3',
'@img/sharp-linux-arm64': '0.34.3',
'@img/sharp-linuxmusl-arm64': '0.34.3',
'@img/sharp-libvips-darwin-arm64': '1.2.0',
'@img/sharp-libvips-linux-arm64': '1.2.0',
'@img/sharp-libvips-linuxmusl-arm64': '1.2.0',
'@libsql/darwin-arm64': '0.4.7',
'@libsql/linux-arm64-gnu': '0.4.7',
'@libsql/linux-arm64-musl': '0.4.7',
'@strongtz/win32-arm64-msvc': '0.4.7',
'@napi-rs/system-ocr-darwin-arm64': '1.0.2',
'@napi-rs/system-ocr-win32-arm64-msvc': '1.0.2'
}
const allX64 = {
'@img/sharp-darwin-x64': '0.34.3',
'@img/sharp-linux-x64': '0.34.3',
'@img/sharp-linuxmusl-x64': '0.34.3',
'@img/sharp-win32-x64': '0.34.3',
'@img/sharp-libvips-darwin-x64': '1.2.0',
'@img/sharp-libvips-linux-x64': '1.2.0',
'@img/sharp-libvips-linuxmusl-x64': '1.2.0',
'@libsql/darwin-x64': '0.4.7',
'@libsql/linux-x64-gnu': '0.4.7',
'@libsql/linux-x64-musl': '0.4.7',
'@libsql/win32-x64-msvc': '0.4.7',
'@napi-rs/system-ocr-darwin-x64': '1.0.2',
'@napi-rs/system-ocr-win32-x64-msvc': '1.0.2'
}
const platformToArch = {
mac: 'darwin',
windows: 'win32',
linux: 'linux'
}
exports.default = async function (context) {
const arch = context.arch
const archType = arch === Arch.arm64 ? 'arm64' : 'x64'
const platform = context.packager.platform.name
const arm64Filters = Object.keys(allArm64).map((f) => '!node_modules/' + f + '/**')
const x64Filters = Object.keys(allX64).map((f) => '!node_modules/' + f + '/*')
const downloadPackages = async (packages) => {
console.log('downloading packages ......')
const downloadPromises = []
for (const name of Object.keys(packages)) {
if (name.includes(`${platformToArch[platform]}`) && name.includes(`-${archType}`)) {
downloadPromises.push(
downloadNpmPackage(
name,
`https://registry.npmjs.org/${name}/-/${name.split('/').pop()}-${packages[name]}.tgz`
)
)
}
}
await Promise.all(downloadPromises)
}
const changeFilters = async (packages, filtersToExclude, filtersToInclude) => {
await downloadPackages(packages)
// remove filters for the target architecture (allow inclusion)
let filters = context.packager.config.files[0].filter
filters = filters.filter((filter) => !filtersToInclude.includes(filter))
// add filters for other architectures (exclude them)
filters.push(...filtersToExclude)
context.packager.config.files[0].filter = filters
}
if (arch === Arch.arm64) {
await changeFilters(allArm64, x64Filters, arm64Filters)
return
}
if (arch === Arch.x64) {
await changeFilters(allX64, arm64Filters, x64Filters)
return
}
}

View File

@@ -1,105 +0,0 @@
const { downloadNpmPackage } = require('./utils')
async function downloadNpm(platform) {
if (!platform || platform === 'mac') {
downloadNpmPackage(
'@libsql/darwin-arm64',
'https://registry.npmjs.org/@libsql/darwin-arm64/-/darwin-arm64-0.4.7.tgz'
)
downloadNpmPackage('@libsql/darwin-x64', 'https://registry.npmjs.org/@libsql/darwin-x64/-/darwin-x64-0.4.7.tgz')
// sharp for macOS
downloadNpmPackage(
'@img/sharp-darwin-arm64',
'https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz'
)
downloadNpmPackage(
'@img/sharp-darwin-x64',
'https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz'
)
downloadNpmPackage(
'@img/sharp-libvips-darwin-arm64',
'https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz'
)
downloadNpmPackage(
'@img/sharp-libvips-darwin-x64',
'https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz'
)
downloadNpmPackage(
'@napi-rs/system-ocr-darwin-arm64',
'https://registry.npmjs.org/@napi-rs/system-ocr-darwin-arm64/-/system-ocr-darwin-arm64-1.0.2.tgz'
)
downloadNpmPackage(
'@napi-rs/system-ocr-darwin-x64',
'https://registry.npmjs.org/@napi-rs/system-ocr-darwin-x64/-/system-ocr-darwin-x64-1.0.2.tgz'
)
}
if (!platform || platform === 'linux') {
downloadNpmPackage(
'@libsql/linux-arm64-gnu',
'https://registry.npmjs.org/@libsql/linux-arm64-gnu/-/linux-arm64-gnu-0.4.7.tgz'
)
downloadNpmPackage(
'@libsql/linux-arm64-musl',
'https://registry.npmjs.org/@libsql/linux-arm64-musl/-/linux-arm64-musl-0.4.7.tgz'
)
downloadNpmPackage(
'@libsql/linux-x64-gnu',
'https://registry.npmjs.org/@libsql/linux-x64-gnu/-/linux-x64-gnu-0.4.7.tgz'
)
downloadNpmPackage(
'@libsql/linux-x64-musl',
'https://registry.npmjs.org/@libsql/linux-x64-musl/-/linux-x64-musl-0.4.7.tgz'
)
downloadNpmPackage(
'@img/sharp-libvips-linux-arm64',
'https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz'
)
downloadNpmPackage(
'@img/sharp-libvips-linux-x64',
'https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz'
)
downloadNpmPackage(
'@img/sharp-libvips-linuxmusl-arm64',
'https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz'
)
downloadNpmPackage(
'@img/sharp-libvips-linuxmusl-x64',
'https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz'
)
}
if (!platform || platform === 'windows') {
downloadNpmPackage(
'@libsql/win32-x64-msvc',
'https://registry.npmjs.org/@libsql/win32-x64-msvc/-/win32-x64-msvc-0.4.7.tgz'
)
downloadNpmPackage(
'@strongtz/win32-arm64-msvc',
'https://registry.npmjs.org/@strongtz/win32-arm64-msvc/-/win32-arm64-msvc-0.4.7.tgz'
)
downloadNpmPackage(
'@img/sharp-win32-arm64',
'https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz'
)
downloadNpmPackage(
'@img/sharp-win32-x64',
'https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz'
)
downloadNpmPackage(
'@napi-rs/system-ocr-win32-arm64-msvc',
'https://registry.npmjs.org/@napi-rs/system-ocr-win32-arm64-msvc/-/system-ocr-win32-arm64-msvc-1.0.2.tgz'
)
downloadNpmPackage(
'@napi-rs/system-ocr-win32-x64-msvc',
'https://registry.npmjs.org/@napi-rs/system-ocr-win32-x64-msvc/-/system-ocr-win32-x64-msvc-1.0.2.tgz'
)
}
}
const platformArg = process.argv[2]
downloadNpm(platformArg)

View File

@@ -1,12 +1,15 @@
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const os = require('os') const os = require('os')
const zlib = require('zlib')
const tar = require('tar')
const { pipeline } = require('stream/promises')
function downloadNpmPackage(packageName, url) { async function downloadNpmPackage(packageName, url) {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'npm-download-')) const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'npm-download-'))
const targetDir = path.join('./node_modules/', packageName) const targetDir = path.join('./node_modules/', packageName)
const filename = packageName.replace('/', '-') + '.tgz' const filename = path.join(tempDir, packageName.replace('/', '-') + '.tgz')
const extractDir = path.join(tempDir, 'extract')
// Skip if directory already exists // Skip if directory already exists
if (fs.existsSync(targetDir)) { if (fs.existsSync(targetDir)) {
@@ -16,23 +19,44 @@ function downloadNpmPackage(packageName, url) {
try { try {
console.log(`Downloading ${packageName}...`, url) console.log(`Downloading ${packageName}...`, url)
const { execSync } = require('child_process')
execSync(`curl --fail -o ${filename} ${url}`) // Download file using fetch API
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const fileStream = fs.createWriteStream(filename)
await pipeline(response.body, fileStream)
console.log(`Extracting ${filename}...`) console.log(`Extracting ${filename}...`)
execSync(`tar -xvf ${filename}`)
execSync(`rm -rf ${filename}`) // Create extraction directory
execSync(`mkdir -p ${targetDir}`) fs.mkdirSync(extractDir, { recursive: true })
execSync(`mv package/* ${targetDir}/`)
// Extract tar.gz file using Node.js streams
await pipeline(fs.createReadStream(filename), zlib.createGunzip(), tar.extract({ cwd: extractDir }))
// Remove the downloaded file
fs.rmSync(filename, { force: true })
// Create target directory
fs.mkdirSync(targetDir, { recursive: true })
// Move extracted package contents to target directory
const packageDir = path.join(extractDir, 'package')
if (fs.existsSync(packageDir)) {
fs.cpSync(packageDir, targetDir, { recursive: true })
}
} catch (error) { } catch (error) {
console.error(`Error processing ${packageName}: ${error.message}`) console.error(`Error processing ${packageName}: ${error.message}`)
if (fs.existsSync(filename)) {
fs.unlinkSync(filename)
}
throw error throw error
} finally {
// Clean up temp directory
if (fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true })
}
} }
fs.rmSync(tempDir, { recursive: true, force: true })
} }
module.exports = { module.exports = {

View File

@@ -7034,14 +7034,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@strongtz/win32-arm64-msvc@npm:^0.4.7":
version: 0.4.7
resolution: "@strongtz/win32-arm64-msvc@npm:0.4.7"
checksum: 10c0/21946f2ed43ff0b2381f945e22cf7f5ef6de412347c36523ed1d72f33591b2b85bf4cc9dd493f0eab95ed5e152d3944a2329791c3d8ed88c7ad450ccd9078015
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@swc/core-darwin-arm64@npm:1.11.21": "@swc/core-darwin-arm64@npm:1.11.21":
version: 1.11.21 version: 1.11.21
resolution: "@swc/core-darwin-arm64@npm:1.11.21" resolution: "@swc/core-darwin-arm64@npm:1.11.21"
@@ -9417,7 +9409,6 @@ __metadata:
"@playwright/test": "npm:^1.52.0" "@playwright/test": "npm:^1.52.0"
"@reduxjs/toolkit": "npm:^2.2.5" "@reduxjs/toolkit": "npm:^2.2.5"
"@shikijs/markdown-it": "npm:^3.12.0" "@shikijs/markdown-it": "npm:^3.12.0"
"@strongtz/win32-arm64-msvc": "npm:^0.4.7"
"@swc/plugin-styled-components": "npm:^7.1.5" "@swc/plugin-styled-components": "npm:^7.1.5"
"@tanstack/react-query": "npm:^5.85.5" "@tanstack/react-query": "npm:^5.85.5"
"@tanstack/react-virtual": "npm:^3.13.12" "@tanstack/react-virtual": "npm:^3.13.12"