Bare standalone packaging — scripts/bare-standalone.cjs, make.cjs, hosts.cjs, prepare-pack.mjs (kernel sync, node_modules flatten, optional sshcrypto.node omit)
Release rolling / release (push) Failing after 1m32s
Release rolling / release (push) Failing after 1m32s
Entries + OTA — bin/bare-os-*.mjs + lib/bare-os-ota.mjs (pear-runtime, --no-updates / BARE_OS_OTA_DISABLE) Upgrade links on seeder/booter package.json Gitea rolling — .gitea/workflows/release-rolling.yml + scripts/gitea-rolling-release.sh (RELEASE_TOKEN) by-arch + pear-ci — scripts/pear-stage-by-arch.sh, ci/snapshot-*.json (PEAR_PRIMARY_KEY) pear run retired from npm/PM2/docs; see docs/BINARY-RELEASE.md
This commit is contained in:
Executable
+180
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Ad-hoc / self-signed codesign for Bare standalone Mach-O binaries.
|
||||
* Ported from peardock's sign-macos-app.cjs (binary path only).
|
||||
*
|
||||
* Env:
|
||||
* MAC_CODESIGN_IDENTITY / CSC_NAME — Developer ID (macOS codesign)
|
||||
* BARE_OS_SKIP_MACOS_SIGN=1 — no-op
|
||||
* BARE_OS_RCODESIGN_CERT_DIR — where to store CI self-signed p12
|
||||
*/
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { spawnSync, execFileSync } = require('child_process')
|
||||
|
||||
function log(...a) {
|
||||
console.log('[sign-macos]', ...a)
|
||||
}
|
||||
|
||||
function which(cmd) {
|
||||
try {
|
||||
const r = spawnSync(process.platform === 'win32' ? 'where' : 'which', [cmd], {
|
||||
encoding: 'utf8',
|
||||
})
|
||||
if (r.status === 0) return r.stdout.trim().split(/\r?\n/)[0]
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function identity() {
|
||||
const id = process.env.MAC_CODESIGN_IDENTITY || process.env.CSC_NAME || ''
|
||||
if (id && id !== '-' && id.toLowerCase() !== 'null') return id
|
||||
return '-'
|
||||
}
|
||||
|
||||
function ensureRcodesignSelfSignedP12(bin) {
|
||||
const certDir =
|
||||
process.env.BARE_OS_RCODESIGN_CERT_DIR ||
|
||||
path.join(__dirname, '..', 'tools', 'rcodesign', 'ci-cert')
|
||||
const p12Path = path.join(certDir, 'bare-os-ci.p12')
|
||||
const password = process.env.BARE_OS_RCODESIGN_P12_PASSWORD || 'bare-os-ci-sign'
|
||||
fs.mkdirSync(certDir, { recursive: true })
|
||||
if (fs.existsSync(p12Path) && fs.statSync(p12Path).size > 100) {
|
||||
return { p12Path, password }
|
||||
}
|
||||
|
||||
log('generating self-signed signing cert for rcodesign…')
|
||||
const gen = spawnSync(
|
||||
bin,
|
||||
[
|
||||
'generate-self-signed-certificate',
|
||||
'--p12-file',
|
||||
p12Path,
|
||||
'--p12-password',
|
||||
password,
|
||||
'--person-name',
|
||||
'bare-os-ci',
|
||||
'--country-name',
|
||||
'US',
|
||||
'--validity-days',
|
||||
'3650',
|
||||
'--team-id',
|
||||
'NONE',
|
||||
'--profile',
|
||||
'developer-id-application',
|
||||
],
|
||||
{ encoding: 'utf8', stdio: 'pipe' }
|
||||
)
|
||||
if (gen.status !== 0 || !fs.existsSync(p12Path)) {
|
||||
const gen2 = spawnSync(
|
||||
bin,
|
||||
[
|
||||
'generate-self-signed-certificate',
|
||||
'--p12-file',
|
||||
p12Path,
|
||||
'--p12-password',
|
||||
password,
|
||||
'--person-name',
|
||||
'bare-os-ci',
|
||||
'--country-name',
|
||||
'US',
|
||||
'--validity-days',
|
||||
'3650',
|
||||
],
|
||||
{ encoding: 'utf8', stdio: 'pipe' }
|
||||
)
|
||||
if (gen2.status !== 0 || !fs.existsSync(p12Path)) {
|
||||
throw new Error(
|
||||
`rcodesign generate-self-signed-certificate failed:\n` +
|
||||
`${gen.stderr || gen.stdout}\n${gen2.stderr || gen2.stdout}`
|
||||
)
|
||||
}
|
||||
}
|
||||
return { p12Path, password }
|
||||
}
|
||||
|
||||
function codesignDarwin(binPath, id) {
|
||||
try {
|
||||
execFileSync('xattr', ['-cr', binPath], { stdio: 'pipe' })
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
const args = ['--force', '--sign', id, '--timestamp=none', binPath]
|
||||
if (id !== '-') {
|
||||
args.splice(3, 1, '--options', 'runtime', '--timestamp')
|
||||
}
|
||||
const r = spawnSync('codesign', args, { encoding: 'utf8' })
|
||||
if (r.status !== 0) {
|
||||
throw new Error(`codesign failed:\n${r.stderr || r.stdout}`)
|
||||
}
|
||||
const v = spawnSync('codesign', ['--verify', '--verbose=2', binPath], {
|
||||
encoding: 'utf8',
|
||||
})
|
||||
if (v.status !== 0) {
|
||||
throw new Error(`codesign verify failed:\n${v.stderr || v.stdout}`)
|
||||
}
|
||||
log('verify ok')
|
||||
}
|
||||
|
||||
function codesignRcodesign(binPath) {
|
||||
const bin = which('rcodesign')
|
||||
if (!bin) {
|
||||
throw new Error(
|
||||
'rcodesign not found. Install tools/rcodesign/<host>/rcodesign or sign on macOS.'
|
||||
)
|
||||
}
|
||||
const { p12Path, password } = ensureRcodesignSelfSignedP12(bin)
|
||||
const r = spawnSync(
|
||||
bin,
|
||||
[
|
||||
'sign',
|
||||
'--p12-file',
|
||||
p12Path,
|
||||
'--p12-password',
|
||||
password,
|
||||
'--code-signature-flags',
|
||||
'runtime',
|
||||
binPath,
|
||||
],
|
||||
{ encoding: 'utf8' }
|
||||
)
|
||||
if (r.status !== 0) {
|
||||
throw new Error(`rcodesign sign failed:\n${r.stderr || r.stdout}`)
|
||||
}
|
||||
log('rcodesign ok')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} binPath
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function signBinary(binPath) {
|
||||
if (process.env.BARE_OS_SKIP_MACOS_SIGN === '1') {
|
||||
log('skip (BARE_OS_SKIP_MACOS_SIGN=1)')
|
||||
return
|
||||
}
|
||||
if (!fs.existsSync(binPath)) throw new Error(`missing binary: ${binPath}`)
|
||||
const id = identity()
|
||||
if (process.platform === 'darwin') {
|
||||
codesignDarwin(binPath, id)
|
||||
} else {
|
||||
codesignRcodesign(binPath)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { signBinary, identity }
|
||||
|
||||
if (require.main === module) {
|
||||
const target = process.argv[2]
|
||||
if (!target) {
|
||||
console.error('Usage: node scripts/sign-macos-binary.cjs <binary>')
|
||||
process.exit(1)
|
||||
}
|
||||
signBinary(path.resolve(target)).catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user