5.1 自由风格项目

项目创建和基本配置

创建自由风格项目:

步骤:
1. 点击"新建任务"
2. 输入项目名称
3. 选择"构建一个自由风格的软件项目"
4. 点击"确定"

基本配置选项:

项目配置页面结构:
├── 常规
├── 源码管理
├── 构建触发器
├── 构建环境
├── 构建
└── 构建后操作

源码管理配置

Git配置示例:

仓库URL:https://github.com/company/myapp.git
凭据:选择已配置的Git凭据
分支:*/main

高级选项:
✓ 浅克隆
✓ 克隆深度:1
✓ 构建前清理工作空间
✓ 检出到子目录:src

SVN配置示例:

仓库URL:https://svn.company.com/repos/myapp/trunk
凭据:SVN用户名密码
本地模块目录:.

高级选项:
✓ 使用svn update
✓ 排除区域:target/, *.log
✓ 包含区域:src/, pom.xml

多仓库配置:

主仓库:
- URL: https://github.com/company/myapp.git
- 分支: */main
- 目录: app

依赖仓库:
- URL: https://github.com/company/shared-lib.git
- 分支: */v1.0
- 目录: lib

配置仓库:
- URL: https://github.com/company/config.git
- 分支: */production
- 目录: config

构建触发器

定时构建配置:

# Cron表达式示例

# 每天凌晨2点构建
0 2 * * *

# 工作日每小时构建
0 * * * 1-5

# 每15分钟构建一次
H/15 * * * *

# 每周日凌晨3点构建
0 3 * * 0

# 每月1号凌晨1点构建
0 1 1 * *

SCM轮询配置:

# 轮询策略

# 每5分钟检查一次
H/5 * * * *

# 工作时间每分钟检查
* 9-17 * * 1-5

# 忽略提交消息包含[skip ci]的提交
# 在高级选项中配置排除策略

Webhook触发配置:

# GitHub Webhook URL
http://jenkins-server:8080/github-webhook/

# GitLab Webhook URL
http://jenkins-server:8080/project/myapp-build

# 通用Webhook URL
http://jenkins-server:8080/generic-webhook-trigger/invoke?token=myapp-token

构建步骤配置

Shell脚本构建:

#!/bin/bash
set -e  # 遇到错误立即退出

echo "=== 开始构建 ==="
echo "构建时间: $(date)"
echo "构建编号: ${BUILD_NUMBER}"
echo "工作空间: ${WORKSPACE}"

# 环境检查
echo "=== 环境检查 ==="
java -version
mvn -version
node --version
npm --version

# 依赖安装
echo "=== 安装依赖 ==="
if [ -f "package.json" ]; then
    npm install
fi

if [ -f "pom.xml" ]; then
    mvn dependency:resolve
fi

# 代码检查
echo "=== 代码检查 ==="
if [ -f "package.json" ]; then
    npm run lint || echo "Lint检查失败,但继续构建"
fi

# 单元测试
echo "=== 运行测试 ==="
if [ -f "pom.xml" ]; then
    mvn test
elif [ -f "package.json" ]; then
    npm test
fi

# 构建应用
echo "=== 构建应用 ==="
if [ -f "pom.xml" ]; then
    mvn clean package -DskipTests
elif [ -f "package.json" ]; then
    npm run build
fi

# 构建Docker镜像
echo "=== 构建Docker镜像 ==="
if [ -f "Dockerfile" ]; then
    docker build -t myapp:${BUILD_NUMBER} .
    docker tag myapp:${BUILD_NUMBER} myapp:latest
fi

echo "=== 构建完成 ==="

Windows批处理构建:

@echo off
setlocal enabledelayedexpansion

echo === 开始构建 ===
echo 构建时间: %date% %time%
echo 构建编号: %BUILD_NUMBER%
echo 工作空间: %WORKSPACE%

REM 环境检查
echo === 环境检查 ===
java -version
if errorlevel 1 (
    echo Java未安装或未配置PATH
    exit /b 1
)

mvn -version
if errorlevel 1 (
    echo Maven未安装或未配置PATH
    exit /b 1
)

REM 清理旧文件
echo === 清理环境 ===
if exist target rmdir /s /q target
if exist node_modules rmdir /s /q node_modules

REM 依赖安装
echo === 安装依赖 ===
if exist package.json (
    npm install
    if errorlevel 1 (
        echo npm install失败
        exit /b 1
    )
)

