Skip to content

Commit

Permalink
jenkins
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzhaomax committed Mar 29, 2024
1 parent 8949017 commit d9f7476
Show file tree
Hide file tree
Showing 3 changed files with 360 additions and 0 deletions.
282 changes: 282 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
//#!groovy

pipeline {
// 指定集群节点
agent any
// 选项
options {
timestamps() //日志会有时间
skipDefaultCheckout() //删除隐式checkout scm语句
disableConcurrentBuilds() //禁止并行
timeout(time: 1, unit: "HOURS") //流水线超市设置1h
buildDiscarder(logRotator(numToKeepStr: "20")) //保留build数量
}
// 声明全局变量
environment {
ENV = "dev" // 根据Config Selection步骤的input而定
TAG = "" // 根据Config Selection步骤的input而定
ProjectKey = "" // 根据SonarQube步骤的input而定
harborUsername = "admin"
harborPassword = "Harbor12345"
harborAddress = "172.16.96.97:9002"
harborRepo = "go-maxms-react"
Container_port = "9600" // 启用随机端口,会被赋值
Host_port = "9600" // 启用随机端口,会被赋值
JobName = "go-maxms-react/main"
DeploymentServerIP = "172.16.96.98"
}
// 流水线阶段
stages {
// 拉取代码
stage("Checkout") {
steps {
echo "--------------------- Checkout Start ---------------------"
timeout(time: 3, unit: "MINUTES"){
checkout([$class: "GitSCM", branches: [[name: '**']], extensions: [], userRemoteConfigs: [[url: 'https://github.com/liuzhaomax/go-maxms-react.git']]])
}
echo "--------------------- Checkout End ---------------------"
}
}
// // 本地github会用到
// stage("Update GitHub") {
// steps {
// echo "--------------------- Update GitHub Start ---------------------"
// script {
// timeout(time: 5, unit: "MINUTES"){
// sh """
// git config --get remote.origin.url
// tr -d
// git rev-parse HEAD
// """
// // setting commit status
// }
// }
// echo "--------------------- Update GitHub End ---------------------"
// }
// }
stage("Config Selection") {
steps {
script {
timeout(time: 2, unit: "MINUTES"){
echo "Getting GitHub Tags..."
def tags = getGitHubTags()
def userInput
try {
timeout(time: 1, unit: "MINUTES") {
userInput = input(
id: "userInput",
message: "Please select environment and tag:",
parameters: [
[$class: "ChoiceParameterDefinition", name: "ENVIRONMENT", choices: "st\nsit\npnv\nqa\nprod", description: "Select environment"],
[$class: "ChoiceParameterDefinition", name: "TAG", choices: tags, description: "Select tag"]
]
)
}
}
catch (e) {
echo "Using default env and tag values due to no operation in 1 min, or Exception caught: ${e}"
}
// 如果用户没有选择,使用默认值
ENV = userInput ? userInput.ENVIRONMENT : "st"
echo "Selected Environment: $ENV"
TAG = userInput ? userInput.TAG : tags.first()
echo "Selected Tag: $TAG"
}
}
}
}
// 检查App版本
stage("Version") {
steps {
echo "--------------------- Version Start ---------------------"
echo "Branch: ${JOB_NAME}"
script {
npmHome = tool "npm"
sh """
export NODE_HOME=${npmHome}
export PATH=\$NODE_HOME/bin:\$PATH
rm -rf server/build
rm -rf node_modules package-lock.json server/node_modules server/package-lock.json
${npmHome}/bin/npm cache clear --force
${npmHome}/bin/node --version
${npmHome}/bin/npm --version
"""
}
echo "--------------------- Version End ---------------------"
}
}
// 语法格式检查
stage("Lint") {
steps {
echo "--------------------- Lint Start ---------------------"
script {
timeout(time: 30, unit: "MINUTES"){
npmHome = tool "npm"
sh """
export NODE_HOME=${npmHome}
export PATH=\$NODE_HOME/bin:\$PATH
${npmHome}/bin/npm config set registry https://registry.npmjs.org/
${npmHome}/bin/npm i --package-lock-only --max_old_space_size=1024
${npmHome}/bin/npm ci --max_old_space_size=1024
${npmHome}/bin/npm run lint
"""
}
}
echo "--------------------- Lint End ---------------------"
}
}
// 构建
stage("Build") {
steps {
echo "--------------------- Build Start ---------------------"
script {
timeout(time: 5, unit: "MINUTES"){
npmHome = tool "npm" //变量名npm在jenkins全局工具里定义的
sh """
export NODE_HOME=${npmHome}
export PATH=\$NODE_HOME/bin:\$PATH
${npmHome}/bin/npm config set registry https://registry.npmjs.org/
${npmHome}/bin/npm install
${npmHome}/bin/npm run build
cd server
${npmHome}/bin/npm install --max_old_space_size=1024
cd ..
"""
}
}
echo "--------------------- Build End ---------------------"
}
}
// 静态代码分析SonarQube
stage("SonarQube") {
steps {
echo "--------------------- SonarQube Start ---------------------"
script {
timeout(time: 5, unit: "MINUTES"){
ProjectKey = genSonarProjectKey()
echo "SonarQube Project Key: ${ProjectKey}"
sonarScannerHome = tool "sonar-scanner"
sh """
export PROJECT_KEY=${ProjectKey}
${sonarScannerHome}/bin/sonar-scanner
"""
}
}
echo "--------------------- SonarQube End ---------------------"
}
}
// 构建镜像
stage("Build Image") {
steps {
echo "--------------------- Build Image Start ---------------------"
timeout(time: 10, unit: "MINUTES"){
sh """
cd server
docker build -t ${ProjectKey}:${TAG} .
cd ..
"""
}
echo "--------------------- Build Image End ---------------------"
}
}
// 推送镜像到Harbor
stage("Push to Harbor") {
steps {
echo "--------------------- Push to Harbor Start ---------------------"
timeout(time: 10, unit: "MINUTES"){
sh """
docker login -u ${harborUsername} -p ${harborPassword} ${harborAddress}
docker tag ${ProjectKey}:${TAG} ${harborAddress}/${harborRepo}/${ProjectKey}:${TAG}
docker push ${harborAddress}/${harborRepo}/${ProjectKey}:${TAG}
"""
}
echo "--------------------- Push to Harbor End ---------------------"
}
}
// 部署容器
stage("Deploy") {
steps {
echo "--------------------- Deploy Start ---------------------"
timeout(time: 10, unit: "MINUTES"){
echo "ENV: ${ENV}"
echo "Port: ${Host_port}"
sh """
chmod +x ./server/deploy.sh
./server/deploy.sh $harborAddress $harborRepo $ProjectKey $TAG $Container_port $Host_port $ENV $DeploymentServerIP
"""
}
echo "--------------------- Deploy End ---------------------"
}
}
}
// 构建后的操作
post {
always {
echo """
********************************************************************
********************************************************************
******************* Pipeline about to Finish ***********************
********************************************************************
********************************************************************
"""
}
cleanup {
sh "docker image prune -f"
sh "rm -rf ${WORKSPACE}/*"
}
}
}

