Skip to content
Merged
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
7 changes: 3 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:

Run-Newman-Test:
docker:
- image: cimg/node:22.13.1
- image: cimg/node:26.5.0
environment:
DEPLOY_ENV: DEV
LOGICAL_ENV: dev
Expand All @@ -110,7 +110,7 @@ jobs:
- run:
name: Install pnpm dependencies
command: |
sudo npm install --global pnpm@10.33.2
sudo npm install --global pnpm@11.15.1
pnpm install --frozen-lockfile
pnpm build
- save_cache:
Expand Down Expand Up @@ -163,7 +163,7 @@ workflows:
branches:
only:
- develop
- typescript
- security_july_2026
- hotfix/deploy
- PM-3458
- build-prod:
Expand All @@ -186,5 +186,4 @@ workflows:
branches:
only:
- develop
- typescript
- dev-circleci
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22.13.1
26.5.0
20 changes: 10 additions & 10 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ This service manages challenge resources, resource roles, and resource-role phas

- TypeScript 5 and NestJS 11
- Prisma 7 with PostgreSQL driver adapters
- Node.js 22.13.1
- pnpm 10.33.2
- Node.js 26.5.0
- pnpm 11.15.1
- PostgreSQL for the resources, member, and challenge data sources

The exact local Node version is recorded in `.nvmrc`. Run `nvm use` after entering this project directory and before running pnpm or Node commands.

## Prerequisites

- Node.js 22.13.1 through nvm
- pnpm 10.33.2
- Node.js 26.5.0 through nvm
- pnpm 11.15.1
- PostgreSQL databases accessible through the existing database URLs
- Docker with BuildKit when building the production image

Expand All @@ -38,7 +38,7 @@ Useful commands are:
- `pnpm build` compiles the TypeScript application.
- `pnpm lint` checks TypeScript source and tests.
- `pnpm prisma:generate` regenerates the three internal clients.
- `pnpm exec prisma migrate deploy` applies the existing resources migration history.
- `./node_modules/.bin/prisma migrate deploy` applies the existing resources migration history without requiring a global pnpm installation.
- `pnpm seed-tables` seeds resource tables.
- `pnpm view-data <ModelName>` displays resource data.
- `pnpm run mock-challenge-api` starts the challenge mock on port 4000.
Expand Down Expand Up @@ -119,7 +119,7 @@ export CHALLENGE_DB_URL="postgresql://user:password@localhost:5732/challengedb"
Apply the checked-in resources migrations and build the application:

```bash
pnpm exec prisma migrate deploy
./node_modules/.bin/prisma migrate deploy
pnpm build
pnpm start
```
Expand All @@ -128,17 +128,17 @@ pnpm start

This upgrade is designed for existing databases. The SQL files and migration lock under `prisma/migrations` are the deployment history and must remain unchanged. Do not reset the database, run `prisma migrate dev`, generate a new migration for this conversion, or use `prisma db push` against a deployed environment.

The production entrypoint runs `pnpm exec prisma migrate deploy` before starting `dist/main.js`. This applies only pending migrations from the unchanged history and does not recreate the schema.
The production entrypoint runs `./node_modules/.bin/prisma migrate deploy` before starting `dist/main.js`. This applies only pending migrations from the unchanged history and does not recreate the schema.

## Docker

Build the Node 22 production image with:
Build the Node 26 production image with:

```bash
./build.sh resources-api-v6
```

The multi-stage build performs a frozen pnpm install, Prisma generation through `postinstall`, lint, and TypeScript compilation. The runtime image contains the compiled application, production dependencies, Prisma CLI and configuration, unchanged migrations, Swagger documentation, the three generated internal clients, and the committed external client. It runs as the non-root `node` user.
The multi-stage build performs a frozen pnpm install, Prisma generation through `postinstall`, lint, and TypeScript compilation. The runtime image contains the compiled application, production dependencies, Prisma CLI and configuration, unchanged migrations, Swagger documentation, the three generated internal clients, and the committed external client. Build-only npm and pnpm tooling is removed from the runtime image, which runs as the non-root `node` user.

