首页 > 解决方案 > 用于克隆 Bitbbuket 存储库并推送到 s3 的 Nodejs-Lambda 函数

问题描述

每当将提交推送到 SCM(使用 webhooks--->APi 网关触发 lambda)以克隆 BitBucket-server 存储库并将其作为 zip 文件推送到 s3 存储桶时,我都使用下面的 node.js 代码运行 lambda 函数,成功克隆存储库时 lambda 函数超时。我正在使用从 apigateway 传递的事件/json 正文。

const axios = require('axios');
const s3 = new AWS.S3();
const crypto = require('crypto');

exports.handler = async (event) => {

        console.log(`Incoming event: ${JSON.stringify(event)}`);
        const eventBody = JSON.parse(event.body);

      
        const normalizedHeaders = normalizeObject(event.headers);

       
        if ('x-event-key' in normalizedHeaders && normalizedHeaders['x-event-key'] === 'diagnostics:ping') {
            return responseToApiGw(200, 'Webhook configured successfully');
        }

       
        if (!(checkSignature(process.env.BITBUCKET_SECRET, normalizedHeaders['x-hub-signature'], event.body))) {
            console.log('Invalid webhook message signature');
            return responseToApiGw(401, 'Signature is not valid');
        }
        console.log('Signature validated successfully');

        if (!(eventBody.changes[0].ref.type === 'BRANCH')) {
            console.log('Invalid event type');
            throw new Error('Invalid event type');
        }

        const repoConfig = {
            serverUrl: process.env.BITBUCKET_SERVER_URL,
            projectName: eventBody.repository.project.key,
            repoName: eventBody.repository.name,
            branch: eventBody.changes[0].ref.displayId,
            token: process.env.BITBUCKET_TOKEN
        };



        const file = await downloadFile(repoConfig);
        console.log(file);

        const s3Upload = await s3.upload({
            Bucket: process.env.S3BUCKET,
            ServerSideEncryption: 'AES256',
            Key: `${repoConfig.projectName}/${repoConfig.repoName}/${repoConfig.branch}.zip`,
            Body: file
        }).promise();
        console.log(s3Upload);

        console.log('Exiting successfully');
        return responseToApiGw(200, 'success');
};

function normalizeObject(inputObject) {
    console.log('info', '>>> normalizeObject()');

    const requestKeys = Object.keys(inputObject);

    let outputObject = {};
    for (let i = 0; i < requestKeys.length; i++) {
        outputObject[requestKeys[i].toLowerCase()] = inputObject[requestKeys[i]];
    }

    console.log('info', '<<< normalizeObject()');
    return outputObject;
}
async function downloadFile(repoConfig) {
    console.log('info', '>>> downloadFile()');
  

    const params = {
        method: 'get',
        baseURL: repoConfig.serverUrl,
        url: `/rest/api/latest/projects/${repoConfig.projectName}/repos/${repoConfig.repoName}/archive?at=refs/heads/${repoConfig.branch}&format=zip`,
        responseType: 'stream',
        headers: {
            Authorization: `Bearer ${repoConfig.token}`
        }
    };

    try {
        const resp = await axios.request(params);
        console.log('info', '<<< downloadFile()');
        return resp.data;
    }
    catch (err) {
        console.log('error', err);
        throw new Error(err);
    }
}
function checkSignature(signingSecret, signature, body) {
    console.log('info', '>>> signingSecret()');
    const hash = crypto.createHmac('sha256', signingSecret).update(body).digest('hex');

    const signatureHash = signature.split('=');
    if (signatureHash[1] === hash) {
        console.log('info', '<<< signingSecret()');
        return true;
    }

    console.log('info', '<<< signingSecret()');
    return false;
}


function responseToApiGw(statusCode, detail) {
    if (!statusCode) {
        throw new TypeError('responseToApiGw() expects at least argument statusCode');
    }
    if (statusCode !== '200' && !detail) {
        throw new TypeError('responseToApiGw() expects at least arguments statusCode and detail');
    }

    let body = {};
    if (statusCode === '200' && detail) {
        body = {
            statusCode: statusCode,
            message: detail
        };
    } else if (statusCode === '200' && !detail) {
        body = {
            statusCode: statusCode
        };
    } else {
        body = {
            statusCode: statusCode,
            fault: detail
        };
    }
    let response = {
        statusCode: statusCode,
        body: JSON.stringify(body),
        headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'POST, GET',
            'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'
        }
    };
    return response;
}```

标签: node.jsgitamazon-web-servicesaws-lambdanode-modules

解决方案


推荐阅读