if exist pom.xml (
    mvn dependency:resolve
    if errorlevel 1 (
        echo Maven依赖解析失败
        exit /b 1
    )
)

REM 运行测试
echo === 运行测试 ===
if exist pom.xml (
    mvn test
    if errorlevel 1 (
        echo 测试失败
        exit /b 1
    )
) else if exist package.json (
    npm test
    if errorlevel 1 (
        echo 测试失败
        exit /b 1
    )
)

REM 构建应用
echo === 构建应用 ===
if exist pom.xml (
    mvn clean package -DskipTests
    if errorlevel 1 (
        echo Maven构建失败
        exit /b 1
    )
) else if exist package.json (
    npm run build
    if errorlevel 1 (
        echo npm构建失败
        exit /b 1
    )
)

echo === 构建完成 ===

Maven构建配置:

<!-- Maven构建步骤配置 -->
<maven>
    <goals>clean compile test package</goals>
    <pom>pom.xml</pom>
    <properties>
        <maven.test.failure.ignore>false</maven.test.failure.ignore>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <settings>
        <globalSettings>/var/lib/jenkins/maven-settings.xml</globalSettings>
    </settings>
    <jvmOptions>-Xmx2048m -XX:MaxPermSize=512m</jvmOptions>
</maven>

构建后操作

归档产物配置:

要归档的文件:
- target/*.jar
- target/*.war
- dist/**/*
- build/libs/*.jar
- *.zip
- docs/**/*.pdf

高级选项:
✓ 仅当构建成功时归档
✓ 指纹识别归档文件
✓ 允许空归档

测试结果发布:

<!-- JUnit测试结果 -->
<testResults>
    <pattern>target/surefire-reports/*.xml</pattern>
    <pattern>target/failsafe-reports/*.xml</pattern>
    <keepLongStdio>true</keepLongStdio>
    <testDataPublishers>
        <attachments>true</attachments>
    </testDataPublishers>
</testResults>

<!-- TestNG测试结果 -->
<testNGResults>
    <pattern>target/surefire-reports/testng-results.xml</pattern>
    <escapeTestDescp>true</escapeTestDescp>
    <escapeExceptionMsg>true</escapeExceptionMsg>
</testNGResults>

邮件通知配置:

邮件通知设置:
收件人:$DEFAULT_RECIPIENTS, dev-team@company.com
主题:$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!
内容:
构建项目:$PROJECT_NAME
构建编号:$BUILD_NUMBER
构建状态:$BUILD_STATUS
构建URL:$BUILD_URL
变更集:$CHANGES

触发条件:
✓ 构建失败
✓ 构建不稳定
✓ 构建恢复正常
✓ 首次失败

5.2 Pipeline项目

Pipeline基础概念

Pipeline类型:

声明式Pipeline (Declarative):
- 结构化语法
- 易于理解和维护
- 内置验证
- 推荐使用

脚本式Pipeline (Scripted):
- 基于Groovy
- 更灵活
- 适合复杂逻辑
- 需要更多经验

Pipeline结构:

// 声明式Pipeline结构
pipeline {
    agent any
    
    environment {
        // 环境变量
    }
    
    parameters {
        // 构建参数
    }
    
    triggers {
        // 触发器
    }
    
    tools {
        // 工具配置
    }
    
    stages {
        stage('Stage Name') {
            steps {
                // 构建步骤
            }
        }
    }
    
    post {
        // 构建后操作
    }
}

声明式Pipeline示例

基础Java项目Pipeline:

pipeline {
    agent any
    
    environment {
        MAVEN_OPTS = '-Xmx2048m'
        JAVA_HOME = '/usr/lib/jvm/java-11-openjdk'
    }
    
    parameters {
        choice(
            name: 'ENVIRONMENT',
            choices: ['dev', 'test', 'staging', 'prod'],
            description: '部署环境'
        )
        booleanParam(
            name: 'SKIP_TESTS',
            defaultValue: false,
            description: '跳过测试'
        )
        string(
            name: 'BRANCH_NAME',
            defaultValue: 'main',
            description: '构建分支'
        )
    }
    
    triggers {
        cron('H 2 * * *')  // 每天凌晨2点
        pollSCM('H/5 * * * *')  // 每5分钟检查SCM
    }
    
    tools {
        maven 'Maven-3.8.6'
        jdk 'JDK-11'
    }
    
    stages {
        stage('Checkout') {
            steps {
                echo "检出代码分支: ${params.BRANCH_NAME}"
                git branch: "${params.BRANCH_NAME}",
                    url: 'https://github.com/company/myapp.git',
                    credentialsId: 'github-credentials'
            }
        }
        
        stage('Build') {
            steps {
                echo '开始构建...'
                sh 'mvn clean compile'
            }
        }
        
        stage('Test') {
            when {
                not { params.SKIP_TESTS }
            }
            parallel {
                stage('Unit Tests') {
                    steps {
                        sh 'mvn test'
                    }
                    post {
                        always {
                            junit 'target/surefire-reports/*.xml'
                        }
                    }
                }
                stage('Integration Tests') {
                    steps {
                        sh 'mvn verify -Dskip.unit.tests=true'
                    }
                    post {
                        always {
                            junit 'target/failsafe-reports/*.xml'
                        }
                    }
                }
            }
        }
        
        stage('Code Quality') {
            parallel {
                stage('SonarQube Analysis') {
                    steps {
                        withSonarQubeEnv('SonarQube') {
                            sh 'mvn sonar:sonar'
                        }
                    }
                }
                stage('Security Scan') {
                    steps {
                        sh 'mvn org.owasp:dependency-check-maven:check'
                    }
                    post {
                        always {
                            publishHTML([
                                allowMissing: false,
                                alwaysLinkToLastBuild: true,
                                keepAll: true,
                                reportDir: 'target/dependency-check-report',
                                reportFiles: 'dependency-check-report.html',
                                reportName: 'Security Report'
                            ])
                        }
                    }
                }
            }
        }
        
        stage('Package') {
            steps {
                sh 'mvn package -DskipTests'
                archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
            }
        }
        
        stage('Docker Build') {
            steps {
                script {
                    def image = docker.build("myapp:${env.BUILD_NUMBER}")
                    image.tag("latest")
                    
                    if (params.ENVIRONMENT == 'prod') {
                        image.tag("stable")
                    }
                }
            }
        }
        
        stage('Deploy') {
            when {
                anyOf {
                    branch 'main'
                    expression { params.ENVIRONMENT != 'dev' }
                }
            }
            steps {
                script {
                    switch(params.ENVIRONMENT) {
                        case 'dev':
                            deployToDev()
                            break
                        case 'test':
                            deployToTest()
                            break
                        case 'staging':
                            deployToStaging()
                            break
                        case 'prod':
                            deployToProduction()
                            break
                    }
                }
            }
        }
    }
    
    post {
        always {
            echo '清理工作空间...'
            cleanWs()
        }
        success {
            echo '构建成功!'
            emailext (
                subject: "✅ 构建成功: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
                body: """构建成功完成!
                
                项目: ${env.JOB_NAME}
                构建号: ${env.BUILD_NUMBER}
                环境: ${params.ENVIRONMENT}
                构建URL: ${env.BUILD_URL}
                """,
                to: "${env.CHANGE_AUTHOR_EMAIL}, dev-team@company.com"
            )
        }
        failure {
            echo '构建失败!'
            emailext (
                subject: "❌ 构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
                body: """构建失败!
                
                项目: ${env.JOB_NAME}
                构建号: ${env.BUILD_NUMBER}
                失败阶段: ${env.STAGE_NAME}
                构建URL: ${env.BUILD_URL}
                控制台: ${env.BUILD_URL}console
                """,
                to: "${env.CHANGE_AUTHOR_EMAIL}, dev-team@company.com"
            )
        }
        unstable {
            echo '构建不稳定!'
        }
        changed {
            echo '构建状态发生变化!'
        }
    }
}

// 部署函数定义
def deployToDev() {
    echo '部署到开发环境...'
    sh '''
        kubectl config use-context dev-cluster
        kubectl set image deployment/myapp myapp=myapp:${BUILD_NUMBER}
        kubectl rollout status deployment/myapp
    '''
}

def deployToTest() {
    echo '部署到测试环境...'
    input message: '确认部署到测试环境?', ok: '部署',
          submitterParameter: 'DEPLOYER'
    sh '''
        kubectl config use-context test-cluster
        kubectl set image deployment/myapp myapp=myapp:${BUILD_NUMBER}
        kubectl rollout status deployment/myapp
    '''
}

def deployToStaging() {
    echo '部署到预发布环境...'
    input message: '确认部署到预发布环境?', ok: '部署',
          submitterParameter: 'DEPLOYER'
    sh '''
        kubectl config use-context staging-cluster
        kubectl set image deployment/myapp myapp=myapp:${BUILD_NUMBER}
        kubectl rollout status deployment/myapp
    '''
}

def deployToProduction() {
    echo '部署到生产环境...'
    timeout(time: 5, unit: 'MINUTES') {
        input message: '确认部署到生产环境?这是一个重要操作!', ok: '部署到生产',
              submitterParameter: 'DEPLOYER',
              submitter: 'admin,release-manager'
    }
    
    // 蓝绿部署
    sh '''
        kubectl config use-context prod-cluster
        
        # 创建新版本部署
        kubectl create deployment myapp-green --image=myapp:${BUILD_NUMBER}
        kubectl scale deployment myapp-green --replicas=3
        
        # 等待新版本就绪
        kubectl rollout status deployment/myapp-green
        
        # 切换流量
        kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}'
        
        # 验证部署
        sleep 30
        
        # 删除旧版本
        kubectl delete deployment myapp-blue || true
        kubectl label deployment myapp-green version=blue
    '''
}

脚本式Pipeline示例

复杂逻辑Pipeline:

node {
    def mvnHome
    def dockerImage
    def buildVersion
    
    try {
        stage('Preparation') {
            // 获取Maven工具
            mvnHome = tool 'Maven-3.8.6'
            
            // 生成构建版本号
            buildVersion = "${env.BUILD_NUMBER}-${env.GIT_COMMIT.take(7)}"
            
            echo "构建版本: ${buildVersion}"
        }
        
        stage('Checkout') {
            // 检出代码
            checkout scm
            
            // 获取Git信息
            def gitCommit = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
            def gitBranch = sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim()
            def gitAuthor = sh(returnStdout: true, script: 'git log -1 --pretty=format:"%an"').trim()
            
            echo "Git提交: ${gitCommit}"
            echo "Git分支: ${gitBranch}"
            echo "提交作者: ${gitAuthor}"
            
            // 设置构建描述
            currentBuild.description = "${gitBranch} - ${gitCommit.take(7)}"
        }
        
        stage('Build') {
            // 设置Maven环境
            withEnv(["MVN_HOME=${mvnHome}", "PATH+MAVEN=${mvnHome}/bin"]) {
                // 检查项目类型
                if (fileExists('pom.xml')) {
                    echo '检测到Maven项目'
                    sh 'mvn clean compile'
                } else if (fileExists('build.gradle')) {
                    echo '检测到Gradle项目'
                    sh './gradlew clean build'
                } else if (fileExists('package.json')) {
                    echo '检测到Node.js项目'
                    sh 'npm install && npm run build'
                } else {
                    error '未识别的项目类型'
                }
            }
        }
        
        stage('Test') {
            parallel (
                "Unit Tests": {
                    try {
                        if (fileExists('pom.xml')) {
                            sh "${mvnHome}/bin/mvn test"
                        } else if (fileExists('build.gradle')) {
                            sh './gradlew test'
                        } else if (fileExists('package.json')) {
                            sh 'npm test'
                        }
                    } catch (Exception e) {
                        currentBuild.result = 'UNSTABLE'
                        echo "单元测试失败: ${e.getMessage()}"
                    } finally {
                        // 发布测试结果
                        if (fileExists('target/surefire-reports/*.xml')) {
                            junit 'target/surefire-reports/*.xml'
                        }
                    }
                },
                "Code Coverage": {
                    try {
                        if (fileExists('pom.xml')) {
                            sh "${mvnHome}/bin/mvn jacoco:report"
                            publishHTML([
                                allowMissing: false,
                                alwaysLinkToLastBuild: true,
                                keepAll: true,
                                reportDir: 'target/site/jacoco',
                                reportFiles: 'index.html',
                                reportName: 'Coverage Report'
                            ])
                        }
                    } catch (Exception e) {
                        echo "代码覆盖率报告生成失败: ${e.getMessage()}"
                    }
                }
            )
        }
        
        stage('Quality Gate') {
            // SonarQube质量门禁
            withSonarQubeEnv('SonarQube') {
                if (fileExists('pom.xml')) {
                    sh "${mvnHome}/bin/mvn sonar:sonar"
                }
            }
            
            // 等待质量门禁结果
            timeout(time: 10, unit: 'MINUTES') {
                def qg = waitForQualityGate()
                if (qg.status != 'OK') {
                    error "质量门禁失败: ${qg.status}"
                }
            }
        }
        
        stage('Package') {
            if (fileExists('pom.xml')) {
                sh "${mvnHome}/bin/mvn package -DskipTests"
                
                // 归档产物
                archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
                
                // 构建Docker镜像
                if (fileExists('Dockerfile')) {
                    dockerImage = docker.build("myapp:${buildVersion}")
                    dockerImage.tag('latest')
                }
            }
        }
        
        stage('Security Scan') {
            // 依赖安全扫描
            try {
                sh "${mvnHome}/bin/mvn org.owasp:dependency-check-maven:check"
            } catch (Exception e) {
                echo "安全扫描警告: ${e.getMessage()}"
                currentBuild.result = 'UNSTABLE'
            }
            
            // Docker镜像安全扫描
            if (dockerImage) {
                try {
                    sh "trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:${buildVersion}"
                } catch (Exception e) {
                    echo "Docker镜像安全扫描发现高危漏洞: ${e.getMessage()}"
                    currentBuild.result = 'UNSTABLE'
                }
            }
        }
        
        stage('Deploy') {
            // 根据分支决定部署策略
            def gitBranch = env.GIT_BRANCH ?: 'unknown'
            
            switch(gitBranch) {
                case 'origin/main':
                case 'main':
                    echo '部署到生产环境'
                    deployToProduction(dockerImage, buildVersion)
                    break
                case 'origin/develop':
                case 'develop':
                    echo '部署到开发环境'
                    deployToDevelopment(dockerImage, buildVersion)
                    break
                case ~/origin\/feature\/.*/':
                    echo '功能分支,部署到测试环境'
                    deployToTest(dockerImage, buildVersion)
                    break
                default:
                    echo "跳过部署,分支: ${gitBranch}"
            }
        }
        
    } catch (Exception e) {
        currentBuild.result = 'FAILURE'
        throw e
    } finally {
        stage('Cleanup') {
            // 清理Docker镜像
            if (dockerImage) {
                sh "docker rmi myapp:${buildVersion} || true"
                sh "docker rmi myapp:latest || true"
            }
            
            // 清理工作空间
            cleanWs()
        }
        
        stage('Notification') {
            // 发送通知
            def status = currentBuild.result ?: 'SUCCESS'
            def color = status == 'SUCCESS' ? 'good' : 'danger'
            
            slackSend(
                channel: '#ci-cd',
                color: color,
                message: "构建 ${status}: ${env.JOB_NAME} - ${env.BUILD_NUMBER} (<${env.BUILD_URL}|查看详情>)"
            )
        }
    }
}

