diff --git a/.github/main.yml b/.github/main.yml new file mode 100644 index 0000000..9d9429a --- /dev/null +++ b/.github/main.yml @@ -0,0 +1,128 @@ +name: Build, Deploy, and Analyze + +on: + push: + branches: + - '**' + pull_request: + branches: + - master + workflow_dispatch: + +jobs: + build: + runs-on: self-hosted + + steps: + # Checkout the repository + - name: Checkout Code + uses: actions/checkout@v3 + + # Install Maven + - name: Install Maven + run: | + sudo apt update + sudo apt install maven -y + mvn -v + + # Set up Java + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + + # Cache Maven dependencies + - name: Cache Maven dependencies + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + # Build the project with Maven + - name: Build with Maven + run: mvn clean install + + # Store artifacts with versioning (Before running the .jar) + - name: Upload Artifacts with Versioning + uses: actions/upload-artifact@v3 + with: + name: my-app-artifact-${{ github.sha }} # Artifact version based on commit SHA + path: target/*.jar # Path to the built artifact (e.g., JAR file or other build outputs) + + # Run the Spring Boot application in the background + - name: Run Spring Boot App + run: mvn spring-boot:run & + + # Wait for the Spring Boot app to fully start + - name: Wait for Spring Boot App to Start + run: | + echo "Waiting for the app to start..." + sleep 15 # Allow time for the Spring Boot app to fully initialize + echo "App should now be running." + + # Validate that the application is running + - name: Validate App is Running + run: | + echo "Checking if the app is running..." + IP_ADDRESS=$(curl -s ifconfig.me) # Fetch public IP address + PORT=8080 + RESPONSE=$(curl --write-out "%{http_code}" --silent --output /dev/null http://$IP_ADDRESS:$PORT) + if [ "$RESPONSE" -eq 200 ]; then + echo "The app is running successfully at http://$IP_ADDRESS:$PORT!" + else + echo "The app failed to start. HTTP response code: $RESPONSE" + exit 1 + fi + + # Display the IP address and port number for accessing the app + - name: Display IP Address and Port + run: | + echo "Fetching the runner's IP address..." + IP_ADDRESS=$(curl -s ifconfig.me) # This fetches the public IP of the runner + PORT=8080 + echo "The app is accessible at: http://$IP_ADDRESS:$PORT" + + # Wait for 3 minutes (180 seconds) + - name: Wait for 3 minutes + run: | + echo "App has been running for 3 minutes. Waiting..." + sleep 180 # Wait for 3 minutes + + # Stop the Spring Boot app gracefully + - name: Gracefully Stop Spring Boot App + run: | + echo "Stopping the app gracefully..." + mvn spring-boot:stop + + sonarcloud-analysis: + runs-on: ubuntu-latest + needs: build # Ensure the build job runs before sonarcloud-analysis job + + steps: + # Checkout the repository + - name: Checkout Code + uses: actions/checkout@v3 + + # Set up Java + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + # SonarCloud Analysis (separate job-feature-1) + - name: SonarCloud Analysis + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_ORG: your-organization # Replace with your actual SonarCloud organization + SONAR_HOST_URL: https://sonarcloud.io + run: | + mvn clean verify sonar:sonar \ + -Dsonar.organization=${{ secrets.SONAR_ORG }} \ + -Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \ + -Dsonar.login=${{ secrets.SONAR_TOKEN }} + diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..d64db37 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,35 @@ +name: Build, Deploy, and Analyze + +on: + push: + branches: + - '**' + pull_request: + branches: + - master + workflow_dispatch: # Allow for manual trigger via GitHub UI + +jobs: + # Call the Java and Maven setup workflow + java-maven-setup: + uses: ./.github/workflows/setup-java-maven.yml # Reference to the consolidated Java and Maven setup workflow + + # Call the build and artifact workflow + build-and-artifact: + uses: ./.github/workflows/build-and-artifact.yml # Reference to the build workflow + needs: java-maven-setup # Ensure Java and Maven setup is completed first + + # Call the Spring Boot run and stop workflow + springboot-run-stop: + uses: ./.github/workflows/springboot-run-stop.yml # Reference to the Spring Boot workflow + needs: build-and-artifact # Ensure the build is completed before running Spring Boot + + # Call the SonarCloud analysis workflow + sonarcloud-analysis: + uses: ./.github/workflows/sonarcloud-analysis.yml # Reference to the SonarCloud analysis workflow + needs: build-and-artifact # Ensure the build job is completed before analysis + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_ORG: ${{ secrets.SONAR_ORG }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + diff --git a/.github/workflows/sonarcloud-analysis.yml b/.github/workflows/sonarcloud-analysis.yml new file mode 100644 index 0000000..2fd94e4 --- /dev/null +++ b/.github/workflows/sonarcloud-analysis.yml @@ -0,0 +1,39 @@ +name: SonarCloud Analysis + +on: + workflow_call: + secrets: + SONAR_TOKEN: # SonarCloud authentication token + required: true + SONAR_ORG: # SonarCloud organization + required: true + SONAR_HOST_URL: # SonarCloud host URL + required: true + +jobs: + sonarcloud-analysis: + runs-on: ubuntu-latest + + steps: + # Checkout the repository + - name: Checkout Code + uses: actions/checkout@v3 + + # Set up Java + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + # Perform SonarCloud Analysis + - name: SonarCloud Analysis + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_ORG: ${{ secrets.SONAR_ORG }} + SONAR_HOST_URL: https://sonarcloud.io + run: | + mvn clean verify sonar:sonar \ + -Dsonar.organization=${{ secrets.SONAR_ORG }} \ + -Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \ + -Dsonar.login=${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/springboot-run-stop.yml b/.github/workflows/springboot-run-stop.yml new file mode 100644 index 0000000..47a45d2 --- /dev/null +++ b/.github/workflows/springboot-run-stop.yml @@ -0,0 +1,46 @@ +name: Spring Boot Run and Stop + +on: + workflow_call: # This workflow can be called from other workflows + +jobs: + springboot-run-stop: + runs-on: self-hosted + + steps: + # Run Spring Boot App + - name: Run Spring Boot App + run: mvn spring-boot:run & + + # Wait for the Spring Boot app to fully start + - name: Wait for Spring Boot App to Start + run: | + echo "Waiting for the app to start..." + sleep 15 + echo "App should now be running." + + # Validate that the application is running + - name: Validate App is Running + run: | + echo "Checking if the app is running..." + IP_ADDRESS=$(curl -s ifconfig.me) # Fetch public IP address + PORT=8080 + RESPONSE=$(curl --write-out "%{http_code}" --silent --output /dev/null http://$IP_ADDRESS:$PORT) + if [ "$RESPONSE" -eq 200 ]; then + echo "The app is running successfully at http://$IP_ADDRESS:$PORT" + else + echo "The app failed to start. HTTP response code: $RESPONSE" + exit 1 + fi + + # Wait for 3 minutes (180 seconds) + - name: Wait for 3 minutes + run: | + echo "App has been running for 3 minutes. Waiting..." + sleep 180 + + # Gracefully Stop Spring Boot App + - name: Gracefully Stop Spring Boot App + run: | + echo "Stopping the app gracefully..." + mvn spring-boot:stop diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..78b61df --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "java.compile.nullAnalysis.mode": "disabled", + "java.configuration.updateBuildConfiguration": "disabled" +} \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..b8e982f --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,48 @@ +@Library('Jenkins_library') _ + +pipeline { + agent { label 'java' } + // agent any + tools { + jdk 'JDK17' + maven 'maven' + } + + stages { + + stage('Checkout') { + steps { + checkout scm + } + } + + stage('Build') { + steps { + //sh 'mvn clean package -DskipTests=false' + script { + // dir('hello-world-war') { + build 'package' + } + } + } + // } + + // stage('Archive Artifact') { + // steps { + // archiveArtifacts artifacts: 'target/*.jar', fingerprint: true + // } + // } + + stage('Run Application') { + steps { + sh 'mvn spring-boot:run' + // dir('/var/lib/jenkins/workspace/Parcel_service_feature-1/target') { + // sh """ + // nohup java -jar simple-parcel-service-app-1.0-SNAPSHOT.jar > app.log 2>&1 & + //echo "Application started" + // """ + // } + } + } + } +} diff --git a/README.md b/README.md index 8b13789..647fea6 100644 --- a/README.md +++ b/README.md @@ -1 +1,119 @@ +Shell script to setup the environment. + +#!/bin/bash +set -e +echo "Starting Maven project setup..." + +# Step 1: Install Java 17 +if ! java -version &>/dev/null; then + echo "Installing Java 17..." + sudo apt update + sudo apt install -y openjdk-17-jdk +else + echo "Java is already installed:" + java -version +fi + +# Set JAVA_HOME +JAVA_HOME_PATH=$(dirname $(dirname $(readlink -f $(which java)))) +if ! grep -q "JAVA_HOME=$JAVA_HOME_PATH" /etc/environment; then + echo "Setting JAVA_HOME..." + echo "JAVA_HOME=$JAVA_HOME_PATH" | sudo tee -a /etc/environment + echo "export JAVA_HOME=$JAVA_HOME_PATH" | sudo tee -a /etc/profile + echo 'export PATH=$JAVA_HOME/bin:$PATH' | sudo tee -a /etc/profile + source /etc/profile + echo "JAVA_HOME set to $JAVA_HOME_PATH" +else + echo "JAVA_HOME is already set." +fi + +# Step 2: Install Maven +if ! mvn -version &>/dev/null; then + echo "Installing Maven..." + sudo apt install -y maven +else + echo "Maven is already installed:" + mvn -version +fi +echo "Environment setup completed. You can now build and run the application manually." +Build the project manually +mvn clean install + +Run the application manually +mvn spring-boot:run +OR +java -jar target/simple-parcel-service-app-1.0-SNAPSHOT.jar + +name: Build, Deploy, and Run + +on: + push: + branches: + - main + pull_request: + +jobs: + build-and-run: + runs-on: ubuntu-latest + + steps: + # Step 1: Checkout code + - name: Checkout Code + uses: actions/checkout@v4 + + # Step 2: Set up Java 17 + - name: Set up Java 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + + # Step 3: Set up Maven + - name: Set up Maven + uses: actions/setup-java@v3 + with: + distribution: 'maven' + + # Step 4: Build the project + - name: Build with Maven + run: mvn clean package + + # Step 5: Upload the built JAR as an artifact + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: built-jar + path: target/simple-parcel-service-app-1.0-SNAPSHOT.jar + + # Step 6: Run the Spring Boot application + - name: Run Application + run: | + nohup mvn spring-boot:run & + sleep 15 # Allow time for the app to fully start + + # Step 7: Validate App is Running + - name: Validate App is Running + run: | + echo "Waiting for the app to start..." + sleep 15 # Allow some time for the Spring Boot app to fully start + echo "Checking if the app is running..." + RESPONSE=$(curl --write-out "%{http_code}" --silent --output /dev/null http://localhost:8080) + if [ "$RESPONSE" -eq 200 ]; then + echo "The app is running successfully!" + else + echo "The app failed to start. HTTP response code: $RESPONSE" + exit 1 + fi + + # Step 8: Wait for 5 minutes + - name: Wait for 5 minutes + run: | + echo "App has been running for 5 minutes. Waiting..." + sleep 300 # Wait for 5 minutes (300 seconds) + + # Step 9: Gracefully Stop Spring Boot App + - name: Gracefully Stop Spring Boot App + run: | + echo "Stopping the app gracefully..." + mvn spring-boot:stop + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..cbe2afd --- /dev/null +++ b/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + com.example + simple-parcel-service-app + 1.0-SNAPSHOT + + + 17 + 2.5.4 + + vikas0105 + https://sonarcloud.io + vikas0105_Parcel-service + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + com.example.SimpleParcelServiceApp + + + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.5.0.1254 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 17 + 17 + + + + + + diff --git a/src/main/java/com/example/SimpleParcelServiceApp.java b/src/main/java/com/example/SimpleParcelServiceApp.java new file mode 100644 index 0000000..3b3732a --- /dev/null +++ b/src/main/java/com/example/SimpleParcelServiceApp.java @@ -0,0 +1,12 @@ +package com.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SimpleParcelServiceApp { + public static void main(String[] args) { + SpringApplication.run(SimpleParcelServiceApp.class, args); + } +} + diff --git a/src/main/java/com/example/controller/ParcelController.java b/src/main/java/com/example/controller/ParcelController.java new file mode 100644 index 0000000..d775b5d --- /dev/null +++ b/src/main/java/com/example/controller/ParcelController.java @@ -0,0 +1,38 @@ +package com.example.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +@RequestMapping("/") +public class ParcelController { + + @GetMapping + public String index() { + return "index"; + } + + @PostMapping("/sendParcel") + public String sendParcel( + @RequestParam("recipientName") String recipientName, + @RequestParam("recipientAddress") String recipientAddress, + @RequestParam("senderName") String senderName, + @RequestParam("senderAddress") String senderAddress, + @RequestParam("parcelContent") String parcelContent, + Model model + ) { + // You can do something with the data, e.g., save it to a database + // For now, let's just add it to the model and display a confirmation + model.addAttribute("recipientName", recipientName); + model.addAttribute("recipientAddress", recipientAddress); + model.addAttribute("senderName", senderName); + model.addAttribute("senderAddress", senderAddress); + model.addAttribute("parcelContent", parcelContent); + return "confirmation"; + } +} + diff --git a/src/main/java/com/example/model/Parcel.java b/src/main/java/com/example/model/Parcel.java new file mode 100644 index 0000000..8ff531d --- /dev/null +++ b/src/main/java/com/example/model/Parcel.java @@ -0,0 +1,6 @@ +package com.example.model; + +public class Parcel { + // Add fields as needed +} + diff --git a/src/main/java/com/example/service/ParcelService.java b/src/main/java/com/example/service/ParcelService.java new file mode 100644 index 0000000..54d51e3 --- /dev/null +++ b/src/main/java/com/example/service/ParcelService.java @@ -0,0 +1,9 @@ +package com.example.service; + +import org.springframework.stereotype.Service; + +@Service +public class ParcelService { + // Add service methods as needed +} + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..e106a90 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,5 @@ +# Thymeleaf Configuration +spring.thymeleaf.prefix=classpath:/templates/ +spring.thymeleaf.suffix=.html +spring.thymeleaf.cache=false + diff --git a/src/main/resources/templates/confirmation.html b/src/main/resources/templates/confirmation.html new file mode 100644 index 0000000..b128817 --- /dev/null +++ b/src/main/resources/templates/confirmation.html @@ -0,0 +1,16 @@ + + + + Parcel Service App - Confirmation + + +

