pipeline { agent none options { disableConcurrentBuilds() timestamps() } parameters { string(name: 'AGENT_LABEL', defaultValue: 'built-in', description: '执行节点标签') string(name: 'GENARRATIVE_WORKSPACE_ROOT', defaultValue: '', description: '源码根目录,留空则使用当前 Jenkins 工作区') string(name: 'DATABASE', defaultValue: '', description: 'SpacetimeDB 数据库名,留空则读取环境变量') string(name: 'SERVER', defaultValue: 'maincloud', description: 'SpacetimeDB server 别名,例如 maincloud/local/dev') string(name: 'SERVER_URL', defaultValue: '', description: 'SpacetimeDB server URL,填写后优先于 SERVER') string(name: 'DEPLOY_DIRECTORY', defaultValue: '/var/lib/jenkins/deploy/Genarrative', description: '固定部署目录,ROOT_DIR 为空时使用其 .spacetimedb') string(name: 'ROOT_DIR', defaultValue: '', description: 'spacetime CLI root-dir,可选,优先于 DEPLOY_DIRECTORY') string(name: 'INCLUDE_TABLES', defaultValue: '', description: '可选,逗号分隔的表名白名单') string(name: 'BOOTSTRAP_SECRET', defaultValue: '', description: '可选,授权临时导出 identity 的迁移引导密钥') string(name: 'OUTPUT_DIRECTORY', defaultValue: 'database-exports', description: '导出文件目录,相对源码根目录或绝对路径') string(name: 'EXPORT_NAME', defaultValue: '', description: '导出文件名,留空则自动使用构建号') } stages { stage('导出数据库') { agent { label "${params.AGENT_LABEL}" } steps { script { // 允许 Jenkins Job 指定固定源码目录;未指定时使用当前工作区,方便临时手工执行。 env.WORKSPACE_ROOT = params.GENARRATIVE_WORKSPACE_ROOT?.trim() ? params.GENARRATIVE_WORKSPACE_ROOT.trim() : pwd() def deployDirectory = params.DEPLOY_DIRECTORY?.trim() if (!deployDirectory) { error('DEPLOY_DIRECTORY 不能为空。') } env.EFFECTIVE_ROOT_DIR = params.ROOT_DIR?.trim() ? params.ROOT_DIR.trim() : "${deployDirectory}/.spacetimedb" def exportName = params.EXPORT_NAME?.trim() if (!exportName) { exportName = "spacetime-migration-${env.BUILD_NUMBER}.json" } if (!(exportName ==~ /^[A-Za-z0-9._-]+$/)) { error("EXPORT_NAME 只能包含字母、数字、点、下划线和短横线,当前值: ${exportName}") } env.EFFECTIVE_EXPORT_NAME = exportName } dir("${env.WORKSPACE_ROOT}") { checkout scm sh """ bash -lc ' set -euo pipefail export_dir="${params.OUTPUT_DIRECTORY}" if [[ -z "\${export_dir}" ]]; then export_dir="database-exports" fi mkdir -p "\${export_dir}" output_path="\${export_dir}/${env.EFFECTIVE_EXPORT_NAME}" args=(scripts/spacetime-export-migration-json.mjs --out "\${output_path}") if [[ -n "${params.DATABASE}" ]]; then args+=(--database "${params.DATABASE}") fi if [[ -n "${params.SERVER}" ]]; then args+=(--server "${params.SERVER}") fi if [[ -n "${params.SERVER_URL}" ]]; then args+=(--server-url "${params.SERVER_URL}") fi if [[ -n "${env.EFFECTIVE_ROOT_DIR}" ]]; then args+=(--root-dir "${env.EFFECTIVE_ROOT_DIR}") fi if [[ -n "${params.INCLUDE_TABLES}" ]]; then args+=(--include "${params.INCLUDE_TABLES}") fi if [[ -n "${params.BOOTSTRAP_SECRET}" ]]; then args+=(--bootstrap-secret "${params.BOOTSTRAP_SECRET}") fi # 复用后端迁移 procedure 导出 JSON,避免 Jenkins 直接拼接表结构和 SQL。 node "\${args[@]}" test -s "\${output_path}" ' """ archiveArtifacts artifacts: "${params.OUTPUT_DIRECTORY ?: 'database-exports'}/${env.EFFECTIVE_EXPORT_NAME}", fingerprint: true } } } } post { success { echo "数据库导出完成: ${env.EFFECTIVE_EXPORT_NAME}" } } }