AWS CodeBuild tsc 错误 TS2307:找不到模块

Mak*_*ker 7 typescript tsc aws-codebuild aws-cdk

我创建了几个不同的 TypeScript cdk 管道,它们在 CodeBuild 阶段都遇到了相同的 tsc 错误。

其中两个管道是通过 cdk 文档复制的:

本质上,npm i(或npm ci) +tsc在本地工作正常,但是当通过 CodeBuild 完成时,似乎我的依赖项没有安装它们的依赖项,从而导致tsc中断。

有没有其他人遇到过这个问题?或者换句话说,为什么npm install+tsc在 CodeBuild 上表现不同?

代码构建日志 1:

[Container] 2021/03/11 19:11:35 Waiting for DOWNLOAD_SOURCE
[Container] 2021/03/11 19:11:36 Phase is DOWNLOAD_SOURCE
[Container] 2021/03/11 19:11:36 CODEBUILD_SRC_DIR=/codebuild/output/src038984068/src
[Container] 2021/03/11 19:11:36 YAML location is /codebuild/readonly/buildspec.yml
[Container] 2021/03/11 19:11:36 Processing environment variables
[Container] 2021/03/11 19:11:36 No runtime version selected in buildspec.
[Container] 2021/03/11 19:11:36 Moving to directory /codebuild/output/src038984068/src
[Container] 2021/03/11 19:11:36 Registering with agent
[Container] 2021/03/11 19:11:36 Phases found in YAML: 2
[Container] 2021/03/11 19:11:36  PRE_BUILD: 1 commands
[Container] 2021/03/11 19:11:36  BUILD: 2 commands
[Container] 2021/03/11 19:11:36 Phase complete: DOWNLOAD_SOURCE State: SUCCEEDED
[Container] 2021/03/11 19:11:36 Phase context status code:  Message: 
[Container] 2021/03/11 19:11:36 Entering phase INSTALL
[Container] 2021/03/11 19:11:36 Phase complete: INSTALL State: SUCCEEDED
[Container] 2021/03/11 19:11:36 Phase context status code:  Message: 
[Container] 2021/03/11 19:11:36 Entering phase PRE_BUILD
[Container] 2021/03/11 19:11:36 Running command npm ci
added 772 packages in 7.728s

[Container] 2021/03/11 19:11:48 Phase complete: PRE_BUILD State: SUCCEEDED
[Container] 2021/03/11 19:11:48 Phase context status code:  Message: 
[Container] 2021/03/11 19:11:48 Entering phase BUILD
[Container] 2021/03/11 19:11:48 Running command npm run build

> cdk-s3-sns-lambda@0.1.0 build /codebuild/output/src038984068/src
> tsc

node_modules/@aws-cdk/aws-codebuild/lib/pipeline-project.d.ts(1,27): error TS2307: Cannot find module 'constructs' or its corresponding type declarations.
(...cascade of missing module errors)
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! cdk-s3-sns-lambda@0.1.0 build: `tsc`
npm ERR! Exit status 2
Run Code Online (Sandbox Code Playgroud)

代码构建日志 2:

[Container] 2021/03/11 19:54:10 Waiting for agent ping
[Container] 2021/03/11 19:54:15 Waiting for DOWNLOAD_SOURCE
[Container] 2021/03/11 19:54:16 Phase is DOWNLOAD_SOURCE
[Container] 2021/03/11 19:54:16 CODEBUILD_SRC_DIR=/codebuild/output/src363431369/src
[Container] 2021/03/11 19:54:16 YAML location is /codebuild/readonly/buildspec.yml
[Container] 2021/03/11 19:54:16 Processing environment variables
[Container] 2021/03/11 19:54:16 No runtime version selected in buildspec.
[Container] 2021/03/11 19:54:16 Moving to directory /codebuild/output/src363431369/src
[Container] 2021/03/11 19:54:16 Registering with agent
[Container] 2021/03/11 19:54:16 Phases found in YAML: 2
[Container] 2021/03/11 19:54:16  INSTALL: 1 commands
[Container] 2021/03/11 19:54:16  BUILD: 2 commands
[Container] 2021/03/11 19:54:16 Phase complete: DOWNLOAD_SOURCE State: SUCCEEDED
[Container] 2021/03/11 19:54:16 Phase context status code:  Message: 
[Container] 2021/03/11 19:54:16 Entering phase INSTALL
[Container] 2021/03/11 19:54:16 Running command npm install
npm WARN read-shrinkwrap This version of npm is compatible with lockfileVersion@1, but package-lock.json was generated for lockfileVersion@2. Ill try to do my best with it!
npm WARN pipeline@0.1.0 No repository field.
npm WARN pipeline@0.1.0 No license field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

