typescript - AWS CodeBuild tsc fel TS2307: Kan inte hitta modul


Jag har skapat ett par olika TypeScript CDK-pipelines, och de stöter alla på samma tsc-fel under CodeBuild-fasen.

Två av dessa pipelines kopierades via cdk-dokumentationen:

  • https://docs.aws.amazon.com/cdk/latest/guide/codepipeline_example.html
  • https://cdkworkshop.com/20-typescript/70-advanced-topics/200-pipelines.html

I princip fungerar npm i (eller npm ci) + tsc bra lokalt, men när det görs via CodeBuild verkar det som att mina beroenden inte har sina beroenden installerade, vilket gör att tsc går sönder.

Har någon annan stött på detta problem? Eller med andra ord, varför beter sig npm install + tsc annorlunda på CodeBuild?

CodeBuild-logg 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

> [email  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! [email  build: `tsc`
npm ERR! Exit status 2

CodeBuild-logg 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 [email  No repository field.
npm WARN [email  No license field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email  (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email : 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

> [email  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! [email  build: `tsc`
npm ERR! Exit status 2

Andra detaljer:

  • Jag såg till att alla mina @aws-cdk/* beroenden var installerade på exakt samma version
  • Återupprepade problemet på cdk 1.60.0, 1.92.0, 1.93.0
  • PipelineStack-klass från CodeBuild-logg 1:
// 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');

  • Genererade buildspec.yaml från CodeBuild-logg 1:
{
  "version": "0.2",
  "phases": {
    "pre_build": {
      "commands": [
        "npm ci"
      ]
    },
    "build": {
      "commands": [
        "npm run build",
        "npx cdk synth"
      ]
    }
  },
  "artifacts": {
    "base-directory": "cdk.out",
    "files": "**/*"
  }
}

Svar #1

Kort svar

Använd samma npm-version lokalt och i CodeBuild. Jag misstänker att problemet uppstår eftersom du använder en nyare npm-version lokalt än den som CodeBuild använder.

Längre svar

CodeBuild kör bygget i en viss miljö (Docker-image), och denna miljö har vissa versioner av runtime/programpaket installerade, t.ex. Node.js/npm. Så om du utvecklar med npm v7.x och din CodeBuild använder npm v6.x, då kommer din package-lock.json-fil som används av npm ci-kommandot inte att vara kompatibel med CodeBuilds miljö, och bygget kommer att misslyckas.
(När du använder CDK väljs imagen åt dig som en del av SimpleSynthAction.standardNpmSynth-aktionen.)
Lyckligtvis kan du ändra en av dem för att matcha den andra.

Gör din lokala version av Node.js/npm matcha den som används i CodeBuild

  1. Först ta reda på vilken Docker-bild CodeBuild använder genom att gå till CodeBuild > Byggprojekt > ditt byggprojekt > Byggdetaljer (nya AWS-konsolen). I avsnittet Miljö listas bilden som används för att bygga under Bild.
  2. Hitta sedan den runtime-version som används av den bilden i denna översikt (om du är intresserad, kolla in bildens Dockerfile). Till exempel är den senaste "nodejs"-runtime som stöds 14, och den stöds endast av bilden "Ubuntu standard:5.0". Standardbilden som används av SimpleSynthAction.standardNpmSynth är "Ubuntu standard:4.0".
  3. Använd det där runtime lokalt.

Få CodeBuild att använda din önskade version(er) av runtime

Återigen finns det flera sätt att uppnå detta:

  1. Välj en annan miljö (Docker-bild) för din build. När du använder CDK kan detta göras t.ex. genom att ange environment-egenskapen för din 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'
        }),
    });
    
  2. Ange körningstidsversioner i buildspec-filen, t.ex.

    phases:
      install:
        runtime-versions:
          nodejs: 14.x
    
  3. Detta kan vara lite mer riskabelt eftersom den version(er) av runtime du anger kan vara inkompatibla med andra runtime-versioner (t.ex. de som redan finns i den valda Docker-bilden).

  4. Installera önskad runtime-version, ja, runtime, t.ex. genom att åsidosätta installCommand med 'npm i -g npm && npm ci' som föreslagits av författaren till GitHub-ärendet som refereras av @therealsebo. Jag skulle personligen inte rekommendera detta, det verkar bara vara lite för mycket av en hack, och det finns ingen garanti för att det kommer att (fortsätta att) fungera.

Bonusinformation

Du kan köra CodeBuild lokalt för att simulera CodeBuild-miljön. Från guiden är det också tydligt att du fattar ett beslut om vilken Docker-bild som ska användas.

Slutsats

Problemet du beskriver kan bara vara ett särskilt problem med npm v6.x kontra v7.x, men jag tror att det representerar en bredare kategori av problem, som alla bör kunna lösas genom att veta vilka versioner av olika paket/runtime som CodeBuild använder, och i huvudsak anpassa dina förväntningar till verkligheten (eller ändra verkligheten).

Svar #2

Jag har stött på samma problem.

Lösningen i det här GH-ärendet (https://github.com/aws/aws-cdk/issues/13339) hjälpte mig.

Jag ändrade min buildspec i CDK på det här sättet

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

detta kommer att generera följande (inline) buildspec för Pipeline Build-steget:

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

Efter att ha pushat koden och kört pipelinen för första gången var jag tvungen att ändra buildspec själv eftersom pipelinens mutationssteg triggas efter byggsteget. Så de nya buildspec-inställningarna kommer att tillämpas efter mutationssteget.

Relaterade artiklar