Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

feat(Dockerfile): use .nvmrc to build the image #1090

Merged
merged 14 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ Runs CodeQL against the PR code
### [on PR, Trunk] One App Unit and Lint Tests
Runs One App's unit tests and linting tests against the PR code

This workflow creates two checks, one for node 14 and one for node 16.

### [on PR] DangerJS
Runs dangerJS against the PR code

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/bundle-size.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16.x
node-version-file: .nvmrc
- uses: preactjs/compressed-size-action@v2
env:
NODE_ENV: development
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ jobs:
one-app-unit-tests:
name: One App Unit and Lint Tests
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, "^18 < 18.16"]
PixnBits marked this conversation as resolved.
Show resolved Hide resolved
steps:
- name: Checkout
uses: actions/checkout@v3
Expand All @@ -22,7 +19,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
node-version-file: .nvmrc
PixnBits marked this conversation as resolved.
Show resolved Hide resolved
- uses: actions/cache@v3
with:
path: ~/.npm
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/on-pr_dangerJS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '16.x'
node-version-file: .nvmrc
- uses: actions/cache@v3
with:
path: ~/.npm
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/on-pr_one-app-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:
${{ runner.os }}-node-
- uses: actions/setup-node@v3
with:
node-version: 16.x
node-version-file: .nvmrc
- name: npm install
run: NODE_ENV=development npm ci
- name: Build docker image
run: docker build -t one-app:at-test . --build-arg USER=root
run: docker build -t one-app:at-test . --build-arg USER=root --build-arg VERSION=$(cat .nvmrc)
- name: Run Integration Tests
run: ONE_DANGEROUSLY_SKIP_ONE_APP_IMAGE_BUILD=true npm run test:integration
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
${{ runner.os }}-node-
- uses: actions/setup-node@v3
with:
node-version: 16.x
node-version-file: .nvmrc
- name: One App release
id: vars
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
- name: Docker login
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin
- name: Build production docker image
run: docker build -t prod .
run: docker build -t prod . --build-arg VERSION=$(cat .nvmrc)
- name: Tag Docker Images
run: |
# Always tag the exact version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
- name: Docker login
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin
- name: Build development docker image
run: docker build -t dev . --target=development
run: docker build -t dev . --target=development --build-arg VERSION=$(cat .nvmrc)
- name: Tag Docker Images
run: |
# Always tag the exact version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v3
with:
node-version: '16.x'
node-version-file: .nvmrc
registry-url: 'https://registry.npmjs.org'
- name: Docker login
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin
Expand Down
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18.17.0
PixnBits marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 4 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
ARG VERSION=latest
PixnBits marked this conversation as resolved.
Show resolved Hide resolved
# Use the pre-baked fat node image only in the builder
# which includes build utils preinstalled (e.g. gcc, make, etc).
# This will result in faster and reliable One App docker image
# builds as we do not have to run apk installs for alpine.
FROM node:18.17.1 as builder
FROM node:$VERSION as builder
WORKDIR /opt/build
RUN npm install -g npm@9.6.7 --registry=https://registry.npmjs.org
COPY --chown=node:node ./ /opt/build
Expand All @@ -29,7 +30,7 @@ RUN NODE_ENV=production npm run build && \

# development image
# docker build . --target=development
FROM node:18.17.1-alpine as development
FROM node:$VERSION-alpine as development
ARG USER
ENV USER ${USER:-node}
ENV NODE_ENV=development
Expand All @@ -47,7 +48,7 @@ COPY --from=builder --chown=node:node /opt/one-app/development ./

# production image
# last so that it's the default image artifact
FROM node:18.17.1-alpine as production
FROM node:$VERSION-alpine as production
ARG USER
ENV USER ${USER:-node}
ENV NODE_ENV=production
Expand Down
63 changes: 58 additions & 5 deletions __tests__/package.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,69 @@
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import fs from 'node:fs/promises';
import path from 'node:path';

import fs from 'fs';
import path from 'path';
import { satisfies, parse } from 'semver';

