添加jenkins配置脚本
This commit is contained in:
169
docs/technical/JENKINS_RUST_BUILD_DEPLOY_PIPELINES_2026-04-23.md
Normal file
169
docs/technical/JENKINS_RUST_BUILD_DEPLOY_PIPELINES_2026-04-23.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# Jenkins Rust 构建与部署流水线方案
|
||||
|
||||
日期:`2026-04-23`
|
||||
|
||||
## 1. 目标
|
||||
|
||||
本方案为当前仓库补齐 3 条 Jenkins 流水线:
|
||||
|
||||
1. `构建`:只负责在仓库根目录执行 `npm run deploy:rust:remote -- --skip-upload`,生成发布包。
|
||||
2. `部署`:只负责把指定发布版本部署到 `/home/ubuntu/Genarrative-deploy/`,禁止人工直接点击执行。
|
||||
3. `构建并部署`:先构建,再把构建出的版本号传给 `部署` 流水线并等待部署完成。
|
||||
|
||||
本次只补 Jenkins 编排与本地部署脚本,不改现有 Rust 发布包构建逻辑,不恢复旧 `server-node` 部署链。
|
||||
|
||||
## 2. 执行约束
|
||||
|
||||
1. 构建产物目录统一使用 `build/<版本号>/`。
|
||||
2. 默认使用 Jenkins `BUILD_NUMBER` 作为版本号,避免依赖时间戳;如有需要也允许显式传 `BUILD_VERSION`。
|
||||
3. `部署` 流水线必须校验当前构建原因包含 `UpstreamCause`,没有上游触发则直接失败。
|
||||
4. `部署` 流水线额外校验上游作业名与传入的 `EXPECTED_UPSTREAM_JOB` 一致;如配置了环境变量 `GENARRATIVE_ALLOWED_UPSTREAM_JOB`,还必须与该值一致。
|
||||
5. `构建并部署` 在触发 `部署` 前先释放自己的构建节点,避免单执行器节点出现死锁。
|
||||
6. `部署` 不重新构建,不重新上传,不从 Jenkins 插件仓库复制产物,直接使用上游构建节点的本地 `build/<版本号>/` 目录。
|
||||
|
||||
## 3. 节点与工作区要求
|
||||
|
||||
这套方案依赖“本地目录发布”,因此有两个前提:
|
||||
|
||||
1. `构建并部署` 与 `部署` 必须落到同一台 Ubuntu Jenkins Agent,或者落到同一块共享文件系统。
|
||||
2. `构建并部署` 触发 `部署` 时,必须把 `SOURCE_NODE_NAME` 和 `SOURCE_WORKSPACE_ROOT` 一并传下去。
|
||||
|
||||
仓库中提供的 Jenkinsfile 已按这个约束实现:
|
||||
|
||||
1. `构建` / `构建并部署` 在指定源码目录内 `checkout scm` 并生成 `build/<版本号>/`。
|
||||
2. `构建并部署` 结束构建节点占用后,再触发 `部署`。
|
||||
3. `部署` 优先按 `SOURCE_NODE_NAME` 调度到同名节点,再读取 `SOURCE_WORKSPACE_ROOT/build/<版本号>/`。
|
||||
|
||||
## 4. 三条流水线定义
|
||||
|
||||
### 4.1 构建
|
||||
|
||||
脚本路径:
|
||||
|
||||
```text
|
||||
jenkins/Jenkinsfile.build
|
||||
```
|
||||
|
||||
核心流程:
|
||||
|
||||
1. 可选执行 `npm ci`。
|
||||
2. 在源码根目录执行:
|
||||
|
||||
```bash
|
||||
npm run deploy:rust:remote -- --skip-upload --name <BUILD_VERSION>
|
||||
```
|
||||
|
||||
3. 校验 `build/<BUILD_VERSION>/` 存在。
|
||||
4. 归档 `build/<BUILD_VERSION>/**` 作为 Jenkins 产物。
|
||||
|
||||
默认版本号:
|
||||
|
||||
```text
|
||||
BUILD_VERSION = Jenkins BUILD_NUMBER
|
||||
```
|
||||
|
||||
### 4.2 部署
|
||||
|
||||
脚本路径:
|
||||
|
||||
```text
|
||||
jenkins/Jenkinsfile.deploy
|
||||
```
|
||||
|
||||
核心流程:
|
||||
|
||||
1. 校验触发原因必须是上游流水线,而不是人工点击。
|
||||
2. 校验 `BUILD_VERSION`、`SOURCE_WORKSPACE_ROOT`、`DEPLOY_DIRECTORY` 非空。
|
||||
3. 执行:
|
||||
|
||||
```bash
|
||||
scripts/jenkins-deploy-release.sh \
|
||||
--source-dir <SOURCE_WORKSPACE_ROOT>/build/<BUILD_VERSION> \
|
||||
--deploy-dir /home/ubuntu/Genarrative-deploy
|
||||
```
|
||||
|
||||
脚本语义:
|
||||
|
||||
1. 若部署目录已有旧版本且存在 `stop.sh`,先执行旧版本 `stop.sh`。
|
||||
2. 直接清空部署目录中的全部旧文件。
|
||||
3. 将指定版本目录中的内容移动到部署目录。
|
||||
4. 执行新版本 `start.sh`。
|
||||
|
||||
这样可以满足你要求的“直接覆盖部署目录中的所有文件”。同时这也意味着部署目录内原有的 `.env`、`.env.local`、日志和本地 SpacetimeDB 数据都会被清掉,最终以构建产物中的文件为准。
|
||||
|
||||
### 4.3 构建并部署
|
||||
|
||||
脚本路径:
|
||||
|
||||
```text
|
||||
jenkins/Jenkinsfile.build-and-deploy
|
||||
```
|
||||
|
||||
核心流程:
|
||||
|
||||
1. 复用与 `构建` 相同的构建命令生成 `build/<BUILD_VERSION>/`。
|
||||
2. 归档 `build/<BUILD_VERSION>/**`。
|
||||
3. 记录当前 `NODE_NAME`、源码根目录、版本号。
|
||||
4. 触发 `部署` 流水线,并传递:
|
||||
- `BUILD_VERSION`
|
||||
- `SOURCE_WORKSPACE_ROOT`
|
||||
- `SOURCE_NODE_NAME`
|
||||
- `DEPLOY_DIRECTORY`
|
||||
- `EXPECTED_UPSTREAM_JOB`
|
||||
|
||||
## 5. Jenkins 参数建议
|
||||
|
||||
三条流水线统一建议暴露以下参数:
|
||||
|
||||
1. `AGENT_LABEL`:默认执行节点标签。
|
||||
2. `GENARRATIVE_WORKSPACE_ROOT`:源码根目录;为空时回退到 Jenkins 当前工作区。
|
||||
3. `BUILD_VERSION`:发布版本号;为空时回退到 `BUILD_NUMBER`。
|
||||
4. `RUN_NPM_CI`:是否在构建前执行 `npm ci`。
|
||||
|
||||
其中仅 `部署` 流水线还需要:
|
||||
|
||||
1. `SOURCE_WORKSPACE_ROOT`
|
||||
2. `SOURCE_NODE_NAME`
|
||||
3. `DEPLOY_DIRECTORY`
|
||||
4. `EXPECTED_UPSTREAM_JOB`
|
||||
|
||||
其中仅 `构建并部署` 流水线还需要:
|
||||
|
||||
1. `DEPLOY_JOB_NAME`
|
||||
|
||||
## 6. 推荐 Job 命名
|
||||
|
||||
建议在 Jenkins 中创建以下 3 个 Pipeline Job,并分别指向仓库中的脚本路径:
|
||||
|
||||
1. `Genarrative-Build` -> `jenkins/Jenkinsfile.build`
|
||||
2. `Genarrative-Deploy` -> `jenkins/Jenkinsfile.deploy`
|
||||
3. `Genarrative-Build-And-Deploy` -> `jenkins/Jenkinsfile.build-and-deploy`
|
||||
|
||||
同时给 `Genarrative-Deploy` 配置环境变量:
|
||||
|
||||
```text
|
||||
GENARRATIVE_ALLOWED_UPSTREAM_JOB=Genarrative-Build-And-Deploy
|
||||
```
|
||||
|
||||
如果 Job 在 Jenkins Folder 下,值应填写完整上游作业名,例如:
|
||||
|
||||
```text
|
||||
game/Genarrative-Build-And-Deploy
|
||||
```
|
||||
|
||||
## 7. 文件清单
|
||||
|
||||
本方案对应的仓库文件:
|
||||
|
||||
```text
|
||||
jenkins/Jenkinsfile.build
|
||||
jenkins/Jenkinsfile.deploy
|
||||
jenkins/Jenkinsfile.build-and-deploy
|
||||
scripts/jenkins-deploy-release.sh
|
||||
```
|
||||
|
||||
## 8. 风险与边界
|
||||
|
||||
1. 该方案依赖本地目录切换,不适用于“构建节点”和“部署节点”完全隔离且不共享文件系统的 Jenkins 架构。
|
||||
2. 当前 `部署` 采取的是“覆盖固定部署目录”的方式,不包含版本回滚目录管理;如需保留完整历史版本,应在后续单独补一层 release/current 软链接结构。
|
||||
3. 当前 `start.sh` / `stop.sh` 仍以发布包内脚本为准,不替代 `systemd`、`supervisor`、`nginx`、`tls` 与日志轮转治理。
|
||||
57
jenkins/Jenkinsfile.build
Normal file
57
jenkins/Jenkinsfile.build
Normal file
@@ -0,0 +1,57 @@
|
||||
pipeline {
|
||||
agent none
|
||||
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
timestamps()
|
||||
}
|
||||
|
||||
parameters {
|
||||
string(name: 'AGENT_LABEL', defaultValue: 'linux', description: '构建节点标签')
|
||||
string(name: 'GENARRATIVE_WORKSPACE_ROOT', defaultValue: '', description: '源码根目录,留空则使用当前 Jenkins 工作区')
|
||||
string(name: 'BUILD_VERSION', defaultValue: '', description: '发布版本号,留空则使用 Jenkins BUILD_NUMBER')
|
||||
booleanParam(name: 'RUN_NPM_CI', defaultValue: false, description: '构建前是否执行 npm ci')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('构建发布包') {
|
||||
agent {
|
||||
label "${params.AGENT_LABEL}"
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
// 统一在脚本块里计算版本号,避免 declarative environment 对表达式求值不一致。
|
||||
env.EFFECTIVE_BUILD_VERSION = params.BUILD_VERSION?.trim() ? params.BUILD_VERSION.trim() : env.BUILD_NUMBER
|
||||
// 允许 Jenkins Job 直接指定固定源码目录,未指定时回退到当前工作区。
|
||||
env.WORKSPACE_ROOT = params.GENARRATIVE_WORKSPACE_ROOT?.trim() ? params.GENARRATIVE_WORKSPACE_ROOT.trim() : pwd()
|
||||
}
|
||||
|
||||
dir("${env.WORKSPACE_ROOT}") {
|
||||
checkout scm
|
||||
|
||||
script {
|
||||
// 是否重装依赖交给流水线参数决定,避免每次构建都重复执行 npm ci。
|
||||
if (params.RUN_NPM_CI) {
|
||||
sh 'npm ci'
|
||||
}
|
||||
}
|
||||
|
||||
sh """
|
||||
set -euo pipefail
|
||||
npm run deploy:rust:remote -- --skip-upload --name "${env.EFFECTIVE_BUILD_VERSION}"
|
||||
test -d "build/${env.EFFECTIVE_BUILD_VERSION}"
|
||||
"""
|
||||
|
||||
archiveArtifacts artifacts: "build/${env.EFFECTIVE_BUILD_VERSION}/**", fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
echo "构建完成,版本号: ${env.EFFECTIVE_BUILD_VERSION}"
|
||||
}
|
||||
}
|
||||
}
|
||||
77
jenkins/Jenkinsfile.build-and-deploy
Normal file
77
jenkins/Jenkinsfile.build-and-deploy
Normal file
@@ -0,0 +1,77 @@
|
||||
pipeline {
|
||||
agent none
|
||||
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
timestamps()
|
||||
}
|
||||
|
||||
parameters {
|
||||
string(name: 'AGENT_LABEL', defaultValue: 'linux', description: '构建节点标签')
|
||||
string(name: 'GENARRATIVE_WORKSPACE_ROOT', defaultValue: '', description: '源码根目录,留空则使用当前 Jenkins 工作区')
|
||||
string(name: 'BUILD_VERSION', defaultValue: '', description: '发布版本号,留空则使用 Jenkins BUILD_NUMBER')
|
||||
booleanParam(name: 'RUN_NPM_CI', defaultValue: false, description: '构建前是否执行 npm ci')
|
||||
string(name: 'DEPLOY_JOB_NAME', defaultValue: 'Genarrative-Deploy', description: '部署流水线作业名')
|
||||
string(name: 'DEPLOY_DIRECTORY', defaultValue: '/home/ubuntu/Genarrative-deploy', description: '固定部署目录')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('构建发布包') {
|
||||
agent {
|
||||
label "${params.AGENT_LABEL}"
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
// 统一在脚本块里计算版本号,避免 declarative environment 对表达式求值不一致。
|
||||
env.EFFECTIVE_BUILD_VERSION = params.BUILD_VERSION?.trim() ? params.BUILD_VERSION.trim() : env.BUILD_NUMBER
|
||||
// 允许 Jenkins Job 直接指定固定源码目录,未指定时回退到当前工作区。
|
||||
env.WORKSPACE_ROOT = params.GENARRATIVE_WORKSPACE_ROOT?.trim() ? params.GENARRATIVE_WORKSPACE_ROOT.trim() : pwd()
|
||||
// 记录当前构建节点名,部署阶段必须回到同一节点读取本地 build 目录。
|
||||
env.SOURCE_NODE_NAME = env.NODE_NAME
|
||||
}
|
||||
|
||||
dir("${env.WORKSPACE_ROOT}") {
|
||||
checkout scm
|
||||
|
||||
script {
|
||||
// 是否重装依赖交给流水线参数决定,避免每次构建都重复执行 npm ci。
|
||||
if (params.RUN_NPM_CI) {
|
||||
sh 'npm ci'
|
||||
}
|
||||
}
|
||||
|
||||
sh """
|
||||
set -euo pipefail
|
||||
npm run deploy:rust:remote -- --skip-upload --name "${env.EFFECTIVE_BUILD_VERSION}"
|
||||
test -d "build/${env.EFFECTIVE_BUILD_VERSION}"
|
||||
"""
|
||||
|
||||
archiveArtifacts artifacts: "build/${env.EFFECTIVE_BUILD_VERSION}/**", fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('触发部署') {
|
||||
steps {
|
||||
// 本阶段没有声明 agent,确保触发下游前已经释放构建节点,避免单执行器死锁。
|
||||
build job: params.DEPLOY_JOB_NAME,
|
||||
wait: true,
|
||||
propagate: true,
|
||||
parameters: [
|
||||
string(name: 'SOURCE_NODE_NAME', value: env.SOURCE_NODE_NAME),
|
||||
string(name: 'SOURCE_WORKSPACE_ROOT', value: env.WORKSPACE_ROOT),
|
||||
string(name: 'BUILD_VERSION', value: env.EFFECTIVE_BUILD_VERSION),
|
||||
string(name: 'DEPLOY_DIRECTORY', value: params.DEPLOY_DIRECTORY),
|
||||
string(name: 'EXPECTED_UPSTREAM_JOB', value: env.JOB_NAME),
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
echo "构建并部署完成,版本号: ${env.EFFECTIVE_BUILD_VERSION}"
|
||||
}
|
||||
}
|
||||
}
|
||||
85
jenkins/Jenkinsfile.deploy
Normal file
85
jenkins/Jenkinsfile.deploy
Normal file
@@ -0,0 +1,85 @@
|
||||
pipeline {
|
||||
agent none
|
||||
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
timestamps()
|
||||
}
|
||||
|
||||
parameters {
|
||||
string(name: 'SOURCE_NODE_NAME', defaultValue: '', description: '上游构建节点名')
|
||||
string(name: 'SOURCE_WORKSPACE_ROOT', defaultValue: '', description: '上游源码根目录')
|
||||
string(name: 'BUILD_VERSION', defaultValue: '', description: '待部署版本号')
|
||||
string(name: 'DEPLOY_DIRECTORY', defaultValue: '/home/ubuntu/Genarrative-deploy', description: '固定部署目录')
|
||||
string(name: 'EXPECTED_UPSTREAM_JOB', defaultValue: '', description: '允许触发本作业的上游作业名')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('校验触发来源') {
|
||||
agent {
|
||||
label 'built-in'
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
def upstreamCause = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause)
|
||||
if (upstreamCause == null) {
|
||||
error('部署流水线禁止人工直接执行,只允许由上游构建并部署流水线触发。')
|
||||
}
|
||||
|
||||
def actualUpstreamJob = upstreamCause.upstreamProject ?: ''
|
||||
def expectedUpstreamJob = params.EXPECTED_UPSTREAM_JOB?.trim()
|
||||
def allowedUpstreamJob = env.GENARRATIVE_ALLOWED_UPSTREAM_JOB?.trim()
|
||||
|
||||
if (!params.BUILD_VERSION?.trim()) {
|
||||
error('BUILD_VERSION 不能为空。')
|
||||
}
|
||||
|
||||
if (!params.SOURCE_WORKSPACE_ROOT?.trim()) {
|
||||
error('SOURCE_WORKSPACE_ROOT 不能为空。')
|
||||
}
|
||||
|
||||
if (!params.SOURCE_NODE_NAME?.trim()) {
|
||||
error('SOURCE_NODE_NAME 不能为空。')
|
||||
}
|
||||
|
||||
if (expectedUpstreamJob && actualUpstreamJob != expectedUpstreamJob) {
|
||||
error("上游作业校验失败,期望 ${expectedUpstreamJob},实际 ${actualUpstreamJob}")
|
||||
}
|
||||
|
||||
if (allowedUpstreamJob && actualUpstreamJob != allowedUpstreamJob) {
|
||||
error("环境门禁校验失败,仅允许 ${allowedUpstreamJob} 触发,实际 ${actualUpstreamJob}")
|
||||
}
|
||||
|
||||
env.UPSTREAM_JOB_NAME = actualUpstreamJob
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('部署指定版本') {
|
||||
agent {
|
||||
label "${params.SOURCE_NODE_NAME}"
|
||||
}
|
||||
|
||||
steps {
|
||||
dir("${params.SOURCE_WORKSPACE_ROOT}") {
|
||||
sh """
|
||||
set -euo pipefail
|
||||
test -d "build/${params.BUILD_VERSION}"
|
||||
chmod +x scripts/jenkins-deploy-release.sh
|
||||
# 只部署上游已构建好的版本目录,避免部署阶段再次构建产生漂移。
|
||||
./scripts/jenkins-deploy-release.sh \
|
||||
--source-dir "build/${params.BUILD_VERSION}" \
|
||||
--deploy-dir "${params.DEPLOY_DIRECTORY}"
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
echo "部署完成,版本号: ${params.BUILD_VERSION},上游作业: ${env.UPSTREAM_JOB_NAME}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,22 @@ copy_required_file() {
|
||||
cp "${source_path}" "${target_path}"
|
||||
}
|
||||
|
||||
copy_optional_file() {
|
||||
local source_path="$1"
|
||||
local target_path_a="$2"
|
||||
local target_path_b="$3"
|
||||
local label="$4"
|
||||
|
||||
if [[ ! -f "${source_path}" ]]; then
|
||||
echo "[deploy:rust] 跳过未找到的可选文件 ${label}: ${source_path}"
|
||||
return
|
||||
fi
|
||||
|
||||
cp "${source_path}" "${target_path_a}"
|
||||
cp "${source_path}" "${target_path_b}"
|
||||
echo "[deploy:rust] 已复制 ${label} -> ${target_path_a} 与 ${target_path_b}"
|
||||
}
|
||||
|
||||
normalize_local_path_for_bash() {
|
||||
local value="$1"
|
||||
|
||||
@@ -228,6 +244,9 @@ mkdir -p "${WEB_DIR}"
|
||||
|
||||
echo "[deploy:rust] 发布包目录: ${TARGET_DIR}"
|
||||
|
||||
copy_optional_file "${REPO_ROOT}/.env" "${TARGET_DIR}/.env" "${WEB_DIR}/.env" ".env"
|
||||
copy_optional_file "${REPO_ROOT}/.env.local" "${TARGET_DIR}/.env.local" "${WEB_DIR}/.env.local" ".env.local"
|
||||
|
||||
if [[ "${SKIP_WEB_BUILD}" -ne 1 ]]; then
|
||||
echo "[deploy:rust] 构建 Vite release -> ${WEB_DIR}"
|
||||
(
|
||||
@@ -571,6 +590,7 @@ cat >"${TARGET_DIR}/README.md" <<EOF
|
||||
|
||||
## 内容
|
||||
|
||||
- \`.env\` / \`.env.local\`:从仓库根目录复制的环境文件,同时各保留一份到 \`web/\`
|
||||
- \`web/\`:Vite release 静态资源
|
||||
- \`api-server\`:x86_64-unknown-linux-gnu release 可执行文件
|
||||
- \`spacetime_module.wasm\`:wasm32-unknown-unknown release 模块
|
||||
|
||||
98
scripts/jenkins-deploy-release.sh
Normal file
98
scripts/jenkins-deploy-release.sh
Normal file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
用法:
|
||||
./scripts/jenkins-deploy-release.sh --source-dir /path/to/build/123 --deploy-dir /home/ubuntu/Genarrative-deploy
|
||||
|
||||
说明:
|
||||
1. 如果部署目录已有旧版本且存在 stop.sh,则先执行旧版本 stop.sh。
|
||||
2. 直接清空部署目录中的全部旧文件。
|
||||
3. 把指定发布目录中的内容移动到部署目录。
|
||||
4. 最后执行新版本 start.sh。
|
||||
|
||||
参数:
|
||||
--source-dir <path> 必填,待部署的发布目录,例如 build/123
|
||||
--deploy-dir <path> 必填,固定部署目录,例如 /home/ubuntu/Genarrative-deploy
|
||||
EOF
|
||||
}
|
||||
|
||||
require_argument() {
|
||||
local value="$1"
|
||||
local label="$2"
|
||||
|
||||
if [[ -z "${value}" ]]; then
|
||||
echo "[jenkins-deploy] 缺少参数: ${label}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
SOURCE_DIR=""
|
||||
DEPLOY_DIR=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--source-dir)
|
||||
SOURCE_DIR="${2:?缺少 --source-dir 的值}"
|
||||
shift 2
|
||||
;;
|
||||
--deploy-dir)
|
||||
DEPLOY_DIR="${2:?缺少 --deploy-dir 的值}"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
echo "[jenkins-deploy] 未知参数: $1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_argument "${SOURCE_DIR}" "--source-dir"
|
||||
require_argument "${DEPLOY_DIR}" "--deploy-dir"
|
||||
|
||||
if [[ ! -d "${SOURCE_DIR}" ]]; then
|
||||
echo "[jenkins-deploy] 发布目录不存在: ${SOURCE_DIR}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE_DIR="$(cd "${SOURCE_DIR}" && pwd)"
|
||||
mkdir -p "${DEPLOY_DIR}"
|
||||
DEPLOY_DIR="$(cd "${DEPLOY_DIR}" && pwd)"
|
||||
|
||||
if [[ ! -f "${SOURCE_DIR}/start.sh" ]]; then
|
||||
echo "[jenkins-deploy] 发布目录缺少 start.sh: ${SOURCE_DIR}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -x "${DEPLOY_DIR}/stop.sh" ]]; then
|
||||
echo "[jenkins-deploy] 先停止旧版本: ${DEPLOY_DIR}"
|
||||
(
|
||||
cd "${DEPLOY_DIR}"
|
||||
./stop.sh
|
||||
)
|
||||
else
|
||||
echo "[jenkins-deploy] 部署目录无可执行 stop.sh,跳过停服"
|
||||
fi
|
||||
|
||||
echo "[jenkins-deploy] 清空部署目录: ${DEPLOY_DIR}"
|
||||
find "${DEPLOY_DIR}" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
|
||||
|
||||
echo "[jenkins-deploy] 移动发布内容: ${SOURCE_DIR} -> ${DEPLOY_DIR}"
|
||||
find "${SOURCE_DIR}" -mindepth 1 -maxdepth 1 -exec mv {} "${DEPLOY_DIR}/" \;
|
||||
|
||||
chmod +x "${DEPLOY_DIR}/start.sh" "${DEPLOY_DIR}/stop.sh"
|
||||
|
||||
echo "[jenkins-deploy] 启动新版本: ${DEPLOY_DIR}"
|
||||
(
|
||||
cd "${DEPLOY_DIR}"
|
||||
./start.sh
|
||||
)
|
||||
|
||||
echo "[jenkins-deploy] 完成"
|
||||
Reference in New Issue
Block a user