{"id":16429800,"url":"https://github.com/pavankjadda/bookstore","last_synced_at":"2025-07-18T08:37:10.007Z","repository":{"id":35300913,"uuid":"137307186","full_name":"pavankjadda/BookStore","owner":"pavankjadda","description":"Spring Boot Project deployed with Jenkins CICD pipeline on OpenShift ","archived":false,"fork":false,"pushed_at":"2022-05-30T14:54:15.000Z","size":34738,"stargazers_count":13,"open_issues_count":0,"forks_count":58,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-04T13:52:50.395Z","etag":null,"topics":["aws","bookstore","cicd","java","jenkins-cicd-pipeline","jenkins-pipeline","jenkinsfile","openshift","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pavankjadda.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-14T04:46:01.000Z","updated_at":"2025-03-22T08:33:07.000Z","dependencies_parsed_at":"2022-08-28T08:02:30.243Z","dependency_job_id":null,"html_url":"https://github.com/pavankjadda/BookStore","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/pavankjadda/BookStore","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavankjadda%2FBookStore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavankjadda%2FBookStore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavankjadda%2FBookStore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavankjadda%2FBookStore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pavankjadda","download_url":"https://codeload.github.com/pavankjadda/BookStore/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavankjadda%2FBookStore/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265728985,"owners_count":23818733,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","bookstore","cicd","java","jenkins-cicd-pipeline","jenkins-pipeline","jenkinsfile","openshift","spring-boot"],"created_at":"2024-10-11T08:24:24.807Z","updated_at":"2025-07-18T08:37:09.966Z","avatar_url":"https://github.com/pavankjadda.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring Boot Project deployed with Jenkins pipeline on OpenShift \nDeploy Spring Boot Project with Jenkins CICD pipeline on OpenShift\n\n## Introduction\n\nOn every pipeline execution, the code goes through the following steps:\n\n1. Code is cloned from **Github** or Gogs, built, tested and analyzed for bugs and bad patterns\n2. The JAR artifact is pushed to **Nexus** Repository manager\n3. A container image (_bookstore:latest_) is built based on the _bookstore_ application JAR artifact\n4. The _bookstore_ container image is deployed in a fresh new container in bookstore_dev project\n5. If tests successful, the **bookstore_dev** image is tagged with the application version in the **bookstore_stage** project\n6. The staged image is deployed in a fresh new container in the **bookstore_stage** project\n\nThe following diagram shows the steps included in the deployment pipeline:\n\n![](src/main/resources/pipeline.png)\n\nThe application used in this pipeline is a Spring Boot application which is available on **src** folder in this repository \n\n## Prerequisites\n* 8+ GB memory\n* redhat-openjdk18-openshift imagestreams imported to OpenShift (see Troubleshooting section for details)\n\n### Start up an OpenShift cluster:\n\n```\nminishift addons enable xpaas\n#Adjust memory and cpus based on your PC, macbook or Ubuntu configuration\nminishift start --memory=10240 --cpus=4 --vm-driver=virtualbox\noc login -u developer\n```\n\n### Pre-pull the images to make sure the deployments go faster:\n\n```\nminishift ssh docker pull openshiftdemos/gogs:0.11.34\nminishift ssh docker pull registry.centos.org/rhsyseng/sonarqube:latest\nminishift ssh docker pull sonatype/nexus3:3.8.0\nminishift ssh docker pull registry.access.redhat.com/openshift3/jenkins-2-rhel7\nminishift ssh docker pull registry.access.redhat.com/openshift3/jenkins-slave-maven-rhel7\nminishift ssh docker pull registry.access.redhat.com/jboss-eap-7/eap70-openshift\n```\n\n### Get OC environment value and add it shell\n##### Execute the following command and follow instructions on screen for next steps\n```\n$ minishift oc-env\n \u003cExecute output of this command to get access to oc environment\u003e\n\n```\n\n## Automated Deploy on OpenShift (Not Recommended)\nYou can se the `scripts/provision.sh` script provided to deploy the entire demo:\n\n  ```\n  ./provision.sh --help\n  ./provision.sh deploy --deploy-che --ephemeral\n  ./provision.sh delete\n  ```\n\n## Manual Deploy on OpenShift\nCreate the following projects for CI/CD components, Dev and Stage environments:\n\n  ```\n  # Create Projects\n  oc new-project bookstore-dev --display-name=\"Bookstore - Dev\"\n  oc new-project bookstore-stage --display-name=\"Bookstore - Stage\"\n  oc new-project cicd --display-name=\"cicd\"\n\n  # Grant Jenkins Access to Projects\n  oc policy add-role-to-user edit system:serviceaccount:cicd:jenkins -n bookstore-dev\n  oc policy add-role-to-user edit system:serviceaccount:cicd:jenkins -n bookstore-stage\n\n  ```  \n  if add-role-to-user step fails execute following step and repeat last step again\n  ```\n  oc login -u system:admin\n  oc adm policy add-cluster-role-to-user cluster-admin \u003cusername\u003e\n  ```\n  \nClone the the project and navigate to the folder\n```\n  git clone https://github.com/pavankjadda/BookStore.git --branch=\u003cbranch name\u003e\n  cd Bookstore\n```\n\nStart Jenkins Persistent pod using following command\n\n  ```\n  oc new-app -n templates/jenkins-persistsnet-template.json\n  ```\nStart SonarQube with Postgres database using following command\n\n```\noc new-app -f templates/sonarqube-postgresql-template.yaml --param=SONARQUBE_VERSION=6.7\n```\n\nStart nexus artifact repository with persistent storage\n```\noc new-app -f templates/nexus3-persistent-template.yaml --param=NEXUS_VERSION=3.15.2\n```\n\n# Jenkinsfile\nFollowing Jenkinsfile (this code located inside cicd-template.yaml file) contains steps to automate the build and deployment process. Please make changes to Jenkinsfile if you want to add/remove steps in future. Next step explains the same process in a manual way. \ndef version, mvnCmd = \"mvn -s templates/cicd-settings-nexus3.xml\"\n      pipeline\n      {\n       agent any\n        tools\n        {\n            maven 'M3'\n        }\n\n        stages\n        {\n          stage('Build App')\n          {\n            steps\n             {\n              git branch: 'openshift-aws', url: 'https://github.com/pavankjadda/BookStore.git'\n              script {\n                  def pom = readMavenPom file: 'pom.xml'\n                  version = pom.version\n              }\n              sh \"mvn install -DskipTests=true\"\n            }\n          }\n          stage('Test')\n          {\n            steps\n            {\n                  echo \"Test Stage\"\n              sh \"${mvnCmd} test -Dspring.profiles.active=test\"\n              //step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml'])\n            }\n          }\n          stage('Code Analysis')\n          {\n            steps\n             {\n              script\n              {\n                      sh \"${mvnCmd} sonar:sonar -Dsonar.host.url=http://sonarqube:9000  -DskipTests=true\"\n              }\n            }\n          }\n          /*\n          stage('Archive App') {\n            steps {\n              sh \"${mvnCmd} deploy -DskipTests=true -P nexus3\"\n            }\n          }*/\n\n          stage('Create Image Builder') {\n\n            when {\n              expression {\n                openshift.withCluster() {\n                  openshift.withProject(env.DEV_PROJECT) {\n                    return !openshift.selector(\"bc\", \"bookstore\").exists()\n                  }\n                }\n              }\n            }\n            steps {\n              script {\n                openshift.withCluster() {\n                  openshift.withProject(env.DEV_PROJECT) {\n                    openshift.newBuild(\"--name=bookstore\", \"--image-stream=redhat-openjdk18-openshift:latest\", \"--binary=true\")\n                  }\n                }\n              }\n            }\n          }\n          stage('Build Image') {\n            steps {\n              sh \"rm -rf ocp \u0026\u0026 mkdir -p ocp/deployments\"\n              sh \"pwd \u0026\u0026 ls -la target \"\n              sh \"cp target/bookstore-*.jar ocp/deployments\"\n\n              script {\n                openshift.withCluster() {\n                  openshift.withProject(env.DEV_PROJECT) {\n                    openshift.selector(\"bc\", \"bookstore\").startBuild(\"--from-dir=./ocp\",\"--follow\", \"--wait=true\")\n                  }\n                }\n              }\n            }\n          }\n          stage('Create DEV') {\n            when {\n              expression {\n                openshift.withCluster() {\n                  openshift.withProject(env.DEV_PROJECT) {\n                    return !openshift.selector('dc', 'bookstore').exists()\n                  }\n                }\n              }\n            }\n            steps {\n              script {\n                openshift.withCluster() {\n                  openshift.withProject(env.DEV_PROJECT) {\n                    def app = openshift.newApp(\"bookstore:latest\")\n                    app.narrow(\"svc\").expose()\n\n                    //http://localhost:8080/actuator/health\n                    openshift.set(\"probe dc/bookstore --readiness --get-url=http://:8080/actuator/health --initial-delay-seconds=30 --failure-threshold=10 --period-seconds=10\")\n                    openshift.set(\"probe dc/bookstore --liveness  --get-url=http://:8080/actuator/health --initial-delay-seconds=180 --failure-threshold=10 --period-seconds=10\")\n\n                    def dc = openshift.selector(\"dc\", \"bookstore\")\n                    while (dc.object().spec.replicas != dc.object().status.availableReplicas) {\n                        sleep 10\n                    }\n                    openshift.set(\"triggers\", \"dc/bookstore\", \"--manual\")\n                  }\n                }\n              }\n            }\n          }\n          stage('Deploy DEV') {\n            steps {\n              script {\n                openshift.withCluster() {\n                  openshift.withProject(env.DEV_PROJECT) {\n                    openshift.selector(\"dc\", \"bookstore\").rollout().latest()\n                  }\n                }\n              }\n            }\n          }\n          stage('Promote to STAGE?') {\n            steps {\n              script {\n                openshift.withCluster() {\n                  openshift.tag(\"${env.DEV_PROJECT}/bookstore:latest\", \"${env.STAGE_PROJECT}/bookstore:${version}\")\n                }\n              }\n            }\n          }\n          stage('Deploy STAGE') {\n            steps {\n              script {\n                openshift.withCluster() {\n                  openshift.withProject(env.STAGE_PROJECT) {\n                    if (openshift.selector('dc', 'bookstore').exists()) {\n                      openshift.selector('dc', 'bookstore').delete()\n                      openshift.selector('svc', 'bookstore').delete()\n                      openshift.selector('route', 'bookstore').delete()\n                    }\n\n                    openshift.newApp(\"bookstore:${version}\").narrow(\"svc\").expose()\n                    openshift.set(\"probe dc/bookstore --readiness --get-url=http://:8080/actuator/health --initial-delay-seconds=30 --failure-threshold=10 --period-seconds=10\")\n                    openshift.set(\"probe dc/bookstore --liveness  --get-url=http://:8080/actuator/health --initial-delay-seconds=180 --failure-threshold=10 --period-seconds=10\")\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n\n---\n\n\n\n\n# Ignore this step (Explains the backend process) \n\nJenkinsfile has same code but this step explains the steps one by one. Wrote this only for understanding purpose. Build Application from source code/get from Artifact Repository. This [article](https://access.redhat.com/documentation/en-us/red_hat_jboss_middleware_for_openshift/3/html-single/red_hat_java_s2i_for_openshift/index) explains\n  the whole process. Here is a short version of it\n\n## Source to Image (S2I) Build (Not recommended)\n\nTo run and configure the Java S2I for OpenShift image, use the OpenShift S2I process.\n\nThe S2I process for the Java S2I for OpenShift image works as follows:\n\nLog into the OpenShift instance by running the following command and providing credentials.\n\n    $ oc login\n\nCreate a new project.\n\n    $ oc new-project \u003cproject-name\u003e\n\nCreate a new application using the Java S2I for OpenShift image. \u003csource-location\u003e can be the URL of a git repository or a path to a local folder.\n\n    $ oc new-app redhat-openjdk18-openshift~\u003csource-location\u003e\nGet the service name.\n\n    $ oc get service\n\nExpose the service as a route to be able to use it from the browser. \u003cservice-name\u003e is the value of NAME field from previous command output.\n\n    $ oc expose svc/\u003cservice-name\u003e --port=8080\n\nGet the route.\n\n    $ oc get route\n\nAccess the application in your browser using the URL (value of HOST/PORT field from previous command output).\n\n## Binary Builds (Build from Jar, War file)\n### To deploy existing applications on OpenShift, you can use the binary source capability.\n\nPrerequisite:\n\nGet the JAR application archive or build the application locally.\nThe example below uses the undertow-servlet quickstart.\n\nClone the source code.\n\n        $ git clone https://github.com/jboss-openshift/openshift-quickstarts.git\n\nConfigure the Red Hat JBoss Middleware Maven repository.\n\nBuild the application.\n\n        $ cd openshift-quickstarts/undertow-servlet/\n\n        $ mvn clean package\n        [INFO] Scanning for projects...\n        ...\n        [INFO]\n        [INFO] ------------------------------------------------------------------------\n        [INFO] Building Undertow Servlet Example 1.0.0.Final\n        [INFO] ------------------------------------------------------------------------\n        ...\n        [INFO] ------------------------------------------------------------------------\n        [INFO] BUILD SUCCESS\n        [INFO] ------------------------------------------------------------------------\n        [INFO] Total time: 1.986 s\n        [INFO] Finished at: 2017-06-27T16:43:07+02:00\n        [INFO] Final Memory: 19M/281M\n        [INFO] ------------------------------------------------------------------------\n\nPrepare the directory structure on the local file system.\n\nApplication archives in the deployments/ subdirectory of the main binary build directory are copied directly to the standard deployments folder of the image being built on OpenShift. For the application to deploy, the directory hierarchy containing the web application data must be correctly structured.\n\nCreate main directory for the binary build on the local file system and deployments/ subdirectory within it. Copy the previously built JAR archive to the deployments/ subdirectory:\n\n#### ignore above two steps as we already did this through Jenkins file\n    $ ls\n    dependency-reduced-pom.xml  pom.xml  README  src  target\n\n    $ mkdir -p ocp/deployments\n\n    $ cp target/undertow-servlet.jar ocp/deployments/\n\n##### Note\nLocation of the standard deployments directory depends on the underlying base image, that was used to deploy the application. See the following table:\n\nPerform the following steps to run application consisting of binary input on OpenShift:\n\nLog into the OpenShift instance by running the following command and providing credentials.\n\n    $ oc login\n\nCreate a new project.\n\n    $ oc new-project \u003cbookstore\u003e\n(Optional) Identify the image stream for the particular image.\n\n    $ oc get is -n openshift | grep ^redhat-openjdk | cut -f1 -d ' '\n    redhat-openjdk18-openshift\nCreate new binary build, specifying image stream and application name.\n\n    $ oc new-build --binary=true \\\n    --name=bookstore \\\n    --image-stream=redhat-openjdk18-openshift:1.3\n    --\u003e Found image c1f5b31 (2 months old) in image stream \"openshift/redhat-openjdk18-openshift\" under tag \"latest\" for \"redhat-openjdk18-openshift\"\n\n    Java Applications\n    -----------------\n    Platform for building and running plain Java applications (fat-jar and flat classpath)\n    Tags: builder, java\n\n    * A source build using binary input will be created\n    * The resulting image will be pushed to image stream \"bookstore:latest\"\n    * A binary build was created, use 'start-build --from-dir' to trigger a new build\n\n        --\u003e Creating resources with label build=jdk-us-app ...\n            imagestream \"bookstore\" created\n            buildconfig \"bookstore\" created\n        --\u003e Success\n\nStart the binary build. Instruct oc executable to use main directory of the binary build we created in previous step as the directory containing binary input for the OpenShift build.\n\n    $ oc start-build bookstore --from-dir=./ocp --follow\n    Uploading directory \"ocp\" as binary input for the build ...\n    build \"bookstore-1\" started\n    Receiving source from STDIN as archive ...\n    ==================================================================\n    Starting S2I Java Build .....\n    S2I source build with plain binaries detected\n    Copying binaries from /tmp/src/deployments to /deployments ...\n    ... done\n    Pushing image 172.30.197.203:5000/bookstore/bookstore:latest ...\n    Pushed 0/6 layers, 2% complete\n    Pushed 1/6 layers, 24% complete\n    Pushed 2/6 layers, 36% complete\n    Pushed 3/6 layers, 54% complete\n    Pushed 4/6 layers, 71% complete\n    Pushed 5/6 layers, 95% complete\n    Pushed 6/6 layers, 100% complete\n    Push successful\n\nCreate a new OpenShift application based on the build.\n\n    $ oc new-app bookstore\n    --\u003e Found image 66f4e0b (About a minute old) in image stream \"bookstore/bookstore\" under tag \"latest\" for \"bookstore\"\n\n        bookstore/bookstore-1:c1dbfb7a\n        ----------------------------------\n        Platform for building and running plain Java applications (fat-jar and flat classpath)\n\n        Tags: builder, java\n\n        * This image will be deployed in deployment config \"jdk-us-app\"\n        * Ports 8080/tcp, 8443/tcp, 8778/tcp will be load balanced by service \"jdk-us-app\"\n          * Other containers can access this service through the hostname \"jdk-us-app\"\n\n    --\u003e Creating resources ...\n        deploymentconfig \"bookstore\" created\n        service \"bookstore\" created\n    --\u003e Success\n        Run 'oc status' to view your app.\n\nExpose the service as route.\n\n    $ oc get svc -o name\n    service/bookstore\n\n    $ oc expose svc/bookstore\n    route \"bookstore\" exposed\n\nAccess the application.\n\nAccess the application in your browser using the URL http://bookstore-bookstore-dev.192.168.99.100.nip.io/books.html#!/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavankjadda%2Fbookstore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpavankjadda%2Fbookstore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavankjadda%2Fbookstore/lists"}