How to deploy nx monorepo applications with AWS Amplify - aws-amplify

Running into several problems while trying to deploy NextJS applications within my mono-repo to AWS Amplify-
Amplify has difficulty detecting that this is a NextJS application
Confusion on where to run build commands from / the location of dist
I found (limited) documentation on creating an amplify.yml spec for a monorepo deployment on AWS Amplify. I'm not quite sure what I want to configure particular variables as, since I'm not sure what Amplify is doing under the hood when you deploy.
Here's what I'm working with:
version: 1
applications:
- appRoot: ./apps/myNextJsApp
frontend:
phases:
preBuild:
commands:
- cd ../..
- yarn install
build:
commands:
- npx nx build myNextJsApp --prod
artifacts:
files:
- dist/apps/myNextJsApp/.next
discard-paths: yes
baseDirectory: location
cache:
paths:
- dist/apps/myNextJsApp/cache
test:
phases:
preTest:
commands:
- *enter command*
test:
commands:
- *enter command*
postTest:
commands:
- *enter command*
artifacts:
files:
- location
- location
configFilePath: *location*
baseDirectory: *location*
My specific questions:
What is the proper appRoot? It would seem to me that it would be the apps/myApp directory, however I see some documentation within Nx that it should be just ./.
Is yarn install my only necessary pre-build command? In that .yml I have it configured for starting in the apps/myApp directory and the cd'ing out to the root where my yarn.lock & package.json are located.
Is npx nx build myApp --prod sufficient?
Is this the correct location in my amplify.yml to specify my .next and cache directories?
What do baseDirectory and discard-paths do?
Thank you in advance to anyone who can help me demystify the amplify.yml.

Related

AWS Amplify - Automating Testing For A Dev Environment with Hosting

Problem: A variety of tutorials from AWS for integrating automated testing with CI/CD look to integrate the testing stage after, or within the build process by using a localhost:3000 server.
However, as AWS Amplify developers know, the local environment can sometimes offer a different user experience to deploying to a development environment, and using that environment with AWS Amplify's hosting service.
Therefore, how do I add testing not only at the build stage with localhost:3000, but also for the development environment's hosted url?
I'm looking to build all my resources (backend and front-end), with a git push to the code commit repository.
Idea of Stages:
Source
Build
Test
Deploy Cloud Formation Stacks
Test
Roll back if failure
Current amplify.yml:
Note: this currently does not work so please do not copy it for your build. Please refer to the hyperlink above.
version: 0.2
frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- npm run build
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- node_modules/**/*
test:
phases:
preTest:
commands:
- npm ci
- npm install wait-on
- npm install pm2
- npm install mocha mochawesome mochawesome-merge mochawesome-report-generator
- npx pm2 start npm -- dev
- 'npx wait-on --timeout 300 http://localhost:3000'
test:
commands:
- 'npx cypress run --reporter mochawesome --reporter-options "reportDir=cypress/report/mochawesome-report,overwrite=false,html=false,json=true,timestamp=mmddyyyy_HHMMss"'
postTest:
commands:
- npx mochawesome-merge cypress/report/mochawesome-report/mochawesome*.json > cypress/report/mochawesome.json
- npx pm2 kill
artifacts:
baseDirectory: cypress
configFilePath: '**/mochawesome.json'
files:
- '**/*.png'
- '**/*.mp4'

AWS Amplify - Lerna Monorepo - Can't install private github package

I am having trouble installing a private github package with my lerna monorepo using AWS Amplify hosting.
I have updated the build settings to create a .npmrc file at the time of build and install the package in the preBuild stage, however when it begins the build stage it cannot find the module.
Reproduction steps
Set up amplify hosting for react app as monorepo (Lerna)
Update build settings to create .npmrc and install package
Run build
Build settings
version: 1
applications:
- backend:
phases:
build:
commands:
- '# Execute Amplify CLI with the helper script'
- amplifyPush --simple
frontend:
phases:
preBuild:
commands:
- yarn install --frozen-lockfile
- echo -e "always-auth=true\n#apptractive:registry=https://npm.pkg.github.com/\n//npm.pkg.github.com/:_authToken=$NPM_AUTH_TOKEN" > .npmrc
- yarn add #apptractive/shared
- yarn add #apptractive/design-system-web
build:
commands:
- yarn run build
artifacts:
baseDirectory: build
files:
- '**/*'
cache:
paths:
- node_modules/**/*
appRoot: packages/backoffice-app
Error that shows
Okay I found that I needed to build the packages within the build script as they were being imported from the monorepo itself and not github packages.
Probably can be done with a better approach, but this got me over the line for now
version: 1
applications:
- backend:
phases:
build:
commands:
- '# Execute Amplify CLI with the helper script'
- amplifyPush --simple
frontend:
phases:
preBuild:
commands:
- yarn global add lerna
- npm config set registry https://npm.pkg.github.com
- npm config set always-auth true
- npm config set //https://npm.pkg.github.com/:_authToken=${NPM_AUTH_TOKEN}
- lerna bootstrap --include-dependencies
- cd ../shared && yarn build
- cd ../design-web && yarn build
build:
commands:
- yarn run build
artifacts:
baseDirectory: build
files:
- '**/*'
cache:
paths:
- node_modules/**/*
appRoot: packages/backoffice-app

Cannot find file './aws-exports' in './src'

