Files
OmniRoute/bin/rollback.sh
Diego Rodrigues de Sa e Souza 5ac4637816 docs: reorganize docs/ + accuracy audit + drop Node 20 (rebased onto current release tip) (#5262)
* docs: move superpowers/research artifacts to isolated _tasks repo + docs tree cleanup

- Move docs/superpowers/{plans,specs} and docs/research/* into the gitignored,
  separately-versioned _tasks/ repo; untrack the two tracked research design docs.
- Add CLAUDE.md "Planning & Research Artifacts" section overriding the superpowers
  default save paths (docs/... -> _tasks/...); align REPOSITORY_MAP and
  DOCUMENTATION_OVERHAUL_PLAN with the new convention.
- Drop 4 now-obsolete /api/discovery/* entries from check-docs-symbols allowlist
  (stale-enforcement) and refresh code/spec path comments to _tasks/...
- Sweeps in concurrent docs-tree restructuring (root-level provider/guide docs,
  compression spec cleanup, .mcp.json.example removal).

* docs: reorganize docs/ tree + fix stale facts across ~26 docs

Phase A — reorganization:
- Move 7 orphan root docs into subfolders (providers/ created; TIERS+USAGE_QUOTA→guides/;
  plugins+PLUGIN_SDK→frameworks/); delete 8 obsolete/redundant docs (SUBMIT_PR superseded
  by CONTRIBUTING; DOCUMENTATION_OVERHAUL_PLAN; INCIDENT_RESPONSE/PERF_BUDGETS/THREAT_MODEL;
  3 ops snapshots). Rebuild README index (was missing ~40 files) + per-folder meta.json nav.
- Clean 14 dangling doc-path references in bin/ ops scripts, scripts/, workflow, tests;
  fix the dockerignore-docs-coverage required-docs path (PROVIDERS→providers/CLAUDE_WEB).

Phase B — content accuracy (verified against code, not the audit summary):
- Functional: ENVIRONMENT flag defaults (INPUT_SANITIZER/MCP_ENFORCE_SCOPES=true,
  COMPRESS_DESCRIPTIONS=false, dynamic heap); MCP-SERVER notion tool names (omniroute_*→
  notion_*) + counts 87→94; coverage gate 75/70→60/60/60/60 (RELEASE_CHECKLIST, COVERAGE_PLAN,
  ERROR_SANITIZATION, CONTRIBUTING); pre-push hook description; regenerate PROVIDER_REFERENCE (237).
- Count drift: providers 237, executors 70, migrations 106, db modules 94, oauth 19,
  strategies 17, MCP 94, flags 38, TS 6.0, open-sse ~900/services 294 across architecture/
  frameworks/ops docs; AUTO-COMBO 9→12 factors w/ correct DEFAULT_WEIGHTS; REASONING +2
  patterns; STEALTH UA defaults; AGENT_PROTOCOLS +cursor-cloud/list-capabilities;
  LANGUAGE_PACKS +id pack.
- Kept Node 20 (runtime guard accepts 20.20.2+; only engines is stricter) and MCP scopes=13
  (mcpScopes.ts) — both were correct in the docs; corrected only the attribution.

* docs: finish content refresh — compression engines, CLI_TOKEN merge, metadata sweep

- Compression: document the additional built-in engines (CCR, headroom, ionizer,
  session-dedup) in COMPRESSION_ENGINES; clarify LLMLingua-2 is the ultra-mode SLM
  backend + cross-ref the extra engines in EXTENDING_COMPRESSION; add the id
  (Indonesian) language pack to LANGUAGE_PACKS.
- AUTO-COMBO: replace the orphan 'How tiers fit' weight table (stale weights) with a
  pointer to the canonical 12-factor DEFAULT_WEIGHTS table.
- Security: merge CLI_TOKEN_AUTH.md (legacy 32-char SHA-256 format) into CLI_TOKEN.md
  as a 'Legacy format — still accepted' section (server accepts both HMAC + legacy),
  delete CLI_TOKEN_AUTH.md, drop it from the index + security nav.
- Metadata: bump stale frontmatter (version/lastUpdated) to 3.8.40/2026-06-28 across the
  doc set audited this pass, and normalize the in-body 'Last updated' header lines to match.

* fix(runtime): drop Node 20 from supported range + align all docs/diagrams/counts

- Node minimum is now 22 (aligned with package.json engines). SUPPORTED_NODE_RANGE in
  src/shared/utils/nodeRuntimeSupport.ts (and the bin/ mirror) drops the 20.x line →
  '>=22.22.2 <23 || >=24.0.0 <27'; getNodeRuntimeSupport now rejects Node 20 as
  unsupported-major. Test updated (TDD): node-runtime-support.test.ts asserts Node 20
  rejected. Docs aligned (TROUBLESHOOTING ×2, TERMUX, RELEASE_CHECKLIST, CODEBASE,
  CLI-TOOLS, README, llm.txt + 42 i18n llm.txt mirrors, skills/cli-serve).
- Diagrams regenerated: mcp-tools-87 -> mcp-tools-94 (34 base + pool 6 = 94) and
  auto-combo-9factor -> auto-combo-12factor (correct DEFAULT_WEIGHTS); SVGs re-rendered
  via mermaid-cli; doc refs + diagrams/README updated; fixed a pre-existing broken
  resilience-3layers image path.
- CLAUDE.md + AGENTS.md aligned to real counts (237 providers, 94 MCP tools / 34 base,
  106 migrations, 94 db modules, 12-factor auto-combo, 17 strategies); README provider
  count 231 -> 237; executor count corrected to 68 (provider executors, excl base/index)
  and OAuth to 18 across architecture docs. check:docs-all now passes (0 strict drift,
  0 broken links); removed dead .mcp.json.example doc link.

* fix(services): update installer Node hint to >=22.22.2 (aligned with dropped Node 20)

* docs: realign counts to current release tip after rebase

The release tip advanced while this work was in flight (Gemini CLI provider/executor
removed by #5246, plus other PRs). Re-counted against the current code and updated:
providers 237->236, executors 68->67, OAuth modules 18->17, open-sse services 294->298;
regenerated PROVIDER_REFERENCE.md (236). check:docs-all passes (0 strict drift).

* docs(changelog) + i18n: record Node 20 drop + fix nodeIncompatibleHint

- CHANGELOG: add [3.8.40] entries for the Node 20.x removal (runtime) and the docs
  reorganization/accuracy audit.
- i18n: nodeIncompatibleHint across all 42 locales no longer lists Node 20.x as
  supported (ASCII + CJK full-width variants), aligned with the dropped Node 20.

* fix(docs): repair CI breakages from the doc moves

- test: cli-plugin-system asserted docs/dev/plugins.md exists; the file moved to
  docs/frameworks/PLUGINS.md — point the test at the new path (Unit fast-path 2/2 fix).
- frontmatter: PLUGINS.md and PLUGIN_SDK.md moved into the fumadocs-indexed
  docs/frameworks/ which requires a 'title' frontmatter; the missing frontmatter
  failed the Next.js MDX build (dast-smoke 'invalid frontmatter'). Added frontmatter
  to both, plus the providers/ docs (consistency; that folder is not indexed).
2026-06-28 22:07:18 -03:00

103 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# bin/rollback.sh — roll OmniRoute back to a previous release to mitigate a bad
# deploy. Part of the deploy-rollback incident-recovery flow.
#
# Methods (auto-detected; override with --method):
# • npm — `npm install -g omniroute@<version>` and, if PM2 manages it,
# `pm2 restart omniroute`. This is how the VPS deploy runs.
# • docker — re-tag the local image omniroute:<version> to omniroute:prod and
# recreate the prod service from docker-compose.prod.yml. (That
# compose builds the `prod` tag locally rather than pulling a
# registry tag, so the versioned image must already exist locally.)
# With no <version>, targets the highest published release strictly below the
# current package.json version.
set -euo pipefail
SCRIPT_NAME="rollback"
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/_ops-common.sh"
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
usage() {
cat <<'EOF'
Usage: bin/rollback.sh [<version>] [--method npm|docker] [--yes|-y] [-h|--help]
Rolls OmniRoute back to <version> (e.g. 3.8.35 or v3.8.35). With no version,
picks the highest published release below the current package.json version.
Auto-detects npm vs docker deployment; override with --method.
EOF
}
VERSION=""
METHOD=""
while [ $# -gt 0 ]; do
case "$1" in
--yes | -y) ASSUME_YES=1; shift ;;
--method) METHOD="${2:?--method needs npm|docker}"; shift 2 ;;
-h | --help) usage; exit 0 ;;
-*) ops_die "unknown argument: $1 (see --help)" ;;
*) VERSION="${1#v}"; shift ;;
esac
done
if [ -z "$METHOD" ]; then
if command -v docker >/dev/null 2>&1 && [ -f "$REPO_ROOT/docker-compose.prod.yml" ] \
&& docker compose -f "$REPO_ROOT/docker-compose.prod.yml" ps -q 2>/dev/null | grep -q .; then
METHOD="docker"
elif command -v npm >/dev/null 2>&1; then
METHOD="npm"
else
ops_die "no deploy method detected (no running prod compose, no npm) — pass --method npm|docker"
fi
fi
# Resolve the previous published version when none was given.
if [ -z "$VERSION" ]; then
ops_require_cmd npm
ops_require_cmd node
current="$(node -p "require('$REPO_ROOT/package.json').version" 2>/dev/null || true)"
[ -n "$current" ] || ops_die "cannot read current version from package.json — pass <version>"
VERSION="$(npm view omniroute versions --json 2>/dev/null | node -e '
let s = "";
process.stdin.on("data", (d) => (s += d)).on("end", () => {
let vs;
try { vs = JSON.parse(s); } catch { vs = []; }
if (!Array.isArray(vs)) vs = [vs];
const ok = (v) => /^[0-9]+\.[0-9]+\.[0-9]+$/.test(v);
const cmp = (a, b) => {
const x = a.split(".").map(Number), y = b.split(".").map(Number);
return x[0] - y[0] || x[1] - y[1] || x[2] - y[2];
};
const cur = process.argv[1];
const prev = vs.filter(ok).filter((v) => cmp(v, cur) < 0).sort(cmp).pop() || "";
process.stdout.write(prev);
});
' "$current")"
[ -n "$VERSION" ] || ops_die "could not resolve the previous published version — pass <version> explicitly"
fi
ops_log "target: omniroute@$VERSION via $METHOD"
ops_confirm "Roll OmniRoute back to $VERSION via $METHOD?" || ops_die "aborted"
case "$METHOD" in
npm)
ops_require_cmd npm
npm install -g "omniroute@$VERSION"
if command -v pm2 >/dev/null 2>&1 && pm2 jlist 2>/dev/null | grep -q '"name":"omniroute"'; then
pm2 restart omniroute --update-env
ops_log "pm2 restarted omniroute"
else
ops_log "installed omniroute@$VERSION — restart the service to apply (no PM2 'omniroute' process found)"
fi
;;
docker)
ops_require_cmd docker
if ! docker image inspect "omniroute:$VERSION" >/dev/null 2>&1; then
ops_die "local image omniroute:$VERSION not found — build it from the $VERSION checkout first (this compose builds the 'prod' tag, it does not pull a registry tag)"
fi
docker tag "omniroute:$VERSION" omniroute:prod
docker compose -f "$REPO_ROOT/docker-compose.prod.yml" up -d --no-build
ops_log "recreated prod service from omniroute:$VERSION"
;;
*) ops_die "unknown method: $METHOD (use npm or docker)" ;;
esac
ops_log "rollback to $VERSION complete"