Files
Genarrative/jenkins/Jenkinsfile.production-stdb-module-publish

183 lines
8.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
pipeline {
agent none
options {
disableConcurrentBuilds()
skipDefaultCheckout(true)
buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20'))
}
environment {
GIT_REMOTE_URL = 'http://127.0.0.1:3000/GenarrativeAI/Genarrative.git'
}
parameters {
choice(name: 'DEPLOY_TARGET', choices: ['development', 'release'], description: '逻辑部署目标development 使用当前 Linux 开发/构建/开发部署 agent')
booleanParam(name: 'CONFIRM_RELEASE_DEPLOY_AGENT', defaultValue: false, description: '确认 release 目标已有独立 release 部署 agent当前 Linux 开发/构建/开发部署 agent 不可冒充 release 部署机')
string(name: 'SOURCE_BRANCH', defaultValue: 'master', description: '部署脚本来源分支')
string(name: 'COMMIT_HASH', defaultValue: '', description: '部署脚本来源 commit上游触发时传实际构建 commit')
string(name: 'NOTIFICATION_EMAILS', defaultValue: '', description: '本次运行追加通知邮箱;会与 Jenkins Secret Text 凭据 genarrative-notification-emails 合并发送')
string(name: 'BUILD_VERSION', defaultValue: '', description: '待发布版本号')
string(name: 'BUILD_JOB_NAME', defaultValue: 'Genarrative-Stdb-Module-Build', description: 'Stdb module 构建流水线作业名')
string(name: 'BUILD_NUMBER_TO_DEPLOY', defaultValue: '', description: '要复制归档产物的上游构建号')
string(name: 'DATABASE', defaultValue: 'genarrative-prod', description: '生产 SpacetimeDB database')
string(name: 'SPACETIME_SERVER', defaultValue: 'local', description: 'SpacetimeDB server alias')
string(name: 'SPACETIME_SERVER_URL', defaultValue: 'http://127.0.0.1:3101', description: '显式 SpacetimeDB server URL填写后优先于 SPACETIME_SERVER')
string(name: 'SPACETIME_ROOT_DIR', defaultValue: '/stdb', description: 'spacetime CLI root-dir需与自托管 spacetimedb.service 一致')
string(name: 'SPACETIME_RUN_AS_USER', defaultValue: 'spacetimedb', description: '执行 spacetime publish 的本机用户,默认使用自托管服务用户')
booleanParam(name: 'CLEAR_DATABASE', defaultValue: false, description: '是否清空数据库后发布')
}
stages {
stage('Prepare') {
agent {
label 'linux && genarrative-build'
}
steps {
script {
if (params.DEPLOY_TARGET == 'release' && !params.CONFIRM_RELEASE_DEPLOY_AGENT) {
error('release 部署需要先配置独立 release 部署 agent并勾选 CONFIRM_RELEASE_DEPLOY_AGENT。当前 Linux 开发/构建/开发部署 agent 不能执行 release 部署。')
}
if (!params.BUILD_VERSION?.trim()) {
error('BUILD_VERSION 不能为空。')
}
if (!params.BUILD_JOB_NAME?.trim()) {
error('BUILD_JOB_NAME 不能为空。')
}
if (!params.BUILD_NUMBER_TO_DEPLOY?.trim()) {
error('BUILD_NUMBER_TO_DEPLOY 不能为空。')
}
if (!params.DATABASE?.trim()) {
error('DATABASE 不能为空。')
}
if (!params.SPACETIME_SERVER?.trim() && !params.SPACETIME_SERVER_URL?.trim()) {
error('SPACETIME_SERVER 与 SPACETIME_SERVER_URL 不能同时为空。')
}
def spacetimeRootDir = params.SPACETIME_ROOT_DIR?.trim() ? params.SPACETIME_ROOT_DIR.trim() : '/stdb'
if (!(spacetimeRootDir ==~ /^\/(?!.*\.\.)[A-Za-z0-9._\/-]+$/)) {
error("SPACETIME_ROOT_DIR 必须是 Linux 绝对路径且不能包含 ..: ${spacetimeRootDir}")
}
def spacetimeRunAsUser = params.SPACETIME_RUN_AS_USER?.trim()
if (spacetimeRunAsUser && !(spacetimeRunAsUser ==~ /^[A-Za-z_][A-Za-z0-9_-]*$/)) {
error("SPACETIME_RUN_AS_USER 只能是本机用户名: ${spacetimeRunAsUser}")
}
def spacetimeServerUrl = params.SPACETIME_SERVER_URL?.trim()
if (spacetimeServerUrl && !(spacetimeServerUrl ==~ /^https?:\/\/[A-Za-z0-9._:-]+$/)) {
error("SPACETIME_SERVER_URL 只能是 http(s) URL且不能包含路径或 shell 特殊字符: ${spacetimeServerUrl}")
}
def spacetimeServer = params.SPACETIME_SERVER?.trim()
if (!spacetimeServerUrl && spacetimeServer && !(spacetimeServer ==~ /^[A-Za-z0-9._:-]+$/)) {
error("SPACETIME_SERVER 只能包含字母、数字、点、下划线、冒号和短横线: ${spacetimeServer}")
}
}
}
}
stage('Checkout Publish Scripts') {
agent {
label "${params.DEPLOY_TARGET == 'development' ? 'linux && genarrative-build' : 'linux && genarrative-release-deploy'}"
}
steps {
checkout([
$class: 'GitSCM',
branches: [[name: "*/${params.SOURCE_BRANCH}"]],
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'CleanBeforeCheckout']],
userRemoteConfigs: [[url: "${GIT_REMOTE_URL}"]],
])
sh '''
bash -lc '
set -euo pipefail
chmod +x scripts/jenkins-checkout-source.sh
SOURCE_BRANCH="${SOURCE_BRANCH:-master}" \
COMMIT_HASH="${COMMIT_HASH:-}" \
GIT_REMOTE_URL="${GIT_REMOTE_URL}" \
SOURCE_COMMIT_FILE=".jenkins-source-commit" \
scripts/jenkins-checkout-source.sh
'
'''
}
}
stage('Fetch Artifact') {
agent {
label "${params.DEPLOY_TARGET == 'development' ? 'linux && genarrative-build' : 'linux && genarrative-release-deploy'}"
}
steps {
copyArtifacts(
projectName: params.BUILD_JOB_NAME,
selector: specific(params.BUILD_NUMBER_TO_DEPLOY),
filter: "build/${params.BUILD_VERSION}/spacetime_module.wasm,build/${params.BUILD_VERSION}/spacetime_module.wasm.sha256,build/${params.BUILD_VERSION}/release-manifest.json",
target: '.',
fingerprintArtifacts: true
)
}
}
stage('Publish Stdb Module') {
agent {
label "${params.DEPLOY_TARGET == 'development' ? 'linux && genarrative-build' : 'linux && genarrative-release-deploy'}"
}
steps {
script {
def clearArg = params.CLEAR_DATABASE ? '--clear-database' : ''
def rootArg = "--root-dir \"${params.SPACETIME_ROOT_DIR?.trim() ? params.SPACETIME_ROOT_DIR.trim() : '/stdb'}\""
def runAsArg = params.SPACETIME_RUN_AS_USER?.trim()
? "--run-as-user \"${params.SPACETIME_RUN_AS_USER.trim()}\""
: ''
def serverArg = params.SPACETIME_SERVER_URL?.trim()
? "--server-url \"${params.SPACETIME_SERVER_URL.trim()}\""
: "--server \"${params.SPACETIME_SERVER}\""
sh """
bash -lc '
set -euo pipefail
chmod +x scripts/deploy/production-stdb-publish.sh scripts/deploy/maintenance-on.sh scripts/deploy/maintenance-off.sh
scripts/deploy/production-stdb-publish.sh \\
--source-dir "build/${params.BUILD_VERSION}" \\
--database "${params.DATABASE}" \\
${rootArg} \\
${runAsArg} \\
${serverArg} \\
${clearArg}
'
"""
}
}
}
}
post {
always {
script {
def notificationParameters = [
string(name: 'SOURCE_JOB_NAME', value: env.JOB_NAME),
string(name: 'SOURCE_BUILD_NUMBER', value: env.BUILD_NUMBER),
string(name: 'SOURCE_BUILD_URL', value: env.BUILD_URL ?: ''),
string(name: 'SOURCE_RESULT', value: currentBuild.currentResult ?: 'UNKNOWN'),
string(name: 'SOURCE_BRANCH', value: params.SOURCE_BRANCH ?: ''),
string(name: 'SOURCE_COMMIT', value: env.SOURCE_COMMIT ?: (params.COMMIT_HASH ?: '')),
string(name: 'BUILD_VERSION', value: env.EFFECTIVE_BUILD_VERSION ?: (params.BUILD_VERSION ?: '')),
string(name: 'DEPLOY_TARGET', value: params.DEPLOY_TARGET ?: ''),
string(name: 'DATABASE', value: params.DATABASE ?: ''),
string(name: 'SUMMARY', value: 'Stdb module 发布流水线结束'),
]
def notificationRecipients = params.NOTIFICATION_EMAILS?.trim()
if (notificationRecipients) {
notificationParameters.add(string(name: 'EMAIL_RECIPIENTS', value: notificationRecipients))
}
try {
build job: 'Genarrative-Notify-Email',
wait: false,
propagate: false,
parameters: notificationParameters
} catch (error) {
echo "邮件通知触发失败: ${error.message}"
}
}
}
success {
echo "Stdb module 发布完成: version=${params.BUILD_VERSION}, database=${params.DATABASE}"
}
}
}