I run NYC in my nodejs program that uses cluster to start child processes. I've used dumb-init to propagate the SIGINT to my program where I gracefully handle the signal. When I kill the program within the docker container, I get the coverage but when I do docker stop it doesn't wait for all the clusters to die, because of this NYC coverage isn't computed.
Is there any way to delay docker from exiting so that the coverage data created is saved?
The dockerfile executes a script which calls yarn start and in the start script, I've added NYC. I tried adding sleep in script after the yarn start but to no avail.
My dockerfile looks like this:-
FROM node:14
ARG ENVIRONMENT_NAME
ARG BUILD_NAME
ARG APP_PATH
ENV APP_PATH=${APP_PATH:-/default/path}
RUN mkdir -p ${APP_PATH}
ADD . ${APP_PATH}
WORKDIR ${APP_PATH}
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn
RUN yarn
RUN yarn build:$BUILD_NAME
FROM node:14-alpine
ARG ENVIRONMENT_NAME
ARG BUILD_NAME
ARG APP_PATH
ENV APP_PATH=${APP_PATH:-/default/path}
RUN yarn global add sequelize-cli@6.2.0 nyc
RUN yarn add shelljs bull dotenv pg sequelize@6.6.5
RUN apk add --no-cache dumb-init
ADD scripts/migrate-and-run.sh ${APP_PATH}/
ADD package.json ${APP_PATH}/
ADD . ${APP_PATH}/
COPY --from=0 ${APP_PATH}/dist ${APP_PATH}/dist
ADD https://keploy-enterprise.s3.us-west-2.amazonaws.com/releases/latest/assets/freeze_time_arm64.so /lib/keploy/freeze_time_arm64.so
RUN chmod +x /lib/keploy/freeze_time_arm64.so
ENV LD_PRELOAD=/lib/keploy/freeze_time_arm64.so
# Set working directory
WORKDIR ${APP_PATH}
ENTRYPOINT ["dumb-init"]
# RUN echo "hi"
# Set entrypoint and command
CMD [ "sh","./scripts/migrate-and-run.sh"]
# Expose port 9000
EXPOSE 9000
The script that is executed in the dockerfile
set -a . ".env$ENVIRONMENT_NAME" set +a
sleep 10
echo $BUILD_NAME
if [ "$BUILD_NAME" == "local" ]
then
npx sequelize-cli db:drop
npx sequelize-cli db:create
fi
npx sequelize-cli db:migrate
# seed data for local builds
if [ "$BUILD_NAME" == "local" ]
then
for file in seeders/*
do
:
npx sequelize-cli db:seed --seed $file
done
fi
yarn start
Maybe there is a way to use the script to help resolve this problem.
You can trap the signal in the script and send it to the running child processes and make the child wait till it is completed.
#!/bin/sh
set -a
. ".env.$ENVIRONMENT_NAME"
set +a
# Function to handle SIGINT signal
handle_int() {
echo "SIGINT received, forwarding to child process..."
kill -INT "$child" 2>/dev/null
echo "Waiting for child process to exit..."
wait "$child"
echo "Child process exited. Waiting for NYC coverage data to be fully written..."
sleep 10 # Wait for 50 seconds
echo "Exiting after delay..."
exit 0
}
# Trap SIGINT signal
trap 'handle_int' INT TERM
sleep 10 # Ensure services like DB are up
echo $BUILD_NAME
if [ "$BUILD_NAME" = "local" ]; then
npx sequelize-cli db:drop
npx sequelize-cli db:create
fi
echo $LD_PRELOAD
npx sequelize-cli db:migrate
# Seed data for local builds
if [ "$BUILD_NAME" = "local" ]; then
for file in seeders/*; do
npx sequelize-cli db:seed --seed $file
done
fi
# Start yarn and get its PID
yarn start &
child=$!
echo "Started yarn with PID $child"
wait "$child"
Here the wait "$child"
command in a shell script is used to pause the execution of the script until the process identified by the variable $child
terminates.
Why This Process Is Beneficial Synchronisation: