mirror of
https://github.com/glittercowboy/get-shit-done
synced 2026-04-25 17:25:23 +02:00
tsc emits .js files as 644; npm install -g creates the bin symlink without chmod-ing the target, so the kernel refuses to exec the file on macOS with a Homebrew npm prefix. Add a chmodSync(cliPath, 0o755) call between the build step and the global install step, matching the pattern already used for hook files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
83 lines
3.3 KiB
JavaScript
83 lines
3.3 KiB
JavaScript
/**
|
|
* Regression test for bug #2525
|
|
*
|
|
* After running the GSD installer on macOS with a Homebrew npm prefix,
|
|
* `gsd-sdk` is installed but `command -v gsd-sdk` returns nothing because
|
|
* `dist/cli.js` is installed with mode 644 (no executable bit). tsc emits
|
|
* .js files as 644, and `npm install -g .` creates the bin symlink without
|
|
* chmod-ing the target. The kernel then refuses to exec the file.
|
|
*
|
|
* Fix: between the `npm run build` step and `npm install -g .`, chmod
|
|
* dist/cli.js to 0o755. This mirrors the pattern already used for hook
|
|
* files at lines 5838, 5846, 5959, and 5965.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const { test, describe } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const INSTALL_PATH = path.join(__dirname, '..', 'bin', 'install.js');
|
|
|
|
describe('bug #2525: dist/cli.js chmod 0o755 after tsc build', () => {
|
|
const content = fs.readFileSync(INSTALL_PATH, 'utf-8');
|
|
|
|
test('install.js exists', () => {
|
|
assert.ok(fs.existsSync(INSTALL_PATH), 'bin/install.js should exist');
|
|
});
|
|
|
|
test('chmodSync is called for dist/cli.js after the build step', () => {
|
|
// Find the installSdkIfNeeded function body
|
|
const fnStart = content.indexOf('function installSdkIfNeeded()');
|
|
assert.ok(fnStart !== -1, 'installSdkIfNeeded function must exist in bin/install.js');
|
|
|
|
// Find the closing brace of the function (next top-level function definition)
|
|
const fnEnd = content.indexOf('\nfunction ', fnStart + 1);
|
|
assert.ok(fnEnd !== -1, 'installSdkIfNeeded function must have a closing boundary');
|
|
|
|
const fnBody = content.slice(fnStart, fnEnd);
|
|
|
|
// Locate the build step
|
|
const buildStep = fnBody.indexOf("'run', 'build'");
|
|
assert.ok(buildStep !== -1, "installSdkIfNeeded must contain the 'run', 'build' spawn call");
|
|
|
|
// Locate the global install step
|
|
const globalStep = fnBody.indexOf("'install', '-g', '.'");
|
|
assert.ok(globalStep !== -1, "installSdkIfNeeded must contain the 'install', '-g', '.' spawn call");
|
|
|
|
// Locate chmodSync for dist/cli.js
|
|
const chmodIdx = fnBody.indexOf("chmodSync");
|
|
assert.ok(chmodIdx !== -1, "installSdkIfNeeded must call chmodSync to set the executable bit on dist/cli.js");
|
|
|
|
// The path may be assembled via path.join(sdkDir, 'dist', 'cli.js') so check
|
|
// for the component strings rather than the joined slash form.
|
|
const cliPathIdx = fnBody.indexOf("'cli.js'");
|
|
assert.ok(cliPathIdx !== -1, "installSdkIfNeeded must reference 'cli.js' (via path.join or literal) for the chmod call");
|
|
|
|
// chmodSync must appear AFTER the build step
|
|
assert.ok(
|
|
chmodIdx > buildStep,
|
|
'chmodSync for dist/cli.js must appear AFTER the npm run build step'
|
|
);
|
|
|
|
// chmodSync must appear BEFORE the global install step
|
|
assert.ok(
|
|
chmodIdx < globalStep,
|
|
'chmodSync for dist/cli.js must appear BEFORE the npm install -g . step'
|
|
);
|
|
});
|
|
|
|
test('chmod mode is 0o755', () => {
|
|
const fnStart = content.indexOf('function installSdkIfNeeded()');
|
|
const fnEnd = content.indexOf('\nfunction ', fnStart + 1);
|
|
const fnBody = content.slice(fnStart, fnEnd);
|
|
|
|
assert.ok(
|
|
fnBody.includes('0o755'),
|
|
"chmodSync call in installSdkIfNeeded must use mode 0o755 (not 0o644 or a bare number)"
|
|
);
|
|
});
|
|
});
|