// 部署函数
def deployToProduction(dockerImage, version) {
    input message: '确认部署到生产环境?', ok: '部署',
          submitterParameter: 'DEPLOYER'
    
    echo "部署版本 ${version} 到生产环境"
    // 生产环境部署逻辑
}

def deployToDevelopment(dockerImage, version) {
    echo "部署版本 ${version} 到开发环境"
    // 开发环境部署逻辑
}

def deployToTest(dockerImage, version) {
    echo "部署版本 ${version} 到测试环境"
    // 测试环境部署逻辑
}

5.3 多配置项目

矩阵构建配置

基本矩阵配置:

配置矩阵:
轴1 - 操作系统:
- linux
- windows
- macos

轴2 - Java版本:
- jdk8
- jdk11
- jdk17

轴3 - 数据库:
- mysql
- postgresql
- h2

总构建数:3 × 3 × 3 = 27个构建

矩阵过滤:

// 排除不兼容的组合
!(os == "windows" && database == "postgresql")

// 只在Linux上测试JDK17
!(javaVersion == "jdk17" && os != "linux")

// 复杂过滤条件
(os == "linux" && javaVersion == "jdk11") || 
(os == "windows" && javaVersion == "jdk8") ||
(os == "macos" && database == "h2")

矩阵构建脚本:

#!/bin/bash

echo "=== 矩阵构建信息 ==="
echo "操作系统: ${os}"
echo "Java版本: ${javaVersion}"
echo "数据库: ${database}"
echo "构建组合: ${os}-${javaVersion}-${database}"

# 设置Java环境
case ${javaVersion} in
    "jdk8")
        export JAVA_HOME=/usr/lib/jvm/java-8-openjdk
        ;;
    "jdk11")
        export JAVA_HOME=/usr/lib/jvm/java-11-openjdk
        ;;
    "jdk17")
        export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
        ;;
esac

# 配置数据库连接
case ${database} in
    "mysql")
        export DB_URL="jdbc:mysql://localhost:3306/testdb"
        export DB_DRIVER="com.mysql.cj.jdbc.Driver"
        ;;
    "postgresql")
        export DB_URL="jdbc:postgresql://localhost:5432/testdb"
        export DB_DRIVER="org.postgresql.Driver"
        ;;
    "h2")
        export DB_URL="jdbc:h2:mem:testdb"
        export DB_DRIVER="org.h2.Driver"
        ;;
esac

# 运行测试
echo "=== 开始测试 ==="
mvn clean test -Ddb.url="${DB_URL}" -Ddb.driver="${DB_DRIVER}"

# 生成报告
echo "=== 生成报告 ==="
mvn surefire-report:report

