76 lines
4.2 KiB
Bash
Executable File
76 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Dedicated local integration fixture; never uses the primary Phase 0 runtime.
|
|
set -euo pipefail
|
|
cd "$(dirname "${BASH_SOURCE[0]}")/.."
|
|
export MC_ROOT="$PWD/.tools/phase4-server"
|
|
export MC_RELEASE_DIR="$PWD/dist/minecraft-lab-neoforge-spike-0.0.4"
|
|
evidence="$PWD/.tools/phase5-evidence"
|
|
restored="$PWD/.tools/phase5-restored-server"
|
|
mkdir -p "$evidence"
|
|
if [[ -e "$restored" ]]; then
|
|
echo "Restore fixture already exists; choose a new destination before repeating." >&2
|
|
exit 1
|
|
fi
|
|
scripts/server.sh up -d --wait --wait-timeout 120
|
|
mkdir -p "$MC_ROOT/runtime/mod-state"
|
|
printf '{"phase":5,"progress":42}\n' > "$MC_ROOT/runtime/mod-state/phase5.json"
|
|
printf 'preserve-unmanaged-phase5\n' > "$MC_ROOT/runtime/config/phase5-unmanaged.txt"
|
|
./mcpack backup > "$evidence/backup.log" 2>&1
|
|
node --input-type=module <<'JS' > "$evidence/snapshot-path.txt"
|
|
import fs from 'node:fs';
|
|
const operation=JSON.parse(fs.readFileSync(process.env.MC_ROOT+'/.mcpack-backup-operation.json'));
|
|
if(operation.phase!=='complete'||!operation.snapshot)throw new Error('Backup did not complete');
|
|
console.log(operation.snapshot);
|
|
JS
|
|
snapshot=$(cat "$evidence/snapshot-path.txt")
|
|
scripts/server.sh exec -T minecraft mc-health > "$evidence/resumed-health.txt"
|
|
scripts/server.sh logs --tail 150 > "$evidence/resumed-start.log"
|
|
mkdir -p "$evidence/failure-bin"
|
|
cat > "$evidence/failure-bin/tar" <<'SH'
|
|
#!/bin/sh
|
|
echo 'intentional Phase 5 archive failure' >&2
|
|
exit 42
|
|
SH
|
|
chmod +x "$evidence/failure-bin/tar"
|
|
if PATH="$evidence/failure-bin:$PATH" ./mcpack backup > "$evidence/failed-backup.log" 2>&1; then
|
|
echo 'Invalid archive unexpectedly succeeded' >&2
|
|
exit 1
|
|
fi
|
|
node --input-type=module <<'JS' > "$evidence/failure-verification.txt"
|
|
import fs from 'node:fs';
|
|
import {execFileSync} from 'node:child_process';
|
|
const root=process.env.MC_ROOT;
|
|
const operation=JSON.parse(fs.readFileSync(root+'/.mcpack-backup-operation.json'));
|
|
if(operation.phase!=='failed'||!operation.stopped_confirmed||operation.snapshot!==null)throw new Error('Incorrect backup failure state');
|
|
const state=JSON.parse(execFileSync('docker',['inspect','minecraft-lab-phase4-minecraft-1']))[0].State;
|
|
if(state.Running)throw new Error('Failed backup unexpectedly restarted server');
|
|
const snapshots=fs.readdirSync(root+'/backups');
|
|
if(snapshots.length!==1||snapshots.some(name=>name.startsWith('.')))throw new Error('Incomplete snapshot published or left behind');
|
|
console.log('Failed backup: non-zero, server stopped, no additional snapshot, no staging directories.');
|
|
JS
|
|
scripts/server.sh down
|
|
./mcpack restore --backup "$snapshot" --destination "$restored" > "$evidence/restore.log" 2>&1
|
|
SNAPSHOT="$snapshot" RESTORED="$restored" node --input-type=module <<'JS' > "$evidence/restore-verification.txt"
|
|
import fs from 'node:fs';
|
|
import assert from 'node:assert/strict';
|
|
import {verifySnapshot,runtimeInventory} from './platform/backups.mjs';
|
|
import {verifyRelease} from './platform/runtime.mjs';
|
|
const metadata=verifySnapshot(process.env.SNAPSHOT);
|
|
assert.deepEqual(runtimeInventory(process.env.RESTORED+'/runtime'),metadata.runtime_inventory);
|
|
assert.equal(verifyRelease(process.env.RESTORED+'/release').identity,metadata.source_release.manifest_sha256);
|
|
assert.equal(fs.readFileSync(process.env.RESTORED+'/runtime/mod-state/phase5.json','utf8'),'{"phase":5,"progress":42}\n');
|
|
assert.equal(fs.readFileSync(process.env.RESTORED+'/runtime/config/phase5-unmanaged.txt','utf8'),'preserve-unmanaged-phase5\n');
|
|
assert(!fs.existsSync(process.env.RESTORED+'/.env'));
|
|
console.log(`Verified ${metadata.runtime_inventory.length} runtime entries including bytes/modes/UID/GID; retained release ${metadata.source_release.name}.`);
|
|
console.log('Mod data outside world, unmanaged config, server.properties, operators and whitelist preserved; host settings not copied.');
|
|
JS
|
|
export MC_ENV_FILE="$MC_ROOT/.env"
|
|
export MC_ROOT="$restored"
|
|
export MC_RELEASE_DIR="$restored/release"
|
|
scripts/server.sh up -d --wait --wait-timeout 120
|
|
scripts/server.sh exec -T minecraft mc-health > "$evidence/restored-health.txt"
|
|
scripts/server.sh logs --tail 150 > "$evidence/restored-start.log"
|
|
scripts/server.sh down
|
|
scripts/spike-server.sh ps > "$evidence/primary-server-status.txt"
|
|
printf 'Phase 5 backup, failure and restored server health checks passed.\n'
|