Skip to content

Commit 2ee9460

Browse files
zhengyangliuclaude
andcommitted
fix(i18n): resolve tx-push-src by absolute path, not via $PATH
The i18n push shelled out to a bare `tx-push-src`, relying on node_modules/.bin being on $PATH. When the CLI is launched by absolute path from a plain `node script.js` process (as the registry sync does), that is not set up, so the command fails with "tx-push-src: not found". Resolve openblock-l10n's tx-push-src bin to an absolute script path and run it with the current Node binary via execFileSync — consistent with the trusted absolute-path launcher, and no longer PATH-dependent. Passing args as an array also fixes splitting on spaces in file paths. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 4837f6f commit 2ee9460

1 file changed

Lines changed: 27 additions & 8 deletions

File tree

src/commands/i18n/push-format-message.js

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* node push-format-message.js [--dir=path/to/resources]
1414
*/
1515

16-
const {execSync} = require('child_process');
16+
const {execFileSync} = require('child_process');
1717
const path = require('path');
1818
const fs = require('fs');
1919

@@ -37,19 +37,38 @@ const parseArgs = () => {
3737
};
3838

3939
/**
40-
* Execute a command synchronously
41-
* @param {string} cmd - Command to execute
40+
* Resolve openblock-l10n's `tx-push-src` bin to an absolute script path. It is
41+
* invoked directly with the current Node binary rather than as a bare command,
42+
* so it does not rely on $PATH or node_modules/.bin being set up — which they are
43+
* not when this CLI is launched by absolute path from a plain `node` process.
44+
* @returns {string} Absolute path to the tx-push-src script
45+
*/
46+
const resolveTxPushSrcBin = () => {
47+
const pkgJsonPath = require.resolve('openblock-l10n/package.json');
48+
const {bin} = require(pkgJsonPath);
49+
const binRel = typeof bin === 'string' ? bin : bin && bin['tx-push-src'];
50+
if (!binRel) {
51+
throw new Error('openblock-l10n does not expose a tx-push-src bin');
52+
}
53+
return path.resolve(path.dirname(pkgJsonPath), binRel);
54+
};
55+
56+
/**
57+
* Run tx-push-src with the current Node binary and explicit args (no shell, no
58+
* $PATH lookup, and no argument splitting on spaces in file paths).
59+
* @param {string} binPath - Absolute path to the tx-push-src script
60+
* @param {string[]} args - Arguments passed to tx-push-src
4261
* @returns {boolean} True if successful, false otherwise
4362
*/
44-
const runCommand = cmd => {
63+
const runTxPushSrc = (binPath, args) => {
4564
try {
46-
const output = execSync(cmd, {encoding: 'utf8'});
65+
const output = execFileSync(process.execPath, [binPath, ...args], {encoding: 'utf8'});
4766
if (output) {
4867
console.log(output);
4968
}
5069
return true;
5170
} catch (error) {
52-
console.error(`Error executing: ${cmd}`);
71+
console.error(`Error executing: tx-push-src ${args.join(' ')}`);
5372
console.error(error.message);
5473
return false;
5574
}
@@ -94,11 +113,11 @@ const main = () => {
94113
}
95114

96115
// Push each resource to Transifex
116+
const txPushSrcBin = resolveTxPushSrcBin();
97117
let allSuccess = true;
98118
for (const resource of resources) {
99119
console.log(`Pushing ${resource.name}...`);
100-
const cmd = `tx-push-src openblock-resources ${resource.name} ${resource.file}`;
101-
const success = runCommand(cmd);
120+
const success = runTxPushSrc(txPushSrcBin, ['openblock-resources', resource.name, resource.file]);
102121

103122
if (success) {
104123
console.log(`✓ ${resource.name} pushed successfully\n`);

0 commit comments

Comments
 (0)