Runtime configuration continues to be injected through the existing environment variables. The default configuration is included in the image; local `env.sh` files remain excluded.

Expand All @@ -159,6 +159,6 @@ pnpm run test:newman
pnpm run test:newman:clear
```

CircleCI performs the Docker build and deployment using the existing `APPNAME`, `DEPLOY_ENV`, and parameter-store paths. The automated-test workflow uses Node 22.13.1, pnpm 10.33.2, and the same deployment environment names.
CircleCI performs the Docker build and deployment using the existing `APPNAME`, `DEPLOY_ENV`, and parameter-store paths. The automated-test workflow uses Node 26.5.0, pnpm 11.15.1, and the same deployment environment names.

See `Verification.md` for the regression checklist.
6 changes: 3 additions & 3 deletions Verification.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Resource API v6 verification

Use this checklist to verify the TypeScript, NestJS, Prisma 7, and Node 22 conversion without changing the service's external behavior.
Use this checklist to verify the TypeScript, NestJS, Prisma 7, and Node 26 runtime without changing the service's external behavior.

## Static verification

Expand Down Expand Up @@ -36,7 +36,7 @@ Build the same image used by CircleCI:
./build.sh resources-api-v6
```

Run it with the existing deployment variables and confirm the logs show migration deployment before `resource-api-v6` starts. The container must run on Node 22.13.1, start `dist/main.js`, and answer:
Run it with the existing deployment variables and confirm the logs show migration deployment before `resource-api-v6` starts. The container must run on Node 26.5.0, start `dist/main.js`, and answer:

