jenkins普通流水模版

pipeline {
    agent any

    environment {
        // 基础配置
        DOCKER_IMAGE = '192.168.73.100:38080/label/test-project'
        PROJECT_URL = '192.168.73.100:48080/testproject/test-project.git'
        PROJECT_BRANCH = 'main'
        REGISTRY_CREDENTIALS_ID = '3a6d2e5c-1b9f-4e8a-9c2d-7e4f6a8b9c3d'
        JENKINS_PROJECT_NAME = 'test-project-正式服'
        K8S_FILE = '/data/kubelet/test-project.yaml'
        DOCKER_FILE_PATH = './'

        // 构建信息
        BUILD_TIMESTAMP = "${new Date().format('yyyyMMdd-HHmmss')}"
        GIT_COMMIT_SHORT = ''
        GIT_TAG = ''
        IMAGE_TAG = ''
        IMAGE_FULL_NAME = ''
    }

    options {
        // 构建选项
        timeout(time: 30, unit: 'MINUTES')
        timestamps()
        ansiColor('xterm')
        disableConcurrentBuilds()
    }

    stages {
        stage('初始化') {
            steps {
                script {
                    echo "🚀 开始构建项目: ${JENKINS_PROJECT_NAME}"
                    echo "📅 构建时间: ${BUILD_TIMESTAMP}"
                    echo "🌿 目标分支: ${PROJECT_BRANCH}"
                }
            }
        }

        stage('代码检出') {
            steps {
                script {
                    withCredentials([string(credentialsId: '2b1c8d7e-9c4f-41a2-8a3b-6d5e1f4a7b8c', variable: 'GITLAB_TOKEN')]) {
                        // 检出代码
                        checkout([
                            $class: 'GitSCM',
                            branches: [[name: "*/${PROJECT_BRANCH}"]],
                            userRemoteConfigs: [[
                                url: "http://oauth2:${GITLAB_TOKEN}@${PROJECT_URL}",
                                credentialsId: '2b1c8d7e-9c4f-41a2-8a3b-6d5e1f4a7b8c'
                            ]],
                            extensions: [
                                [$class: 'CleanBeforeCheckout'],
                                [$class: 'SubmoduleOption', recursiveSubmodules: true]
                            ]
                        ])

                        // 获取Git信息
                        env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()

                        // 检查当前提交是否有标签
                        def currentTags = sh(script: 'git tag --points-at HEAD', returnStdout: true).trim()

                        if (currentTags) {
                            // 如果有多个标签,取最新的一个
                            env.GIT_TAG = currentTags.split('\n').last()
                            env.IMAGE_TAG = env.GIT_TAG
                            echo "🏷️  当前提交有标签: ${env.GIT_TAG}"
                        } else {
                            // 检查最近的标签
                            def latestTag = sh(script: 'git describe --tags --abbrev=0 2>/dev/null || echo ""', returnStdout: true).trim()

                            if (latestTag) {
                                // 计算距离最新标签的提交数
                                def commitCount = sh(script: "git rev-list --count ${latestTag}..HEAD", returnStdout: true).trim()
                                if (commitCount == "0") {
                                    // 当前提交就是最新标签
                                    env.GIT_TAG = latestTag
                                    env.IMAGE_TAG = env.GIT_TAG
                                    echo "🏷️  使用最新标签: ${env.GIT_TAG}"
                                } else {
                                    // 有新的提交,使用commit ID
                                    env.IMAGE_TAG = env.GIT_COMMIT_SHORT
                                    echo "📝 距离最新标签 ${latestTag} 有 ${commitCount} 个提交,使用commit ID: ${env.GIT_COMMIT_SHORT}"
                                }
                            } else {
                                // 没有任何标签,使用commit ID
                                env.IMAGE_TAG = env.GIT_COMMIT_SHORT
                                echo "📝 没有找到任何标签,使用commit ID: ${env.GIT_COMMIT_SHORT}"
                            }
                        }

                        // 构建完整镜像名称
                        env.IMAGE_FULL_NAME = "${DOCKER_IMAGE}:${env.IMAGE_TAG}"

                        echo "🐳 镜像名称: ${env.IMAGE_FULL_NAME}"
                        echo "📋 Git信息:"
                        echo "   - 提交ID: ${env.GIT_COMMIT_SHORT}"
                        echo "   - 标签: ${env.GIT_TAG ?: '无'}"
                        echo "   - 镜像标签: ${env.IMAGE_TAG}"
                    }
                }
            }
        }

        stage('代码质量检查') {
            parallel {
                stage('代码规范检查') {
                    steps {
                        script {
                            echo "🔍 执行代码规范检查..."
                            // 这里可以添加具体的代码检查命令
                            // 例如: npm run lint, pylint, sonarqube等

                            // 模拟检查过程
                            sleep(5)
                            echo "✅ 代码规范检查完成"
                        }
                    }
                }

                stage('安全扫描') {
                    steps {
                        script {
                            echo "🛡️  执行安全扫描..."
                            // 这里可以添加安全扫描工具
                            // 例如: OWASP ZAP, Trivy等

                            // 模拟扫描过程
                            sleep(8)
                            echo "✅ 安全扫描完成"
                        }
                    }
                }
            }
        }

        stage('构建测试') {
            parallel {
                stage('单元测试') {
                    steps {
                        script {
                            echo "🧪 执行单元测试..."
                            // 这里添加具体的测试命令
                            // 例如: npm test, pytest等

                            // 模拟测试过程
                            sleep(10)
                            echo "✅ 单元测试完成"
                        }
                    }
                }

                stage('集成测试') {
                    steps {
                        script {
                            echo "🔗 执行集成测试..."
                            // 这里添加集成测试命令

                            // 模拟测试过程
                            sleep(12)
                            echo "✅ 集成测试完成"
                        }
                    }
                }
            }
        }

        stage('构建应用') {
            steps {
                script {
                    echo "🔨 开始构建应用..."
                    echo "📦 构建镜像: ${env.IMAGE_FULL_NAME}"

                    // 这里添加具体的构建命令
                    // 例如: docker build, npm run build等

                    // 模拟构建过程
                    sleep(15)
                    echo "✅ 应用构建完成"
                }
            }
        }

        stage('构建Docker镜像') {
            steps {
                script {
                    echo "🐳 构建Docker镜像..."
                    /*
                    withCredentials([usernamePassword(credentialsId: REGISTRY_CREDENTIALS_ID, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')]) {
                        // 构建Docker镜像
                        sh """
                            docker build -t ${env.IMAGE_FULL_NAME} ${DOCKER_FILE_PATH}
                            docker tag ${env.IMAGE_FULL_NAME} ${DOCKER_IMAGE}:latest
                        """
                    }
                    */
                    echo "✅ Docker镜像构建完成: ${env.IMAGE_FULL_NAME}"
                }
            }
        }

        stage('推送镜像') {
            steps {
                script {
                    echo "📤 推送Docker镜像到仓库..."
                    /*
                    withCredentials([usernamePassword(credentialsId: REGISTRY_CREDENTIALS_ID, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')]) {
                        // 登录镜像仓库
                        sh "echo '${REGISTRY_PASS}' | docker login 192.168.73.100:38080 -u ${REGISTRY_USER} --password-stdin"

                        // 推送镜像
                        sh """
                            docker push ${env.IMAGE_FULL_NAME}
                            docker push ${DOCKER_IMAGE}:latest
                        """
                    }
                    */
                    echo "✅ 镜像推送完成"
                }
            }
        }

        stage('部署到测试环境') {
            steps {
                script {
                    echo "🚀 部署到测试环境..."
                    /*
                    // 更新Kubernetes配置文件中的镜像标签
                    sh """
                        sed -i 's|image: ${DOCKER_IMAGE}:.*|image: ${env.IMAGE_FULL_NAME}|g' ${K8S_FILE}
                    """

                    // 应用Kubernetes配置
                    sh "kubectl apply -f ${K8S_FILE}"

                    // 等待部署完成
                    sh "kubectl rollout status deployment/test-project --timeout=300s"
                    */
                    echo "✅ 测试环境部署完成"
                }
            }
        }

        stage('健康检查') {
            steps {
                script {
                    echo "🏥 执行健康检查..."

                    // 等待服务启动
                    // sleep(30)

                    // 这里可以添加具体的健康检查逻辑
                    // 例如: curl检查API端点,数据库连接测试等

                    echo "✅ 健康检查通过"
                }
            }
        }

        stage('创建Git标签') {
            when {
                expression {
                    // 只有在没有标签且构建成功时才创建标签
                    return !env.GIT_TAG && currentBuild.result == 'SUCCESS'
                }
            }
            steps {
                script {
                    echo "🏷️  创建Git标签..."

                    withCredentials([string(credentialsId: '2b1c8d7e-9c4f-41a2-8a3b-6d5e1f4a7b8c', variable: 'GITLAB_TOKEN')]) {
                        // 创建新标签
                        def newTag = "v${BUILD_TIMESTAMP}"
                        sh """
                            git config user.email "jenkins@example.com"
                            git config user.name "Jenkins"
                            git tag -a ${newTag} -m "Auto-generated tag for build ${BUILD_NUMBER}"
                            git push origin ${newTag}
                        """

                        echo "✅ 创建标签: ${newTag}"
                    }
                }
            }
        }
    }

    post {
        always {
            script {
                echo "🧹 清理工作空间..."
                // 注释掉Docker镜像清理
                /*
                // 清理Docker镜像
                sh "docker rmi ${env.IMAGE_FULL_NAME} || true"
                sh "docker rmi ${DOCKER_IMAGE}:latest || true"

                // 清理未使用的Docker镜像
                sh "docker image prune -f || true"
                */

                echo "✅ 工作空间清理完成"
            }
        }

        success {
            script {
                echo "🎉 构建成功!"
                echo "📊 构建信息:"
                echo "   - 构建号: ${BUILD_NUMBER}"
                echo "   - 镜像: ${env.IMAGE_FULL_NAME}"
                echo "   - 标签: ${env.IMAGE_TAG}"
                echo "   - 耗时: ${currentBuild.durationString}"

                // 这里可以添加成功通知
                // 例如: 发送邮件、钉钉、企业微信等
            }
        }

        failure {
            script {
                echo "❌ 构建失败!"
                echo "🔍 请检查构建日志以获取详细信息"

                // 这里可以添加失败通知
                // 例如: 发送邮件、钉钉、企业微信等
            }
        }

        unstable {
            script {
                echo "⚠️  构建不稳定"
            }
        }

        aborted {
            script {
                echo "⏹️  构建被中断"
            }
        }
    }
}

