固定错误spawnsync bash eNoent在CDK兰伯达期间捆绑在CI管道上
#lambda #node #调试 #continuosintegration

tldr;

如果您在捆绑lambda函数时正在努力处理spawnSync bash ENOENT. at AssetStaging.bundle错误,请查看CDK NodejsFunctionbundling道具,然后尝试forceDockerBundling: true选项。

阅读更多有关完整上下文和解释的信息。


本周,我遇到了一个奇怪的问题,该问题导致Gitlab上的CI/CD管道停止工作,我想在这里分享解决方案以备将来参考。

语境

后端在负载平衡器后面的AWS Fargate上有一个后端。
部署发生在gitlab上,堆栈用CDK编写,因此部署作业正在使用docker:20-dind(Docker中的Docker)图像运行以捆绑二进制,构建Docker Image,将其上传到ECR,然后将其上传到Fargate任务中。 /p>

通常,在以前的项目中,我总是使用koude5来构建我的lambdas并运行CDK部署,但是随着该lake and to Backend和ECS + ECR,我必须使用DinD

然后,我添加到堆栈中的一个目标群体,指向用节点编写的lambda( 一种重构的宿主模式方法I described here)。

我直接从Mac部署到了短暂的环境,一切都很好。
一旦我推动更改,GitLab管道尝试从Gitlab Runner部署,我就会遇到一个奇怪的错误:

Error(`Failed to bundle asset ${this.node.path}, bundle output is located at ${bundleErrorDir}: ${err}`); -error: Error: spawnSync bash ENOENT. at AssetStaging.bundle

调查

一切看起来都不错,文件在那里,沿着一个管道作业将文物传递给另一个管道,每个依赖项都正确地安装了。

快速搜索导致StackOverflow,但答案无济于事。我已经在使用koude6并将其安装在依赖项中。

其他一些搜索引导我进入this,最后到达了这个repo,我注意到我忽略的lambda.nodejsfunction构造的参数:

forceDockerBundling?类型:布尔值(可选,默认:false)
即使可能捆绑在码头容器中,武力捆绑在码头容器中。
如果您的函数依赖于应安装的节点模块(nodeMotules),这将很有用。

老实说,我从没想过要强迫Docker捆绑,如果Esbuild的性能更高,为什么要这样做?

无论如何,到了早晨,我真的已经尝试了多个没有成功的事情,那为什么不呢?最终,管道中的CDK是在Docker中使用Docker,Esbuild不起作用,因此试图强迫Docker Bundling有道理。

你知道吗?当然可以。

解决方案

由于我不想放弃我的 esbuild 在我的Mac上本地捆绑时,我寻找env variables to figure out if I am running on Gitlab,这是最终的工作代码:

 const myLambda = new NodejsFunction(this, `my-lambda`, {
     functionName: `my-lambda`,
     entry: 'lambdas/my-lambda.ts'),
     timeout: Duration.seconds(15),
     handler: 'handler',
     runtime: Runtime.NODEJS_16_X,
     bundling: {
        forceDockerBundling: Boolean(process.env.CI), 
        // use esbuild when running locally otherwise rely on docker
        define: {},
        minify: true,
        externalModules: ['aws-sdk'],
     }
  })


由于这在部署时间引起了很多沮丧和头痛,我希望它对他人有用。