added 762 packages from 491 contributors and audited 764 packages in 12.459s

28 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities


[Container] 2021/03/11 19:54:30 Phase complete: INSTALL State: SUCCEEDED
[Container] 2021/03/11 19:54:30 Phase context status code:  Message: 
[Container] 2021/03/11 19:54:30 Entering phase PRE_BUILD
[Container] 2021/03/11 19:54:30 Phase complete: PRE_BUILD State: SUCCEEDED
[Container] 2021/03/11 19:54:30 Phase context status code:  Message: 
[Container] 2021/03/11 19:54:30 Entering phase BUILD
[Container] 2021/03/11 19:54:30 Running command npm run build

> pipeline@0.1.0 build /codebuild/output/src363431369/src
> tsc

node_modules/@aws-cdk/aws-codebuild/lib/artifacts.d.ts(1,21): error TS2307: Cannot find module '@aws-cdk/aws-s3' or its corresponding type declarations.
(...more missing module errors)
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! pipeline@0.1.0 build: `tsc`
npm ERR! Exit status 2
Run Code Online (Sandbox Code Playgroud)

其他详情:

  • 我确保我所有的 @aws-cdk/* deps 都安装在完全相同的版本上
  • 在 cdk 1.60.0、1.92.0、1.93.0 上重现问题
  • CodeBuild 日志 1 中的 PipelineStack 类:
// lib/pipeline-stack.ts
import * as cdk from '@aws-cdk/core';
import * as codecommit from '@aws-cdk/aws-codecommit';
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import * as codepipeline_actions from '@aws-cdk/aws-codepipeline-actions';
import { SimpleSynthAction, CdkPipeline } from '@aws-cdk/pipelines';

export class PipelineStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id);

    const repo = new codecommit.Repository(this, 'UploadRepo', {
      repositoryName: 'cdk-s3-sns-lambda'
    });

    const sourceArtifact = new codepipeline.Artifact();
    const cloudAssemblyArtifact = new codepipeline.Artifact();

    new CdkPipeline(this, 'CodePipeline', {
      crossAccountKeys: false,
      cloudAssemblyArtifact,
      sourceAction: new codepipeline_actions.CodeCommitSourceAction({
        actionName: 'CodeCommit',
        output: sourceArtifact,
        repository: repo
      }),
      synthAction: SimpleSynthAction.standardNpmSynth({
        sourceArtifact,
        cloudAssemblyArtifact,
        buildCommand: 'npm run build'
      }),
    });
  }
}


// bin/pipeline.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { PipelineStack } from '../lib/pipeline-stack';

const app = new cdk.App();
new PipelineStack(app, 'AppPipelineStack');

Run Code Online (Sandbox Code Playgroud)
  • buildspec.yaml从 CodeBuild 日志 1生成:
{
  "version": "0.2",
  "phases": {
    "pre_build": {
      "commands": [
        "npm ci"
      ]
    },
    "build": {
      "commands": [
        "npm run build",
        "npx cdk synth"
      ]
    }
  },
  "artifacts": {
    "base-directory": "cdk.out",
    "files": "**/*"
  }
}
Run Code Online (Sandbox Code Playgroud)

ste*_*sen 5

简短回答

在本地和 CodeBuild 中使用相同的 npm 版本。我怀疑出现此问题是因为您在本地使用的 npm 版本比 CodeBuild 使用的版本更新。

更长的答案

