Having trouble locating the asset at /home/runner/CDK_Test/frontend/frontendapp/build while executing CDK deploy with GitHub Action

When attempting to execute `cdk deploy` on GitHub Actions, I encountered an issue with finding the build from frontendapp. I double-checked the build path for any errors but found none. Interestingly, running `cdk deploy --all` locally successfully displays the website content coming from frontendapp/build.

The error message received was:

Error: Cannot find asset at /home/runner/work/CDK_Test/CDK_Test/frontend/frontendapp/build
...
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

      ... (remaining workflow steps omitted for brevity)

cdk/lib/cdk_test-frontend-stack.ts snippet codes:

const distribution = new cloudfront.CloudFrontWebDistribution(
    this,
    "cloudfront",
    {
      originConfigs: [
       ... (snippet continuation)
        
    });
  
  new s3deploy.BucketDeployment(this, "DeployWebsite", {
    sources: [s3deploy.Source.asset("./frontend/frontendapp/build")],
    destinationBucket: websiteBucket,
    distribution,
    });

Listing of files and directories under frontend/frontendapp/build:

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

I have attempted to run `npm run build` within frontend/frontendapp before pushing to GitHub for automated CDK deployment. Despite this, the deployment failed. Any suggestions or solutions would be greatly appreciated. Thank you!

Answer №1

If you want to solve your issue, follow these steps:

  1. Make sure you have separate packages for your frontend and cdk directories. Each directory should have its own package.json and package-lock.json, or the equivalent files if you're using a different package manager.
  2. In your Actions steps named Install dependencies and CDK deploy, add working-directory: cdk.
  3. Add frontend install, build, and test steps in your Actions file before the CDK deploy step:
    - 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
    
    Ensure that npm run build is executed on your Actions runner to populate the build/ directory properly.
  4. Change
    source: [s3deploy.Source.asset("./frontend/frontendapp/build")],
    to
    sources: [s3deploy.Source.asset("../frontend/frontendapp/build")],
    by changing the path prefix from . to ...

You may need some minor tweaks based on your project structure, but following these steps should resolve your issue.

I recommend having separate package.json files for CDK and frontend code because:

  1. They are distinct packages with their own dependencies.
  2. It eliminates confusion when executing npm commands and including the correct files in build artifacts.

I have successfully deployed a project similar to yours by implementing the above recommendations. You can find it at https://github.com/douglasnaphas/anagrampoems.

While you may skip some suggestions, adding an npm run build step for the frontend code in GitHub Actions is crucial, ensuring it runs in the correct directory.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What sets the do/tap operator apart from other observable operators?

Can anyone clarify the distinction in simple terms between the typical observable operators used for observing output and why do/tap appear to serve the same purpose? What is the reason for utilizing do/tap? ...

I am retrieving data from a service and passing it to a component using Angular and receiving '[object Object]'

Searching for assistance with the problem below regarding my model class. I've attempted various approaches using the .pipe.map() and importing {map} from rxjs/operators, but still encountering the error message [object Object] export class AppProfile ...

Angular HttpInterceptor failing to trigger with nested Observables

Utilizing a HttpInterceptor is essential for adding my Bearer token to all calls made to my WebApi. The interceptor seamlessly functions with all basic service calls. However, there is one specific instance where I must invoke 2 methods and utilize the re ...

The raw password value must be provided and cannot be left blank

I am currently learning Java Springboot and working on creating a todo app with React (TypeScript) and Springboot. As I attempt to signup, an error occurs stating "rawPassword cannot be null" from Springboot. My frontend is running on localhost:3000 and b ...

Ways to retrieve specific Observable elements?

Having a function like this: getCategories(): Observable<any> { return this.category.find({where: {clientId: this.userApi.getCurrentId()}}) }; The return type of this.category.find is Observable<T[]>. When I invoke g ...

Passing TypeScript Interface Functions as Parameters

The course flags an error in the code: Argument of type {"name":string} is not assignable to a parameter of type 'squareDescriptor'. The property "size" is missing in the type {"name":string;}. Course link: I personally tested the code and did ...

Strange occurrences observed while looping through an enum in TypeScript

Just now, I came across this issue while attempting to loop through an enum. Imagine you have the following: enum Gender { Male = 1, Female = 2 } If you write: for (let gender in Gender) { console.log(gender) } You will notice that it iter ...

Combining objects in JavaScript

I am currently working on converting the object received from the server into a format compatible with the backend system. I have a received object that looks like this { 'User.permissions.user.view.dashboard': true, 'Admin.permissio ...

How can one interpret the act of "passing" an interface to an RxJS Store using angle brackets?

When working with NgRx and typescript, I often come across this syntax within class constructors: import { Store, select } from '@ngrx/store' class MyClass { constructor(private store: Store<AppState>) { this.count$ = store.pipe(sele ...

Tips for creating unit tests for my Angular service that utilizes the mergeMap() function?

As a beginner with the karma/jasmine framework, I am currently exploring how to add a test case for my service method shown below: public getAllChassis(): Observable<Chassis[]> { return this.http.get('chassis').pipe( merge ...

How to generate a SHA256 hash of the body and encode it in base64 using Python compared to

I'm aiming to hash the body using SHA256 and then encode it with base64. I'm in the process of converting my code from Python to TypeScript. From what I gathered via a Google search, it seems like crypto can be utilized instead of hashlib and ba ...

Using typescript, we can pass a generic class as a parameter to a function

Currently, I am faced with the challenge of passing a class reference as a function parameter, and then calling a static method on this particular class. Additionally, there is a possibility that in the future, I may need to instantiate the class and inclu ...

Ditch the if-else ladder approach and instead, opt for implementing a strategic design

I am currently working on implementing a strategic design pattern. Here is a simple if-else ladder that I have: if(dataKeyinresponse === 'year') { bsd = new Date(moment(new Date(item['key'])).startOf('year&apos ...

What is the best way to get both the id and name of a selected item in Angular?

Within my select field, data is dynamically populated based on names. My objective is to not only capture the selected name but also its corresponding ID. Here's a snippet of my HTML template: <select class="custom-select d-block w-100" id="test" ...

Separate files containing TypeScript decorators are defined within a project

(Let's dive into Typescript and Angular2, shall we?) Having primarily coded in Symfony2 with annotations, I found it convenient to configure entity mapping, routing, and other features using yaml, xml, or plain PHP. This flexibility was great for cre ...

A more efficient method for refreshing Discord Message Embeds using a MessageComponentInteraction collector to streamline updates

Currently, I am working on developing a horse race command for my discord bot using TypeScript. The code is functioning properly; however, there is an issue with updating an embed that displays the race and the participants. To ensure the update works co ...

Issues with sending emails through Nodemailer in a Next.js project using Typescript

I'm currently working on a personal project using Nodemailer along with Next.js and Typescript. This is my first time incorporating Nodemailer into my project, and I've encountered some issues while trying to make it work. I've been followin ...

Facing the issue once more - Angular displaying "Http failure response for... 0 Unknown Error"

I have been researching extensively on this issue, particularly on Stack Overflow. Many of the responses point to it being a CORS problem, but I am uncertain if that is the case in my situation. Therefore, I am reaching out for help once again and would gr ...

A step-by-step guide to activating multi-selection in the Primary SideBar of Visual Studio Code using your custom extension

Currently, I'm in the process of developing an extension for Visual Studio Code where I've added a new activityBar containing treeViews that showcase information pulled from a JSON file. My goal is to enable users to multi-select certain displaye ...

What could be the reason for receiving an undefined value when trying to determine the size of the Set

Within one of my functions, I am encountering the following code: this.personService.getPersonInfo(this.personId).subscribe((res => { let response = res.body; let num = response.personList.size; ... })) Here is what the expe ...