Bamboo中Node.js任务异常却显示成功,如何让任务正确失败?
如何让Bamboo中的Node.js任务在失败时触发构建失败
我在Bamboo服务器上运行一个Node.js任务,每次Pull Request完成后执行。现在的问题是,不管任务出现异常、npm包错误还是其他类型的错误,构建始终显示成功,每次都得手动检查状态,非常麻烦。请问怎么配置才能让Node.js任务执行失败时触发构建失败?
原代码:
const sfdx = require('sfdx-node'); const ORG_NAME = 'CH_JWT'; const FIRST_DEPLOY_PATH = 'force-app/main/default'; const SECOND_DEPLOY_PATH = 'deploy_prod'; console.log("Arguments:"); process.argv.forEach(function (val, index, array) { console.log(index + ': ' + val); }); execute(process.argv[2], process.argv[3], process.argv[4]) return; // Function definition function execute(sf_username, sf_client_id, executionScript){ let authObj = { username: sf_username, clientid: sf_client_id, jwtkeyfile: 'server.key', setalias: ORG_NAME }; let firstDeployObj = { SOURCEPATH: FIRST_DEPLOY_PATH, targetusername: ORG_NAME }; let secondDeployObj = { SOURCEPATH: SECOND_DEPLOY_PATH, targetusername: ORG_NAME }; let prodDeployment = false; if(executionScript === "default" || executionScript === "validateUat" || executionScript === "validateProd"){ firstDeployObj.checkonly = true; secondDeployObj.checkonly = true; } if(executionScript === "validateProd" || executionScript === "deployProd"){ prodDeployment = true; } executeDeployment(authObj, firstDeployObj, secondDeployObj, prodDeployment); } function executeDeployment(authObj, firstDeployObj, secondDeployObj, prodDeployment) { sfdx.auth.jwt.grant(authObj).then((result) => { console.log('Authorization result: ' + JSON.stringify(result)); sfdx.force.source.deploy(firstDeployObj) .then((deploymentResult) => { if(!deploymentResult){ throw new Error('First deployment step failed'); } console.log('First deployment step result: ' + getInfoString(deploymentResult)); if(prodDeployment){ sfdx.force.source.deploy(secondDeployObj) .then((deploymentResult2) => { if(!validationResult){ throw new Error('Validation failed'); } console.log('Second deployment step result: ' + getInfoString(deploymentResult2)); }) .catch(err => { console.log(err); throw new Error('Second deployment step failed') }); } }) .catch(err => { console.log("Something went wrong:"); console.log(err); //Make job fail throw new Error('Deployment failed') }); }) .catch(err => { console.log(err); assert.equal(1,2); throw new Error('Authorization failed'); }); } function getInfoString(responseObject){ //construct response info return JSON.stringify(responseObject); }
核心原因
Bamboo通过Node.js进程的退出码判断构建状态:退出码为0时标记成功,非0则标记失败。当前代码中,异步操作抛出的错误没有触发进程退出,Node.js进程最终会以0码退出,导致Bamboo误判构建成功。
修复步骤
- 让异步函数返回Promise,并在顶层统一处理所有未捕获错误,调用
process.exit(1)返回非零退出码,触发Bamboo构建失败。 - 修复代码笔误:原代码中
executeDeployment里的validationResult未定义,应改为deploymentResult2。 - 使用async/await简化异步流程,避免Promise嵌套导致的错误遗漏,让错误逻辑更清晰。
修改后的代码
const sfdx = require('sfdx-node'); const ORG_NAME = 'CH_JWT'; const FIRST_DEPLOY_PATH = 'force-app/main/default'; const SECOND_DEPLOY_PATH = 'deploy_prod'; console.log("Arguments:"); process.argv.forEach(function (val, index, array) { console.log(index + ': ' + val); }); // 顶层执行并统一处理错误,触发进程退出 execute(process.argv[2], process.argv[3], process.argv[4]) .catch(err => { console.error("构建失败:", err); process.exit(1); // 返回非零退出码,通知Bamboo构建失败 }); // 改为async函数,返回Promise async function execute(sf_username, sf_client_id, executionScript){ let authObj = { username: sf_username, clientid: sf_client_id, jwtkeyfile: 'server.key', setalias: ORG_NAME }; let firstDeployObj = { SOURCEPATH: FIRST_DEPLOY_PATH, targetusername: ORG_NAME }; let secondDeployObj = { SOURCEPATH: SECOND_DEPLOY_PATH, targetusername: ORG_NAME }; let prodDeployment = false; if(executionScript === "default" || executionScript === "validateUat" || executionScript === "validateProd"){ firstDeployObj.checkonly = true; secondDeployObj.checkonly = true; } if(executionScript === "validateProd" || executionScript === "deployProd"){ prodDeployment = true; } await executeDeployment(authObj, firstDeployObj, secondDeployObj, prodDeployment); } // 改为async函数,用await处理异步操作 async function executeDeployment(authObj, firstDeployObj, secondDeployObj, prodDeployment) { const authResult = await sfdx.auth.jwt.grant(authObj); console.log('Authorization result: ' + JSON.stringify(authResult)); const deploymentResult = await sfdx.force.source.deploy(firstDeployObj); if(!deploymentResult){ throw new Error('First deployment step failed'); } console.log('First deployment step result: ' + getInfoString(deploymentResult)); if(prodDeployment){ const deploymentResult2 = await sfdx.force.source.deploy(secondDeployObj); if(!deploymentResult2){ // 修复原代码的未定义变量问题 throw new Error('Validation failed'); } console.log('Second deployment step result: ' + getInfoString(deploymentResult2)); } } function getInfoString(responseObject){ return JSON.stringify(responseObject); }
Bamboo端补充配置
确保Bamboo的Node.js任务配置满足:
- 执行命令为
node your-script.js(替换为你的脚本文件名) - 不要勾选“忽略退出码”相关选项,让Bamboo默认根据进程退出码判断构建状态
内容的提问来源于stack exchange,提问作者Denys Yelchaninov
相关产品推荐
相关产品推荐

