mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-16 08:00:29 +02:00
Add files via upload
This commit is contained in:
@@ -174,10 +174,20 @@ go build -o cyberstrike-ai cmd/server/main.go
|
|||||||
|
|
||||||
### Version Update (No Breaking Changes)
|
### Version Update (No Breaking Changes)
|
||||||
|
|
||||||
**CyberStrikeAI version update (when there are no compatibility changes):**
|
**CyberStrikeAI one-click upgrade (recommended):**
|
||||||
1. Download the latest source code.
|
1. (First time) enable the script: `chmod +x upgrade.sh`
|
||||||
2. Copy the old project's `/data` folder and `config.yaml` file into the new source directory.
|
2. Upgrade with: `./upgrade.sh` (optional flags: `--tag vX.Y.Z`, `--no-venv`, `--preserve-custom`, `--yes`)
|
||||||
3. Restart with: `chmod +x run.sh && ./run.sh`
|
3. The script will back up your `config.yaml` and `data/`, upgrade the code from GitHub Release, update `config.yaml`'s `version`, then restart the server.
|
||||||
|
|
||||||
|
Recommended one-liner:
|
||||||
|
`chmod +x upgrade.sh && ./upgrade.sh --yes`
|
||||||
|
|
||||||
|
If something goes wrong, you can restore from `.upgrade-backup/` (or manually copy `/data` and `config.yaml` back) and run `./run.sh` again.
|
||||||
|
|
||||||
|
Requirements / tips:
|
||||||
|
* You need `curl` or `wget` for downloading Release packages.
|
||||||
|
* `rsync` is recommended/required for the safe code sync.
|
||||||
|
* If GitHub API rate-limits you, set `export GITHUB_TOKEN="..."` before running `./upgrade.sh`.
|
||||||
|
|
||||||
⚠️ **Note:** This procedure only applies to version updates without compatibility or breaking changes. If a release includes compatibility changes, this method may not apply.
|
⚠️ **Note:** This procedure only applies to version updates without compatibility or breaking changes. If a release includes compatibility changes, this method may not apply.
|
||||||
|
|
||||||
|
|||||||
+13
-3
@@ -173,9 +173,19 @@ go build -o cyberstrike-ai cmd/server/main.go
|
|||||||
|
|
||||||
### CyberStrikeAI 版本更新(无兼容性问题)
|
### CyberStrikeAI 版本更新(无兼容性问题)
|
||||||
|
|
||||||
1. 下载最新源代码;
|
1. (首次使用)启用脚本:`chmod +x upgrade.sh`
|
||||||
2. 将旧项目的 `/data` 文件夹、`config.yaml` 文件复制至新版源代码目录;
|
2. 一键升级:`./upgrade.sh`(可选参数:`--tag vX.Y.Z`、`--no-venv`、`--preserve-custom`、`--yes`)
|
||||||
3. 执行命令重启:`chmod +x run.sh && ./run.sh`
|
3. 脚本会备份你的 `config.yaml` 和 `data/`,从 GitHub Release 升级代码,更新 `config.yaml` 的 `version` 字段后重启服务。
|
||||||
|
|
||||||
|
推荐的一键指令:
|
||||||
|
`chmod +x upgrade.sh && ./upgrade.sh --yes`
|
||||||
|
|
||||||
|
如果升级失败,可以从 `.upgrade-backup/` 恢复,或按旧方式手动拷贝 `/data` 和 `config.yaml` 后再运行 `./run.sh`。
|
||||||
|
|
||||||
|
依赖/提示:
|
||||||
|
* 需要 `curl` 或 `wget` 用于下载 GitHub Release 包。
|
||||||
|
* 建议/需要 `rsync` 用于安全同步代码。
|
||||||
|
* 如果遇到 GitHub API 限流,运行前设置 `export GITHUB_TOKEN="..."` 再执行 `./upgrade.sh`。
|
||||||
|
|
||||||
⚠️ **注意:** 仅适用于无兼容性变更的版本更新。若版本存在兼容性调整,此方法不适用。
|
⚠️ **注意:** 仅适用于无兼容性变更的版本更新。若版本存在兼容性调整,此方法不适用。
|
||||||
|
|
||||||
|
|||||||
+397
@@ -0,0 +1,397 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# CyberStrikeAI GitHub one-click upgrade script (Release/Tag)
|
||||||
|
#
|
||||||
|
# Default preserves:
|
||||||
|
# - config.yaml
|
||||||
|
# - data/
|
||||||
|
# - venv/ (disabled with --no-venv)
|
||||||
|
#
|
||||||
|
# Optional preserves (may overwrite upstream updates):
|
||||||
|
# - roles/
|
||||||
|
# - skills/
|
||||||
|
# - tools/
|
||||||
|
# Enable with --preserve-custom
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
BINARY_NAME="cyberstrike-ai"
|
||||||
|
CONFIG_FILE="$ROOT_DIR/config.yaml"
|
||||||
|
DATA_DIR="$ROOT_DIR/data"
|
||||||
|
VENV_DIR="$ROOT_DIR/venv"
|
||||||
|
KNOWLEDGE_BASE_DIR="$ROOT_DIR/knowledge_base"
|
||||||
|
|
||||||
|
BACKUP_BASE_DIR="$ROOT_DIR/.upgrade-backup"
|
||||||
|
|
||||||
|
GITHUB_REPO="Ed1s0nZ/CyberStrikeAI"
|
||||||
|
|
||||||
|
TAG=""
|
||||||
|
PRESERVE_CUSTOM=0
|
||||||
|
PRESERVE_VENV=1
|
||||||
|
STOP_SERVICE=1
|
||||||
|
FORCE_STOP=0
|
||||||
|
YES=0
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage:
|
||||||
|
./upgrade.sh [--tag vX.Y.Z] [--preserve-custom] [--no-venv] [--no-stop]
|
||||||
|
[--force-stop] [--yes]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--tag <tag> Specify GitHub Release tag (e.g. v1.3.28).
|
||||||
|
If omitted, the script uses the latest release.
|
||||||
|
--preserve-custom Preserve roles/skills/tools (may overwrite upstream files).
|
||||||
|
Use with caution.
|
||||||
|
--no-venv Do not preserve venv/ (Python deps will be re-installed).
|
||||||
|
--no-stop Do not try to stop the running service.
|
||||||
|
--force-stop If no process matching current directory is found, also stop
|
||||||
|
any cyberstrike-ai processes (use with caution).
|
||||||
|
--yes Do not ask for confirmation.
|
||||||
|
|
||||||
|
Description:
|
||||||
|
The script backs up config.yaml/data/ (and optionally venv/roles/skills/tools) to
|
||||||
|
.upgrade-backup/
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
log() { printf "%s\n" "$*"; }
|
||||||
|
info() { log "[INFO] $*"; }
|
||||||
|
warn() { log "[WARN] $*"; }
|
||||||
|
err() { log "[ERROR] $*"; }
|
||||||
|
|
||||||
|
have_cmd() { command -v "$1" >/dev/null 2>&1; }
|
||||||
|
|
||||||
|
http_get() {
|
||||||
|
# $1: url
|
||||||
|
if have_cmd curl; then
|
||||||
|
# If GITHUB_TOKEN is provided, use it for api.github.com to avoid low rate limits.
|
||||||
|
if [[ -n "${GITHUB_TOKEN:-}" && "$1" == https://api.github.com/* ]]; then
|
||||||
|
curl -fsSL -H "Authorization: Bearer ${GITHUB_TOKEN}" "$1"
|
||||||
|
else
|
||||||
|
curl -fsSL "$1"
|
||||||
|
fi
|
||||||
|
elif have_cmd wget; then
|
||||||
|
wget -qO- "$1"
|
||||||
|
else
|
||||||
|
err "curl or wget is required to download GitHub releases. Please install one of them."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_service() {
|
||||||
|
# Try to stop the service that is running from the current project directory.
|
||||||
|
# If nothing is found and --force-stop is enabled, stop all cyberstrike-ai processes.
|
||||||
|
if [[ "$STOP_SERVICE" -ne 1 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local pids=""
|
||||||
|
if have_cmd pgrep; then
|
||||||
|
# Prefer matches where the command line contains the current project path.
|
||||||
|
pids="$(pgrep -f "${ROOT_DIR}.*${BINARY_NAME}" || true)"
|
||||||
|
if [[ -z "$pids" && "$FORCE_STOP" -eq 1 ]]; then
|
||||||
|
warn "No ${BINARY_NAME} process found under the current directory. Will try to force-stop all matching ${BINARY_NAME} processes."
|
||||||
|
pids="$(pgrep -f "${BINARY_NAME}" || true)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$pids" ]]; then
|
||||||
|
info "No ${BINARY_NAME} process detected (or no matching process). Skipping stop step."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
warn "Detected running PID(s): ${pids}"
|
||||||
|
for pid in $pids; do
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
info "Sending SIGTERM to PID=${pid}..."
|
||||||
|
kill -TERM "$pid" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Wait for exit
|
||||||
|
local deadline=$((SECONDS + 20))
|
||||||
|
while [[ $SECONDS -lt $deadline ]]; do
|
||||||
|
local alive=0
|
||||||
|
for pid in $pids; do
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
alive=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ "$alive" -eq 0 ]]; then
|
||||||
|
info "Service stopped."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
warn "Timed out waiting for processes to exit. Still running PID(s): ${pids} (may still hold file handles)."
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
backup_dir_tgz() {
|
||||||
|
# $1: label, $2: path
|
||||||
|
local label="$1"
|
||||||
|
local path="$2"
|
||||||
|
if [[ -e "$path" ]]; then
|
||||||
|
info "Backing up ${label} -> ${BACKUP_BASE_DIR}/$(basename "$path").tgz"
|
||||||
|
tar -czf "${BACKUP_BASE_DIR}/$(basename "$path").tgz" -C "$ROOT_DIR" "$(basename "$path")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
backup_config() {
|
||||||
|
if [[ -f "$CONFIG_FILE" ]]; then
|
||||||
|
cp -a "$CONFIG_FILE" "${BACKUP_BASE_DIR}/config.yaml"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_git_style_env() {
|
||||||
|
# No hard requirement; just a sanity check.
|
||||||
|
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||||
|
err "Could not find ${CONFIG_FILE}. Please verify you are in the correct project directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm_or_exit() {
|
||||||
|
if [[ "$YES" -eq 1 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -t 0 ]]; then
|
||||||
|
err "Non-interactive terminal detected. Please add --yes to continue."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
warn "About to perform upgrade:"
|
||||||
|
info " - Preserve config.yaml: yes"
|
||||||
|
info " - Preserve data/: yes"
|
||||||
|
if [[ "$PRESERVE_VENV" -eq 1 ]]; then
|
||||||
|
info " - Preserve venv/: yes"
|
||||||
|
else
|
||||||
|
info " - Preserve venv/: no (will remove old venv and re-install deps)"
|
||||||
|
fi
|
||||||
|
if [[ "$PRESERVE_CUSTOM" -eq 1 ]]; then
|
||||||
|
info " - Preserve roles/skills/tools: yes (may overwrite upstream updates)"
|
||||||
|
else
|
||||||
|
info " - Preserve roles/skills/tools: no (will use upstream versions)"
|
||||||
|
fi
|
||||||
|
info " - Stop service: ${STOP_SERVICE}"
|
||||||
|
echo ""
|
||||||
|
read -r -p "Continue? (y/N) " ans
|
||||||
|
if [[ "${ans:-N}" != "y" && "${ans:-N}" != "Y" ]]; then
|
||||||
|
err "Cancelled."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_tag() {
|
||||||
|
if [[ -n "$TAG" ]]; then
|
||||||
|
info "Using specified tag: $TAG"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local api_url="https://api.github.com/repos/${GITHUB_REPO}/releases/latest"
|
||||||
|
info "Fetching latest Release..."
|
||||||
|
local json
|
||||||
|
json="$(http_get "$api_url")"
|
||||||
|
TAG="$(printf '%s' "$json" | python3 - <<'PY'
|
||||||
|
import json, sys
|
||||||
|
data=json.loads(sys.stdin.read() or "{}")
|
||||||
|
print(data.get("tag_name",""))
|
||||||
|
PY
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [[ -z "$TAG" ]]; then
|
||||||
|
local msg
|
||||||
|
msg="$(printf '%s' "$json" | python3 -c "import sys,json; d=json.loads(sys.stdin.read() or '{}'); print(d.get('message',''))" 2>/dev/null || true)"
|
||||||
|
if [[ -n "$msg" ]]; then
|
||||||
|
err "Failed to fetch latest tag: ${msg}"
|
||||||
|
else
|
||||||
|
err "Failed to fetch latest tag. Please try using --tag to specify the version."
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
info "Latest Release tag: $TAG"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_config_version() {
|
||||||
|
# Replace config.yaml's version: ... with the specified tag.
|
||||||
|
local new_tag="$1"
|
||||||
|
python3 - "$CONFIG_FILE" "$new_tag" <<PY
|
||||||
|
import re, sys
|
||||||
|
path=sys.argv[1]
|
||||||
|
tag=sys.argv[2]
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
lines=f.readlines()
|
||||||
|
|
||||||
|
out=[]
|
||||||
|
replaced=False
|
||||||
|
for line in lines:
|
||||||
|
if re.match(r'^\s*version\s*:', line):
|
||||||
|
out.append(f'version: "{tag}"\\n')
|
||||||
|
replaced=True
|
||||||
|
else:
|
||||||
|
out.append(line)
|
||||||
|
|
||||||
|
if not replaced:
|
||||||
|
# If no version field is found, insert at the beginning (near the top).
|
||||||
|
out.insert(0, f'version: "{tag}"\\n')
|
||||||
|
|
||||||
|
with open(path, "w", encoding="utf-8") as f:
|
||||||
|
f.writelines(out)
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_code() {
|
||||||
|
local tmp_dir="$1"
|
||||||
|
local new_src_dir="$2"
|
||||||
|
|
||||||
|
# rsync sync: overwrite files from the new version and delete removed files.
|
||||||
|
# Preserve user data/config (and optional directories).
|
||||||
|
|
||||||
|
if ! have_cmd rsync; then
|
||||||
|
err "rsync not found. This script depends on rsync for safe synchronization. Please install it and retry."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -a rsync_excludes
|
||||||
|
rsync_excludes+=( "--exclude=.upgrade-backup/" )
|
||||||
|
rsync_excludes+=( "--exclude=config.yaml" )
|
||||||
|
rsync_excludes+=( "--exclude=data/" )
|
||||||
|
|
||||||
|
if [[ "$PRESERVE_VENV" -eq 1 ]]; then
|
||||||
|
rsync_excludes+=( "--exclude=venv/" )
|
||||||
|
fi
|
||||||
|
|
||||||
|
# knowledge_base may not be referenced in config, but many users treat it as the knowledge files directory.
|
||||||
|
if [[ -d "$KNOWLEDGE_BASE_DIR" ]]; then
|
||||||
|
rsync_excludes+=( "--exclude=knowledge_base/" )
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$PRESERVE_CUSTOM" -eq 1 ]]; then
|
||||||
|
rsync_excludes+=( "--exclude=roles/" )
|
||||||
|
rsync_excludes+=( "--exclude=skills/" )
|
||||||
|
rsync_excludes+=( "--exclude=tools/" )
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure this upgrade script itself is not deleted.
|
||||||
|
rsync_excludes+=( "--exclude=upgrade.sh" )
|
||||||
|
|
||||||
|
# shellcheck disable=SC2068
|
||||||
|
info "Syncing code into current directory (preserving data/config; using rsync --delete)..."
|
||||||
|
rsync -a --delete \
|
||||||
|
${rsync_excludes[@]} \
|
||||||
|
"${new_src_dir}/" "${ROOT_DIR}/"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
ensure_git_style_env
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--tag)
|
||||||
|
TAG="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--preserve-custom)
|
||||||
|
PRESERVE_CUSTOM=1
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
--no-venv)
|
||||||
|
PRESERVE_VENV=0
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
--no-stop)
|
||||||
|
STOP_SERVICE=0
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
--force-stop)
|
||||||
|
FORCE_STOP=1
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
--yes)
|
||||||
|
YES=1
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
err "Unknown parameter: $1"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
confirm_or_exit
|
||||||
|
|
||||||
|
stop_service
|
||||||
|
|
||||||
|
resolve_tag
|
||||||
|
|
||||||
|
local ts
|
||||||
|
ts="$(date +"%Y%m%d_%H%M%S")"
|
||||||
|
BACKUP_BASE_DIR="${BACKUP_BASE_DIR}/${ts}"
|
||||||
|
mkdir -p "$BACKUP_BASE_DIR"
|
||||||
|
|
||||||
|
info "Starting backup into: $BACKUP_BASE_DIR"
|
||||||
|
backup_config
|
||||||
|
backup_dir_tgz "data" "$DATA_DIR"
|
||||||
|
if [[ "$PRESERVE_VENV" -eq 1 ]]; then
|
||||||
|
backup_dir_tgz "venv" "$VENV_DIR"
|
||||||
|
else
|
||||||
|
if [[ -d "$VENV_DIR" ]]; then
|
||||||
|
warn "With --no-venv: removing old venv/ (run.sh will re-install Python deps after upgrade)."
|
||||||
|
rm -rf "$VENV_DIR"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -d "$KNOWLEDGE_BASE_DIR" ]]; then
|
||||||
|
backup_dir_tgz "knowledge_base" "$KNOWLEDGE_BASE_DIR"
|
||||||
|
fi
|
||||||
|
if [[ "$PRESERVE_CUSTOM" -eq 1 ]]; then
|
||||||
|
backup_dir_tgz "roles" "$ROOT_DIR/roles"
|
||||||
|
backup_dir_tgz "skills" "$ROOT_DIR/skills"
|
||||||
|
backup_dir_tgz "tools" "$ROOT_DIR/tools"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local tmp_dir
|
||||||
|
tmp_dir="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$tmp_dir" >/dev/null 2>&1 || true' EXIT
|
||||||
|
|
||||||
|
local tarball="${tmp_dir}/source.tar.gz"
|
||||||
|
local url="https://github.com/${GITHUB_REPO}/archive/refs/tags/${TAG}.tar.gz"
|
||||||
|
info "Downloading source package: ${url}"
|
||||||
|
http_get "$url" >"$tarball"
|
||||||
|
|
||||||
|
info "Extracting source package..."
|
||||||
|
tar -xzf "$tarball" -C "$tmp_dir"
|
||||||
|
|
||||||
|
# GitHub tarball usually creates a top-level directory.
|
||||||
|
local extracted_dir
|
||||||
|
extracted_dir="$(ls -d "${tmp_dir}"/*/ 2>/dev/null | head -n 1 || true)"
|
||||||
|
if [[ -z "$extracted_dir" || ! -f "${extracted_dir}/run.sh" ]]; then
|
||||||
|
err "run.sh not found in the extracted directory. Please check network/download contents."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sync_code "$tmp_dir" "$extracted_dir"
|
||||||
|
|
||||||
|
# Update config.yaml version display
|
||||||
|
if [[ -f "$CONFIG_FILE" ]]; then
|
||||||
|
info "Updating config.yaml version field to: $TAG"
|
||||||
|
update_config_version "$TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Upgrade complete. Starting service..."
|
||||||
|
chmod +x ./run.sh
|
||||||
|
./run.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
||||||
Reference in New Issue
Block a user