Yos
Yos

Reputation: 301

How to execute a command from a docker image in a gitlab job?

I created a docker image which stores an npm project. The npm project has an npm script which runs tests. I use Gitlab for CI/CD where I want to define a job which will pull my image and run the npm script. This is the .gitlab.yml:

stages:
  - test

.test-api:
  image: $CI_REGISTRY_IMAGE
  stage: test
  script:
    - cd packages/mypackage && npm run test:ci
  artifacts:
    paths:
      - packages/mypackage/test-report.html
    expire_in: 1 week

test-api-beta:
  extends: .test-api
  environment:
    name: some-env
  variables:
    CI_REGISTRY_IMAGE: my_image_name

The gitlab job fails with the error:

> [email protected] test:ci /builds/my-organization/my-project/packages/mypackage
> DEBUG=jest-mongodb:* NODE_ENV=test ts-node --transpile-only --log-error node_modules/.bin/jest --watchAll=false --detectOpenHandles --bail
sh: 1: ts-node: not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh
npm ERR! errno ENOENT
npm ERR! [email protected] test:ci: `DEBUG=jest-mongodb:* NODE_ENV=test ts-node --transpile-only --log-error node_modules/.bin/jest --watchAll=false --detectOpenHandles --bail`
npm ERR! spawn ENOENT
npm ERR! 
npm ERR! Failed at the [email protected] test:ci script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?
npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-04-28T09_05_39_023Z-debug.log

The main issue is the error npm WARN Local package.json exists, but node_modules missing, did you mean to install?. This means that the gitlab script is executed on the actual git repository of my project instead of being executed on the docker image. Indeed my repository doesn't contain node_modules so the job fails. But why doesn't gitlab execute the script on the actual image?

The docker image has a CMD directive: CMD ["npm", "run", "start"]

Maybe the CMD somehow interferes with the gitlab script?

P.S. pulling the docker image manually and executing the npm script locally works.

This is my Dockerfile:

FROM node:14.15.1
COPY ./package.json /src/package.json

WORKDIR /src
RUN npm install
COPY ./lerna.json /src/lerna.json
COPY ./packages/mypackage/package.json /src/packages/mypackage/package.json
RUN npm run clean
COPY . /src
EXPOSE 8082
CMD ["npm" , "run", "start"]

EDIT: As per M. Iduoad answer if the script is changed as follows:

.test-api:
  image: $CI_REGISTRY_IMAGE
  stage: test
  script:
    - cd /src/packages/mypackage && npm run test:ci
  artifacts:
    paths:
      - packages/mypackage/test-report.html
    expire_in: 1 week

the npm script works. We need to cd /src/packages/mypackage because this is the location of script in the Dockerfile.

Upvotes: 2

Views: 7888

Answers (1)

Iduoad
Iduoad

Reputation: 975

Gitlab always clones you repo and checkout the branch you are triggering the pipeline against and run your commands on that code (same folder CI_PROJECT_DIR)

So in order to use you version of the code you should either move to folder where it is located in your docker image.

.test-api:
  image: $CI_REGISTRY_IMAGE
  stage: test
  script:
    - cd /the/absolute/path/of/the/project/ && npm run test:ci

Doing this, defies gitlab-ci's way of doing things. Since you job will always run on the same code(the one in the image) every time your gitlab job is run. When gitlab-ci is a CI system and is intended to run you jobs against the code in your git repo.

So to summarize, I suggest you add a stage where you install you dependencies (node_modules)

stages:
  - install
  - test

install-deps:
  image: node:latest # or the version you are using
  stage: install
  script: 
    - npm install
  cache:
    key: some-key
    paths:
      - $CI_PROJECT_DIR/node_modules
.test-api:
  image: $CI_REGISTRY_IMAGE
  stage: test
  script:
    - npm run test:ci
  cache:
    key: some-key
    paths:
      - $CI_PROJECT_DIR/node_modules
  artifacts:
    paths:
      - packages/mypackage/test-report.html
    expire_in: 1 week

This will use gitlab-ci's cache feature, to store the node_module across you jobs and across your pipeline. You can control how to use and share the cache across pipelines and jobs, by changing the key. (read more about the cache on gitlab's docs)

Upvotes: 4

Related Questions