Невозможно найти актив в /home/runner/CDK_Test/frontend/frontendapp/build при запуске развертывания CDK на GitHub. Действие

Ему не удалось найти сборку из frontendapp, когда я попытался запустить развертывание cdk в действиях GitHub. Я проверил путь к сборке, и, похоже, проблем нет. Я попробовал запустить cdk deploy --all локально, и он работает, когда я открываю веб-сайт, на котором отображается содержимое из frontendapp/build.

Сообщение об ошибке:

Run cdk deploy --all
/home/runner/work/CDK_Test/CDK_Test/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1
"use strict";var _a;Object.defineProperty(exports,"__esModule",{value:!0}),exports.AssetStaging=void 0;var jsiiDeprecationWarnings=()=>{var tmp=require("../../.warnings.jsii.js");return jsiiDeprecationWarnings=()=>tmp,tmp};const JSII_RTTI_SYMBOL_1=Symbol.for("jsii.rtti");var crypto=()=>{var tmp=require("crypto");return crypto=()=>tmp,tmp},path=()=>{var tmp=require("path");return path=()=>tmp,tmp},constructs_1=()=>{var tmp=require("constructs");return constructs_1=()=>tmp,tmp},fs=()=>{var tmp=require("fs-extra");return fs=()=>tmp,tmp},assets_1=()=>{var tmp=require("./assets");return assets_1=()=>tmp,tmp},bundling_1=()=>{var tmp=require("./bundling");return bundling_1=()=>tmp,tmp},fs_1=()=>{var tmp=require("./fs");return fs_1=()=>tmp,tmp},fingerprint_1=()=>{var tmp=require("./fs/fingerprint");return fingerprint_1=()=>tmp,tmp},names_1=()=>{var tmp=require("./names");return names_1=()=>tmp,tmp},asset_staging_1=()=>{var tmp=require("./private/asset-staging");return asset_staging_1=()=>tmp,tmp},cache_1=()=>{var tmp=require("./private/cache");return cache_1=()=>tmp,tmp},stack_1=()=>{var tmp=require("./stack");return stack_1=()=>tmp,tmp},stage_1=()=>{var tmp=require("./stage");return stage_1=()=>tmp,tmp},cxapi=()=>{var tmp=require("../../cx-api");return cxapi=()=>tmp,tmp};const ARCHIVE_EXTENSIONS=[".tar.gz",".zip",".jar",".tar",".tgz"],ASSET_SALT_CONTEXT_KEY = "@aws-cdk/core:assetHashSalt";class AssetStaging extends constructs_1().Construct{static clearAssetHashCache(){this.assetCache.clear(),(0,fingerprint_1().clearLargeFileFingerprintCache)()}constructor(scope,id,props){super(scope,id);try{jsiiDeprecationWarnings().aws_cdk_lib_AssetStagingProps(props)}catch(error){throw process.env.JSII_DEBUG!= = "1"&&error.name== = "DeprecationError"&&Error.captureStackTrace(error,AssetStaging),error}const salt=this.node.tryGetContext(ASSET_SALT_CONTEXT_KEY);if (this.sourcePath=path().resolve(props.sourcePath),this.fingerprintOptions = {...props,exclude:[".is_custom_resource",...props.exclude??[]],extraHash:props.extraHash||salt?`${props.extraHash??""}${salt??""}`:void 0},!fs().existsSync(this.sourcePath))throw new Error(`Cannot find asset at ${this.sourcePath}`);this.sourceStats=fs().statSync(this.sourcePath);const outdir=stage_1().Stage.of(this)?.assetOutdir;if (!outdir)throw new Error('unable to determine cloud assembly asset output directory. Assets must be defined indirectly within a "Stage" or an "App" scope');this.assetOutdir=outdir,this.customSourceFingerprint=props.assetHash,this.hashType=determineHashType(props.assetHashType,this.customSourceFingerprint);let stageThisAsset,skip=!1;if (props.bundling){skip=!stack_1().Stack.of(this).bundlingRequired;const bundling=props.bundling;stageThisAsset=()=>this.stageByBundling(bundling,skip)}else stageThisAsset=()=>this.stageByCopying();this.cacheKey=calculateCacheKey({outdir:this.assetOutdir,sourcePath:path().resolve(props.sourcePath),bundling:props.bundling,assetHashType:this.hashType,customFingerprint:this.customSourceFingerprint,extraHash:props.extraHash,exclude:props.exclude,ignoreMode:props.ignoreMode,skip});const staged=AssetStaging.assetCache.obtain(this.cacheKey,stageThisAsset);this.stagedPath=staged.stagedPath,this.absoluteStagedPath=staged.stagedPath,this.assetHash=staged.assetHash,this.packaging=staged.packaging,this.isArchive=staged.isArchive}get sourceHash(){return this.assetHash}relativeStagedPath(stack){try{jsiiDeprecationWarnings().aws_cdk_lib_Stack(stack)}catch(error){throw process.env.JSII_DEBUG!= = "1"&&error.name== = "DeprecationError"&&Error.captureStackTrace(error,this.relativeStagedPath),error}const asmManifestDir=stage_1().Stage.of(stack)?.outdir;return asmManifestDir?path().relative(this.assetOutdir,this.stagedPath).startsWith("..")||this.stagingDisabled?this.stagedPath:path().relative(asmManifestDir,this.stagedPath):this.stagedPath}stageByCopying(){const assetHash=this.calculateHash(this.hashType),stagedPath=this.stagingDisabled?this.sourcePath:path().resolve(this.assetOutdir,renderAssetFilename(assetHash,getExtension(this.sourcePath)));if (!this.sourceStats.isDirectory()&&!this.sourceStats.isFile())throw new Error(`Asset ${this.sourcePath} is expected to be either a directory or a regular file`);return this.stageAsset(this.sourcePath,stagedPath,"copy"),{assetHash,stagedPath,packaging:this.sourceStats.isDirectory()?assets_1().FileAssetPackaging.ZIP_DIRECTORY:assets_1().FileAssetPackaging.FILE,isArchive:this.sourceStats.isDirectory()||ARCHIVE_EXTENSIONS.includes(getExtension(this.sourcePath).toLowerCase())}}stageByBundling(bundling,skip){if (!this.sourceStats.isDirectory())throw new Error(`Asset ${this.sourcePath} is expected to be a directory when bundling`);if (skip){let hashType=this.hashType;return(hashType===assets_1().AssetHashType.OUTPUT||hashType===assets_1().AssetHashType.BUNDLE)&&(this.customSourceFingerprint=names_1().Names.uniqueId(this),hashType=assets_1().AssetHashType.CUSTOM),{assetHash:this.calculateHash(hashType,bundling),stagedPath:this.sourcePath,packaging:assets_1().FileAssetPackaging.ZIP_DIRECTORY,isArchive:!0}}let assetHash=this.hashType===assets_1().AssetHashType.SOURCE||this.hashType===assets_1().AssetHashType.CUSTOM?this.calculateHash(this.hashType,bundling):void 0;const bundleDir=this.determineBundleDir(this.assetOutdir,assetHash);this.bundle(bundling,bundleDir);const bundlingOutputType=bundling.outputType??bundling_1().BundlingOutput.AUTO_DISCOVER,bundledAsset=determineBundledAsset(bundleDir,bundlingOutputType);assetHash=assetHash??this.calculateHash(this.hashType,bundling,bundledAsset.path);const stagedPath=path().resolve(this.assetOutdir,renderAssetFilename(assetHash,bundledAsset.extension));return this.stageAsset(bundledAsset.path,stagedPath,"move"),bundledAsset.packaging===assets_1().FileAssetPackaging.FILE&&(this.hashType===assets_1().AssetHashType.OUTPUT||this.hashType===assets_1().AssetHashType.BUNDLE?fs().removeSync(path().dirname(bundledAsset.path)):fs().closeSync(fs().openSync(bundledAsset.path,"w"))),{assetHash,stagedPath,packaging:bundledAsset.packaging,isArchive:bundlingOutputType!==bundling_1().BundlingOutput.SINGLE_FILE}}get stagingDisabled(){return!!this.node.tryGetContext(cxapi().DISABLE_ASSET_STAGING_CONTEXT)}stageAsset(sourcePath,targetPath,style){if (fs().existsSync(targetPath)){style== = "move"&&sourcePath!==targetPath&&fs().removeSync(sourcePath);return}if (style= = "move"){fs().renameSync(sourcePath,targetPath);return}if (this.sourceStats.isFile())fs().copyFileSync(sourcePath,targetPath);else if (this.sourceStats.isDirectory())fs().mkdirSync(targetPath),fs_1().FileSystem.copyDirectory(sourcePath,targetPath,this.fingerprintOptions);else throw new Error(`Unknown file type: ${sourcePath}`)}determineBundleDir(outdir,sourceHash){return sourceHash?path().resolve(outdir,renderAssetFilename(sourceHash)):path().resolve(outdir,`bundling-temp-${this.cacheKey}`)}bundle(options,bundleDir){if (fs().existsSync(bundleDir))return;fs().ensureDirSync(bundleDir),fs().chmodSync(bundleDir,511);let localBundling;try{if (process.stderr.write(`Bundling asset ${this.node.path}...
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ^
Error: Cannot find asset at /home/runner/work/CDK_Test/CDK_Test/frontend/frontendapp/build
    at new AssetStaging (/home/runner/work/CDK_Test/CDK_Test/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:2119)
    at new Asset (/home/runner/work/CDK_Test/CDK_Test/node_modules/aws-cdk-lib/aws-s3-assets/lib/asset.js:1:1141)
    at Object.bind (/home/runner/work/CDK_Test/CDK_Test/node_modules/aws-cdk-lib/aws-s3-deployment/lib/source.js:1:1460)
    at /home/runner/work/CDK_Test/CDK_Test/node_modules/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.js:1:3768
    at Array.map (<anonymous>)
    at new BucketDeployment (/home/runner/work/CDK_Test/CDK_Test/node_modules/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.js:1:3749)
    at new FrontendStack (/home/runner/work/CDK_Test/CDK_Test/cdk/lib/cdk_test-frontend-stack.ts:70:3)
    at new AppStack (/home/runner/work/CDK_Test/CDK_Test/cdk/lib/cdk_test-app-stack.ts:11:27)
    at Object.<anonymous> (/home/runner/work/CDK_Test/CDK_Test/cdk/lib/cdk_test-app-stack.ts:32:1)
    at Module._compile (node:internal/modules/cjs/loader:1358:14)

Subprocess exited with error 1
Error: Process completed with exit code 1.

.github/workflows/deploy.yml:

name: Deploy to AWS

on:
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

env:
  AWS_REGION: 'us-east-1'

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm install

      - name: Install AWS CDK
        run: npm install -g aws-cdk

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          role-to-assume: ${{secrets.ROLE_TO_ASSUME}}
          aws-region: ${{ env.AWS_REGION }}
          role-session-name: GitHubActions

      - name: CDK deploy
        run: cdk deploy --all

      - name: Run Sequelize commands
        env:
          DB_USERNAME: ${{ secrets.USERNAME }}
          DB_PASSWORD: ${{ secrets.PASSWORD }}
          DB_NAME: ${{ secrets.DATABASE }}
          DB_HOST: ${{ secrets.HOST }}
        run: |
          npx sequelize db:migrate

Коды фрагмента cdk/lib/cdk_test-frontend-stack.ts:

const distribution = new cloudfront.CloudFrontWebDistribution(
    this,
    "cloudfront",
    {
      originConfigs: [
        {
          s3OriginSource: {
            s3BucketSource: websiteBucket,
            originAccessIdentity: identity,
          },
          behaviors: [
            {
              viewerProtocolPolicy:
                cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
              allowedMethods: cloudfront.CloudFrontAllowedMethods.GET_HEAD,
              compress: true,
              isDefaultBehavior: true,
            },
          ],
        },
      ],
      defaultRootObject: "./frontend/frontendapp/build/index.html",
    }
  );
  
  new s3deploy.BucketDeployment(this, "DeployWebsite", {
    sources: [s3deploy.Source.asset("./frontend/frontendapp/build")],
    destinationBucket: websiteBucket,
    distribution,
    });

frontend/frontendapp/build — список файлов и каталогов сборки:

- static (dir)
- asset-manifest.json
- favicon.ico
- index.html
- logo512.png
- manifest.json
- robots.txt

Я попробовал запустить npm run build внутри frontend/frontendapp, прежде чем отправить его на GitHub, где он автоматизирует развертывание с помощью CDK. Однако развертывание не удалось. Есть ли у вас какие-либо предложения или решения по этому поводу? Заранее спасибо.


69
1

Ответ:

Решено

Я считаю, что ваша проблема будет решена, если вы:

  1. Убедитесь, что у вас есть отдельные пакеты для frontend и cdk. В каждом каталоге должны быть свои package.json и package-lock.json или эквивалентные файлы, если вы используете что-то отличное от npm.
  2. Добавьте working-directory: cdk к шагам действий с именами Install dependencies и CDK deploy.
  3. Добавьте шаги установки, сборки и тестирования внешнего интерфейса в файл действий перед шагом CDK deploy, например
    - name: Install frontend
      working-directory: frontend
      run: npm install
    - name: Build frontend
      working-directory: frontend
      run: npm run build
    - name: Test frontend
      working-directory: frontend
      run: npm test
    
    Я думаю, что это самый существенный недостающий элемент. Если npm run build не произойдет для кода интерфейса в вашем средстве Actions, каталог build/ не будет заполнен. Артефакт build/, вероятно, игнорируется Git, поскольку его содержимое создано из других файлов и поэтому не должно находиться в системе контроля версий. Таким образом, даже если вы запустите npm run build перед отправкой, файлы будут недоступны в Действиях.
  4. Измените sources: [s3deploy.Source.asset("./frontend/frontendapp/build")], на sources: [s3deploy.Source.asset("../frontend/frontendapp/build")],, изменив префикс пути с . на ...

Вам могут потребоваться некоторые незначительные корректировки, например, если у вас есть package.json в frontend/frontendapp/, а не в frontend/, но я верю, что все это сработает, если вы выполните шаги, описанные выше.

Я считаю, что лучше иметь отдельные package.json для кода CDK и кода внешнего интерфейса, потому что:

  1. Это отдельные пакеты. Зависимость одного не является зависимостью другого.
  2. Это позволяет избежать путаницы, связанной с попытками убедиться, что команды npm нацелены на правильный проект и что артефакты сборки включают правильные файлы.

У меня есть один из моих проектов, настроенный очень похоже на ваш, с использованием приведенных выше рекомендаций, и его развертывание работает успешно. Проект находится по адресу https://github.com/douglasnaphas/anagrampoems.

Вероятно, вы могли бы проигнорировать все мои рекомендации, за исключением добавления шага npm run build GitHub Actions для кода внешнего интерфейса, если вы убедитесь, что он происходит в правильном каталоге.