// 工具函数
def notify(String message, String type = 'info') {
    def emoji = [
        'info': 'ℹ️',
        'success': '✅',
        'warning': '⚠️',
        'error': '❌'
    ]

    echo "${emoji[type]} ${message}"
}

def getBuildDuration() {
    def duration = currentBuild.duration
    def minutes = duration.intdiv(60000)
    def seconds = (duration % 60000).intdiv(1000)
    return "${minutes}分${seconds}秒"
}

<think>好的,我现在需要帮助用户理解他们提到的CI/CD流程,尤其是在生产环境中涉及两种不同的roles和两次提交的问题,以及ThinkPHP和Nginx的特殊配置。让我先理清楚用户当前的流程和困惑点。 用户已经熟悉从GitLab检出仓库,使用PyCharm创建Dockerfile和Jenkinsfile,提交到仓库,然后在Jenkins中创建测试环境的流水线。但在生产环境中,存在两种roles,需要两次提交,并且ThinkPHP和Nginx的配置不同。用户可能不太明白为什么需要两次提交,以及不同roles如何影响流程。 首先,我需要明确CI/CD的基本流程,然后解释测试环境和生产环境的差异,特别是多roles的情况。可能涉及到不同环境的配置管理,比如使用不同的分支、标签或仓库来区分测试和生产。两次提交可能是指需要分别处理代码和应用配置,或者不同的服务需要不同的流水线步骤。 ThinkPHP可能在流水线中有特殊处理,比如需要额外的构建步骤或测试,而备份仓库可能是为了生产环境的回滚或合规性要求。Nginx配置的不同可能涉及SSL、路由规则或负载均衡设置,这些在测试和生产环境中可能有差异,需要通过不同的方式注入或管理。 接下来,我需要考虑用户提到的“两种不同的roles”,这可能是指Ansible roles或者不同的服务器角色,比如应用服务器和Web服务器。不同的roles可能需要不同的部署步骤或配置,因此在CI/CD流程中需要分开处理,导致两次提交。 用户可能需要了解如何结构化他们的仓库和流水线,以支持多环境和多roles的部署。可能需要使用Jenkinsfile的不同阶段,或者参数化构建来区分环境。另外,备份仓库的需求可能涉及镜像仓库或代码仓库的复制,确保生产环境有冗余。 我需要详细解释这些概念,提供可能的流程图,并举例说明如何设置Jenkinsfile和Dockerfile来处理不同的环境和roles。同时,需要强调配置管理的最佳实践,比如使用环境变量、配置文件模板或配置管理工具(如Ansible)来区分不同环境的设置。 最后,确保用户理解每个步骤的目的,以及为什么生产环境需要更复杂的流程,包括安全性、可靠性和可维护性方面的考虑。可能需要分步骤解释,从代码提交到构建、测试、部署到测试环境,再通过审批或触发条件部署到生产环境的不同roles,以及备份策略的实现方式。</think>我为您梳理CI/CD生产环境部署的流程差异及核心概念,结合您提到的ThinkPHP/双roles/双提交等场景,用结构化的方式逐步解析: --- ### 一、基础CI/CD流程图(测试环境) ```mermaid graph TD A[GitLab代码提交] --> B[Jenkins触发流水线] B --> C{环境判断} C -->|测试环境| D[拉取代码] D --> E[构建Docker镜像] E --> F[推送镜像到测试仓库] F --> G[部署到测试K8s集群] ``` ### 二、生产环境特殊需求拆解 1. **双Roles场景**(常见于微服务架构) - Role A:应用服务(如ThinkPHP业务逻辑) - Role B:网关服务(特殊Nginx配置) 2. **双提交需求本质**: - 提交1:应用代码+基础Dockerfile(对应Role A) - 提交2:基础设施配置(对应Role B的Nginx规则) --- ### 三、生产环境部署流程图 ```mermaid graph TD A[GitLab代码提交] --> B{触发条件判断} B -->|应用代码变更| C[应用镜像流水线] B -->|Nginx配置变更| D[网关配置流水线] C --> E[构建业务镜像] E --> F[推送生产镜像仓库] F --> G[蓝绿部署到生产集群] D --> H[生成Nginx配置] H --> I[加密配置文件] I --> J[同步到Nginx集群] J --> K[热重载Nginx服务] ``` --- ### 四、关键差异点解析 1. **ThinkPHP特殊处理**: - 需要`composer install --no-dev`生产模式 - 可能要求`.env.production`配置注入 - 示例Dockerfile片段: ```dockerfile FROM php:7.4-fpm RUN composer install --no-dev --optimize-autoloader COPY .env.production .env ``` 2. **Nginx配置差异**: - 生产环境需要HTTPS配置 - 特殊路由规则(如/api路由到ThinkPHP) - 示例配置片段: ```nginx server { listen 443 ssl; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; location /api { proxy_pass http://thinkphp-service:9000; } } ``` 3. **双提交实现方式**: - 方式一:使用Git子模块 ``` your-repo/ ├── app/ # 主代码库(提交1) └── infra/ # 子模块链接配置库(提交2) ``` - 方式二:多仓库触发(推荐) ```groovy // Jenkinsfile片段 pipeline { triggers { upstream upstreamProjects: 'app-ci-pipeline', threshold: hudson.model.Result.SUCCESS } } ``` --- ### 五、生产环境最佳实践 1. **镜像管理策略**: - 测试镜像:`registry.test.com/app:v1.2.3-test` - 生产镜像:`registry.prod.com/app:v1.2.3-prod` 2. **配置分离方案**: ```bash # 通过Kubernetes ConfigMap注入 kubectl create configmap nginx-prod-config \ --from-file=nginx.conf=./prod/nginx.conf \ --namespace=production ``` 3. **备份机制实现**: - 镜像备份:`docker tag | docker push backup-registry` - 配置备份:使用`git tag v1.2.3-prod-backup`标记配置版本 --- ### 六、故障排查checklist 当流水线异常时,按顺序检查: 1. 镜像签名验证:`cosign verify --key cosign.pub $IMAGE` 2. 配置加密状态:`gpg --decrypt nginx.conf.gpg` 3. 部署审批状态:检查Jenkins的`input`步骤是否超时 4. 网络策略:确保生产集群到镜像仓库的白名单 需要我进一步解释哪个具体环节?可以提供您实际看到的Jenkins控制台日志片段或Dockerfile内容,我可以针对性分析问题根源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值