skip to Main Content

I have a node webapp that I run locally to run test specs. I use mocha and karma as a spec runner. Here are one of my npm commands to run a test suite:

{
  "scripts": {
   "test-jobs-once-docker": "mocha --reporter spec "server/**/*.spec.js""
  }
}

When I run docker-compose up locally, the command works and the specs run in the docker container.

Here is my docker-compose.yml:


version: "3"
services:  
  mongo:     
    image: mongo:3.4
    ports:
      - 27017:27017
    restart: always    
  redis:
    image: redis:7.0.8    
    ports:
      - 6379:6379
    restart: always        
  webapp:
    build:
      context: .
      args:
        - NODE_ENV=dockerTest
    platform: linux/amd64
    ports:
      - 9000:9000
    depends_on:
      - redis
    environment:
      - PORT=9000
      - NODE_ENV=dockerTest
      - REDIS_URL=redis://redis:6379            
    command: ['npm', 'run', 'test-jobs-once-docker']

Here is the Dockerfile:

FROM --platform=linux/amd64 ubuntu:20.04

ENV APP_HOME="/app"

WORKDIR /app

USER root
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update 
    && apt-get install -y curl 
    && apt-get -y autoclean

ENV NODE_VERSION=12.9.0
ENV NVM_DIR /usr/local/nvm
ENV CHROME_BIN=/usr/bin/google-chrome

RUN mkdir -p /usr/local/nvm/ && 
    curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.2/install.sh | bash

RUN /bin/bash -c "source $NVM_DIR/nvm.sh 
    && nvm install $NODE_VERSION 
    && nvm alias default $NODE_VERSION 
    && nvm use default"

ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH

RUN apt-get install python -y
RUN apt-get install libkrb5-dev -y
RUN apt-get install libpng-dev -y 
RUN apt-get install libfontconfig1 fontconfig libfontconfig1-dev -y

RUN apt-get install build-essential  -y

COPY ./package*.json ./
COPY .npmrc ./

RUN npm install
COPY . /app


RUN touch ./server/config/local.env.js

ENV PORT=9000

EXPOSE 8080
EXPOSE 9000

However, when I run this in GitHub Actions it says:

mocha: command not found

Here is my workflow:

name: Run Test Suite
on: [push, pull_request]

jobs:
  run-tests-docker:
    runs-on: ubuntu-20.04
    steps: 
    - name: Check out code
      uses: actions/checkout@v2

    - name: Build Docker Containers & Run Test Specs
      run:  docker-compose -f "docker-compose.yml" up -d --build
          
    - name: Run Test Specs
      run:  npm run test-jobs-once-docker
      env:
        NODE_ENV: dockerTest
   
    - name: Stop Containers
      if: always()
      run: docker-compose -f "docker-compose.yml" down

When I run this on GitHub Actions, I comment out the command property on the webapp in the docker-compose.yml so the command is executed in the job on GitHub Actions instead of when the container builds. I feel like this is the problem. I am not sure how to inspect the container that is built and used in GitHub Actions to see if the node_modules exists.

Does anybody know how I can get access to the mocha executable so I can run my tests in GitHub Actions?

Update:

