GitLab CI stuck on running NodeJS server - node.js

I'm trying to use GitLab CI to build, test and deploy an Express app on a server (the Runner is running with the shell executor). However, the test:async and deploy_staging jobs do not terminate. But when checking the terminal inside GitLab, the Express server does indeed start. What gives ?
stages:
- build
- test
- deploy
### Jobs ###
build:
stage: build
script:
- npm install -q
- npm run build
- knex migrate:latest
- knex seed:run
artifacts:
paths:
- build/
- node_modules/
tags:
- database
- build
test:lint:
stage: test
script:
- npm run lint
tags:
- lint
# Run the Express server
test:async:
stage: test
script:
- npm start &
- curl http://localhost:3000
tags:
- server
deploy_staging:
stage: deploy
script:
- npm start
environment:
name: staging
url: my_url_here
tags:
- deployment
The npm start is just node build/bundle.js. The build script is using Webpack.

Note: solution works fine when using a gitlab runner with shell executor
Generally in Gitlab CI we run ordered jobs with specific tasks that should be executed one after the end of the other.
So for the job build we have the npm install -q command that runs and terminates with an exit status (0 exit status if the command was succesful), then runs the next command npm run build and so on until the job is terminated.
For the test job we have npm start & process that keeps running so the job wont be able to terminate.
The problem is that sometimes we need to have some process that need to run in background or having some process that keeps living between tasks. For example in some kind of test we need to keep the server running, something like that:
test:
stage: test
script:
- npm start
- npm test
in this case npm test will never start because npm statrt keeps running without terminating.
The solution is to use before_script where we run a shell script that keeps npm start process running then we call after_script to kill that npm start process
so on our .gitlab-ci.yml we write
test:
stage: test
before_script:
- ./serverstart.sh
script:
- npm test
after_script:
- kill -9 $(ps aux | grep '\snode\s' | awk '{print $2}')
and on the serverstart.sh
# !/bin/bash
# start the server and send the console and error logs on nodeserver.log
npm start > nodeserver.log 2>&1 &
# keep waiting until the server is started
# (in this case wait for mongodb://localhost:27017/app-test to be logged)
while ! grep -q "mongodb://localhost:27017/app-test" nodeserver.log
do
sleep .1
done
echo -e "server has started\n"
exit 0
thanks to that serverstart.sh script is terminated while keeping npm start process alive and help us by the way move to the job where we have npm test.
npm test terminates and pass to after script where we kill all nodejs process.

You are starting a background job during your test phase which never terminates - therefore the job runs forever.
The idea of the GitLab CI jobs are shortly-running tasks - like compiling, executing unit tests or gathering information such as code coverage - which are executed in a predefined order. In your case, the order is build -> test -> deploy; since the test job doesn't finish, deploy isn't even executed.
Depending on your environment, you will have to create a different job for deploying your node app. For example, you can push the build output to a remote server using a tool like scp or upload it to AWS; after that, you reference the final URL in the url: field in your .gitlab-ci.yml.

Related

Gitlab CI/CD how to catch curl response in pipeline

I have a pipeline which starts some maven/java app, now I want to add a test stage , where I check if the app starts successfully , for example: when the build stage finishes, I check with curl
127.0.0.1:8080 if response 200 ok , else failed.
How can I create a Gitlab pipline for this use case?
stages:
- build
- deploy
- test
build:
stage: build
script:
- echo Build Stage 1
tags:
- java-run
deploy:
stage: deploy
tags:
- java-run
script:
- "some script"
test:
stage: test
tags:
- java-run
script:
I'm making some assumptions around your use-case here, so let me know if they aren't right. I'm assuming:
You're starting the java app remotely (I.e., your pipeline is deploying it to a cloud provider or non-CI/CD server)
Your server running CI/CD has access to the application via the internet
If so, assuming that you want your job to fail if the service is not accessible, you can simply curl the url using the -f flag, and it will fail if it receives a 404 error. Examples:
test:
image: alpine:latest
script:
- apk add curl
- curl -o /dev/null -s -w "%{http_code}\n" https://httpstat.us/404 -f
The above job will fail, as curl returns exit code 22 when it receives a >= 400 error code and the -f flag is used:
Now, if you're attempting to run the app in your CI/CD (which is why you're referring to 127.0.0.1 in your question), then you can't run the app locally in one job and test in another. The job would only exist and run within the context of the container that's running it, and test is in a separate container because it's a separate job. You have two options if you're attempting to run your app within the context of CI/CD and test it:
You can run your tests in the same job where you start the app (you may need to run the app using nohup to run it in the background)
You can package your app into a docker container, then run it as a service in your test job.

How to run commands in parallel Gitlab CI/CD pipeline?

I have a test command in my repo that should work when my server is up because the tests interact with the server once it is running.
On my local i use two commands on first terminal npm run dev - this gets the server running and on second terminal i run the command npm run test that runs test which only pass when the first command is running. How do i achieve this in my gitlab CICD test stage job?
currently i am doing this
test_job:
stage: test
script:
- npm run dev
- npm run test
so the pipeline executes npm run dev which doesnt self terminate and my pipeline gets stuck cant seem to find the solution. Help and suggestions are appreciated. Stack is typescript express graphql
You have two options that you can use for this:
If you're building your server into a container prior to this test job, you can run the container as a service, which will allow you to access it via it's service alias. That would look something like this:
test_job:
stage: test
services:
- name: my_test_container:latest
alias: test_container
script:
- npm run test # should hit http://test_container:<port> to access service
You can use the nohup linux command to run your service in the background. This will run the command in the background once it's started up, and it will die when the CI job ends (as part of shutting down the job). That would look like this:
test_job:
stage: test
script:
- nohup npm run dev &
- npm run test

