Add install-kit to repo drift checker
This commit is contained in:
Executable
+53
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
KIT_DIR="install-kit-awindows-20260427-211240"
|
||||||
|
|
||||||
|
python - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
root=Path('.')
|
||||||
|
kit=Path('install-kit-awindows-20260427-211240')
|
||||||
|
if not kit.exists():
|
||||||
|
raise SystemExit('Install kit directory not found')
|
||||||
|
|
||||||
|
def sha(path: Path) -> str:
|
||||||
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||||
|
|
||||||
|
all_compared=[]
|
||||||
|
mismatches=[]
|
||||||
|
missing_in_repo=[]
|
||||||
|
|
||||||
|
for kp in sorted(p for p in kit.rglob('*') if p.is_file() and p.name!='MANIFEST.txt'):
|
||||||
|
rel=kp.relative_to(kit)
|
||||||
|
rp=root/rel
|
||||||
|
if not rp.exists():
|
||||||
|
missing_in_repo.append(str(rel))
|
||||||
|
continue
|
||||||
|
all_compared.append(str(rel))
|
||||||
|
if sha(kp)!=sha(rp):
|
||||||
|
mismatches.append(str(rel))
|
||||||
|
|
||||||
|
ps_mismatches=[p for p in mismatches if p.startswith('windows/') and p.endswith('.ps1') or p.endswith('.psm1') or p.endswith('.psd1')]
|
||||||
|
|
||||||
|
print(f'Compared files: {len(all_compared)}')
|
||||||
|
print(f'Missing in repo: {len(missing_in_repo)}')
|
||||||
|
print(f'Mismatched content: {len(mismatches)}')
|
||||||
|
if missing_in_repo:
|
||||||
|
print('--- Missing in repo ---')
|
||||||
|
for p in missing_in_repo:
|
||||||
|
print(p)
|
||||||
|
if mismatches:
|
||||||
|
print('--- Mismatches ---')
|
||||||
|
for p in mismatches:
|
||||||
|
print(p)
|
||||||
|
print(f'PowerShell mismatches: {len(ps_mismatches)}')
|
||||||
|
if ps_mismatches:
|
||||||
|
print('--- PowerShell mismatches ---')
|
||||||
|
for p in ps_mismatches:
|
||||||
|
print(p)
|
||||||
|
PY
|
||||||
+14
-3
@@ -4,17 +4,17 @@ set -euo pipefail
|
|||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
echo "[1/3] Bash syntax check"
|
echo "[1/4] Bash syntax check"
|
||||||
find aw-server proxmox -type f -name "*.sh" -print0 | xargs -0 -r -n1 bash -n
|
find aw-server proxmox -type f -name "*.sh" -print0 | xargs -0 -r -n1 bash -n
|
||||||
|
|
||||||
echo "[2/3] Shellcheck (if available)"
|
echo "[2/4] Shellcheck (if available)"
|
||||||
if command -v shellcheck >/dev/null 2>&1; then
|
if command -v shellcheck >/dev/null 2>&1; then
|
||||||
find aw-server proxmox -type f -name "*.sh" -print0 | xargs -0 -r shellcheck
|
find aw-server proxmox -type f -name "*.sh" -print0 | xargs -0 -r shellcheck
|
||||||
else
|
else
|
||||||
echo "shellcheck not found, skipping."
|
echo "shellcheck not found, skipping."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[3/3] PowerShell parse check (if pwsh available)"
|
echo "[3/4] PowerShell parse check (if pwsh available)"
|
||||||
if command -v pwsh >/dev/null 2>&1; then
|
if command -v pwsh >/dev/null 2>&1; then
|
||||||
pwsh -NoLogo -NoProfile -Command '
|
pwsh -NoLogo -NoProfile -Command '
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
@@ -28,4 +28,15 @@ else
|
|||||||
echo "pwsh not found, skipping."
|
echo "pwsh not found, skipping."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
echo "[4/4] Ansible syntax check (if ansible-playbook available)"
|
||||||
|
if command -v ansible-playbook >/dev/null 2>&1; then
|
||||||
|
for playbook in ansible/*.yml; do
|
||||||
|
ansible-playbook --syntax-check "$playbook" -i ansible/inventory.example.ini >/dev/null
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "ansible-playbook not found, skipping."
|
||||||
|
fi
|
||||||
|
|
||||||
echo "quality-gate: OK"
|
echo "quality-gate: OK"
|
||||||
|
|||||||
Executable
+79
@@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
KIT_DIR="install-kit-awindows-20260427-211240"
|
||||||
|
MANIFEST="$KIT_DIR/MANIFEST.txt"
|
||||||
|
ZIP_ARCHIVE="install-kit-awindows-20260427-211240.zip"
|
||||||
|
TAR_ARCHIVE="install-kit-awindows-20260427-211240.tar.gz"
|
||||||
|
|
||||||
|
required_files=(
|
||||||
|
"$MANIFEST"
|
||||||
|
"$KIT_DIR/README-INSTALL-KIT.txt"
|
||||||
|
"$KIT_DIR/windows/deploy-ensemble.ps1"
|
||||||
|
"$KIT_DIR/windows/validate-deployment.ps1"
|
||||||
|
"$KIT_DIR/ansible/deploy_aw_windows_phase2.yml"
|
||||||
|
"$KIT_DIR/aw-server/install_aw_server.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "[1/4] Required files presence"
|
||||||
|
for file in "${required_files[@]}"; do
|
||||||
|
[[ -f "$file" ]] || { echo "Missing required file: $file"; exit 1; }
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[2/4] Manifest checksum verification"
|
||||||
|
sha256sum -c "$MANIFEST" >/dev/null
|
||||||
|
|
||||||
|
echo "[3/4] Manifest completeness"
|
||||||
|
python - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
kit=Path('install-kit-awindows-20260427-211240')
|
||||||
|
manifest=kit/'MANIFEST.txt'
|
||||||
|
listed=[]
|
||||||
|
for line in manifest.read_text().splitlines():
|
||||||
|
line=line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
parts=line.split(' ',1)
|
||||||
|
if len(parts)!=2:
|
||||||
|
print(f'Invalid MANIFEST line: {line}')
|
||||||
|
sys.exit(1)
|
||||||
|
listed.append(parts[1])
|
||||||
|
listed_set=set(listed)
|
||||||
|
actual_set={str(p) for p in kit.rglob('*') if p.is_file() and p.name!='MANIFEST.txt'}
|
||||||
|
missing=sorted(listed_set-actual_set)
|
||||||
|
extra=sorted(actual_set-listed_set)
|
||||||
|
if missing or extra:
|
||||||
|
print('Missing files listed in MANIFEST:', missing)
|
||||||
|
print('Files not listed in MANIFEST:', extra)
|
||||||
|
sys.exit(1)
|
||||||
|
print(f'MANIFEST complete: {len(actual_set)} files tracked')
|
||||||
|
PY
|
||||||
|
|
||||||
|
echo "[4/4] Archive composition check"
|
||||||
|
python - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import tarfile, zipfile, sys
|
||||||
|
kit_prefix='install-kit-awindows-20260427-211240/'
|
||||||
|
zip_path=Path('install-kit-awindows-20260427-211240.zip')
|
||||||
|
tar_path=Path('install-kit-awindows-20260427-211240.tar.gz')
|
||||||
|
if not zip_path.exists() or not tar_path.exists():
|
||||||
|
print('Archives not found')
|
||||||
|
sys.exit(1)
|
||||||
|
with zipfile.ZipFile(zip_path) as z:
|
||||||
|
zip_files=sorted(i for i in z.namelist() if not i.endswith('/'))
|
||||||
|
with tarfile.open(tar_path, 'r:gz') as t:
|
||||||
|
tar_files=sorted(m.name for m in t.getmembers() if m.isfile())
|
||||||
|
if zip_files != tar_files:
|
||||||
|
print('ZIP and TAR contents differ')
|
||||||
|
sys.exit(1)
|
||||||
|
if not all(f.startswith(kit_prefix) for f in zip_files):
|
||||||
|
print('Unexpected archive prefix layout')
|
||||||
|
sys.exit(1)
|
||||||
|
print(f'Archives match: {len(zip_files)} files')
|
||||||
|
PY
|
||||||
|
|
||||||
|
echo "validate_install_kit: OK"
|
||||||
Reference in New Issue
Block a user