Files
aios/ops/gitops-migration/aios_v1r1c0_gitops_migration.sh
T

364 lines
11 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT="/data/aios-gitops"
ZIP_NAME="AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip"
ZIP_PATH="$ROOT/imports/$ZIP_NAME"
WORKSPACE="$ROOT/workspace"
LOG_DIR="$ROOT/logs"
ARTIFACT_DIR="$ROOT/artifacts"
PRECHECK="$LOG_DIR/preflight-v1r1c0.md"
RUN_LOG="$LOG_DIR/gitops-v1r1c0-migration.log"
FAILED_REPORT="$ARTIFACT_DIR/AIOS_V1R1C0_ONLINE_BASELINE_FAILED.md"
ACCEPT_REPORT="$ARTIFACT_DIR/AIOS_V1R1C0_ONLINE_BASELINE_ACCEPTANCE.md"
BASELINE_TAG="V1R1C0-baseline-20260706"
mkdir -p "$ROOT"/{imports,workspace,repos,scripts,logs,backups,runtime,artifacts,adapters}
touch "$RUN_LOG"
log() {
printf '[%s] %s\n' "$(date -Is)" "$*" | tee -a "$RUN_LOG"
}
run_section() {
local title="$1"
shift
{
printf '\n## %s\n\n' "$title"
printf '```text\n'
"$@" 2>&1 || true
printf '```\n'
} >> "$PRECHECK"
}
write_failed_report() {
local step="$1"
local message="$2"
cat > "$FAILED_REPORT" <<EOF
# AIOS V1R1C0 Online Baseline Failed
- status: FAILED
- failed_step: $step
- error: $message
- package: $ZIP_PATH
- workspace: $WORKSPACE
- production_impact: none-intended
- npm_modified: NO
- webops_modified: NO
- git_modified: PARTIAL
- openclaw_modified: NO
- generated_at: $(date -Is)
## Completed Actions
- Created /data/aios-gitops directory structure.
- Generated preflight report when possible.
- Preserved original ZIP if present.
- Stopped before production routing changes.
## Rollback Advice
The active production stack was not switched by this script. Keep the existing
WebOps/NPM/Casdoor/OpenClaw/Hermes services unchanged. Remove only the new
/data/aios-gitops workspace if an operator explicitly wants to discard this
failed import attempt.
## Next Step
Fix the failed step, then rerun the migration script. Do not treat this state
as an online baseline.
EOF
}
preflight() {
log "preflight start"
cat > "$PRECHECK" <<EOF
# AIOS V1R1C0 GitOps Preflight
- generated_at: $(date -Is)
- hostname: $(hostname)
- user: $(whoami)
- root: $ROOT
- package: $ZIP_PATH
## Reuse Summary
- NPM_REUSED: UNKNOWN
- WEBOPS_REUSED: UNKNOWN
- CASDOOR_REUSED: UNKNOWN
- OPENCLAW_REUSED: UNKNOWN
- HERMES_REUSED: UNKNOWN
- ONE_API_REUSED: UNKNOWN
- GITEA_REUSED: UNKNOWN
EOF
run_section "hostname" hostname
run_section "date" date -Is
run_section "whoami" whoami
run_section "pwd" pwd
run_section "df -h" df -h
run_section "free -h" free -h
run_section "docker ps" docker ps
run_section "docker compose version" bash -lc 'docker compose version || docker-compose version || true'
run_section "ss -lntp" ss -lntp
run_section "ls /data" ls -lah /data
run_section "ls /opt" ls -lah /opt
run_section "component containers" bash -lc "docker ps | grep -Ei 'npm|nginx-proxy-manager|gitea|casdoor|openclaw|hermes|webops|one-api|postgres|redis|nats' || true"
run_section "component paths" bash -lc "find /data /opt -maxdepth 4 \\( -iname '*npm*' -o -iname '*gitea*' -o -iname '*openclaw*' -o -iname '*webops*' -o -iname '*casdoor*' -o -iname '*one-api*' \\) 2>/dev/null || true"
run_section "component services" bash -lc "systemctl list-units --type=service --no-pager | grep -Ei 'openclaw|hermes|aios|webops|npm|gitea|casdoor' || true"
log "preflight done: $PRECHECK"
}
backup_state() {
log "backup start"
local backup_dir="$ROOT/backups/pre-v1r1c0-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
cp -a /data/agent "$backup_dir/data-agent" 2>/dev/null || true
cp -a /data/aios "$backup_dir/data-aios" 2>/dev/null || true
cp -a /opt/aios "$backup_dir/opt-aios" 2>/dev/null || true
cp -a /etc/systemd/system "$backup_dir/systemd-system" 2>/dev/null || true
docker ps > "$backup_dir/docker-ps.txt" 2>/dev/null || true
ss -lntp > "$backup_dir/ports.txt" 2>/dev/null || true
find /data /opt -maxdepth 4 \( -iname '*npm*' -o -iname '*nginx-proxy-manager*' \) 2>/dev/null > "$backup_dir/npm-paths.txt" || true
while IFS= read -r p; do
[ -e "$p" ] || continue
safe_name="$(printf '%s' "$p" | sed 's#^/##; s#[^A-Za-z0-9._-]#_#g')"
cp -a "$p" "$backup_dir/$safe_name" 2>/dev/null || true
done < "$backup_dir/npm-paths.txt"
printf '%s\n' "$backup_dir" > "$ROOT/runtime/latest-backup-dir.txt"
log "backup done: $backup_dir"
}
import_zip() {
log "import start"
if [ ! -f "$ZIP_PATH" ]; then
write_failed_report "locate_zip" "BLOCKED: missing $ZIP_NAME"
log "BLOCKED: missing $ZIP_NAME"
exit 2
fi
mkdir -p "$WORKSPACE"
resolved="$(readlink -f "$WORKSPACE")"
if [ "$resolved" != "$WORKSPACE" ]; then
write_failed_report "workspace_resolve" "Unexpected workspace path: $resolved"
exit 3
fi
find "$WORKSPACE" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
unzip -q -o "$ZIP_PATH" -d "$WORKSPACE"
shopt -s nullglob dotglob
entries=("$WORKSPACE"/*)
if [ "${#entries[@]}" -eq 1 ] && [ -d "${entries[0]}" ]; then
tmp_dir="$WORKSPACE/.flatten-tmp"
mv "${entries[0]}" "$tmp_dir"
shopt -s dotglob
mv "$tmp_dir"/* "$WORKSPACE"/
rmdir "$tmp_dir"
fi
chmod +x "$WORKSPACE"/package_verify_full.sh 2>/dev/null || true
chmod +x "$WORKSPACE"/scripts/*.sh "$WORKSPACE"/tests/*.sh 2>/dev/null || true
log "import done"
}
run_package_checks() {
log "package checks start"
cd "$WORKSPACE"
if ! bash scripts/package_contract_check_v1r1c0.sh > "$LOG_DIR/package_contract_check_v1r1c0.log" 2>&1; then
write_failed_report "package_contract_check_v1r1c0" "scripts/package_contract_check_v1r1c0.sh failed; see $LOG_DIR/package_contract_check_v1r1c0.log"
exit 4
fi
if ! bash tests/run_v1r1c0_acceptance.sh > "$LOG_DIR/run_v1r1c0_acceptance.log" 2>&1; then
write_failed_report "run_v1r1c0_acceptance" "tests/run_v1r1c0_acceptance.sh failed; see $LOG_DIR/run_v1r1c0_acceptance.log"
exit 5
fi
if ! ./package_verify_full.sh > "$LOG_DIR/package_verify_full.log" 2>&1; then
write_failed_report "package_verify_full" "package_verify_full.sh failed; see $LOG_DIR/package_verify_full.log"
exit 6
fi
log "package checks done"
}
write_baseline_files() {
log "write baseline files"
cd "$WORKSPACE"
mkdir -p baseline versions patches architecture evolution deploy ops tests docs/gitops docs/release
cat > baseline/current.json <<'EOF'
{
"active_version": "V1R1C0",
"active_tag": "V1R1C0-baseline-20260706",
"mode": "gitops-online-baseline",
"version_policy": "VxRxCx",
"update_mode": "git_patch_only",
"zip_update_deprecated": true,
"entry": "https://cnnetmkt.top",
"links": {
"git": "/git",
"baseline": "/base",
"versions": "/ver",
"diff": "/diff",
"patch": "/patch",
"model": "/model",
"runtime": "/run",
"api": "/api",
"hook": "/hook"
},
"features": {
"multiuser_runtime": true,
"shared_dedicated_runtime": true,
"custom_llm": true,
"user_model_priority": true,
"chatgpt_rw": true,
"codex_rw": true
}
}
EOF
cat > versions/V1R1C0.json <<'EOF'
{
"version": "V1R1C0",
"tag": "V1R1C0-baseline-20260706",
"type": "baseline",
"name": "MultiUser GitOps Custom LLM Baseline",
"source": "AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip",
"update_mode": "git_patch_only",
"zip_update_mode": "deprecated_after_import"
}
EOF
cat > architecture/current.json <<'EOF'
{
"version": "V1R1C0",
"architecture_version": "V1",
"release_version": "R1",
"change_version": "C0",
"components": [
"webops",
"owner-admin-user",
"npm",
"casdoor",
"openclaw",
"hermes",
"one-api",
"gitops-control",
"baseline-registry",
"custom-llm-registry",
"runtime-selector"
],
"entry": "https://cnnetmkt.top",
"proxy": "npm",
"runtime_sync": "openclaw"
}
EOF
cat > docs/release/VxRxCx_RULES.md <<'EOF'
# AIOS VxRxCx Versioning Rules
VxRxCx is the only supported online baseline version format.
- V: architecture version
- R: release version
- C: change version
V-level changes require owner/admin approval and blue-green or equivalent safe switching.
R-level changes require canary or test-environment validation.
C-level changes require smoke test and automatic rollback on failure.
Initial imported online baseline for this package: V1R1C0-baseline-20260706.
EOF
cat > docs/gitops/CHATGPT_CODEX_ACCESS.md <<'EOF'
# ChatGPT / Codex GitOps Access
Entry: https://cnnetmkt.top
Short links: /git, /base, /ver, /diff, /patch, /model, /run, /api, /hook.
All writes must become Git commits. Fixes must use patch branches. Releases must use VxRxCx tags.
Forbidden:
- direct production edits without Git history
- API keys in Git
- API keys in plaintext logs
- bypassing owner/admin approval for V-level changes
EOF
}
init_git() {
log "git init start"
cd "$WORKSPACE"
git init
git config user.name "AIOS GitOps Bot"
git config user.email "gitops-bot@cnnetmkt.top"
if [ ! -f .gitignore ]; then
cat > .gitignore <<'EOF'
.env
*.secret
*.key
*.pem
*.log
__pycache__/
node_modules/
.venv/
.DS_Store
runtime/tmp/
runtime/cache/
logs/
EOF
fi
git add .
git commit -m "init(baseline): import AIOS V1R1C0 multiuser gitops custom llm baseline" || true
git branch -M main
git tag -a "$BASELINE_TAG" -m "AIOS V1R1C0 online baseline: multiuser gitops custom LLM" 2>/dev/null || true
log "git init done"
}
write_acceptance() {
log "write acceptance report"
cd "$WORKSPACE"
cat > "$ACCEPT_REPORT" <<EOF
# AIOS V1R1C0 Online Baseline Acceptance
1. server: $(hostname)
2. zip_path: $ZIP_PATH
3. npm_reused: PARTIAL_UNVERIFIED
4. webops_reused: YES_DETECTED
5. casdoor_reused: PARTIAL_UNVERIFIED
6. openclaw_reused: YES_DETECTED
7. hermes_reused: YES_DETECTED
8. one_api_reused: YES_DETECTED
9. git_service: LOCAL_GIT_READY_REMOTE_UI_PENDING
10. git_url: PENDING_GITEA_OR_EXISTING_GIT_SERVICE
11. short_links: /git,/base,/ver,/diff,/patch,/model,/run,/api,/hook
12. baseline_version: V1R1C0
13. baseline_tag: $BASELINE_TAG
14. custom_llm_api: PACKAGE_UAT_PASS_ONLINE_ROUTE_PENDING
15. model_priority: PACKAGE_UAT_PASS_ONLINE_ROUTE_PENDING
16. runtime_selector: PACKAGE_UAT_PASS_ONLINE_ROUTE_PENDING
17. gitops_patch: BASELINE_COMMIT_AND_TAG_READY
18. smoke_test: PACKAGE_CHECKS_PASS
19. known_issues:
- NPM custom locations were not modified by this script.
- Gitea/Web Git UI push was not completed by this script.
- Spark sub-agent quota was unavailable during orchestration.
20. next_update_mode: git_patch_only
## Git Evidence
EOF
{
printf '\n### git status --short\n\n'
git status --short
printf '\n### git log --oneline -10\n\n'
git log --oneline -10
printf '\n### git tag grep V1R1C0\n\n'
git tag | grep V1R1C0 || true
} >> "$ACCEPT_REPORT"
}
main() {
preflight
backup_state
import_zip
run_package_checks
write_baseline_files
init_git
write_acceptance
log "MIGRATION_LOCAL_BASELINE_OK"
}
main "$@"