diff --git a/webhook.cjs b/webhook.cjs index 04fc41a..d04d421 100644 --- a/webhook.cjs +++ b/webhook.cjs @@ -117,26 +117,68 @@ function verifySignature(rawBody, signature) { ) } +function executableExists(filePath) { + try { + return fs.existsSync(filePath) && fs.statSync(filePath).isFile() + } catch { + return false + } +} + +function cargoCommand() { + if (process.env.CARGO && executableExists(process.env.CARGO)) return process.env.CARGO + + const homeCargo = path.join(os.homedir(), '.cargo', 'bin', process.platform === 'win32' ? 'cargo.exe' : 'cargo') + if (executableExists(homeCargo)) return homeCargo + + for (const candidate of [ + '/usr/local/cargo/bin/cargo', + '/usr/local/bin/cargo', + '/usr/bin/cargo', + ]) { + if (executableExists(candidate)) return candidate + } + + return process.platform === 'win32' ? 'cargo.exe' : 'cargo' +} + function commandFor(command) { + if (command === 'cargo') return cargoCommand() if (process.platform !== 'win32') return command if (command === 'npm') return 'npm.cmd' if (command === 'pm2') return 'pm2.cmd' return command } +function commandNotFoundMessage(command) { + if (command !== 'cargo') return `${command} was not found` + return [ + 'cargo was not found by the deploy webhook', + 'Install Rust on the host, or set CARGO to the absolute cargo binary path', + `Checked PATH plus ${path.join(os.homedir(), '.cargo', 'bin', process.platform === 'win32' ? 'cargo.exe' : 'cargo')}`, + ].join('. ') +} + function run(command, args, options = {}) { return new Promise((resolve, reject) => { const label = [command, ...args].join(' ') console.log(`deploy step started: ${label}`) - const child = spawn(commandFor(command), args, { + const resolvedCommand = commandFor(command) + const child = spawn(resolvedCommand, args, { cwd: __dirname, env: { ...process.env, ...options.env }, shell: process.platform === 'win32', stdio: 'inherit', }) - child.on('error', reject) + child.on('error', (error) => { + if (error.code === 'ENOENT') { + reject(new Error(commandNotFoundMessage(command))) + return + } + reject(error) + }) child.on('exit', (code) => { if (code === 0) { console.log(`deploy step completed: ${label}`)