I am doing a very simple CI/CD using codepipeline with (codeCommit, codebuild, codeDeploy).
I have a simple node.js app that has a unittest like this below
const Allsayings = require('./testAllsayings');
function logPass(tName){
console.log("PASS - " + tName);
}
function logFail(tName){
console.log("FAIL - " + tName )
}
// T01 - Search for a saying and succeed
let say01 = new Allsayings();
say01.addQuote("Everyone is looking for something.");
say01.addQuote("Let's try to figure this out together, so help me please");
let output01 = aq01.findSaying("Not here");
if (output01.search("Before you embark") > -1){
logPass("T01");
} else {
logFail("T01");
}
I want that when the unit test fails it halt/stop the deployment or the progression of the pipeline.
my byuildspec
version: 0.2
phases:
install:
runtime-versions:
nodejs: 16
commands:
- echo Installing
pre_build:
commands:
- echo Installing source NPM dependencies.
- cd serverSide
- npm install
build:
commands:
- echo Build started on `date`
- npm install pm2#latest -g
# buildspec is able to get into your servSide file?
- ls
- echo "for debugging ... starting test"
- node testAllsayings.js
- echo "test is successful ... "
post_build:
commands:
- echo Build completed on `date`
artifacts:
files:
- '**/*'
However, my problem is that when I run codepipeline the codebuild completes successfully despite I made my unittest fail and here is a part of the codebuild log
[Container] 2022/10/03 00:45:05 Running command echo "for debugging ... starting test"
for debugging ... starting test
[Container] 2022/10/03 00:45:05 Running command node testAllsayings.js
Fail - T01
[Container] 2022/10/03 00:45:05 Running command echo "test is successful ... "
test is successful ...
I read this, and I moved the command node testAllsayings.js to the pre_build stage, but still everything worked without stopping the build stage or deployment stage.
So I found a solution. For code build to catch the error from the unittest, the function has to exist with one. So I added this line of code and now code build stops when the unittest fails.
function logFail(tName){
console.log("FAIL - " + tName )
process.exitCode(1);
}
Related
I am new to gitlab runner and trying to setup acceptance_stage after unit test passes.
The tests run on a windows machine when the job is triggered.
The job exits when tests pass, but the job stalls when test fails. I have only 1 test right now and I am planning to run multiple tests in parallel when this issue is fixed.
The test is triggered using maven command. (I have tweaked the test in such a way so that it fails.)The test fails on this command :
mvn verify -P rest-test-run -Denvironment="qa" -Dwebdriver.chrome.driver="C:\tools\chromedriver.exe"
and the job stalls and is unable to execute the next command.
Here is the sample yaml file that i am using to trigger acceptance stage:
stages:
- test
acceptance_tests:
stage: test
tags:
- playground
only:
- ci_cd_test
before_script:
- export POM_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
- cd ..
- git clone "git#gitlab.<project>" "<automation project name>" 2> /dev/null || (cd "<automation project name>" ; git pull)
- cd <webapp project name>
- export DB_URL=jdbc url
- export DB_USER=username
- export DB_PASSWORD=password
variables:
GIT_STRATEGY: none
script:
# flyway migrates
- java -Dfile.encoding=UTF-8 -jar <webapp project name>/target/<webapp project name>-$POM_VERSION.jar flyway migrate
# Bring up the app
- ./start.sh
# Run cucumber test
- cd ../<automation project name>
- mvn verify -P rest-test-run -Denvironment="qa" -Dwebdriver.chrome.driver="C:\tools\chromedriver.exe"
- cd ../<webapp project name>
# Stop the app
- ./stop.sh
I have also attached a screen shot of the stalling job.
Some troubleshooting ideas that I tried implementing:
upgraded surefireplugin(the version that I use in 2.22.0)
added a cleanup_job in yaml file
ran tests not in parallel
the above ideas did not solve the problem.
I am making a pipeline on Jenkins to test and deploy my node.js application using Docker containers. But I am getting my pipeline stuck because a test is failing. The behaviour I would expect is pipeline finishes without executing next stages but it will not get stuck.
Jenkinsfile:
pipeline {
agent any
stages {
stage('Build') {
steps {
sh '''docker build --tag my-web:$BUILD_NUMBER .
docker stop my-web&& docker rm my-web
echo "Build step finished"'''
}
}
stage('Unit test') {
steps {
sh '''docker build -t my-web-test -f Dockerfile.test .
docker run --rm my-web-test
'''
}
}
stage('Run') {
steps {
sh '''docker run --name my-web -p 3000:3000 my-web:$BUILD_NUMBER node /var/www/index.js &
'''
echo 'RUNNING'
}
}
stage('End') {
steps {
echo 'End of pipeline'
}
}
}
}
Dockerfile.test:
FROM node:alpine
RUN mkdir /var/test
WORKDIR /var/test
COPY package.json /var/test/
RUN npm install && npm install -g mocha
COPY src/ /var/test/
CMD ["mocha", "tests/", "--recursive"]
When I trigger the pipeline:
If I remove Unit test stage from pipeline everything works OK and application begins running.
If I do not remove Unit test stage, testing stage begins and I get a result of 14 test passed and 1 failed but the pipeline hangs in this step so Run step never triggers and the pipeline keeps in Running status.
14 passing (2s)
1 failing
1) Checking user first-time-login
Should redirect to change-password page:
Error: expected "Location" of "/dashboard/change-password", got "/dashboard"
at Test._assertHeader (node_modules/supertest/lib/test.js:249:12)
at Test._assertFunction (node_modules/supertest/lib/test.js:283:11)
at Test.assert (node_modules/supertest/lib/test.js:173:18)
at localAssert (node_modules/supertest/lib/test.js:131:12)
at /var/test/node_modules/supertest/lib/test.js:128:5
at Test.Request.callback (node_modules/superagent/lib/node/index.js:728:3)
at IncomingMessage.<anonymous> (node_modules/superagent/lib/node/index.js:916:18)
at endReadableNT (_stream_readable.js:1154:12)
at processTicksAndRejections (internal/process/task_queues.js:77:11)
Newer versions of mocha need to exit, otherwise the server keeps running so next stage is never reached.
mocha --exit
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.
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.
I started working on my first CodePipeline with node.js app which is hosted on github. I would like to create simple pipe as follow:
Github repo triggers pipe
Test env (Elastic Beanstalk app) is built from S3 .zip file
Test env runs npm test and npm lint
If everything is OK then QA env (another EB app) is built
For above pipe I've created .config files under .ebextensions directory:
I would like to use npm install --production for QA and PROD env, but it seems that EC2 can't find node nor npm. I checked logs and EC2 triggered npm install by default in temporary folder, then it fails on my first script and app catalogue is always empty.
container_commands:
install-dev:
command: "npm install"
test: "[ \"$NODE_ENV\" = \"TEST\" ]"
ignoreErrors: false
install-prod:
command: "npm install --production"
test: "[ \"$NODE_ENV\" != \"TEST\" ]"
ignoreErrors: false
Is it posible to run unit tests and linting without jenkins?
container_commands:
lint:
command: "npm run lint"
test: "[ \"$NODE_ENV\" = \"TEST\" ]"
ignoreErrors: false
test:
command: "npm run test"
test: "[ \"$NODE_ENV\" = \"TEST\" ]"
ignoreErrors: false
I set NODE_ENV for each Elastic Beanstalk instance. No matter what I will do every time my pipe fails because of npm is not recognized, but how is it possible if I'm running 64bit Amazon Linux with node.js ? What's more I cannot find any examples about CodePipeline with node.js in AWS Docs. Thanks in advance!
If you're using AWS for CI/CD, you can use CodeBuild. However, Github provides a great feature called Actions for running Unit Tests, which I find much simpler than AWS. Anyway, I will walk you through both examples:
Using AWS for running Unit Tests
Essentially, you could create a new stage into your CodePipeline, and configure the CodeBuild for running Unit Tests, e.g.
First, add a buildspec.yml file in the root folder of your app so you can use the following example:
version: 0.2
phases:
install:
runtime-versions:
nodejs: 10
commands:
- echo Installing Mocha globally...
- npm install -g mocha
pre_build:
commands:
- echo Installing dependencies...
- npm install
- npm install unit.js
build:
commands:
- echo Build started on `date`
- echo Run Unit Tests and so on
- npm run test
- npm run lint
post_build:
commands:
- echo Build completed on `date`
# THIS IS OPTIONAL
artifacts:
files:
- app.js
- package.json
- src/app/*
- node_modules/**/*
You can find everything you need in the BackSpace Academy, this course is for free:
AWS DevOps CI/CD - CodePipeline, Elastic Beanstalk and Mocha
Using Github for running Unit Tests
You could create your custom actions using Github, it will automatically set up everything you need in your root folder, e.g.
After choosing the appropriate workflow, it will automatically generate a folder/file ".github > workflow > nodejs.yml".
So it will look like this:
name: Node CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [8.x, 10.x, 12.x]
steps:
- uses: actions/checkout#v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node#v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install, build, and test
run: |
npm install
npm run build --if-present
npm test
env:
CI: true
I hope you could find everything you need in this answer. Cheers
Have you incorporated CodeBuild into your pipeline?
You should
1) Create a pipeline whose source is your github account. Go through the setup procedure so that commits on a particular branch trigger the Codepipeline
2) Create a test stage in your Codepipeline which leverages the CodeBuild service. In order to run your Node tests, you might need to provide a configured build environment. And you probably also need to provide a build spec file that specifies the tests to run etc.
3) Assuming that the test stage passes, you can determine if the pipeline continues to another stage which is linked to an elasticbeanstalk app environment which supports the Node platform. These environments are purely for artifacts that have passed testing, so I see no need to have the .ebextensions commands written above.
Have a read of what CodeBuild can do to help you run tests for Node,
https://aws.amazon.com/codebuild/
Good luck!