# 归档结果
echo "=== 归档结果 ==="
mkdir -p "reports/${os}-${javaVersion}-${database}"
cp -r target/site/surefire-report.html "reports/${os}-${javaVersion}-${database}/"
cp target/surefire-reports/*.xml "reports/${os}-${javaVersion}-${database}/"

并行执行优化

节点标签配置:

节点标签策略:
linux-node1: linux && jdk8 && mysql
linux-node2: linux && jdk11 && postgresql
windows-node1: windows && jdk8 && mysql
macos-node1: macos && jdk11 && h2

标签表达式:
${os} && ${javaVersion} && ${database}

构建优先级:

高优先级组合:
- linux + jdk11 + mysql (主要生产环境)
- linux + jdk8 + postgresql (遗留系统)

中优先级组合:
- windows + jdk11 + mysql
- linux + jdk17 + mysql

低优先级组合:
- 其他测试组合

5.4 文件夹项目

项目组织结构

按团队组织:

Jenkins项目结构:
├── Frontend Team/
│   ├── webapp-build
│   ├── mobile-app-build
│   └── component-library-build
├── Backend Team/
│   ├── user-service-build
│   ├── order-service-build
│   └── payment-service-build
├── DevOps Team/
│   ├── infrastructure-deploy
│   ├── monitoring-setup
│   └── backup-jobs
└── QA Team/
    ├── integration-tests
    ├── performance-tests
    └── security-tests

按环境组织:

Jenkins项目结构:
├── Development/
│   ├── myapp-dev-build
│   ├── myapp-dev-deploy
│   └── myapp-dev-test
├── Testing/
│   ├── myapp-test-build
│   ├── myapp-test-deploy
│   └── myapp-test-integration
├── Staging/
│   ├── myapp-staging-build
│   ├── myapp-staging-deploy
│   └── myapp-staging-smoke-test
└── Production/
    ├── myapp-prod-deploy
    ├── myapp-prod-rollback
    └── myapp-prod-monitoring

文件夹权限管理

权限配置示例:

Frontend Team文件夹权限:
- frontend-developers: Read, Build, Configure
- frontend-lead: All permissions
- qa-team: Read, Build
- devops-team: Read

Production文件夹权限:
- release-managers: All permissions
- senior-developers: Read, Build
- junior-developers: Read only
- auditors: Read only

权限继承配置:

// 文件夹权限脚本
folder('Frontend Team') {
    description('前端团队项目')
    
    authorization {
        permission('hudson.model.Item.Read', 'frontend-developers')
        permission('hudson.model.Item.Build', 'frontend-developers')
        permission('hudson.model.Item.Configure', 'frontend-lead')
        permission('hudson.model.Item.Delete', 'frontend-lead')
    }
    
    properties {
        folderCredentialsProperty {
            domainCredentials {
                domainCredentials {
                    domain {
                        name('frontend-domain')
                        description('前端团队凭据域')
                    }
                    credentials {
                        usernamePassword {
                            scope('GLOBAL')
                            id('frontend-git-credentials')
                            username('frontend-bot')
                            password('${FRONTEND_BOT_PASSWORD}')
                            description('前端Git访问凭据')
                        }
                    }
                }
            }
        }
    }
}

5.5 任务模板和最佳实践

项目模板设计

通用构建模板:

// 通用Pipeline模板
@Library('jenkins-shared-library') _

pipeline {
    agent {
        label params.BUILD_NODE ?: 'linux'
    }
    
    parameters {
        string(
            name: 'GIT_REPO',
            description: 'Git仓库URL'
        )
        string(
            name: 'GIT_BRANCH',
            defaultValue: 'main',
            description: 'Git分支'
        )
        choice(
            name: 'BUILD_TYPE',
            choices: ['maven', 'gradle', 'npm', 'docker'],
            description: '构建类型'
        )
        choice(
            name: 'DEPLOY_ENV',
            choices: ['none', 'dev', 'test', 'staging', 'prod'],
            description: '部署环境'
        )
        booleanParam(
            name: 'RUN_TESTS',
            defaultValue: true,
            description: '运行测试'
        )
        booleanParam(
            name: 'RUN_SECURITY_SCAN',
            defaultValue: false,
            description: '运行安全扫描'
        )
    }
    
    environment {
        BUILD_VERSION = "${env.BUILD_NUMBER}-${env.GIT_COMMIT?.take(7) ?: 'unknown'}"
        ARTIFACT_NAME = "${env.JOB_BASE_NAME}-${BUILD_VERSION}"
    }
    
    stages {
        stage('Checkout') {
            steps {
                script {
                    checkout([
                        $class: 'GitSCM',
                        branches: [[name: params.GIT_BRANCH]],
                        userRemoteConfigs: [[url: params.GIT_REPO]]
                    ])
                }
            }
        }
        
        stage('Build') {
            steps {
                script {
                    switch(params.BUILD_TYPE) {
                        case 'maven':
                            mavenBuild()
                            break
                        case 'gradle':
                            gradleBuild()
                            break
                        case 'npm':
                            npmBuild()
                            break
                        case 'docker':
                            dockerBuild()
                            break
                        default:
                            error "不支持的构建类型: ${params.BUILD_TYPE}"
                    }
                }
            }
        }
        
        stage('Test') {
            when {
                expression { params.RUN_TESTS }
            }
            steps {
                script {
                    runTests(params.BUILD_TYPE)
                }
            }
            post {
                always {
                    publishTestResults testResultsPattern: 'target/surefire-reports/*.xml, build/test-results/**/*.xml, test-results.xml'
                }
            }
        }
        
        stage('Security Scan') {
            when {
                expression { params.RUN_SECURITY_SCAN }
            }
            steps {
                script {
                    runSecurityScan(params.BUILD_TYPE)
                }
            }
        }
        
        stage('Package') {
            steps {
                script {
                    packageArtifacts(params.BUILD_TYPE)
                }
            }
        }
        
        stage('Deploy') {
            when {
                expression { params.DEPLOY_ENV != 'none' }
            }
            steps {
                script {
                    deployToEnvironment(params.DEPLOY_ENV)
                }
            }
        }
    }
    
    post {
        always {
            cleanWs()
        }
        success {
            script {
                sendNotification('success')
            }
        }
        failure {
            script {
                sendNotification('failure')
            }
        }
    }
}

