You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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误判构建成功。

修复步骤

  1. 让异步函数返回Promise,并在顶层统一处理所有未捕获错误,调用process.exit(1)返回非零退出码,触发Bamboo构建失败。
  2. 修复代码笔误:原代码中executeDeployment里的validationResult未定义,应改为deploymentResult2。
  3. 使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:50:35