Search code examples
typescriptdevopsmerncicdts-jest

Gitlab CICD Can not detect ts-node despite installed


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:

project structure

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.


Solution

  • 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