共享库使用

共享库结构:

jenkins-shared-library/
├── vars/
│   ├── mavenBuild.groovy
│   ├── gradleBuild.groovy
│   ├── npmBuild.groovy
│   ├── dockerBuild.groovy
│   ├── runTests.groovy
│   ├── runSecurityScan.groovy
│   ├── packageArtifacts.groovy
│   ├── deployToEnvironment.groovy
│   └── sendNotification.groovy
├── src/
│   └── com/
│       └── company/
│           └── jenkins/
│               ├── BuildUtils.groovy
│               ├── DeployUtils.groovy
│               └── NotificationUtils.groovy
└── resources/
    ├── templates/
    │   ├── Dockerfile.template
    │   └── k8s-deployment.yaml
    └── scripts/
        ├── security-scan.sh
        └── deploy.sh

共享库函数示例:

// vars/mavenBuild.groovy
def call(Map config = [:]) {
    def goals = config.goals ?: 'clean compile'
    def profiles = config.profiles ?: ''
    def javaVersion = config.javaVersion ?: '11'
    
    echo "Maven构建: goals=${goals}, profiles=${profiles}, java=${javaVersion}"
    
    withEnv(["JAVA_HOME=/usr/lib/jvm/java-${javaVersion}-openjdk"]) {
        sh "mvn ${goals} ${profiles ? '-P' + profiles : ''}"
    }
}

// vars/deployToEnvironment.groovy
def call(String environment) {
    def config = readYaml file: "deploy-config/${environment}.yaml"
    
    echo "部署到环境: ${environment}"
    
    switch(environment) {
        case 'dev':
            deployToDev(config)
            break
        case 'test':
            deployToTest(config)
            break
        case 'staging':
            deployToStaging(config)
            break
        case 'prod':
            deployToProduction(config)
            break
        default:
            error "不支持的环境: ${environment}"
    }
}

