Skip to content
Open
Show file tree
Hide file tree
Changes from all 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: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22.23.1
26.5.1
17 changes: 13 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# syntax=docker/dockerfile:1.7

ARG NODE_VERSION=22.23.1
ARG NODE_VERSION=26.5.1
ARG ALPINE_VERSION=3.24
ARG NODE_PACKAGE_VERSION=26.5.1-r0
ARG OPENSSL_PACKAGE_VERSION=3.5.8-r0
ARG PNPM_VERSION=11.20.0
ARG PRISMA_VERSION=7.9.1

Expand Down Expand Up @@ -30,10 +33,16 @@ COPY prisma.config.ts ./
RUN pnpm install --prod --frozen-lockfile \
&& SUPPORT_DATABASE_URL="postgresql://user:pass@localhost:5432/topcoder?schema=support" prisma generate

FROM node:${NODE_VERSION}-alpine AS production
FROM alpine:${ALPINE_VERSION} AS production
ARG NODE_PACKAGE_VERSION
ARG OPENSSL_PACKAGE_VERSION
RUN apk upgrade --no-cache \
&& rm -rf /usr/local/lib/node_modules/npm \
&& rm -f /usr/local/bin/npm /usr/local/bin/npx
&& apk add --no-cache \
"libcrypto3=${OPENSSL_PACKAGE_VERSION}" \
"libssl3=${OPENSSL_PACKAGE_VERSION}" \
"nodejs-current=${NODE_PACKAGE_VERSION}" \
&& addgroup -S node \
&& adduser -S -G node node
ENV NODE_ENV=production
WORKDIR /usr/src/app
COPY --from=build --chown=node:node /usr/src/app/dist ./dist
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ successful ticket response. Logs exclude markdown, addresses, and secrets.

## Local development

Node.js 26.5.1 is the supported development and production runtime. Run
`nvm use` in this project before invoking pnpm so the local toolchain matches
the container runtime.

```bash
nvm use
cp .env.example .env
Expand Down Expand Up @@ -209,8 +213,10 @@ shared Topcoder deployment suite with `APPNAME=support-api-v6` and platform
The pipeline deploys to an existing ECS service; it intentionally does not
provision infrastructure. Before the first deployment, operations must provide
the ECR repository, ECS service/task family, target group, database and secret,
and SSM values. Container startup applies pending Prisma migrations before the
API process starts; Prisma's advisory lock keeps concurrent ECS task starts
and SSM values. The production image installs Alpine 3.24's dynamically linked
Node.js 26.5.1 package and OpenSSL 3.5.8 libraries, while npm and pnpm remain in
build-only stages. Container startup applies pending Prisma migrations before
the API process starts; Prisma's advisory lock keeps concurrent ECS task starts
safe. API Gateway must map `/v6/support` to the target group.

Serving Platform UI at `support.topcoder.com` is a separate infrastructure
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"description": "Topcoder member support ticket API",
"packageManager": "pnpm@11.20.0",
"engines": {
"node": ">=22.23.1"
"node": ">=26.5.1"
},
"scripts": {
"build": "nest build",
Expand Down
31 changes: 18 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ peerDependencyRules:
- react-dom

overrides:
'@istanbuljs/load-nyc-config>js-yaml': 3.15.1
'@eslint/eslintrc>js-yaml': 4.3.1
'cosmiconfig>js-yaml': 4.3.1
'@nestjs/swagger>js-yaml': 5.2.3
'@prisma/config>deepmerge-ts': 8.0.0
axios: 1.18.1
follow-redirects: 1.16.0
form-data: 4.0.6
Expand Down
7 changes: 7 additions & 0 deletions test/app-startup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ describe('production startup', () => {
it('uses the migration-aware startup script in the production image', () => {
const dockerfile = readFileSync(join(projectRoot, 'Dockerfile'), 'utf8');

expect(dockerfile).toContain('ARG ALPINE_VERSION=3.24');
expect(dockerfile).toContain('ARG NODE_PACKAGE_VERSION=26.5.1-r0');
expect(dockerfile).toContain('ARG OPENSSL_PACKAGE_VERSION=3.5.8-r0');
expect(dockerfile).toContain('FROM alpine:${ALPINE_VERSION} AS production');
expect(dockerfile).toContain('"nodejs-current=${NODE_PACKAGE_VERSION}"');
expect(dockerfile).toContain('"libcrypto3=${OPENSSL_PACKAGE_VERSION}"');
expect(dockerfile).toContain('"libssl3=${OPENSSL_PACKAGE_VERSION}"');
expect(dockerfile).toContain(
'COPY --from=build --chown=node:node --chmod=755 /usr/src/app/appStartUp.sh ./appStartUp.sh',
);
Expand Down