#!/usr/bin/env node /** * 把 SSH 私钥转换为“单行 base64”,用于放入 Gitea Secrets(例如 DEV_SSH_KEY_B64)。 * * 用法: * 1) 从文件读取: * node scripts/ssh-key-to-b64.mjs ~/.ssh/deploy_key * * 2) 从 stdin 读取(直接粘贴私钥内容,结束后按 Ctrl+D): * node scripts/ssh-key-to-b64.mjs - * * 3) 输出同时复制到剪贴板(仅 macOS,需系统自带 pbcopy): * node scripts/ssh-key-to-b64.mjs ~/.ssh/deploy_key --clipboard * * 注意: * - 请不要把输出写入仓库或提交到 git。 * - 工作流会优先使用 *_SSH_KEY_B64(更稳,避免多行换行丢失)。 */ import fs from 'node:fs'; import { spawnSync } from 'node:child_process'; function printHelp() { console.log(`用法: node scripts/ssh-key-to-b64.mjs <私钥文件路径> [--clipboard] node scripts/ssh-key-to-b64.mjs - [--clipboard] 示例: node scripts/ssh-key-to-b64.mjs ~/.ssh/deploy_key node scripts/ssh-key-to-b64.mjs - --clipboard `); } const args = process.argv.slice(2); const clipboard = args.includes('--clipboard') || args.includes('-c'); const help = args.includes('--help') || args.includes('-h'); const input = args.find((a) => !a.startsWith('-')); if (help || !input) { printHelp(); process.exit(help ? 0 : 1); } function readAllStdin() { return fs.readFileSync(0); } let buf; try { if (input === '-') { buf = readAllStdin(); } else { buf = fs.readFileSync(input); } } catch (e) { console.error(`读取失败:${String(e?.message || e)}`); process.exit(1); } // 规范化:去掉末尾的换行/回车(避免少数环境里复制粘贴多一个空行) let text = buf.toString('utf8').replace(/\r/g, ''); text = text.replace(/\n+$/g, '\n'); if (!text.includes('BEGIN') || !text.includes('PRIVATE KEY')) { console.error('提示:输入内容看起来不像 SSH 私钥(未检测到 PRIVATE KEY 头部)。仍会继续转换,但请确认输入正确。'); } const b64 = Buffer.from(text, 'utf8').toString('base64'); if (clipboard) { if (process.platform !== 'darwin') { console.error('当前不是 macOS,无法使用 --clipboard(需要 pbcopy)。将仅输出到 stdout。'); } else { const r = spawnSync('pbcopy', [], { input: b64, encoding: 'utf8' }); if (r.status !== 0) { console.error(`复制到剪贴板失败:pbcopy 退出码=${r.status}`); } else { console.error('已复制到剪贴板:请粘贴到 Gitea Secrets(例如 DEV_SSH_KEY_B64)。'); } } } // 只输出 base64(单行) process.stdout.write(b64);