// 保留最近5个构建,其中必须包含至少一次成功构建
def keepBuilds() {
def buildsToKeep = []
def successFound = false

for (int i = currentBuild.number - 1; i >= 1 && buildsToKeep.size() < 5; i--) {
def build = Jenkins.instance.getItemByFullName(env.JOB_NAME).getBuildByNumber(i)

if (build.result == "SUCCESS") {
buildsToKeep << build
successFound = true
} else if (build.result == "FAILURE" || build.result == "ABORTED") {
// 如果前一次构建成功,则保留这一次构建
if (successFound) {
buildsToKeep << build
}
}
}

// 设置保留的构建
currentBuild.rawBuild.getAction(hudson.tasks.LogRotator.class).setBuildKeepDependencies(buildsToKeep)
}

// 组合job name为蛇形
def rewriteJobNameInSnake() {
String[] strArr = JOB_NAME.split("/")
String projectName = strArr[0..-1].join("_")
return projectName
}

// 生成sonar的project key
def genSonarProjectKey() {
String[] strArr = JOB_NAME.split("/")
String pk = strArr[0]
for (int i = 1; i < strArr.size(); i++) {
pk += "_" + strArr[i]
}
pk = pk.replaceAll("%2F", "_")
return pk.toLowerCase()
}

// 获取github tags
def getGitHubTags() {
// 获取GitHub仓库的标签列表
def tagsCommand = 'git ls-remote --tags origin'
def tagsOutput = sh(script: tagsCommand, returnStdout: true).trim()
// 处理输出,提取标签的名称
def tagList = tagsOutput.readLines().collect { it.replaceAll(/.*refs\/tags\/(.*)(\^\{\})?/, '$1') }
// 在 tagList 的 0 号索引位置,添加一个快照标签
def timestamp = new Date().format("yyyyMMddHHmmss")
tagList.add(0, "SNAPSHOT-$timestamp")
return tagList
}
61 changes: 61 additions & 0 deletions server/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#! /bin/sh

