返回 CodeWhale
prepare-local-release-assets.js
根目录 / scripts / release / prepare-local-release-assets.js
1 #!/usr/bin/env node
2
3 const crypto = require("crypto");
4 const fs = require("fs/promises");
5 const path = require("path");
6
7 const {
8 allReleaseAssetNames,
9 BUNDLE_ASSET_NAMES,
10 BUNDLE_CHECKSUM_MANIFEST,
11 CHECKSUM_MANIFEST,
12 detectBinaryNames,
13 } = require("../../npm/codewhale/scripts/artifacts");
14
15 const WINDOWS_LAUNCHER = "codewhale.bat";
16 const WINDOWS_CLI_ASSET = "codewhale-windows-x64.exe";
17
18 async function sha256(filePath) {
19 const content = await fs.readFile(filePath);
20 return crypto.createHash("sha256").update(content).digest("hex");
21 }
22
23 async function main() {
24 const prepareAllAssets =
25 process.env.CODEWHALE_PREPARE_ALL_ASSETS === "1" ||
26 process.env.DEEPSEEK_TUI_PREPARE_ALL_ASSETS === "1" ||
27 process.env.DEEPSEEK_PREPARE_ALL_ASSETS === "1";
28 const outputDir = path.resolve(
29 process.argv[2] || path.join("target", "npm-release-assets"),
30 );
31 const buildDir = path.resolve(
32 process.argv[3] || path.join("target", "release"),
33 );
34 const { codewhale, codew } = detectBinaryNames();
35 const isWindows = process.platform === "win32";
36 const sourceBinary = path.join(
37 buildDir,
38 isWindows ? "codewhale.exe" : "codewhale",
39 );
40
41 const assets = [
42 {
43 source: sourceBinary,
44 target: codewhale,
45 },
46 {
47 source: sourceBinary,
48 target: codew,
49 },
50 ];
51
52 if (prepareAllAssets) {
53 for (const assetName of allReleaseAssetNames()) {
54 if (
55 assetName === WINDOWS_LAUNCHER ||
56 assetName === CHECKSUM_MANIFEST ||
57 assetName === BUNDLE_CHECKSUM_MANIFEST
58 ) {
59 continue;
60 }
61 if (assets.some((asset) => asset.target === assetName)) {
62 continue;
63 }
64 assets.push({
65 source: sourceBinary,
66 target: assetName,
67 });
68 }
69 }
70
71 await fs.mkdir(outputDir, { recursive: true });
72
73 const manifestLines = [];
74 for (const asset of assets) {
75 const outputPath = path.join(outputDir, asset.target);
76 await fs.copyFile(asset.source, outputPath);
77 manifestLines.push(`${await sha256(outputPath)} ${asset.target}`);
78 }
79
80 if (assets.some((asset) => asset.target === WINDOWS_CLI_ASSET)) {
81 const batContent = [
82 "@echo off",
83 "where wt >nul 2>nul",
84 "set NO_ANIMATIONS=1",
85 'if "%ERRORLEVEL%"=="0" (',
86 ' wt --title Codewhale cmd /k "%~dp0codewhale-windows-x64.exe"',
87 ") else (",
88 ' "%~dp0codewhale-windows-x64.exe"',
89 ")",
90 "",
91 ].join("\r\n");
92 const batPath = path.join(outputDir, WINDOWS_LAUNCHER);
93 await fs.writeFile(batPath, batContent, "utf8");
94 const batHash = await sha256(batPath);
95 manifestLines.push(`${batHash} ${WINDOWS_LAUNCHER}`);
96 console.log(`Generated ${batPath}`);
97 }
98
99 if (prepareAllAssets) {
100 const bundleManifestLines = [];
101 for (const assetName of BUNDLE_ASSET_NAMES) {
102 const assetPath = path.join(outputDir, assetName);
103 bundleManifestLines.push(`${await sha256(assetPath)} ${assetName}`);
104 }
105 bundleManifestLines.sort();
106 const bundleManifestPath = path.join(outputDir, BUNDLE_CHECKSUM_MANIFEST);
107 await fs.writeFile(
108 bundleManifestPath,
109 `${bundleManifestLines.join("\n")}\n`,
110 "utf8",
111 );
112 manifestLines.push(
113 `${await sha256(bundleManifestPath)} ${BUNDLE_CHECKSUM_MANIFEST}`,
114 );
115 console.log(`Wrote bundle checksum manifest ${bundleManifestPath}`);
116 }
117
118 manifestLines.sort();
119 const manifestPath = path.join(outputDir, CHECKSUM_MANIFEST);
120 await fs.writeFile(manifestPath, `${manifestLines.join("\n")}\n`, "utf8");
121
122 const preparedCount = prepareAllAssets
123 ? allReleaseAssetNames().length
124 : assets.length + 1;
125 console.log(`Prepared ${preparedCount} assets in ${outputDir}`);
126 console.log(`Wrote checksum manifest ${manifestPath}`);
127 }
128
129 main().catch((error) => {
130 console.error("Failed to prepare local release assets:", error.message);
131 process.exit(1);
132 });
133
133 lines JAVASCRIPT