CodeBuild 在特定环境(Docker 镜像)中运行构建,并且该环境安装了特定版本的运行时/包,例如 Node.js/npm。因此,如果您使用 npm v7.x 进行开发,而您的 CodeBuild 使用 npm v6.x,那么该命令使用的 package-lock.json 文件npm ci将与 CodeBuild 的环境不兼容,并且构建将会失败。
(使用 CDK 时,系统会在操作过程中为您选择图像SimpleSynthAction.standardNpmSynth。)
幸运的是,您可以更改其中一个以匹配另一个。

使您的 Node.js/npm 本地版本与 CodeBuild 中使用的版本相匹配

  1. 首先通过转至 CodeBuild > 构建项目 >您的构建项目> 构建详细信息(新的 AWS 控制台)找出 CodeBuild 使用哪个 Docker 映像。在“环境”部分中,用于构建的映像列在“映像”下。
  2. 然后在此概述中找到该映像使用的运行时版本(如果您感兴趣,请查看该映像的Dockerfile)。例如,支持的最新“nodejs”运行时是 14,并且仅受“Ubuntu standard:5.0”映像支持。使用的默认镜像SimpleSynthAction.standardNpmSynth是“Ubuntu standard:4.0”。
  3. 在本地使用该运行时。

让 CodeBuild 使用您所需的运行时版本

同样,有多种方法可以实现这一目标:

  1. 为您的构建选择另一个环境(Docker 映像)。environment当您使用 CDK 时,可以通过指定以下属性来完成synthAction
    new CdkPipeline(this, 'CodePipeline', {
        crossAccountKeys: false,
        cloudAssemblyArtifact,
        sourceAction: new codepipeline_actions.CodeCommitSourceAction({
            actionName: 'CodeCommit',
            output: sourceArtifact,
            repository: repo
        }),
        synthAction: SimpleSynthAction.standardNpmSynth({
            sourceArtifact,
            cloudAssemblyArtifact,
            environment: {
                buildImage: LinuxBuildImage.STANDARD_5_0
            },
            buildCommand: 'npm run build'
        }),
    });
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在构建规范文件中指定运行时版本,例如
    phases:
      install:
        runtime-versions:
          nodejs: 14.x
    
    Run Code Online (Sandbox Code Playgroud) 这可能风险更大,因为您指定的运行时版本可能与其他运行时版本(例如,所选 Docker 映像中已有的版本)不兼容。
  3. 安装所需的运行时版本,例如,通过覆盖@therealsebo 引用的GitHub 问题的作者的建议来installCommand覆盖。我个人不会推荐这个,它看起来有点太多了,并且不能保证它会(继续)工作。'npm i -g npm && npm ci'

奖金信息

您可以在本地运行CodeBuild来模拟CodeBuild环境。从指南中还可以清楚地看出,您正在决定使用哪个 Docker 映像。

结论

您描述的问题可能只是 npm v6.x 与 v7.x 的一个特殊问题,但我认为它代表了更广泛的问题类别,所有这些问题都应该通过了解 CodeBuild 使用不同包/运行时的哪些版本来解决,本质上是使您的期望与现实保持一致(或改变现实)。


小智 4

我一直面临着同样的问题。

此 GH 问题 ( https://github.com/aws/aws-cdk/issues/13339 ) 中的解决方法帮助了我。

我像这样改变了 CDK 中的构建规范

synthAction: SimpleSynthAction.standardNpmSynth({
  sourceArtifact,
  cloudAssemblyArtifact,
  installCommand: 'npm i -g npm && npm ci'
}),
Run Code Online (Sandbox Code Playgroud)

这将为管道构建步骤生成以下(内联)构建规范:

{
  "version": "0.2",
  "phases": {
    "pre_build": {
      "commands": [
        "npm i -g npm && npm ci"
      ]
    },
    "build": {
      "commands": [
        "npx cdk synth"
      ]
    }
  },
  "artifacts": {
    "base-directory": "cdk.out",
    "files": "**/*"
  }
}
Run Code Online (Sandbox Code Playgroud)

第一次推送代码并运行管道后,我必须自己修改构建规范,因为管道突变步骤是在构建步骤之后触发的。因此,新的构建规范设置将在突变步骤之后应用。