I noticed that the node_modules folder is not in the directory the rest of my app is in. I’m going to guess this is part of the problem, this is the $PATH variable and files in the directory after the environment builds in github actions (also note the Dockerfile and nvm

/home/runner/.local/bin:/opt/pipx_bin:/home/runner/.cargo/bin:/home/runner/.config/composer/vendor/bin:/usr/local/.ghcup/bin:/home/runner/.dotnet/tools:/snap/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Dockerfile
Gemfile
Gemfile.lock
Procfile
README.md
app.json
bower.json
client
database.json
docker-compose.yml
e2e
karma.conf.js
package-lock.json
package.json
server
shared
webpack-dev.config.js
webpack-production.config.js
webpack.common.js

3

Answers


  1. Your problem seems to be related to the context in which the mocha command is being executed.

    • When you run the mocha command inside your Docker container, it has access to the node_modules directory that was installed during the Docker build process (since npm install is executed in the Dockerfile).
    • However, when you try to run mocha directly from your GitHub Actions workflow, it does not have access to those node_modules as it is outside the Docker container context.

    Make sure that node_modules is correctly installed: If you want to keep running the tests from the GitHub Actions workflow, you could ensure that the node_modules directory is correctly installed. You can do this by running npm install in your GitHub Actions workflow:

    - name: Install Dependencies
      run:  npm install
    
    - name: Run Test Specs
      run:  npm run test-jobs-once-docker
      env:
        NODE_ENV: dockerTest
    

    However, keep in mind that this might not work if your tests rely on other aspects of your Docker environment that are not replicated in your GitHub Actions runner.

    And make sure the working directory is correct: Make sure that the GitHub Actions runner is in the correct directory when it tries to run npm run test-jobs-once-docker. If it is not in the right directory, it might not find the node_modules directory. You can use the working-directory option in your GitHub Actions workflow to ensure that the runner is in the correct directory:

    - name: Run Test Specs
      run:  npm run test-jobs-once-docker
      env:
        NODE_ENV: dockerTest
      working-directory: /path/to/your/app
    

    Replace /path/to/your/app with the actual path to your app in the runner’s filesystem.


    The alternative approach would be to run the tests within the Docker container**: Instead of trying to run npm run test-jobs-once-docker from the GitHub Actions workflow, you could run the tests within the Docker container itself. This would ensure that the mocha command has access to the node_modules directory. You can do this by modifying your GitHub Actions workflow to execute the command inside the Docker container. Here is an example of how you could do that:

    - name: Run Test Specs
      run:  docker exec <container-id> npm run test-jobs-once-docker
      env:
        NODE_ENV: dockerTest
    

    Note that <container-id> should be replaced with the ID or name of your Docker container. You can get this information from the output of docker-compose up -d --build.

    You can get the container ID of your Docker container by using the docker ps command with a filter for the container name. The filter matches on all or part of a container’s name.

    This is how you could use it in your GitHub Actions workflow:

    - name: Get Container ID
      run: echo "CONTAINER_ID=$(docker ps -aqf "name=webapp")" >> $GITHUB_ENV
    

    In this step, the command docker ps -aqf "name=webapp" lists all containers and filters for the one named "webapp". The -aq flags stand for "all" and "quiet" respectively, meaning the command will return all containers (not just the running ones) and will only print their container IDs.

    The echo "CONTAINER_ID=$(docker ps -aqf "name=webapp")" >> $GITHUB_ENV command writes the output (the container ID) to the GITHUB_ENV file, which makes it available as an environment variable in subsequent steps of the workflow.

    You can then use this container ID in subsequent steps like so:

    - name: Inspect Node Modules
      run: docker exec ${{ env.CONTAINER_ID }} ls -la /app/node_modules
    
    Login or Signup to reply.
  2. In order to have mocha and/or karma within your image, so you can run them, in your Dockerfile after:

    RUN npm install
    

    add:

    RUN npm install -g mocha
    

    this will make mocha and karma available as commands in your PATH, so you can then run "mocha –reporter spec "server/**/*.spec.js""

    Login or Signup to reply.
  3. the mocha command is not found because it is not available in the environment where you try to run it:

          run:  npm run test-jobs-once-docker
    

    While there is an npm command available and the file package.json accessible for it, it effectively executes the npm package script called test-jobs-once-docker, specifically:

    mocha --reporter spec "server/**/*.spec.js"
    

    The subshell npm invokes then is not able to find mocha resulting in the error message in question.


    This just to understand the error message.


    The rest is not entirely clear from your question. And this effects the environment that you need to execute the mocha command line successfully. The fitting environment, which you also confirm working, you specifically reject:

    When I run this on GitHub Actions, I comment out the command property on the webapp in the docker-compose.yml so the command is executed in the job on GitHub Actions […]

    The rationale you give:

    so the command is executed in the job on GitHub Actions instead of when the container builds.

    And then:

    I feel like this is the problem.

    Indeed! The whole setup is done to run this command but then you disable the command because you do the whole setup?

    This makes no sense. Indeed you want to run it when it builds, you have this in your pipeline, even named:

    Build Docker Containers & Run Test Specs

    Just do it. Don’t comment out the command. Otherwise you’re starting the container but without running the command. The command you want to run.

    docker-compose -f "docker-compose.yml" up -d --build
    

    It is either the misunderstanding running the setup in background, or it is fine, but then you need to execute the command in the running container (and keep the command in the compose config commented):

    docker-compose exec webapp npm run test-jobs-once-docker
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search