```text
GET /v6/resources/health
Expand Down Expand Up @@ -90,5 +90,5 @@ On the `typescript` branch, confirm that:
- The Docker build completes frozen pnpm installation, Prisma generation, lint, and Nest compilation.
- Deployment still uses `APPNAME=resources-api-v6` and the existing DEV/PROD parameter-store paths.
- Dependency setup removes the image's preconfigured Chrome and Docker APT sources before updating package indexes; both tools are already installed in that image.
- The Newman job runs on Node 22.13.1 with pnpm 10.33.2 from the repository root.
- The Newman job runs on Node 26.5.0 with pnpm 11.15.1 from the repository root.
- The health wait succeeds before the Postman scripts run and Newman artifacts are retained.
2 changes: 1 addition & 1 deletion appStartUp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if [[ -n "${DATABASE_URL:-}" ]]; then
fi

echo "Database - applying existing migrations."
pnpm exec prisma migrate deploy
./node_modules/.bin/prisma migrate deploy

echo "Starting resource-api-v6."
exec node dist/main.js
24 changes: 16 additions & 8 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
# syntax=docker/dockerfile:1

FROM node:22.13.1-alpine AS build
ARG NODE_VERSION=26.5.0
ARG ALPINE_VERSION=3.23

FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS build

ARG PNPM_VERSION=11.15.1

ENV CI=true
WORKDIR /resources-api

RUN apk add --no-cache bash git openssh-client openssl \
&& npm install --global pnpm@10.33.2
RUN apk upgrade --no-cache \
&& apk add --no-cache bash git openssh-client openssl \
&& npm install --global "pnpm@${PNPM_VERSION}" \
&& npm cache clean --force

# Install from the lockfile before copying the rest of the application. The
# package postinstall hook generates the three Prisma 7 service clients
# without connecting to a database. The committed external client is copied
# later with the rest of the source tree and is not regenerated.
COPY package.json pnpm-lock.yaml prisma.config.ts tsconfig.json tsconfig.build.json ./
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml prisma.config.ts tsconfig.json tsconfig.build.json ./
COPY prisma ./prisma
RUN pnpm install --frozen-lockfile

Expand All @@ -22,18 +29,19 @@ RUN mkdir -p src/scripts/seed \
&& pnpm build \
&& pnpm prune --prod

FROM node:22.13.1-alpine AS production
FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS production

ENV NODE_ENV=production
WORKDIR /resources-api

RUN apk add --no-cache bash openssl \
&& npm install --global pnpm@10.33.2
RUN apk upgrade --no-cache \
&& apk add --no-cache bash openssl \
&& rm -rf /usr/local/lib/node_modules/npm \
&& rm -f /usr/local/bin/npm /usr/local/bin/npx

COPY --from=build --chown=node:node /resources-api/dist ./dist
COPY --from=build --chown=node:node /resources-api/node_modules ./node_modules
COPY --from=build --chown=node:node /resources-api/package.json ./package.json
COPY --from=build --chown=node:node /resources-api/pnpm-lock.yaml ./pnpm-lock.yaml
COPY --from=build --chown=node:node /resources-api/config ./config
COPY --from=build --chown=node:node /resources-api/prisma.config.ts ./prisma.config.ts
COPY --from=build --chown=node:node /resources-api/prisma ./prisma
Expand Down
37 changes: 10 additions & 27 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.0.0",
"description": "Topcoder Challenge Resources API v6",
"main": "dist/main.js",
"packageManager": "pnpm@10.33.2",
"packageManager": "pnpm@11.15.1",
"scripts": {
"build": "nest build",
"start": "node dist/main.js",
Expand Down Expand Up @@ -34,7 +34,7 @@
"@nestjs/cli": "^11.0.0",
"@nestjs/schematics": "^11.0.0",
"@types/express": "^4.17.21",
"@types/node": "^22.10.7",
"@types/node": "^26.1.1",
"@types/pg": "^8.15.5",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
Expand All @@ -55,9 +55,8 @@
"@nestjs/common": "^11.1.8",
"@nestjs/core": "^11.1.8",
"@nestjs/platform-express": "^11.1.8",
"@prisma/adapter-pg": "7.4.2",
"@prisma/client": "7.4.2",
"aws-sdk": "^2.466.0",
"@prisma/adapter-pg": "7.8.0",
"@prisma/client": "7.8.0",
"bluebird": "^3.5.1",
"body-parser": "^1.15.1",
"config": "^3.0.1",
Expand All @@ -68,43 +67,27 @@
"get-parameter-names": "^0.3.0",
"http-json-response": "^1.0.1",
"http-status-codes": "^1.3.0",
"joi": "^14.0.0",
"lodash": "^4.17.19",
"joi": "^18.2.3",
"lodash": "^4.18.1",
"moment": "^2.30.1",
"pg": "^8.16.3",
"prisma": "7.4.2",
"prisma": "7.8.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"superagent": "^10.3.0",
"swagger-ui-express": "^4.1.3",
"tc-bus-api-wrapper": "github:topcoder-platform/tc-bus-api-wrapper.git",
"tc-core-library-js": "https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/1075136355e1e1c4779f2138a30f3ffbd718bfa4",
"uuid": "^11.0.3",
"uuid": "^14.0.1",
"winston": "^3.2.1",
"xss": "^1.0.7",
"yamljs": "^0.3.0"
},
"prisma": {
"schema": "./prisma/schema.prisma"
},
"pnpm": {
"overrides": {
"@topcoder-platform/topcoder-bus-api-wrapper>tc-core-library-js": "https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/1075136355e1e1c4779f2138a30f3ffbd718bfa4"
},
"onlyBuiltDependencies": [
"@prisma/client",
"@prisma/engines",
"prisma"
],
"ignoredBuiltDependencies": [
"@scarf/scarf",
"aws-sdk",
"core-js",
"dtrace-provider"
]
},
"engines": {
"node": "22.x"
"node": "26.x"
},
"nyc": {
"exclude": [
Expand All @@ -115,6 +98,6 @@
]
},
"volta": {
"node": "22.13.1"
"node": "26.5.0"
}
}
Loading
Loading