How to run a persistent process using GitHub Actions?

I would like to start my web server using npm start which will continue to run even after the GitHub Actions workflow completes. I attempted to do this using the action - run: npm start &. However, this doesn't work. I suspect this command spawns the web server as a child process of the workflow runner, and once the workflow runner completes all of the steps it terminates and also terminates all of the child processes that it started. Is there a way to start a web server for example that will keep running even after the workflow completes? I know I could use services, but that adds a lot of hassle and I want to keep things simple and in one place.
This is my current workflow:
name: deploy-workflow
on: [push]
jobs:
deploy-job:
runs-on: self-hosted
defaults:
run:
shell: bash
working-directory: ./my-app # Root directory of the repository.
steps:
- uses: actions/checkout#v2 # Check out the repository.
- run: npm stop || true
- run: npm install
- run: npm start &

Gitlab runner does not fail build even tests fails

I'm trying to setup gitlab ci for my project.
My gitlab-ci script looks like:
stages:
- build
before_script:
- docker info
- chmod -R a+x scripts
build:
stage: build
script:
- pwd
- ./scripts/ci-prepare.sh
- ./scripts/dotnet-build.sh
- ./scripts/dotnet-tests.sh
- ./scripts/dotnet-publish.sh
- ./scripts/docker-publish-ci.sh
after_script:
- ./scripts/ci-success.sh
In build log I have this information:
Total tests: 6. Passed: 5. Failed: 1. Ommited: 0.
But event tests fails the build process is finished with success exit code.
Why?
I have no configured allow_failure option.
I added set -e in bash scripts and it works properly.
Gitlab CI checks the exit code of a command or script to decide if it has failed or succeeded.
A successful command returns a 0. All other exit codes are considered as an error.
I don't know what kind of software you are using for your tests - I think you should just return the exit code of your tests in your scripts.

npm scripts hang indefinitely on Concourse CI

On Concourse, I am running integration tests where I run certain npm scripts. There is a particular script that build my backend/frontend and then proceeds to run the tests. However once the test is done (fail or succeed). the npm script does not stop. It doesn't error out and hangs indefinitely either when the tests fail or succeeds. I have run this script on a local machine and a local container and the npm script works fine. Only on Concourse, the script hangs forever.
To give more context to my setup here is a sample of the npm script which is run on the frontend
"ci:start:backend": "npm run --prefix ../emailservice/mock-service dev & npm run --prefix ../server-repo ci:start:server & sleep 3"
"ci:test:system": "npm run ci:start:backend && npm run build:dist:serve & sleep 90 && npm run test:browser:ci"
npm run ci:test:system is the main script that is run. What it does it will start running an email service, a server and the frontend all at once in order to run the tests. It is a messy way of doing things but it works for both local and in containers. This method has been done for similar tests for server testing and it is running on concourse fine.
The task of the pipeline can be seen below
# runs unit tests for frontend
- name: run-tests
plan:
- get: frontend-repo
- get: server-repo
- get: emailservice
- task: run-npm-tests
privileged: true
config:
platform: linux
image_resource:
type: docker-image
source:
repository: jonoc/techradar-integration
inputs:
- name: frontend-repo
- name: server-repo
- name: emailservice
run:
path: sh
args:
- -exc
- |
mongod --fork --logpath /var/log/mongodb.log
export SHELL=/bin/bash
cd server-repo
npm install --silent
cd ../emailservice/mock-service
npm install --silent
cd ../../frontend-repo
npm install --silent
npm rebuild node-sass --silent
npm run postinstall --silent
npm run ci:test:system
Everything seems to be not out of the ordinary but concourse refuses to give a green or red build. I suspect it is due to the other scripts that are run forever but are hanging in the background and concourse does not want to end. However running npm run ci:start:backend in concourse will work fine, but running npm run test:browser:ci will hang forever which further adds confusion to whats the problem.
Concourse version:3.3.2
Deployment type (BOSH/Docker/binary):Docker
Infrastructure/IaaS:AWS/EC2
Browser (if applicable):Chrome
Did this used to work? Never
Are you sure that your resources are available in the tasks docker container?
You specify multiple inputs here
- name: frontend-repo
- name: server-repo
- name: emailservice
But concourse requires you to specify a proper path for each input if you have more than one.
Try to hijack the task container after execution and check if the resources are available. You can also execute the script in the container, so you can debug it easier.
fly -t <your_target> hijack -j demo_job/demo_task
My issue is resolved by changing up my npm scripts. Turns out chaining npm run --prefix ../emailservice/mock-service dev & npm run --prefix ../server-repo ci:start:server & sleep 3 with the other scripts causes some issues on Concourse.
I modified the npm scripts to use npm-run-all and use the -r parameter to finish the script when my tests are done

Resources