I'm on the third module of this AWS tutorial to build a React app with AWS, Amplify and GraphQL but the build keeps breaking. When I ran amplify push --y the CLI generated ./src/aws-exports.js and added the same file to the .gitignore. So I'm not surprised the build is failing, since that file isn't included when I push my changes.
So I'm not sure what to do here. Considering it's automatically added to the .gitignore I'm hesitant to remove it.
Any suggestions?
I'm assuming you are trying to build your app in a CI/CD environment?
If that's the case then you need to build the backend part of your amplify app before you can build the frontend component.
For example, my app is building from the AWS amplify console and in my build settings I have
version: 0.1
backend:
phases:
build:
commands:
- '# Execute Amplify CLI with the helper script'
- amplifyPush --simple
frontend:
phases:
preBuild:
commands:
- yarn install --frozen-lockfile
build:
commands:
- yarn build
artifacts:
baseDirectory: build
files:
- "**/*"
cache:
paths:
- node_modules/**/*
Note that the backend is building first with the amplifyPush --simple command. This is what generates the aws-exports.js file.
The 'aws-exports.js' file gets created automatically when AWS Amplify runs the CI/CD deployment build process and gets configured with the appropriate settings for the environment you are deploying to.
And for this reason it is included in the .gitignore. You don't want your local test configuration to be used in your production deployment for example.
As per Matthe's answer above the should be generated when the build script runs the 'amplifyPush' command. For some reason this is not working for me at the moment though!
AWS added support to automatically generate the aws-exports.js at build time to avoid getting the error: https://docs.aws.amazon.com/amplify/latest/userguide/amplify-config-autogeneration.html

Lerna on AWS CodeBuild & CodeDeploy Not Installing Local Dependencies

So I have a Typescript project called backend with a depedency like such in its package.json:
"dependencies": {
"#the-couple-game/helpers": "^1.0.0",
}
And helpers (also Typescript) is in another folder with its package.json like such:
{
"name": "#the-couple-game/helpers",
}
So running lerna bootstrap should link the two and install #the-couple-game/helpers in backend's node_modules which it does locally.
However, doing the same (with --no-ci because I don't want npm ci) using Codebuild using the below buildspec.yml does not add a #the-couple-game/helpers in backend's node_modules. So if I run backend's transpiled index.js it would complain about the missing module.
version: 0.1
phases:
install:
commands:
- npm install -g lerna
pre_build:
commands:
- lerna bootstrap --no-ci --concurrency 4
build:
commands:
- lerna run build --concurrency 4
artifacts:
files:
- "**/*"
For now, I have to resort to manually doing a lerna bootstrap after deployment to CodeDeploy (using a script called from appspec.yml) so it installs the missing module but shouldn't Codebuild have covered that part?
Thanks.
So it turns out AWS CodePipeline doesn't support symlinks in source (Codebuild in my case). Reference
So after deployment, I'll have to lerna link using a shell script to create the links which is not an expensive job for my micro ec2 instance to do.

How to utilize .ebextension while using CodePipeline

I'm using CodePipeline to deploy whatever is on master branch of the git to Elastic Beanstalk.
I followed this tutorial to extend the default nginx configuration (specifically the max-body-size): https://medium.com/swlh/using-ebextensions-to-extend-nginx-default-configuration-in-aws-elastic-beanstalk-189b844ab6ad
However, because I'm not using the standard eb deploy command, I dont think the CodePipeline flow is going into the .ebextension directory and doing the things its supposed to do.
Is there a way to use code pipeline (so i can have CI/CD from master) as well as utilize the benefits of .ebextension?
Does this work if you use the eb deploy command directly? If yes, then I would try using the pipeline execution history to find a recent artifact to download and test with the eb deploy command.
If CodePipeline's Elastic Beanstalk Job Worker does not play well with ebextensions, I would consider it completely useless to deploy to Elastic Beanstalk.
I believe there is some problem with the ebextensions themselves. You can investigate the execution in these log files to see if something is going wrong during deployment:
/var/log/eb-activity.log
/var/log/eb-commandprocessor.log
/var/log/eb-version-deployment.log
All the config files under .ebextension will be executed based on the order of precedence while deploying on the Elastic Beanstalk. So, it is doesn't matter whether you are using codepipeline or eb deploy, all the file in ebextension directory will be executed. So, you don't have to worry about that.
Be careful about the platform you're using, since “64bit Amazon Linux 2 v5.0.2" instead of .ebextension you have to use .platform.
Create .platform directory instead of .ebextension
Create the subfolders and the proxy.conf file like in this path .platform/nginx/conf.d/proxy.conf
In proxy.conf write what you need, in case of req body size just client_max_body_size 20M;
I resolved the problem. You need include .ebextension folder in your deploy.
I only copy the dist files, then I need include too:
- .ebextensions/**/*
Example:
## Required mapping. Represents the buildspec version. We recommend that you use 0.2.
version: 0.2
phases:
## install: install dependencies you may need for your build
install:
runtime-versions:
nodejs: 12
commands:
- echo Installing Nest...
- npm install -g #nestjs/cli
## pre_build: final commands to execute before build
pre_build:
commands:
- echo Installing source NPM dependencies...
- npm install
## build: actual build commands
build:
commands:
# Build your app
- echo Build started on `date`
- echo Compiling the Node.js code
- npm run build
## Clean up node_modules to keep only production dependencies
# - npm prune --production
## post_build: finishing touches
post_build:
commands:
- echo Build completed on `date`
# Include only the files required for your application to run.
artifacts:
files:
- dist/**/*
- package.json
- node_modules/**/*
- .ebextensions/**/*
Ande the config file /.ebextensions/.node-settings.config:
option_settings:
aws:elasticbeanstalk:container:nodejs:
NodeCommand: "npm run start:prod"

Resources