Parcel Sent Successfully!

+

Recipient's Name:

+

Recipient's Address:

+

Sender's Name:

+

Sender's Address:

+

Parcel Content:

+ + + diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html new file mode 100644 index 0000000..32b1b5b --- /dev/null +++ b/src/main/resources/templates/index.html @@ -0,0 +1,35 @@ + + + + Parcel Service App + + +

Welcome to the Parcel Service App!

+ +
+ + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+ + + diff --git a/target/classes/application.properties b/target/classes/application.properties new file mode 100644 index 0000000..e106a90 --- /dev/null +++ b/target/classes/application.properties @@ -0,0 +1,5 @@ +# Thymeleaf Configuration +spring.thymeleaf.prefix=classpath:/templates/ +spring.thymeleaf.suffix=.html +spring.thymeleaf.cache=false + diff --git a/target/classes/com/example/SimpleParcelServiceApp.class b/target/classes/com/example/SimpleParcelServiceApp.class new file mode 100644 index 0000000..2f50f98 Binary files /dev/null and b/target/classes/com/example/SimpleParcelServiceApp.class differ diff --git a/target/classes/com/example/controller/ParcelController.class b/target/classes/com/example/controller/ParcelController.class new file mode 100644 index 0000000..57734de Binary files /dev/null and b/target/classes/com/example/controller/ParcelController.class differ diff --git a/target/classes/com/example/model/Parcel.class b/target/classes/com/example/model/Parcel.class new file mode 100644 index 0000000..4f08b8d Binary files /dev/null and b/target/classes/com/example/model/Parcel.class differ diff --git a/target/classes/com/example/service/ParcelService.class b/target/classes/com/example/service/ParcelService.class new file mode 100644 index 0000000..3c8ad2f Binary files /dev/null and b/target/classes/com/example/service/ParcelService.class differ diff --git a/target/classes/templates/index.html b/target/classes/templates/index.html new file mode 100644 index 0000000..4d27e35 --- /dev/null +++ b/target/classes/templates/index.html @@ -0,0 +1,11 @@ + + + + + Simple Parcel Service + + +

+ + +