I am relatively new to setting up GitLab CI. I am currently implementing a small web application using the MERN pipeline (MongoDB, express, react, Nodejs). I want to create a very small project similar to google drive where users can store and route their files online. Here is the structure of my project:
I have only configured unit tests for the backend with Jest and super test. I have installed all required packages and set up jest.config.ts for compiling typescript tests. However, I have no idea why the test file can not detect my installed jest if I only do the npm install required packages in the backend folder. So I installed all required packages for testing in both the root folder and the backend folder. Here are my packages:
cloud_todo/package.json:
{
"dependencies": {
"supertest": "^6.3.3"
},
"devDependencies": {
"@babel/core": "^7.22.1",
"@babel/preset-env": "^7.22.4",
"@types/jest": "^29.5.2",
"@types/supertest": "^2.0.12",
"babel-jest": "^29.5.0",
"jest": "^29.5.0",
"ts-jest": "^29.1.0"
}
}
cloud_todo/backend/package.json:
{
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "dist/server.js",
"scripts": {
"start": "nodemon src/server.ts",
"lint": "eslint . --ext .ts",
"test": "jest --testTimeout=10000 --forceExit"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.0",
"body-parser": "^1.20.2",
"connect-mongo": "^4.6.0",
"cross-env": "^7.0.3",
"dotenv": "^16.0.3",
"envalid": "^7.3.1",
"express": "^4.18.2",
"express-session": "^1.17.3",
"http-errors": "^2.0.0",
"jest": "^29.5.0",
"leaked-handles": "^5.2.0",
"mongodb": "^5.5.0",
"mongodb-memory-server": "^8.12.2",
"mongoose": "^6.8.1",
"morgan": "^1.10.0",
"multer": "^1.4.5-lts.1",
"multer-gridfs-storage": "^5.0.2",
"supertest": "^6.3.3",
"ts-dev": "^2.1.16",
"ts-jest": "^29.1.0"
},
"devDependencies": {
"@types/bcrypt": "^5.0.0",
"@types/express": "^4.17.15",
"@types/express-session": "^1.17.7",
"@types/http-errors": "^2.0.1",
"@types/jest": "^29.5.2",
"@types/morgan": "^1.9.3",
"@types/multer": "^1.4.7",
"@types/multer-gridfs-storage": "^4.0.5",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.6",
"eslint": "^8.30.0",
"eslint-plugin-react": "^7.32.2",
"nodemon": "^2.0.20",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
}
}
cloud_todo/backend/jest.config.ts:
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/
export default {
coverageProvider: "v8",
moduleFileExtensions: [
"js",
"mjs",
"cjs",
"jsx",
"ts",
"tsx",
"json",
"node"
],
roots: [
"<rootDir>"
],
testMatch: [
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[tj]s?(x)"
],
transform: {"^.+\\.(ts|tsx)$": "ts-jest"},
};
After setting all this up, backend unit test works well locally. So I further set up gitlab CI/CD pipeline with following yml file
cloud_todo/.gitlab-ci.yml
image: node:latest
stages:
- npm
- test
npm:
stage: npm
script:
- npm install
- cd backend
- npm install --legacy-peer-deps
- npm i ts-node -D --legacy-peer-deps
- cd ..
- cd frontend
- npm install --legacy-peer-deps
cache:
paths:
- node_modules/
artifacts:
expire_in: 1 days
when: on_success
paths:
- node_modules/
test:
stage: test
dependencies:
- npm
script:
- cd backend
- npm test
However I keep getting following in my pipeline:
$ cd backend
$ npm test
> [email protected] test
> jest --testTimeout=10000 --forceExit
Error: Jest: Failed to parse the TypeScript config file /builds/BWN133/cloud_todo/backend/jest.config.ts
Error: Jest: 'ts-node' is required for the TypeScript configuration files. Make sure it is installed
Error: Cannot find package 'ts-node' imported from /builds/BWN133/cloud_todo/node_modules/jest-config/build/readConfigFileAndSetRootDir.js
at readConfigFileAndSetRootDir (/builds/BWN133/cloud_todo/node_modules/jest-config/build/readConfigFileAndSetRootDir.js:116:13)
at async readInitialOptions (/builds/BWN133/cloud_todo/node_modules/jest-config/build/index.js:400:13)
at async readConfig (/builds/BWN133/cloud_todo/node_modules/jest-config/build/index.js:147:48)
at async readConfigs (/builds/BWN133/cloud_todo/node_modules/jest-config/build/index.js:421:26)
at async runCLI (/builds/BWN133/cloud_todo/node_modules/@jest/core/build/cli/index.js:152:59)
at async Object.run (/builds/BWN133/cloud_todo/node_modules/jest-cli/build/run.js:124:37)
Cleaning up project directory and file based variables
00:00
ERROR: Job failed: exit code 1
Can anyone provide me with any hints? Greatly appreciated!
I have tried to install ts-node in the yml script and change different docker images but none of those works.
I also have tried some random things on the internet but those have no help for my project.
First, use either artifacts or cache to pass the installed node_modules between jobs. I suggest cache for this. So you can remove everything artifacts related from the npm job.
Second, you need to define the cache in both jobs, or define it on a global level so it is applied to all jobs.
Third, as far as I see, you have three node_modules folders and your tests probably need all of them, the specific error is happening because you only defined the path to the node_modules in the project root, but not in the backend folder.
Try this:
image: node:latest
cache:
paths:
- node_modules/
- backend/node_modules
- frontend/node_modules
stages:
- npm
- test
npm:
stage: npm
script:
- npm install
- cd backend
- npm install --legacy-peer-deps
- npm i ts-node -D --legacy-peer-deps
- cd ..
- cd frontend
- npm install --legacy-peer-deps
test:
stage: test
script:
- cd backend
- npm test