const PACKAGE_DIR_PATH = path.resolve(path.join(__dirname, '../'));

describe('package.json', () => {
it('is formatted properly', () => {
const rawPkg = fs.readFileSync(path.join(PACKAGE_DIR_PATH, 'package.json'), 'utf8');
it('is parseable', async () => {
expect.assertions(1);
const rawPkg = await fs.readFile(path.join(PACKAGE_DIR_PATH, 'package.json'), 'utf8');
expect(() => JSON.parse(rawPkg)).not.toThrow();
});
it('is formatted like npm does', async () => {
expect.assertions(1);
const rawPkg = await fs.readFile(path.join(PACKAGE_DIR_PATH, 'package.json'), 'utf8');
const parsedPkg = JSON.parse(rawPkg);
expect(rawPkg).toEqual(`${JSON.stringify(parsedPkg, null, 2)}\n`);
const builtPkg = { ...parsedPkg };

[
'dependencies',
'devDependencies',
'optionalDependencies',
].forEach((listName) => {
if (!Object.hasOwnProperty.call(parsedPkg, listName)) {
return;
}
builtPkg[listName] = Object
.entries(parsedPkg[listName])
.sort(([packageNameA], [packageNameB]) => (
// let the engine do the work of sorting the strings
[packageNameA, packageNameB].sort()[0] === packageNameA ? -1 : 1)
)
// ECMAScript Objects do not have an order to their keys, but the V8 implementation does
.reduce(
(orderedList, [packageName, versionRange]) => {
// adding properties one at a time is less bad than rebuilding (via destructuring) a
// new object every iteration of the loop
/* eslint-disable-next-line no-param-reassign */
orderedList[packageName] = versionRange;
return orderedList;
},
{}
);
});

expect(rawPkg).toEqual(`${JSON.stringify(builtPkg, null, 2)}\n`);
});

describe('engines', () => {
describe('node', () => {
it('is satisified by .nvmrc', async () => {
expect.assertions(1);
const rawNVM = await fs.readFile(path.join(PACKAGE_DIR_PATH, '.nvmrc'), 'utf8');
const { engines } = JSON.parse(await fs.readFile(path.join(PACKAGE_DIR_PATH, 'package.json')));
expect(satisfies(rawNVM, engines.node)).toBe(true);
});
it('is inline with .nvmrc', async () => {
expect.assertions(1);
const rawNVM = await fs.readFile(path.join(PACKAGE_DIR_PATH, '.nvmrc'), 'utf8');
const { engines } = JSON.parse(await fs.readFile(path.join(PACKAGE_DIR_PATH, 'package.json')));
expect(engines.node).toBe(`^${parse(rawNVM).major}`);
PixnBits marked this conversation as resolved.
Show resolved Hide resolved
});
});
});
});
4 changes: 2 additions & 2 deletions docs/guides/Running-In-Production.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ You can build the One App [Docker](https://www.docker.com/) image and run it in
```bash
git clone https://github.com/americanexpress/one-app.git
cd one-app
docker build .
docker build . --build-arg VERSION=$(cat .nvmrc)
```

Or you can build from source which creates your server side assets at `./lib` and your client
Expand Down Expand Up @@ -217,6 +217,6 @@ under the "Software" category click "Edit". Enter all the required environment v

After the deployment is complete, you can navigate to your application by clicking on "Go to environment". If the application health displays an error, One App might be failing to start due to a missing environment variable or missing configuration. You can request the logs and the console should display the reason why One App is crashing.

More information on how to deploy Docker containers on AWS Elastic Beanstalk can be found on the official [AWS Documentation](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker.html).
More information on how to deploy Docker containers on AWS Elastic Beanstalk can be found on the official [AWS Documentation](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker.html).

[☝️ Return To Top](#running-in-production)
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"description": "One Amex SPA technology stack.",
"main": "index.js",
"engines": {
"node": ">=16",
"npm": ">=8"
"node": "^18",
"npm": "^9"
},
"scripts": {
"preinstall": "npx check-engines@1",
Expand Down
Loading