From c29fdbf3f0bdb7333f982472d914e778b99e7699 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 11 May 2024 16:13:15 -0500 Subject: [PATCH] added ci for testing --- build.gradle | 11 ++- jenkins-build/Jenkinsfile | 119 +++++++++++++++++++++++++++++ jenkins-build/build-info | 50 ++++++++++++ jenkins-build/cloud-formation.yaml | 82 ++++++++++++++++++++ settings.gradle | 2 +- 5 files changed, 262 insertions(+), 2 deletions(-) create mode 100644 jenkins-build/Jenkinsfile create mode 100644 jenkins-build/build-info create mode 100644 jenkins-build/cloud-formation.yaml diff --git a/build.gradle b/build.gradle index e2f5769e8..3bd9ed04e 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,7 @@ plugins { id 'org.graalvm.buildtools.native' version '0.9.28' id 'io.spring.javaformat' version '0.0.41' id "io.spring.nohttp" version "0.0.11" + id 'jacoco' } apply plugin: 'java' @@ -14,7 +15,13 @@ apply plugin: 'io.spring.javaformat' gradle.startParameter.excludedTaskNames += [ "checkFormatAot", "checkFormatAotTest" ] group = 'org.springframework.samples' -version = '3.2.0' + +//project always has the property version +if (project.findProperty('version') != 'unspecified') { + version = findProperty('version') +} else { + version = '3.2.0' +} java { sourceCompatibility = JavaVersion.VERSION_17 @@ -80,3 +87,5 @@ checkFormatAotTest.enabled = false formatAot.enabled = false formatAotTest.enabled = false + +test.finalizedBy(jacocoTestReport) diff --git a/jenkins-build/Jenkinsfile b/jenkins-build/Jenkinsfile new file mode 100644 index 000000000..df5602169 --- /dev/null +++ b/jenkins-build/Jenkinsfile @@ -0,0 +1,119 @@ +String buildVersion +String environment='CI' +String buildName='spring-petclinic-aws' +String ciBucketName='xchu-jenkins-artifacts-build-us-east-1' +String rcBucketName='xchu-jenkins-artifacts-rc-us-east-1' +String awsCred='lab-aws' +String awsRegion='lab-aws' + +pipeline { + stages { + stage ('Choose Version') { + steps { + // calculate version from git tags and commit history + sh 'rm -rf generated' + sh 'mkdir generated' + echo 'Choosing Version' + sh 'chmod 755 ./jenkins-build/build-info' + sh './jenkins-build/build-info' + script { + def buildProperties = readProperties file: "${env.WORKSPACE}/generated/BUILD_INFO.txt" + buildVersion = buildProperties.get('build.version') + branchName = buildProperties.get('git.branch.name') + cloudFormationFile="./generated/cloud-formation-${buildVersion}.yaml" + } + } + } + stage('Validate CF') { + steps{ + sh "mv jenkins-build/cloud-formation.yaml ${cloudFormationFile}" + sh 'ls' + withAWS(credentials:"${awsCred}", region:"${awsRegion}"){ + cfnValidate(file:"${cloudFormationFile}") + } + } + } + stage('Compile') { + steps{ + sh "./gradlew clean build -x test -Pversion=${buildVersion} -DrootProjectName=${buildName}" + //make the jar file name cohesive + } + stage('Tests') { + parallel unitTest: { + stage ('unitTest') { + timeout(time: 5, unit: 'MINUTES') { + sh './gradlew test' + echo 'Unittest done' + } + } + }, + checkstyle: { + stage ('checkStyle') { + sh './gradlew validate' + echo 'checkStyle done' + } + }, + codeCoverage: { + stage ('codeCoverage') { + sh './gradlew jacocoTestReport' + echo 'Code coverage test done' + } + } + } + stage('Publish to S3'){ + steps{ + withAWS(credentials:"${awsCred}", region:"${awsRegion}"){ + //Upload application code + s3Upload(bucket:"${ciBucketName}", file: "build/libs/${buildName}-${buildVersion}.jar", path:"${buildName}/${buildVersion}/") + //Upload CloudFormation + s3Upload(bucket:"${ciBucketName}", file: "${cloudFormationFile}", path:"${buildName}/${buildVersion}/") + } + } + } + stage('Publish to RC - If main branch'){ + when { + branch 'main' + } + steps{ + withAWS(credentials:"${awsCred}", region:"${awsRegion}"){ + //Upload application code to release candidate + s3Upload(bucket:"${rcBucketName}", file: "build/libs/${buildName}-${buildVersion}.jar", path:"${buildName}/${buildVersion}/") + + //Upload CloudFormation to release candidate + s3Upload(bucket:"${rcBucketName}", file: "${cloudFormationFile}", path:"${buildName}/${buildVersion}/") + + //Upload Build_info to release candidate + s3Upload(bucket:"${rcBucketName}", file: "${env.WORKSPACE}/generated/BUILD_INFO.txt", path:"${buildName}/${buildVersion}/") + + } + } + } + stage('Publish Report Html') { + steps { + echo 'Publishing unittest report...' + publishHTML([allowMissing: true, + alwaysLinkToLastBuild: true, + keepAll: true, + reportDir: 'build/reports/tests/test', + reportFiles: 'index.html', + reportName: 'Unittest Report', + reportTitles: 'The unittest report']) + echo 'Publishing jacoco report...' + publishHTML([allowMissing: true, + alwaysLinkToLastBuild: true, + keepAll: true, + reportDir: 'build/reports/jacoco/test/html', + reportFiles: 'index.html', + reportName: 'Jacoco Coverage Report', + reportTitles: 'The coverage report by jacoco']) + } + } + } + post { + always { + archiveArtifacts artifacts: 'generated/**' + echo 'Cleaning up...' + cleanWs() + } + } +} \ No newline at end of file diff --git a/jenkins-build/build-info b/jenkins-build/build-info new file mode 100644 index 000000000..c26143a82 --- /dev/null +++ b/jenkins-build/build-info @@ -0,0 +1,50 @@ +#!/bin/bash +set -e + +baseVersion="0.0.0" +revisionsSince="0" + +echo "Available" tags +git tag -l + +if semver $(git tag -l) &>/dev/null +then + baseVersion=$(semver $(semver $(git tag -l)) | tail -n1) + echo "Base Version is now: $baseVersion" +fi + +if [ "$baseVersion" = "0.0.0" ] +then + revisionsSince=$(git rev-list --count HEAD) +else + revisionsSince=$(git rev-list "$baseVersion"..HEAD --count) +fi + +echo "Calculating Version." +calculatedVersion="$baseVersion-$revisionsSince" + +branchName=$(git rev-parse --abbrev-ref HEAD | tr / -) + +echo $branchName + +if [ "$branchName" != "master" ] +then + calculatedVersion="$calculatedVersion-$branchName" +fi + +echo "New version is $calculatedVersion" + +semVersion=$(semver "$calculatedVersion" | tail -n1) + +if [ "$1" = "package" ] +then + echo "Forcing package.json to version $semVersion" + npm --no-git-tag-version -f version $semVersion +fi + +mkdir -p generated +echo "build.version=$calculatedVersion" > ./generated/BUILD_INFO.txt +echo "git.branch.name=$branchName" >> ./generated/BUILD_INFO.txt +echo "git.commit.hash=$(git rev-parse HEAD)" >> ./generated/BUILD_INFO.txt +echo "git.commit.short=$(git rev-parse --short HEAD)" >> ./generated/BUILD_INFO.txt + \ No newline at end of file diff --git a/jenkins-build/cloud-formation.yaml b/jenkins-build/cloud-formation.yaml new file mode 100644 index 000000000..f68c271b3 --- /dev/null +++ b/jenkins-build/cloud-formation.yaml @@ -0,0 +1,82 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: Deploy an EC2 instance to run the Petclinic app. +Parameters: + ArtifactPath: + Type: String + Description: The path to the jar file. + AppFile: + Type: String + Description: The name of the jar file. + LatestAmiId: + Type: 'AWS::SSM::Parameter::Value' + Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' + ServerPort: + Type: Number + Default: 8080 + Description: The port on which the server will listen. + +Resources: + InstanceSecurityGroup: + Type: 'AWS::EC2::SecurityGroup' + Properties: + GroupDescription: Allow http to instance + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: !Ref ServerPort + ToPort: !Ref ServerPort + CidrIp: 0.0.0.0/0 + + InstanceRole: + Type: 'AWS::IAM::Role' + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Action: + - 'sts:AssumeRole' + Policies: + - PolicyName: AccessArtifact + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 's3:GetObject' + Resource: + - !Sub 'arn:aws:s3:::${ArtifactPath}/*.jar' + + InstanceProfile: + Type: 'AWS::IAM::InstanceProfile' + Properties: + Roles: + - !Ref InstanceRole + + EC2Instance: + Type: 'AWS::EC2::Instance' + Properties: + InstanceType: t2.micro + ImageId: LatestAmiId # Amazon Linux 2 AMI in us-east-1 + SecurityGroups: + - !Ref InstanceSecurityGroup + IamInstanceProfile: !Ref InstanceProfile + UserData: + Fn::Base64: !Sub | + #!/bin/bash + yum update -y + yum install -y java-17-amazon-corretto-devel + aws s3 cp s3://${ArtifactPath}/${AppFile} /home/ec2-user/ + java -jar /home/ec2-user/${AppFile} --server.port=${ServerPort} + +Outputs: + InstanceId: + Description: The Instance ID + Value: !Ref EC2Instance + WebsiteURL: + Description: URL to access the Java application + Value: !Sub "http://${EC2Instance.PublicIp}:${ServerPort}" + Export: + Name: ServerURL \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index e60ee14fa..4d7270201 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = 'spring-petclinic' +rootProject.name = System.getProperty('rootProjectName')?:'spring-petclinic'