Jenkins是目前大多数中小公司运用的CI、CD工具,其间Jenkins的使命又分一般使命和流水线使命,一般使命的构建和布置在我之前的一篇文章中写过运用教程# 依据 Docker 装置 Jenkins,并装备运用 Jenkins 打包 Node 前后端服务布置到长途服务器,但其间流水线使命可完结咱们更复杂的需求也更自由,不过上手难度也略微高点。
一、装置Jenkins
引荐运用 Docker 来装置Jenkins,更方便后期的迁移布置等,详细装置过程可参阅
# 依据 Docker 装置 Jenkins,并装备运用 Jenkins 打包 Node 前后端服务布置到长途服务器
二、一般流水线
这儿我将演示运用流水线来布置一个前端项目,其他项目也同样是这几个过程
首先创建一个流水线使命
在流水线装备这有两种方法,第一种是直接把流水线脚本写在装备文本框这,第二种是把脚本写在项目根目录下,用Jenkinsfile
文件来写入,图下面能够看到有个流水线语法
的按钮,是能够把详细操作用可视化的方法生成脚本。
咱们在文本框这写入以下脚本内容:
pipeline {
agent any
stages {
stage('Build') {
steps {
nodejs('node16') {
sh '''
if hash pnpm 2>/dev/null;
then
echo "pnpm"
else
npm i pnpm -g --registry https://registry.npmmirror.com/
fi
pnpm i
pnpm run build
'''
}
echo '构建完结'
}
}
stage('Zip') {
steps {
sh '''
tar -zcvf ${JOB_BASE_NAME}.tgz ./dist/*
rm -rf ./dist/*
mv ${JOB_BASE_NAME}.tgz ./dist
'''
echo '打包完结'
}
}
stage('Deploy') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'tencent', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'echo \'布置完结\'', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
Stages
: 这个字段下分了几个独自的stage
,会从上至下依次履行stage
,如果是方才说的第一种方法,应该还会比上面多个拉取代码的阶段。详细拉取代码的语法能够用上面的流水线语法
页面可视化生成。
stage('Build')
: 代码构建阶段,这儿由于是前端项目,用到了node
来构建,需求装置NodeJS
插件,然后去全局工具装备里装置一下详细的node
版本及设置下别名。
stage('Zip')
: 紧缩阶段,由于咱们前端代码布置只需求布置dist目录
,把这个目录tgz紧缩
一下发到目标服务器。
stage('Deploy')
: 布置阶段,需求装置一个Publish Over SSH
插件,然后经过上面的流水线语法
去可视化装备布置到服务器的装备,最终把生成的脚本粘贴到这就行。
到这咱们构建及布置代码到服务器的根本装备就完结了,大部分项目其实发版流程便是这几步,下面还有几种流水线进阶用法。
三、多环境布置流水线
有时候咱们会遇到多环境布置的状况,如开发坏境,出产环境等,大概便是咱们经过在流水线增加一个布置坏境的参数来操控,在每次构建前选择一下布置的坏境,详细脚本如下:
pipeline {
agent any
parameters {
choice(
description: '你需求哪个机器进行布置?',
name: 'deploy_hostname',
choices: ['tencent', 'dev01', 'tencent、dev01']
)
}
stages {
stage('Build') {
steps {
nodejs('node16') {
sh '''
if hash pnpm 2>/dev/null;
then
echo "pnpm"
else
npm i pnpm -g --registry https://registry.npmmirror.com/
fi
pnpm i
pnpm run build
'''
}
echo '构建完结'
}
}
stage('Zip') {
steps {
sh '''
tar -zcvf ${JOB_BASE_NAME}.tgz ./dist/*
rm -rf ./dist/*
mv ${JOB_BASE_NAME}.tgz ./dist
'''
}
}
stage('Deploy to tencent'){
when {
expression { deploy_hostname == 'tencent' }
}
steps{
sshPublisher(publishers: [sshPublisherDesc(configName: 'tencent', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'echo \'布置完结\'', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage('Deploy to dev01'){
when {
expression { deploy_hostname == 'dev01' }
}
steps{
sshPublisher(publishers: [sshPublisherDesc(configName: 'dev01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'echo \'布置完结\'', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage('Deploy to tencent、dev01'){
when {
expression { deploy_hostname == 'tencent、dev01' }
}
steps{
sshPublisher(publishers: [sshPublisherDesc(configName: 'tencent', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'echo \'布置完结\'', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
sshPublisher(publishers: [sshPublisherDesc(configName: 'dev01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'echo \'布置完结\'', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
能够看到除了咱们之前装备的agent
和stages
还多了一个parameters
的参数装备,增加了一个deploy_hostname
的选择参数,有三个值'tencent', 'dev01', 'tencent、dev01'
在详细的stage
里边也多了when
的装备,便是依据咱们选择的布置环境参数来履行相应坏境的布置流程,当when
里边的条件不满足时,流水线会跳过里边的steps
四、多分支流水线
还有种状况是项目多分支的状况下,每个分支或许对应的布置坏境,或许履行条件不一样,就会用到Jenkins的多分支流水线
在新建Jenkins使命时选择多分支流水线
在分支源里装备对应的git项目地址
和认证凭证
,保存后他会主动扫描项目里边的分支,咱们需求在每个分支下创建一个Jenkinsfile
文件,把咱们的脚本写在这个文件里
详细的构建布置脚本可参阅之前的一般流水线,如果需求WebHook主动触发的可参阅下面脚本
pipeline {
agent any
triggers {
GenericTrigger (
causeString: 'Triggered',
genericVariables: [[key: 'ref', value: '$.ref']],
printContributedVariables: true,
printPostContent: true,
token: 'test01'
)
}
stages {
stage('Build') {
steps {
nodejs('node16') {
sh '''
if hash pnpm 2>/dev/null;
then
echo "pnpm"
else
npm i pnpm -g --registry https://registry.npmmirror.com/
fi
pnpm i
pnpm run build
'''
}
echo '构建完结'
}
}
stage('Zip') {
steps {
sh '''
tar -zcvf ${JOB_BASE_NAME}.tgz ./dist/*
rm -rf ./dist/*
mv ${JOB_BASE_NAME}.tgz ./dist
'''
}
}
stage('Deploy to tencent'){
when {
branch 'master'
}
steps{
sshPublisher(publishers: [sshPublisherDesc(configName: 'tencent', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'echo \'布置完结\'', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage('Deploy to dev01'){
when {
branch 'dev'
}
steps{
sshPublisher(publishers: [sshPublisherDesc(configName: 'dev01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'echo \'布置完结\'', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
能够看到上面增加了一个triggers
装备,这个需求装置Generic Webhook Trigger
插件,然后按上面那样装备,其间的token装备能够随意改动,便是咱们最终触发hooks的url最终面的参数。
装备完结后,就能够告诉http://JENKINS_URL/generic-webhook-trigger/invoke?token=test01
来触发咱们的hook,一般咱们需求在gitlab的Webhooks进行装备触发hooks
到此Jenkins多种流水线的装备介绍就完结了,详细细节有不了解的小伙伴可在下面谈论区留言。关于流水线语法每个装备的详解可参阅# Jenkinsfile声明式语法详解