diff --git a/README.md b/README.md index 6361536..d7ab094 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,54 @@ CGO_ENABLED=0 go build -tags embedui -o artex ./cmd/artex --- +## 更新升级 + +> 升级只换程序、不动数据:Postgres 数据卷 `pgdata`、`./data`(jwt.key / SQLite 等)、`./skills` 都会保留。**数据库迁移无需手动执行**——`artex` 每次启动会幂等重跑 `schema.sql`(含 `ADD COLUMN` / `CREATE INDEX IF NOT EXISTS`),即“重启即迁移”。升级前仍建议先备份 `./data` 与数据库。 + +### 方式一:一键更新脚本(推荐) + +```bash +cd ARTEX +./update.sh +``` + +脚本先可选 `git pull` 拉取最新代码,再让你选 **① Docker 更新** 或 **② 本地编译更新**(与 `install.sh` 对应): + +- **① Docker**:可指定目标镜像 tag(回车沿用 `.env` 的 `ARTEX_TAG`,缺省 `latest`)→ `docker compose pull` → `docker compose up -d`(换新镜像重启即自动迁移)。 +- **② 本地**:重建前端静态产物 → 重新编译 `./artex`(完成后重启进程生效)。 + +### 方式二:Docker Compose(手动) + +```bash +cd ARTEX +git pull # 更新 compose / 脚本(可选) +# 指定版本:在 .env 设 ARTEX_TAG=v0.2.0;不设则用 latest +docker compose pull artex +docker compose up -d artex # 换新镜像重启 → 自动迁移 schema +docker image prune -f # 清理旧镜像(可选) +``` + +### 方式三:预编译二进制(Releases) + +到 [Releases](https://github.com/Autumn-27/ARTEX/releases) 下载新版本 zip,停掉旧进程后覆盖 `artex` 与 `skills/`(保留你的 `config.json` 与 `data/`),重启即可: + +```bash +cp -r <解压目录>/skills ./ && cp <解压目录>/artex ./ +./artex +``` + +### 方式四:从源码编译 + +```bash +git pull +cd web && npm ci && npm run build:static && cd .. +cp -r web/out server/webui/dist +CGO_ENABLED=0 go build -tags embedui -o artex ./cmd/artex +# 重启 ./artex +``` + +--- + ## 配置 **数据库**(`config.json`,或用环境变量 `ARTEX_PG_DSN` 覆盖): diff --git a/update.sh b/update.sh new file mode 100755 index 0000000..3a870c6 --- /dev/null +++ b/update.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +# ARTEX 更新脚本:① Docker 更新(拉新镜像重建) ② 本地编译更新(重建二进制) +# 与 install.sh 对应:install 负责首次落地,update 负责升级到新版本。 +# DB 迁移无需手动执行——artex 每次启动都会幂等重跑 schema.sql(含 ADD COLUMN/CREATE +# INDEX IF NOT EXISTS),所以“重启即迁移”。数据(pgdata 卷、./data、./skills)不受影响。 +set -euo pipefail +cd "$(cd "$(dirname "$0")" && pwd)" + +info(){ printf '\033[36m[*]\033[0m %s\n' "$*"; } +ok(){ printf '\033[32m[+]\033[0m %s\n' "$*"; } +warn(){ printf '\033[33m[!]\033[0m %s\n' "$*"; } +die(){ printf '\033[31m[x]\033[0m %s\n' "$*" >&2; exit 1; } +ask(){ local p="$1" d="${2:-}" a; read -rp "$p${d:+ [$d]}: " a; echo "${a:-$d}"; } + +# ── 可选:同步仓库到最新代码(compose/脚本/本地编译源码都靠它更新)─────── +sync_repo(){ + [ -d .git ] && command -v git >/dev/null 2>&1 || { warn "非 git 工作副本,跳过 git pull"; return; } + [ "$(ask '拉取最新代码 (git pull --ff-only)? (y/n)' y)" = y ] || return + if ! git pull --ff-only; then + warn "git pull 未能快进(本地有改动或分支分叉)——请手动处理后重试,本次沿用当前代码" + fi +} + +# ── ① Docker 更新 ─────────────────────────────── +update_docker(){ + command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1 \ + || die "未检测到 docker / docker compose,请先用 ./install.sh 安装部署" + [ -f .env ] || die "未找到 .env,请先运行 ./install.sh 完成首次部署" + + # 可选:升级到指定版本 tag(不填则沿用 .env 中的 ARTEX_TAG,缺省为 latest) + local tag; tag="$(ask '目标镜像 tag(回车沿用 .env / latest)' '')" + if [ -n "$tag" ]; then + if grep -q '^ARTEX_TAG=' .env; then + sed -i.bak "s|^ARTEX_TAG=.*|ARTEX_TAG=${tag}|" .env && rm -f .env.bak + else + printf '\nARTEX_TAG=%s\n' "$tag" >> .env + fi + ok "已将 ARTEX_TAG 设为 ${tag}" + fi + + info "拉取新镜像…" + docker compose pull + info "重建并启动(artex 重启时自动迁移 schema)…" + docker compose up -d + ok "更新完成 → http://localhost:8787" + info "查看日志:docker compose logs -f artex" + info "清理旧镜像(可选):docker image prune -f" +} + +# ── ② 本地编译更新 ────────────────────────────── +update_local(){ + command -v go >/dev/null 2>&1 || die "未检测到 Go(>=1.26):https://go.dev/dl/" + [ -f config.json ] || warn "未找到 config.json——若首次部署请改用 ./install.sh" + ok "Go: $(go version)" + + if command -v npm >/dev/null 2>&1; then + info "重建前端静态产物…" + ( cd web && npm ci && npm run build:static ) + rm -rf server/webui/dist && cp -r web/out server/webui/dist + info "重新编译内嵌单二进制…" + CGO_ENABLED=0 go build -tags embedui -trimpath -o artex ./cmd/artex + else + warn "未检测到 npm:编译**不内嵌前端**的后端(前端需另跑 npm run dev)" + CGO_ENABLED=0 go build -o artex ./cmd/artex + fi + ok "编译完成 → ./artex" + warn "请重启正在运行的 artex 进程以生效(重启时会自动迁移 schema)" +} + +echo "==============================" +echo " ARTEX 更新" +echo " 1) Docker 更新(拉新镜像重建)" +echo " 2) 本地更新(go 重新编译)" +echo "==============================" +case "$(ask '选择' 1)" in + 1) sync_repo; update_docker ;; + 2) sync_repo; update_local ;; + *) die "无效选择" ;; +esac