Skip to content

Commit 75d749f

Browse files
committed
chore: add backup and deployment scripts
1 parent df1221e commit 75d749f

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ manifest.json
1414

1515
# FS
1616
.state
17+
.backups
1718
logs
1819
/data/*
1920
!/data/.gitkeep
2021

2122
.env
22-
devOnly/
23+
localOnly/
2324
.vscode

tools/sovereign-backup.mjs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/**
2+
* Minimal Sovereign backup
3+
* - Picks: /data/* and /platform/.env (relative to repo root)
4+
* - Writes: /.backups/sv_<YYYYMMDD-HHMMSS>.tar.gz
5+
*
6+
* Usage:
7+
* node tools/backup.mjs
8+
* # or (with shebang)
9+
* ./tools/backup.mjs
10+
*/
11+
12+
import { promises as fs } from "fs";
13+
import path from "path";
14+
import { fileURLToPath } from "url";
15+
import { spawn } from "child_process";
16+
17+
const __filename = fileURLToPath(import.meta.url);
18+
const __dirname = path.dirname(__filename);
19+
const ROOT = path.resolve(__dirname, ".."); // repo root (tools/..)
20+
21+
const DATA_DIR = path.join(ROOT, "data");
22+
const ENV_FILE = path.join(ROOT, "platform", ".env");
23+
const MANIFEST_FILE = path.join(ROOT, "manifest.json");
24+
const BACKUP_DIR = path.join(ROOT, ".backups");
25+
26+
function tsNow() {
27+
const d = new Date();
28+
const pad = (n) => String(n).padStart(2, "0");
29+
const y = d.getFullYear();
30+
const m = pad(d.getMonth() + 1);
31+
const day = pad(d.getDate());
32+
const h = pad(d.getHours());
33+
const min = pad(d.getMinutes());
34+
const s = pad(d.getSeconds());
35+
return `${y}${m}${day}-${h}${min}${s}`;
36+
}
37+
38+
async function exists(p, type = "any") {
39+
try {
40+
const st = await fs.stat(p);
41+
if (type === "dir") return st.isDirectory();
42+
if (type === "file") return st.isFile();
43+
return true;
44+
} catch {
45+
return false;
46+
}
47+
}
48+
49+
function log(msg) {
50+
console.log(`[backup] ${msg}`);
51+
}
52+
53+
async function ensureDir(p) {
54+
await fs.mkdir(p, { recursive: true });
55+
}
56+
57+
function run(cmd, args, opts = {}) {
58+
return new Promise((resolve, reject) => {
59+
const child = spawn(cmd, args, { stdio: "inherit", ...opts });
60+
child.on("close", (code) => {
61+
if (code === 0) return resolve();
62+
reject(new Error(`${cmd} ${args.join(" ")} exited with ${code}`));
63+
});
64+
});
65+
}
66+
67+
async function main() {
68+
await ensureDir(BACKUP_DIR);
69+
70+
// Make sure there's something to back up
71+
const hasData = await exists(DATA_DIR, "dir");
72+
const hasEnv = await exists(ENV_FILE, "file");
73+
const hasManifest = await exists(MANIFEST_FILE, "file");
74+
75+
if (!hasData && !hasEnv && !hasManifest) {
76+
throw new Error(
77+
`Nothing to back up. Expected at least one of:\n - ${DATA_DIR}\n - ${ENV_FILE}\n - ${MANIFEST_FILE}`
78+
);
79+
}
80+
81+
const stamp = tsNow();
82+
const outFile = path.join(BACKUP_DIR, `sv_${stamp}.tar.gz`);
83+
84+
// Build item list relative to ROOT and use -C ROOT so paths in archive are tidy
85+
const items = [];
86+
if (hasData) items.push("data");
87+
if (hasEnv) items.push("platform/.env");
88+
if (hasManifest) items.push("manifest.json");
89+
90+
log(`Creating archive: ${outFile}`);
91+
log(
92+
`Including: ${items.map((i) => (i === "manifest.json" ? "/manifest.json" : i === "platform/.env" ? "/platform/.env" : "/" + i)).join(", ")}`
93+
);
94+
95+
// tar -czf <out> -C <ROOT> <items...>
96+
await run("tar", ["-czf", outFile, "-C", ROOT, ...items]);
97+
98+
log("Done.");
99+
console.log(outFile);
100+
}
101+
102+
main().catch((e) => {
103+
console.error(e.message || e);
104+
process.exit(1);
105+
});

tools/sovereign-deploy.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
sudo -u sovereign bash -lc '
2+
set -euo pipefail
3+
cd /srv/sovereign
4+
git fetch --all --prune
5+
git checkout main
6+
git pull --ff-only
7+
corepack enable || true
8+
corepack prepare yarn@stable --activate || true
9+
yarn install --frozen-lockfile || yarn install
10+
yarn build
11+
yarn prisma migrate deploy
12+
'
13+
pm2 reload sovereign

0 commit comments

Comments
 (0)