From 3f5d5b637b36080dff25b4a3fd2e21376c280cb5 Mon Sep 17 00:00:00 2001 From: Mandel Olaiya Date: Mon, 30 Mar 2026 00:03:52 +0200 Subject: [PATCH] Use deploy entrypoint for multilingual audit --- Jenkinsfile | 2 +- Jenkinsfile.multilingual-nightly | 2 +- docs/CI_MULTILINGUAL_AUDIT.md | 6 +- scripts/run_remote_multilingual_audit.sh | 86 +++++++----------------- 4 files changed, 30 insertions(+), 66 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e411759..5750d7b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,7 @@ pipeline { environment { PYENVPIPELINE_VIRTUALENV = '1' GIT_SSH_COMMAND = 'ssh -o StrictHostKeyChecking=accept-new' - STAGING_AUDIT_MINION = 'welkombij.mandelblog.com' + STAGING_AUDIT_PROJECT_NAME = 'mandelstudio' STAGING_AUDIT_PROJECT_DIR = '/home/www-mandelstudio/mandelstudio' STAGING_AUDIT_MANAGE = '/var/lib/virtualenv/mandelstudio/bin/manage.py' } diff --git a/Jenkinsfile.multilingual-nightly b/Jenkinsfile.multilingual-nightly index b8b672f..6fe900e 100644 --- a/Jenkinsfile.multilingual-nightly +++ b/Jenkinsfile.multilingual-nightly @@ -10,7 +10,7 @@ pipeline { skipDefaultCheckout(true) } environment { - STAGING_AUDIT_MINION = 'welkombij.mandelblog.com' + STAGING_AUDIT_PROJECT_NAME = 'mandelstudio' STAGING_AUDIT_PROJECT_DIR = '/home/www-mandelstudio/mandelstudio' STAGING_AUDIT_MANAGE = '/var/lib/virtualenv/mandelstudio/bin/manage.py' } diff --git a/docs/CI_MULTILINGUAL_AUDIT.md b/docs/CI_MULTILINGUAL_AUDIT.md index dd4ea4a..26e2826 100644 --- a/docs/CI_MULTILINGUAL_AUDIT.md +++ b/docs/CI_MULTILINGUAL_AUDIT.md @@ -58,10 +58,10 @@ This keeps deploys safe without making warning-level cleanup a hard blocker. ## Jenkins requirements No dedicated staging SSH credential is required for the multilingual audit stage. -The audit runs from the Jenkins built-in node through the same `serverpillar` / Salt transport used by staging deployment. +The audit runs through `/srv/apps/mandel-dashboard/bin/deploy_stg_from_jenkins.py --command`, using the same sudo-whitelisted deployment entrypoint as staging deployment. Current implementation uses the following environment defaults: -- `STAGING_AUDIT_MINION=welkombij.mandelblog.com` +- `STAGING_AUDIT_PROJECT_NAME=mandelstudio` - `STAGING_AUDIT_PROJECT_DIR=/home/www-mandelstudio/mandelstudio` - `STAGING_AUDIT_MANAGE=/var/lib/virtualenv/mandelstudio/bin/manage.py` @@ -101,7 +101,7 @@ This happens when the remote audit times out or fails, and is intentional so Jen ## Local rerun To rerun the same remote audit flow locally: ```bash -export STAGING_AUDIT_MINION='welkombij.mandelblog.com' +export STAGING_AUDIT_PROJECT_NAME='mandelstudio' export STAGING_AUDIT_PROJECT_DIR='/home/www-mandelstudio/mandelstudio' export STAGING_AUDIT_MANAGE='/var/lib/virtualenv/mandelstudio/bin/manage.py' ./scripts/run_remote_multilingual_audit.sh diff --git a/scripts/run_remote_multilingual_audit.sh b/scripts/run_remote_multilingual_audit.sh index 8c0f40c..32a3061 100755 --- a/scripts/run_remote_multilingual_audit.sh +++ b/scripts/run_remote_multilingual_audit.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -: "${STAGING_AUDIT_MINION:?STAGING_AUDIT_MINION is required}" +: "${STAGING_AUDIT_PROJECT_NAME:?STAGING_AUDIT_PROJECT_NAME is required}" : "${STAGING_AUDIT_PROJECT_DIR:?STAGING_AUDIT_PROJECT_DIR is required}" : "${STAGING_AUDIT_MANAGE:?STAGING_AUDIT_MANAGE is required}" @@ -15,81 +15,45 @@ trap 'rm -f "$TMP_FILE"' EXIT REMOTE_CMD="cd '${STAGING_AUDIT_PROJECT_DIR}' && '${STAGING_AUDIT_MANAGE}' audit_locales --format=json" set +e -sudo -n -u mandel -g www-data /srv/apps/mandel-dashboard/.venv/bin/python - "$STAGING_AUDIT_MINION" "$REMOTE_CMD" "$AUDIT_TIMEOUT_SECONDS" <<'PY2' > "$TMP_FILE" +STAGING_AUDIT_PROJECT_NAME="$STAGING_AUDIT_PROJECT_NAME" REMOTE_CMD="$REMOTE_CMD" AUDIT_TIMEOUT_SECONDS="$AUDIT_TIMEOUT_SECONDS" python3 - <<'PY2' > "$TMP_FILE" import json +import os import subprocess import sys -minion = sys.argv[1] -remote_cmd = sys.argv[2] -timeout_seconds = int(sys.argv[3]) +project = os.environ["STAGING_AUDIT_PROJECT_NAME"] +remote_cmd = os.environ["REMOTE_CMD"] +timeout_seconds = int(os.environ["AUDIT_TIMEOUT_SECONDS"]) cmd = [ - "/usr/bin/salt", "--out=json", minion, - "cmd.run_all", remote_cmd, "python_shell=True", + "sudo", "-n", "-u", "mandel", "-g", "www-data", + "/srv/apps/mandel-dashboard/.venv/bin/python", + "/srv/apps/mandel-dashboard/bin/deploy_stg_from_jenkins.py", + project, + "--command", + remote_cmd, ] try: - result = subprocess.run( - cmd, - capture_output=True, - text=True, - timeout=timeout_seconds, - check=False, - ) + result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout_seconds, check=False) except subprocess.TimeoutExpired: print(json.dumps({ - "run_id": None, - "total_urls_checked": 0, - "issues_found": 0, - "summary": {}, - "issues": {}, - "error": f"Salt multilingual audit timed out after {timeout_seconds} seconds", + "error": "audit_failed", + "details": f"Audit command timed out after {timeout_seconds} seconds", + "exit_code": 124, }, indent=2)) sys.exit(2) - +stdout = result.stdout.strip() +stderr = result.stderr.strip() if result.returncode != 0: - print(json.dumps({ - "run_id": None, - "total_urls_checked": 0, - "issues_found": 0, - "summary": {}, - "issues": {}, - "error": f"Salt audit transport failed with exit status {result.returncode}: {(result.stderr or result.stdout).strip()}", - }, indent=2)) - sys.exit(2) - -try: - payload = json.loads(result.stdout) - if not isinstance(payload, dict) or minion not in payload: - raise ValueError("Missing minion payload") - minion_payload = payload[minion] - if not isinstance(minion_payload, dict): - raise ValueError("Unexpected minion payload type") - retcode = int(minion_payload.get("retcode", 1)) - stdout = minion_payload.get("stdout", "") - stderr = minion_payload.get("stderr", "") - if retcode != 0: + if stdout: + print(stdout) + else: print(json.dumps({ - "run_id": None, - "total_urls_checked": 0, - "issues_found": 0, - "summary": {}, - "issues": {}, - "error": f"Remote multilingual audit failed with exit status {retcode}: {(stderr or stdout).strip()}", + "error": "audit_failed", + "details": stderr or f"Audit command failed with exit status {result.returncode}", + "exit_code": result.returncode, }, indent=2)) - sys.exit(2) - audit = json.loads(stdout) -except Exception as exc: - print(json.dumps({ - "run_id": None, - "total_urls_checked": 0, - "issues_found": 0, - "summary": {}, - "issues": {}, - "error": f"Unable to parse salt audit response: {exc}", - }, indent=2)) sys.exit(2) - -print(json.dumps(audit, indent=2, sort_keys=True)) +print(stdout) PY2 status=$? set -e