feca-mailshots-plugin/scripts/cleanup_testing_artefacts.sh

251 lines
9.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
resolve_repo_root() {
local candidate
for candidate in "${SCRIPT_DIR}/.." "${SCRIPT_DIR}/../.." "${PWD}"; do
if [[ -f "${candidate}/credentials/.env" ]]; then
(cd "${candidate}" && pwd)
return 0
fi
done
return 1
}
if ! REPO_ROOT="$(resolve_repo_root)"; then
echo "Error: could not locate repository root containing credentials/.env" >&2
exit 1
fi
ENV_FILE="${REPO_ROOT}/credentials/.env"
if [[ ! -f "${ENV_FILE}" ]]; then
echo "Error: credentials file not found: ${ENV_FILE}" >&2
exit 1
fi
load_env_value() {
local key="$1"
local line
line="$(grep -E "^${key}=" "${ENV_FILE}" | tail -n 1 || true)"
line="${line#*=}"
line="${line%\"}"
line="${line#\"}"
line="${line%\'}"
line="${line#\'}"
printf '%s' "${line}"
}
DB_NAME="$(load_env_value MAILSHOTS_REMOTE_MYSQL_DB)"
MYSQL_USER="$(load_env_value REMOTE_MYSQL_USER)"
MYSQL_PASSWORD="$(load_env_value REMOTE_MYSQL_PASSWORD)"
REMOTE_MYSQL_HOST="$(load_env_value REMOTE_MYSQL_HOST)"
REMOTE_MYSQL_PORT="$(load_env_value REMOTE_MYSQL_PORT)"
LOCAL_TUNNEL_PORT="${LOCAL_PORT:-13306}"
# Match scripts/mysql_tunnel.sh defaults unless explicitly overridden.
MYSQL_HOST="${MYSQL_HOST:-127.0.0.1}"
MYSQL_PORT="${MYSQL_PORT:-${LOCAL_TUNNEL_PORT}}"
if [[ -z "${DB_NAME}" ]]; then
echo "Error: MAILSHOTS_REMOTE_MYSQL_DB is missing in ${ENV_FILE}" >&2
exit 1
fi
if [[ -z "${MYSQL_USER}" || -z "${MYSQL_PASSWORD}" ]]; then
echo "Error: REMOTE_MYSQL_USER/REMOTE_MYSQL_PASSWORD missing in ${ENV_FILE}" >&2
exit 1
fi
if [[ -z "${MYSQL_HOST}" || -z "${MYSQL_PORT}" ]]; then
echo "Error: MYSQL host/port is empty. Set REMOTE_MYSQL_HOST/REMOTE_MYSQL_PORT or MYSQL_HOST/MYSQL_PORT." >&2
exit 1
fi
DRY_RUN=0
AUTO_YES=0
INCLUDE_CREDENTIALS=0
USE_REMOTE=0
INCLUDE_MAILSHOT_TEST=0
# Strict, test-suite-specific markers only.
ARTEFACT_REGEX='^(e2e_|phase2_db_access_|phase3_|phase4_)'
MAILSHOT_PURPOSE_REGEX='^(e2e_|Phase3 Mailshot |Phase4 )'
usage() {
cat <<'USAGE'
Usage: cleanup_testing_artefacts.sh [options]
Options:
--dry-run Show row counts only; make no changes.
--yes Skip confirmation prompt.
--include-credentials Also delete test-marked rows in mailshot_credentials.
--include-mailshot-test Also delete test-marked rows in mailshot_test.
--remote Connect directly to REMOTE_MYSQL_HOST:REMOTE_MYSQL_PORT.
-h, --help Show this help text.
Environment overrides:
LOCAL_PORT, MYSQL_HOST, MYSQL_PORT
USAGE
}
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run) DRY_RUN=1 ;;
--yes) AUTO_YES=1 ;;
--include-credentials) INCLUDE_CREDENTIALS=1 ;;
--include-mailshot-test) INCLUDE_MAILSHOT_TEST=1 ;;
--remote) USE_REMOTE=1 ;;
-h|--help)
usage
exit 0
;;
*)
echo "Error: unknown option: $1" >&2
usage
exit 1
;;
esac
shift
done
if [[ "${USE_REMOTE}" -eq 1 ]]; then
MYSQL_HOST="${REMOTE_MYSQL_HOST}"
MYSQL_PORT="${REMOTE_MYSQL_PORT}"
fi
MYSQL_CMD=(mysql --protocol=TCP "-h${MYSQL_HOST}" "-P${MYSQL_PORT}" "-u${MYSQL_USER}" "-p${MYSQL_PASSWORD}" -N -B)
echo "Target database: ${DB_NAME}"
echo "MySQL endpoint: ${MYSQL_HOST}:${MYSQL_PORT}"
echo "Cleanup mode: selective delete only (no TRUNCATE)."
echo "Artefact regex: ${ARTEFACT_REGEX}"
echo "Mailshot purpose regex: ${MAILSHOT_PURPOSE_REGEX}"
for t in mailshot_last_run mailshot_queries mailshot_attachments mailshot_pdf_assets mailshots mailshot_credentials mailshot_test; do
exists="$("${MYSQL_CMD[@]}" -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${DB_NAME}' AND table_name='${t}';")"
if [[ "${exists}" != "1" ]]; then
echo "Error: required table ${DB_NAME}.${t} does not exist." >&2
exit 1
fi
done
candidate_counts_sql="
SELECT 'mailshot_queries' AS t, COUNT(*) AS c
FROM \`${DB_NAME}\`.\`mailshot_queries\`
WHERE \`name\` REGEXP '${ARTEFACT_REGEX}'
UNION ALL
SELECT 'mailshot_attachments' AS t, COUNT(*) AS c
FROM \`${DB_NAME}\`.\`mailshot_attachments\`
WHERE \`name\` REGEXP '${ARTEFACT_REGEX}'
OR COALESCE(\`file_name\`, '') REGEXP '${ARTEFACT_REGEX}'
UNION ALL
SELECT 'mailshot_pdf_assets' AS t, COUNT(*) AS c
FROM \`${DB_NAME}\`.\`mailshot_pdf_assets\`
WHERE \`name\` REGEXP '${ARTEFACT_REGEX}'
OR COALESCE(\`file_name\`, '') REGEXP '${ARTEFACT_REGEX}'
UNION ALL
SELECT 'mailshots' AS t, COUNT(*) AS c
FROM \`${DB_NAME}\`.\`mailshots\`
WHERE COALESCE(\`Purpose\`, '') REGEXP '${MAILSHOT_PURPOSE_REGEX}'
OR COALESCE(\`DataSource\`, '') REGEXP '${ARTEFACT_REGEX}'
UNION ALL
SELECT 'mailshot_last_run' AS t, COUNT(*) AS c
FROM \`${DB_NAME}\`.\`mailshot_last_run\` lr
WHERE COALESCE(lr.\`data_source\`, '') REGEXP '${ARTEFACT_REGEX}'
OR COALESCE(lr.\`recipient_key\`, '') REGEXP '^phase[0-9]'
OR lr.\`mailshot_id\` IN (
SELECT m.\`id\` FROM \`${DB_NAME}\`.\`mailshots\` m
WHERE COALESCE(m.\`Purpose\`, '') REGEXP '${MAILSHOT_PURPOSE_REGEX}'
OR COALESCE(m.\`DataSource\`, '') REGEXP '${ARTEFACT_REGEX}'
);"
echo
echo "Candidate rows to delete:"
"${MYSQL_CMD[@]}" -e "${candidate_counts_sql}" | while IFS=$'\t' read -r t c; do
printf ' %-26s %s\n' "${t}" "${c}"
done
if [[ "${INCLUDE_MAILSHOT_TEST}" -eq 1 ]]; then
c="$("${MYSQL_CMD[@]}" -e "SELECT COUNT(*) FROM \`${DB_NAME}\`.\`mailshot_test\` WHERE COALESCE(\`Name\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`Email\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`Email\`, '') LIKE '%@example.test';")"
printf ' %-26s %s\n' "mailshot_test (optional)" "${c}"
else
echo " mailshot_test skipped (use --include-mailshot-test)"
fi
if [[ "${INCLUDE_CREDENTIALS}" -eq 1 ]]; then
c="$("${MYSQL_CMD[@]}" -e "SELECT COUNT(*) FROM \`${DB_NAME}\`.\`mailshot_credentials\` WHERE COALESCE(\`smtp_host\`, '') LIKE 'smtp.test.%' OR COALESCE(\`imap_host\`, '') LIKE 'imap.test.%' OR COALESCE(\`smtp_user\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`imap_user\`, '') REGEXP '${ARTEFACT_REGEX}';")"
printf ' %-26s %s\n' "mailshot_credentials (optional)" "${c}"
else
echo " mailshot_credentials skipped (use --include-credentials)"
fi
if [[ "${DRY_RUN}" -eq 1 ]]; then
echo
echo "Dry run complete. No changes made."
exit 0
fi
if [[ "${AUTO_YES}" -ne 1 ]]; then
echo
read -r -p "Proceed to delete only the candidate test artefact rows above? [y/N] " reply
if [[ ! "${reply}" =~ ^[Yy]$ ]]; then
echo "Aborted. No changes made."
exit 0
fi
fi
delete_sql="
DELETE FROM \`${DB_NAME}\`.\`mailshot_last_run\`
WHERE COALESCE(\`data_source\`, '') REGEXP '${ARTEFACT_REGEX}'
OR COALESCE(\`recipient_key\`, '') REGEXP '^phase[0-9]'
OR \`mailshot_id\` IN (
SELECT \`id\` FROM (
SELECT m.\`id\`
FROM \`${DB_NAME}\`.\`mailshots\` m
WHERE COALESCE(m.\`Purpose\`, '') REGEXP '${MAILSHOT_PURPOSE_REGEX}'
OR COALESCE(m.\`DataSource\`, '') REGEXP '${ARTEFACT_REGEX}'
) x
);
DELETE FROM \`${DB_NAME}\`.\`mailshots\`
WHERE COALESCE(\`Purpose\`, '') REGEXP '${MAILSHOT_PURPOSE_REGEX}'
OR COALESCE(\`DataSource\`, '') REGEXP '${ARTEFACT_REGEX}';
DELETE FROM \`${DB_NAME}\`.\`mailshot_queries\`
WHERE \`name\` REGEXP '${ARTEFACT_REGEX}';
DELETE FROM \`${DB_NAME}\`.\`mailshot_attachments\`
WHERE \`name\` REGEXP '${ARTEFACT_REGEX}'
OR COALESCE(\`file_name\`, '') REGEXP '${ARTEFACT_REGEX}';
DELETE FROM \`${DB_NAME}\`.\`mailshot_pdf_assets\`
WHERE \`name\` REGEXP '${ARTEFACT_REGEX}'
OR COALESCE(\`file_name\`, '') REGEXP '${ARTEFACT_REGEX}';
"
"${MYSQL_CMD[@]}" -e "${delete_sql}"
if [[ "${INCLUDE_MAILSHOT_TEST}" -eq 1 ]]; then
"${MYSQL_CMD[@]}" -e "DELETE FROM \`${DB_NAME}\`.\`mailshot_test\` WHERE COALESCE(\`Name\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`Email\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`Email\`, '') LIKE '%@example.test';"
fi
if [[ "${INCLUDE_CREDENTIALS}" -eq 1 ]]; then
"${MYSQL_CMD[@]}" -e "DELETE FROM \`${DB_NAME}\`.\`mailshot_credentials\` WHERE COALESCE(\`smtp_host\`, '') LIKE 'smtp.test.%' OR COALESCE(\`imap_host\`, '') LIKE 'imap.test.%' OR COALESCE(\`smtp_user\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`imap_user\`, '') REGEXP '${ARTEFACT_REGEX}';"
fi
echo
echo "Cleanup complete. Remaining candidate row counts:"
"${MYSQL_CMD[@]}" -e "${candidate_counts_sql}" | while IFS=$'\t' read -r t c; do
printf ' %-26s %s\n' "${t}" "${c}"
done
if [[ "${INCLUDE_MAILSHOT_TEST}" -eq 1 ]]; then
c="$("${MYSQL_CMD[@]}" -e "SELECT COUNT(*) FROM \`${DB_NAME}\`.\`mailshot_test\` WHERE COALESCE(\`Name\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`Email\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`Email\`, '') LIKE '%@example.test';")"
printf ' %-26s %s\n' "mailshot_test (optional)" "${c}"
fi
if [[ "${INCLUDE_CREDENTIALS}" -eq 1 ]]; then
c="$("${MYSQL_CMD[@]}" -e "SELECT COUNT(*) FROM \`${DB_NAME}\`.\`mailshot_credentials\` WHERE COALESCE(\`smtp_host\`, '') LIKE 'smtp.test.%' OR COALESCE(\`imap_host\`, '') LIKE 'imap.test.%' OR COALESCE(\`smtp_user\`, '') REGEXP '${ARTEFACT_REGEX}' OR COALESCE(\`imap_user\`, '') REGEXP '${ARTEFACT_REGEX}';")"
printf ' %-26s %s\n' "mailshot_credentials (optional)" "${c}"
fi