def isProductionDeploy() { return params.DEPLOY_ENV == "production" } def isTestDeploy() { def branch = env.BRANCH_NAME ?: "" return params.DEPLOY_ENV == "test" && !params.SKIP_DEPLOY && branch == env.TEST_BRANCH } @NonCPS boolean isUserTriggeredBuild() { return currentBuild.rawBuild.getCauses().any { cause -> cause.class.name == "hudson.model.Cause\$UserIdCause" } } pipeline { agent any options { timestamps() disableConcurrentBuilds() buildDiscarder(logRotator(numToKeepStr: "30", artifactNumToKeepStr: "10")) } parameters { choice( name: "DEPLOY_ENV", choices: ["test", "production"], description: "test: develop 合并后自动部署测试环境;production: 仅允许手动输入 Tag 部署" ) string(name: "RELEASE_TAG", defaultValue: "", description: "生产部署必填,必须是 Gitea 中已存在的 Tag") booleanParam(name: "SKIP_DEPLOY", defaultValue: false, description: "只构建检查,不执行部署") } environment { PROJECT_NAME = "access-manage" TEST_BRANCH = "develop" DEPLOY_BASE_DIR = "/srv/www" } stages { stage("Validate deploy policy") { steps { script { if (isProductionDeploy()) { if (!isUserTriggeredBuild()) { error("生产环境禁止自动触发,只能在 Jenkins 手动 Build With Parameters。") } if (!params.RELEASE_TAG?.trim()) { error("生产环境部署必须填写 RELEASE_TAG,且只能从项目 Tag 部署。") } } if (params.DEPLOY_ENV == "test" && env.BRANCH_NAME && env.BRANCH_NAME != env.TEST_BRANCH) { echo "当前分支 ${env.BRANCH_NAME} 不是 ${env.TEST_BRANCH},本次只构建检查,不自动部署测试环境。" } } } } stage("Checkout production tag") { when { expression { isProductionDeploy() } } steps { sh ''' set -euo pipefail git fetch --tags --force origin '+refs/tags/*:refs/tags/*' tag_commit="$(git rev-parse -q --verify "refs/tags/${RELEASE_TAG}^{commit}")" if [ -z "${tag_commit}" ]; then echo "Tag not found: ${RELEASE_TAG}" >&2 exit 1 fi git checkout -f "${tag_commit}" git log -1 --oneline ''' } } stage("Install") { steps { sh ''' corepack enable || true pnpm install --frozen-lockfile ''' } } stage("Verify") { steps { sh "pnpm typecheck" } } stage("Build") { steps { script { sh isProductionDeploy() ? "pnpm build:pro" : "pnpm build:test" } } } stage("Deploy test") { when { expression { isTestDeploy() } } steps { sh "bash deploy/jenkins/deploy-backend.sh test" } } stage("Deploy production") { when { expression { isProductionDeploy() && !params.SKIP_DEPLOY } } steps { sh "bash deploy/jenkins/deploy-backend.sh production" } } } }