diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..9fd6582e58 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,275 @@ +pipeline { + agent none + stages { + stage('worker build') { + agent { + docker { + image 'maven:3.6.1-jdk-8-alpine' + args '-v $HOME/.m2/root/.m2' + } + + } + when { + changeset '**/worker/**' + } + steps { + echo 'Compiling worker app' + dir(path: 'worker') { + sh 'mvn compile' + } + + } + } + + stage('worker test') { + agent { + docker { + image 'maven:3.6.1-jdk-8-alpine' + args '-v $HOME/.m2/root/.m2' + } + + } + when { + changeset '**/worker/**' + } + steps { + echo 'Running unit Tests on worker app' + dir(path: 'worker') { + sh 'mvn clean test' + } + + } + } + + stage('worker package') { + agent { + docker { + image 'maven:3.6.1-jdk-8-alpine' + args '-v $HOME/.m2/root/.m2' + } + + } + when { + branch 'master' + changeset '**/worker/**' + } + steps { + echo 'Packaging worker app' + dir(path: 'worker') { + sh 'mvn package -DskipTests' + archiveArtifacts(artifacts: '**/target/*.jar', fingerprint: true) + } + + } + } + + stage('worker-docker-package') { + agent any + when { + changeset '**/worker/**' + branch 'master' + } + steps { + echo 'Packaging worker app with docker' + script { + docker.withRegistry('https://index.docker.io/v1/', 'dockerlogin'){ + def workerImage = docker.build("cheloghm/worker:v${env.BUILD_ID}", "./worker") + workerImage.push() + workerImage.push("${env.BRANCH_NAME}") + } + } + + } + } + + stage('vote build') { + agent { + docker { + image 'python:2.7.16-slim' + args '--user root' + } + + } + when { + changeset '**/vote/**' + } + steps { + echo 'Compiling vote app' + dir(path: 'vote') { + sh 'pip install -r requirements.txt' + } + + } + } + + stage('vote test') { + agent { + docker { + image 'python:2.7.16-slim' + args '--user root' + } + + } + when { + changeset '**/vote/**' + } + steps { + echo 'Running unit Tests on vote app' + dir(path: 'vote') { + sh 'pip install -r requirements.txt' + sh 'nosetests -v' + } + + } + } + + stage('vote integration'){ + agent any + when{ + changeset "**/vote/**" + branch 'master' + } + steps{ + echo 'Running Integration Tests on vote app' + dir('vote'){ + sh 'sh integration_test.sh' + } + } + } + + stage('vote-docker-package') { + agent any + when { + changeset '**/vote/**' + branch 'master' + } + steps { + echo 'Packaging vote app with docker' + script { + docker.withRegistry('https://index.docker.io/v1/', 'dockerlogin'){ + def voteImage = docker.build("cheloghm/vote:v${env.BUILD_ID}", "./vote") + voteImage.push() + voteImage.push("${env.BRANCH_NAME}") + } + } + + } + } + + stage('result build') { + agent { + docker { + image 'node:8.16.0-alpine' + } + + } + when { + changeset '**/result/**' + } + steps { + echo 'Compiling result app' + dir(path: 'result') { + sh 'npm install' + } + + } + } + + stage('result test') { + agent { + docker { + image 'node:8.16.0-alpine' + } + + } + when { + changeset '**/result/**' + } + steps { + echo 'Running unit Tests on result app' + dir(path: 'result') { + sh 'npm install' + sh 'npm test' + } + + } + } + + stage('result-docker-package') { + agent any + when { + changeset '**/result/**' + branch 'master' + } + steps { + echo 'Packaging result app with docker' + script { + docker.withRegistry('https://index.docker.io/v1/', 'dockerlogin'){ + def resultImage = docker.build("cheloghm/result:v${env.BUILD_ID}", "./result") + resultImage.push() + resultImage.push("${env.BRANCH_NAME}") + } + } + + } + } + + stage('Sonarqube') { + agent any + when{ + branch 'master' + } + tools { + jdk "JDK11" // the name you have given the JDK installation in Global Tool Configuration + } + + environment{ + sonarpath = tool 'SonarScanner' + } + + steps { + echo 'Running Sonarqube Analysis..' + withSonarQubeEnv('sonar-instavote') { + sh "${sonarpath}/bin/sonar-scanner -Dproject.settings=sonar-project.properties -Dorg.jenkinsci.plugins.durabletask.BourneShellScript.HEARTBEAT_CHECK_INTERVAL=86400" + } + } + } + + + stage("Quality Gate") { + steps { + timeout(time: 1, unit: 'HOURS') { + // Parameter indicates whether to set pipeline to UNSTABLE if Quality Gate fails + // true = set pipeline to UNSTABLE, false = don't + waitForQualityGate abortPipeline: true + } + } + } + + stage('Deploy to Dev') { + agent any + when { + branch 'master' + } + steps { + sh 'docker-compose up -d' + } + } + + } + post { + always { + echo 'Pipeline for instavote app is complete...' + } + + failure { + slackSend(channel: 'instavote-ci', message: "Build Failed - ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)") + } + + success { + echo 'Pipeline for worker is complete...' + slackSend(channel: 'instavote-ci', message: "Build Succeeded - ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)") + } + + } +} \ No newline at end of file diff --git a/README.md b/README.md index b8ad8a94af..513c42d635 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Example Voting App ========= +This ia a sample instavote application. + Getting started --------------- diff --git a/TEST.md b/TEST.md new file mode 100644 index 0000000000..cc7c298588 --- /dev/null +++ b/TEST.md @@ -0,0 +1,5 @@ +Just testing the webhook +Clean up +Fix the mono-pipeline first +Got the mono-pipeline working by changing the images of the different micro-services to smaller compatible images, +so it can easily be pulled during the build process. diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000000..dfd70e3d75 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,52 @@ +version: "3.8" + +volumes: + db-data: + +networks: + instavote: + driver: bridge + +services: + vote: + image: cheloghm/vote:latest + build: ./vote + ports: + - 5002:80 + depends_on: + - redis + networks: + - instavote + + redis: + image: redis:alpine + networks: + - instavote + + db: + image: postgres:9.4 + volumes: + - "db-data:/var/lib/postgresql/data" + networks: + - instavote + environment: + - POSTGRES_HOST_AUTH_METHOD=trust + + result: + image: cheloghm/result:latest + build: ./vote + ports: + - 5003:4000 + depends_on: + - db + networks: + - instavote + + worker: + image: cheloghm/worker:latest + build: ./vote + depends_on: + - redis + - db + networks: + - instavote \ No newline at end of file diff --git a/result/Jenkinsfile b/result/Jenkinsfile new file mode 100644 index 0000000000..972866977b --- /dev/null +++ b/result/Jenkinsfile @@ -0,0 +1,70 @@ +pipeline{ + + agent none + + stages{ + stage('build'){ + agent{ + docker{ + nodejs 'NodeJS 8.9.0' + } + } + when{ + changeset "**/result/**" + } + steps{ + echo 'Compiling result app' + dir('result'){ + sh 'npm install' + } + } + } + stage('test'){ + agent{ + docker{ + nodejs 'NodeJS 8.9.0' + } + } + when{ + changeset "**/result/**" + } + steps{ + echo 'Running unit Tests on result app' + dir('result'){ + sh 'npm install' + sh 'npm test' + } + } + } + stage('docker-package'){ + agent any + when{ + changeset "**/result/**" + branch 'master' + } + steps{ + echo 'Packaging result app with docker' + script{ + docker.withRegistry('https://index.docker.io/v1/', 'dockerlogin'){ + def resultImage = docker.build("cheloghm/result:v${env.BUILD_ID}", "./result") + resultImage.push() + resultImage.push("latest") + } + } + } + } + } + + post{ + always{ + echo 'Pipeline for result is complete...' + } + failure{ + slackSend (channel: "instavote-ci", message: "Build Failed - ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)") + } + success{ + echo 'Pipeline for result is complete...' + slackSend (channel: "instavote-ci", message: "Build Succeeded - ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)") + } + } +} \ No newline at end of file diff --git a/result/test/mock.test.js b/result/test/mock.test.js index f99dfdae97..bdcd486e79 100644 --- a/result/test/mock.test.js +++ b/result/test/mock.test.js @@ -26,4 +26,10 @@ describe('mock test 4', () => { }); }); +describe('mock test 5', () => { + it('unit test 5', () => { + expect(true).to.be.true; + }); +}); + diff --git a/sonar-project.properties b/sonar-project.properties index fa91ad96cc..a9f766985d 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,6 +1,6 @@ # Uncomment and update Org matching your configurations on Sonarcloud -#sonar.organization=your-org -sonar.projectKey=your-org_example-voting-app +sonar.organization=cheloghm +sonar.projectKey=cheloghm_example-voting-app sonar.projectName=Instavote AIO sonar.projectVersion=1.0 # Comma-separated paths to directories with sources (required) diff --git a/vote/Jenkinsfile b/vote/Jenkinsfile new file mode 100644 index 0000000000..219afdac3d --- /dev/null +++ b/vote/Jenkinsfile @@ -0,0 +1,73 @@ +pipeline{ + + agent none + + stages{ + stage('build'){ + agent{ + docker{ + image 'python:2.7.16-slim' + args '--user root' + } + } + when{ + changeset "**/vote/**" + } + steps{ + echo 'Compiling vote app' + dir('vote'){ + sh 'pip install -r requirements.txt' + } + } + } + stage('test'){ + agent{ + docker{ + image 'python:2.7.16-slim' + args '--user root' + } + } + when{ + changeset "**/vote/**" + } + steps{ + echo 'Running unit Tests on vote app' + dir('vote'){ + sh 'pip install -r requirements.txt' + sh 'nosetests -v' + } + } + } + stage('docker-package'){ + agent any + when{ + changeset "**/vote/**" + branch 'master' + } + steps{ + echo 'Packaging vote app with docker' + script{ + docker.withRegistry('https://index.docker.io/v1/', 'dockerlogin'){ + def voteImage = docker.build("cheloghm/vote:v${env.BUILD_ID}", "./vote") + voteImage.push() + voteImage.push("latest") + } + } + } + } + + } + + post{ + always{ + echo 'Pipeline for vote is complete...' + } + failure{ + slackSend (channel: "instavote-ci", message: "Build Failed - ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)") + } + success{ + echo 'Pipeline for vote is complete...' + slackSend (channel: "instavote-ci", message: "Build Succeeded - ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)") + } + } +} \ No newline at end of file diff --git a/vote/tests/test_frontend.py b/vote/tests/test_frontend.py index 5e3d37a3d1..1171e29d7f 100644 --- a/vote/tests/test_frontend.py +++ b/vote/tests/test_frontend.py @@ -10,7 +10,6 @@ def setUp(self): self.app = app.test_client() self.app.testing = True - def test_home_status_code(self): """Assert that the home page loads successfully""" result = self.app.get('/') diff --git a/worker/Dockerfile b/worker/Dockerfile new file mode 100644 index 0000000000..463956bad0 --- /dev/null +++ b/worker/Dockerfile @@ -0,0 +1,11 @@ +FROM maven:3.8.6 + +WORKDIR /app + +COPY . . + +RUN mvn package -DskipTests && \ + mv target/worker-jar-with-dependencies.jar /run/worker.jar && \ + rm -rf * + +CMD java -jar /run/worker.jar diff --git a/worker/Jenkinsfile b/worker/Jenkinsfile new file mode 100644 index 0000000000..5d600ccb1c --- /dev/null +++ b/worker/Jenkinsfile @@ -0,0 +1,90 @@ +pipeline{ + + agent none + + stages{ + stage('build'){ + agent{ + docker{ + image 'maven:3.8.6' + args '-v $HOME/.m2/root/.m2' + } + } + when{ + changeset "**/worker/**" + } + steps{ + echo 'Compiling worker app' + dir('worker'){ + sh 'mvn compile' + } + } + } + stage('test'){ + agent{ + docker{ + image 'maven:3.8.6' + args '-v $HOME/.m2/root/.m2' + } + } + when{ + changeset "**/worker/**" + } + steps{ + echo 'Running unit Tests on worker app' + dir('worker'){ + sh 'mvn clean test' + } + } + } + stage('package'){ + agent{ + docker{ + image 'maven:3.8.6' + args '-v $HOME/.m2/root/.m2' + } + } + when{ + branch 'master' + changeset "**/worker/**" + } + steps{ + echo 'Packaging worker app' + dir('worker'){ + sh 'mvn package -DskipTests' + archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true + } + } + } + stage('docker-package'){ + agent any + when{ + changeset "**/worker/**" + branch 'master' + } + steps{ + echo 'Packaging worker app with docker' + script{ + docker.withRegistry('https://index.docker.io/v1/', 'dockerlogin'){ + def workerImage = docker.build("cheloghm/worker:v${env.BUILD_ID}", "./worker") + workerImage.push() + workerImage.push("latest") + } + } + } + } + } + + post{ + always{ + echo 'Pipeline for worker is complete...' + } + failure{ + slackSend (channel: "instavote-ci", message: "Build Failed - ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)") + } + success{ + echo 'Pipeline for worker is complete...' + slackSend (channel: "instavote-ci", message: "Build Succeeded - ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)") + } + } +} \ No newline at end of file diff --git a/worker/README.md b/worker/README.md new file mode 100644 index 0000000000..831bbe16a3 --- /dev/null +++ b/worker/README.md @@ -0,0 +1,13 @@ +## Worker Java App + +### Worker Build +* Build Status +![GitHub branch checks state](https://img.shields.io/github/checks-status/cheloghm/example-voting-app/master) + +### Worker Test +* Build Status +[![Build Status](http://localhost:8080/buildStatus/icon?job=instavote%2Fworker-test&subject=Unittest)](http://localhost:8080/job/instavote/job/worker-test/) + +### Worker Package +* Build Status +[![Build Status](http://localhost:8080/buildStatus/icon?job=instavote%2Fworker-package)](http://localhost:8080/job/instavote/job/worker-package/)