def deployToDev(config) {
    sh """
        kubectl config use-context ${config.cluster}
        kubectl apply -f k8s/dev/
        kubectl set image deployment/${config.appName} ${config.appName}=${config.image}:${env.BUILD_VERSION}
        kubectl rollout status deployment/${config.appName}
    """
}

def deployToProduction(config) {
    input message: "确认部署到生产环境?", ok: "部署",
          submitterParameter: 'DEPLOYER'
    
    // 蓝绿部署逻辑
    sh """
        kubectl config use-context ${config.cluster}
        
        # 创建绿色环境
        sed 's/{{VERSION}}/${env.BUILD_VERSION}/g' k8s/prod/deployment.yaml | kubectl apply -f -
        
        # 等待就绪
        kubectl rollout status deployment/${config.appName}-green
        
        # 切换流量
        kubectl patch service ${config.appName} -p '{"spec":{"selector":{"version":"green"}}}'
        
        # 健康检查
        sleep 30
        
        # 清理蓝色环境
        kubectl delete deployment ${config.appName}-blue || true
    """
}

构建优化策略

缓存策略:

// Maven依赖缓存
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                // 使用本地Maven仓库缓存
                sh '''
                    # 创建缓存目录
                    mkdir -p ${WORKSPACE}/.m2/repository
                    
                    # 使用缓存的Maven仓库
                    mvn clean compile -Dmaven.repo.local=${WORKSPACE}/.m2/repository
                '''
            }
        }
    }
    
    post {
        always {
            // 缓存Maven依赖
            stash includes: '.m2/repository/**', name: 'maven-cache'
        }
    }
}

// Docker层缓存
stage('Docker Build') {
    steps {
        script {
            // 使用多阶段构建和缓存
            def image = docker.build("myapp:${env.BUILD_NUMBER}", 
                "--cache-from myapp:latest --build-arg BUILDKIT_INLINE_CACHE=1 .")
        }
    }
}

并行构建优化:

stage('Parallel Tasks') {
    parallel {
        stage('Unit Tests') {
            agent { label 'test-runner' }
            steps {
                sh 'mvn test'
            }
        }
        stage('Integration Tests') {
            agent { label 'integration-test' }
            steps {
                sh 'mvn verify -Dskip.unit.tests=true'
            }
        }
        stage('Code Quality') {
            agent { label 'sonar-scanner' }
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh 'mvn sonar:sonar'
                }
            }
        }
        stage('Security Scan') {
            agent { label 'security-scanner' }
            steps {
                sh 'mvn org.owasp:dependency-check-maven:check'
            }
        }
    }
}

5.6 本章小结

本章全面介绍了Jenkins构建任务管理的各个方面:

项目类型掌握: 1. 自由风格项目:传统构建任务的配置和管理 2. Pipeline项目:现代化的代码化构建流程 3. 多配置项目:矩阵构建和跨平台测试 4. 文件夹项目:项目组织和权限管理

核心技能: 1. 配置管理:源码管理、触发器、构建步骤 2. Pipeline开发:声明式和脚本式Pipeline 3. 并行优化:提高构建效率和资源利用 4. 模板设计:标准化和可重用的构建模板

最佳实践: - 选择合适的项目类型 - 使用Pipeline实现代码化 - 合理设计项目组织结构 - 优化构建性能和资源使用 - 建立标准化的构建模板

下一章预告: 下一章将介绍Jenkins插件系统,包括插件的安装、配置和开发。

5.7 练习与思考

实践练习

  1. 自由风格项目

    • 创建一个Java项目的自由风格构建
    • 配置Git源码管理和Maven构建
    • 设置测试结果发布和邮件通知
  2. Pipeline项目

    • 将自由风格项目转换为Pipeline
    • 实现并行测试和部署阶段
    • 添加质量门禁和安全扫描
  3. 多配置项目

    • 创建跨平台测试的矩阵构建
    • 配置不同Java版本和数据库的组合
    • 优化构建时间和资源使用
  4. 项目组织

    • 设计团队项目的文件夹结构
    • 配置权限和凭据管理
    • 创建项目模板和共享库

思考题

  1. 在什么情况下选择自由风格项目而不是Pipeline?
  2. 如何设计一个既灵活又标准化的Pipeline模板?
  3. 多配置项目的矩阵构建如何平衡覆盖率和效率?
  4. 大型组织中如何有效管理数百个Jenkins项目?
  5. 如何实现构建任务的版本控制和变更管理?