diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..4252dfe --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,193 @@ +pipeline { + + environment { + devRegistry = 'ghcr.io/datakaveri/rs-proxy-dev' + deplRegistry = 'ghcr.io/datakaveri/rs-proxy-depl' + registryUri = 'https://ghcr.io' + registryCredential = 'datakaveri-ghcr' + GIT_HASH = GIT_COMMIT.take(7) + } + + agent { + node { + label 'slave1' + } + } + + stages { + + stage('Build images') { + steps{ + script { + echo 'Pulled - ' + env.GIT_BRANCH + devImage = docker.build( devRegistry, "-f ./docker/dev.dockerfile .") + deplImage = docker.build( deplRegistry, "-f ./docker/depl.dockerfile .") + } + } + } + + stage('Unit Tests and Code Coverage Test'){ + steps{ + script{ + sh 'cp /home/ubuntu/configs/rs-proxy-config-test.json ./secrets/all-verticles-configs/config-test.json' + catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE') { + sh "mvn clean test checkstyle:checkstyle pmd:pmd" + } + } + } + post{ + always { + xunit ( + thresholds: [ skipped(failureThreshold: '0'), failed(failureThreshold: '0') ], + tools: [ JUnit(pattern: 'target/surefire-reports/*.xml') ] + ) + jacoco classPattern: 'target/classes', exclusionPattern: 'iudx/rs/proxy/apiserver/ApiServerVerticle.class,iudx/rs/proxy/database/example/postgres/PostgresServiceImpl.class,**/*VertxEBProxy.class,**/Constants.class,**/*Verticle.class,iudx/rs/proxy/apiserver/*.class,iudx/rs/proxy/deploy/*.class,**/*AuthenticationService.class,**/*MeteringService.class,**/*CacheService.class,**/*Method.class,**/*DatabaseService.class,**/*ApiServerConstants.class,**/*CacheServiceVertxProxyHandler.class,**/*MeteringServiceVertxProxyHandler.class,**/*AuthenticationServiceVertxProxyHandler.class,**/ConsentLoggingServiceVertxProxyHandler.class,**/database/**,**/databroker/**,**/JwtDataConverter.class,**/PayloadSigningManager.class', execPattern: 'target/jacoco.exec', sourcePattern: 'src/main/java' + + recordIssues( + enabledForFailure: true, + blameDisabled: true, + forensicsDisabled: true, + qualityGates: [[threshold:0, type: 'TOTAL', unstable: false]], + tool: checkStyle(pattern: 'target/checkstyle-result.xml') + ) + recordIssues( + enabledForFailure: true, + blameDisabled: true, + forensicsDisabled: true, + qualityGates: [[threshold:100, type: 'TOTAL', unstable: false]], + tool: pmdParser(pattern: 'target/pmd.xml') + ) + } + failure{ + error "Test failure. Stopping pipeline execution!" + } + cleanup{ + script{ + sh 'sudo rm -rf target/' + } + } + } + } + + stage('Start RS-Proxy for Integration Testing'){ + steps{ + script{ + sh 'scp src/test/resources/IUDX-Resource-Proxy-Server-Consumer-APIs.postman_collection_5.5.0.json jenkins@jenkins-master:/var/lib/jenkins/iudx/rs-proxy/Newman/' + sh 'docker compose -f docker-compose.test.yml up -d integTest' + sh 'sleep 30' + } + } + post{ + failure{ + script{ + sh 'docker compose -f docker-compose.test.yml down --remove-orphans' + } + } + } + } + + + stage('Integration Tests and OWASP ZAP pen test'){ + steps{ + node('built-in') { + script{ + startZap ([host: '0.0.0.0', port: 8090, zapHome: '/var/lib/jenkins/tools/com.cloudbees.jenkins.plugins.customtools.CustomTool/OWASP_ZAP/ZAP_2.11.0']) + sh 'curl http://0.0.0.0:8090/JSON/pscan/action/disableScanners/?ids=10096' + sh 'HTTP_PROXY=\'127.0.0.1:8090\' newman run /var/lib/jenkins/iudx/rs-proxy/Newman/IUDX-Resource-Proxy-Server-Consumer-APIs.postman_collection_5.5.0.json -e /home/ubuntu/configs/rs-proxy-postman-env.json -n 2 --insecure -r htmlextra --reporter-htmlextra-export /var/lib/jenkins/iudx/rs-proxy/Newman/report/report.html --reporter-htmlextra-skipSensitiveData' + runZapAttack() + } + } + } + post{ + always{ + node('built-in') { + publishHTML([allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: '/var/lib/jenkins/iudx/rs-proxy/Newman/report/', reportFiles: 'report.html', reportTitles: '', reportName: 'Integration Test Report']) + script{ + archiveZap failHighAlerts: 1, failMediumAlerts: 1, failLowAlerts: 1 + } + } + } + failure{ + error "Test failure. Stopping pipeline execution!" + } + cleanup{ + script{ + sh 'docker compose -f docker-compose.test.yml down --remove-orphans' + } + } + } + } + + stage('Continuous Deployment') { + when { + allOf { + anyOf { + changeset "docker/**" + changeset "docs/**" + changeset "pom.xml" + changeset "src/main/**" + triggeredBy cause: 'UserIdCause' + } + expression { + return env.GIT_BRANCH == 'origin/main'; + } + } + } + stages { + stage('Push Images') { + steps { + script { + docker.withRegistry( registryUri, registryCredential ) { + devImage.push("5.5.0-alpha-${env.GIT_HASH}") + deplImage.push("5.5.0-alpha-${env.GIT_HASH}") + } + } + } + } + stage('Docker Swarm deployment') { + steps { + script { + sh "ssh azureuser@docker-swarm 'docker service update rs-proxy_rs-proxy --image ghcr.io/datakaveri/rs-proxy-depl:5.5.0-alpha-${env.GIT_HASH}'" + sh 'sleep 10' + } + } + post{ + failure{ + error "Failed to deploy image in Docker Swarm" + } + } + } + stage('Integration test on swarm deployment') { + steps { + node('built-in') { + script{ + sh 'newman run /var/lib/jenkins/iudx/fs/Newman/IUDX-Resource-Proxy-Server-Consumer-APIs.postman_collection_5.5.0.json -e /home/ubuntu/configs/cd/rs-proxy-postman-env.json --insecure -r htmlextra --reporter-htmlextra-export /var/lib/jenkins/iudx/rs-proxy/Newman/report/cd-report.html --reporter-htmlextra-skipSensitiveData' + } + } + } + post{ + always{ + node('built-in') { + script{ + publishHTML([allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: '/var/lib/jenkins/iudx/rs-proxy/Newman/report/', reportFiles: 'cd-report.html', reportTitles: '', reportName: 'Docker-Swarm Integration Test Report']) + } + } + } + failure{ + error "Test failure. Stopping pipeline execution!" + } + } + } + } + } + } + post{ + failure{ + script{ + if (env.GIT_BRANCH == 'origin/main') + emailext recipientProviders: [buildUser(), developers()], to: '$RS_PROXY_RECIPIENTS, $DEFAULT_RECIPIENTS', subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', body: '''$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS: +Check console output at $BUILD_URL to view the results.''' + } + } + } +} \ No newline at end of file diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 0000000..ddf9960 --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,40 @@ +version: '3.7' + +networks: + rs-proxy-net: + driver: bridge + +services: + integTest: + image: ghcr.io/datakaveri/rs-proxy-depl:latest + env_file: + - /home/ubuntu/configs/.rs-proxy.env + volumes: + - /home/ubuntu/configs/rs-proxy-config-dev.json:/usr/share/app/configs/config.json + - /home/ubuntu/configs/keystore-rs-proxy.jks:/usr/share/app/configs/keystore.jks + - type: volume + source: rs-proxy-volume + target: /usr/share/app/storage/temp-dir + depends_on: + - "zookeeper" + ports: + - "8080:8080" + restart: on-failure + networks: + - rs-proxy-net + logging: + driver: "json-file" + options: + max-file: "5" + max-size: "100m" + command: bash -c "exec java $$RS_JAVA_OPTS -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.Log4j2LogDelegateFactory -jar ./fatjar.jar --host $$(hostname) -c configs/config.json" + + zookeeper: + image: zookeeper:latest + expose: + - "2181" + networks: + - rs-proxy-net + +volumes: + rs-proxy-volume: \ No newline at end of file