harbor_addr=$1
harbor_repo=$2
project=$3
version=$4
container_port=$5
host_port=$6
environment=$7
deployment_server_ip=$8

# 确保没有container在运行
containerID=$(docker -H tcp://$deployment_server_ip:2375 ps -a | grep "${project}" | awk '{print $1}')

echo "History Container ID: $containerID"

if [ "$containerID" != "" ]; then
docker -H tcp://$deployment_server_ip:2375 stop "$containerID"
docker -H tcp://$deployment_server_ip:2375 rm "$containerID"
fi

# 清除同名image
imageIDRemote=$(docker -H tcp://$deployment_server_ip:2375 images | grep "${project}" | awk '{print $3}' | head -n 1)

echo "History Image ID Remote: $imageIDRemote"

if [ "$imageIDRemote" != "" ]; then
docker -H tcp://$deployment_server_ip:2375 rmi "$imageIDRemote"
fi

# 即将部署的镜像
imageName="$harbor_addr/$harbor_repo/$project:$version"

echo "Image Name: $imageName"

# 远程登录harbor
docker -H tcp://$deployment_server_ip:2375 login -u admin -p Harbor12345 "$harbor_addr"

docker -H tcp://$deployment_server_ip:2375 pull "$imageName"

docker -H tcp://$deployment_server_ip:2375 run \
--name="$project" \
-d \
--restart=always \
--privileged=true \
-p "${host_port}:${container_port}" \
-e ENV="${environment}" \
-v /root/www/"${project}":/usr/src/app/www \
-v /root/logs/"${project}":/usr/src/app/log \
"$imageName"

echo "SUCCESS: Container Created"

# 部署后,清除jenkins服务器产生的image
imageIDLocal=$(docker images | grep "${project}" | awk '{print $3}' | head -n 1)

echo "History Image ID Local: $imageIDLocal"

if [ "$imageIDLocal" != "" ]; then
docker rmi -f "$imageIDLocal"
fi
17 changes: 17 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
sonar.host.url=http://172.16.96.97:9001

sonar.projectKey=${env.PROJECT_KEY}
sonar.projectName=${JOB_NAME}
sonar.sourceEncoding=UTF-8

#sonar.projectVersion=1.0

#sonar.login=${env.SONAR_ACCESS_TOKEN}
sonar.login=squ_d106b36ec221b6b317880e261792e131a6e3200a
sonar.sources=.

sonar.nodejs.executable=/usr/bin/node
sonar.inclusions=src/pages/**/*.js
sonar.coverage.exclusions=node_modules/**/*,coverage/**/*,server/build/**/*,config/**/*,scripts/**/*,public/**/*,src/config/**/*,src/app/**/*,src/assets/**/*,src/env/**/*,src/layouts/**/*,src/index.js,src/state/**/*,*/**/*.test.js
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.qualitygate.wait=true

0 comments on commit d9f7476

Please sign in to comment.