diff options
Diffstat (limited to 'docs/archive/2026-01-relay-ngit-dev-migration/scripts/validate-service.sh')
| -rwxr-xr-x | docs/archive/2026-01-relay-ngit-dev-migration/scripts/validate-service.sh | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/docs/archive/2026-01-relay-ngit-dev-migration/scripts/validate-service.sh b/docs/archive/2026-01-relay-ngit-dev-migration/scripts/validate-service.sh new file mode 100755 index 0000000..6988af3 --- /dev/null +++ b/docs/archive/2026-01-relay-ngit-dev-migration/scripts/validate-service.sh | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | #!/usr/bin/env bash | ||
| 2 | # | ||
| 3 | # validate-service.sh - Validate service name for structured logging | ||
| 4 | # | ||
| 5 | # This helper script validates that a service name is appropriate for | ||
| 6 | # Phase 4 log extraction. Structured logging ([PARSE_FAIL], [PURGATORY_EXPIRED]) | ||
| 7 | # only exists in ngit-grasp services, NOT in ngit-relay services. | ||
| 8 | # | ||
| 9 | # USAGE: | ||
| 10 | # Source this script and call the validation function: | ||
| 11 | # | ||
| 12 | # source validate-service.sh | ||
| 13 | # validate_service_for_structured_logging "$SERVICE_NAME" || exit 1 | ||
| 14 | # | ||
| 15 | # BACKGROUND: | ||
| 16 | # Phase 4 of the migration analysis extracts structured log entries from | ||
| 17 | # journald. These log entries only exist in ngit-grasp services. If you | ||
| 18 | # accidentally specify an ngit-relay service, Phase 4 will find no logs | ||
| 19 | # and produce empty results. | ||
| 20 | # | ||
| 21 | # This validation prevents that common mistake by: | ||
| 22 | # 1. Checking if the service name contains "ngit-relay" (error) | ||
| 23 | # 2. Warning if the service name doesn't contain "ngit-grasp" | ||
| 24 | # 3. Optionally checking if structured logs actually exist | ||
| 25 | # | ||
| 26 | # SEE ALSO: | ||
| 27 | # docs/how-to/migrate-to-ngit-grasp.md - Full migration guide | ||
| 28 | # 30-extract-parse-failures.sh - Uses this validation | ||
| 29 | # 31-extract-purgatory-expiry.sh - Uses this validation | ||
| 30 | # | ||
| 31 | |||
| 32 | # Colors for output (disabled if not a terminal) | ||
| 33 | if [[ -t 1 ]]; then | ||
| 34 | _VS_RED='\033[0;31m' | ||
| 35 | _VS_YELLOW='\033[0;33m' | ||
| 36 | _VS_NC='\033[0m' | ||
| 37 | else | ||
| 38 | _VS_RED='' | ||
| 39 | _VS_YELLOW='' | ||
| 40 | _VS_NC='' | ||
| 41 | fi | ||
| 42 | |||
| 43 | # Validates that the service name is appropriate for structured logging | ||
| 44 | # | ||
| 45 | # Arguments: | ||
| 46 | # $1 - service_name: The systemd service name to validate | ||
| 47 | # $2 - check_logs: Whether to check if logs actually exist (default: "true") | ||
| 48 | # $3 - interactive: Whether to prompt for confirmation (default: "true") | ||
| 49 | # | ||
| 50 | # Returns: | ||
| 51 | # 0 - Service is valid for structured logging | ||
| 52 | # 1 - Service is invalid or user declined to continue | ||
| 53 | # | ||
| 54 | # Example: | ||
| 55 | # validate_service_for_structured_logging "ngit-grasp.service" || exit 1 | ||
| 56 | # validate_service_for_structured_logging "ngit-grasp.service" "false" # Skip log check | ||
| 57 | # validate_service_for_structured_logging "ngit-grasp.service" "true" "false" # Non-interactive | ||
| 58 | # | ||
| 59 | validate_service_for_structured_logging() { | ||
| 60 | local service_name="$1" | ||
| 61 | local check_logs="${2:-true}" | ||
| 62 | local interactive="${3:-true}" | ||
| 63 | |||
| 64 | # Check if service name looks like ngit-relay (ERROR - wrong service type) | ||
| 65 | if [[ "$service_name" == *"ngit-relay"* ]]; then | ||
| 66 | echo -e "${_VS_RED}ERROR: Service name appears to be ngit-relay: $service_name${_VS_NC}" >&2 | ||
| 67 | echo "" >&2 | ||
| 68 | echo "Structured logging ([PARSE_FAIL], [PURGATORY_EXPIRED]) only exists in" >&2 | ||
| 69 | echo "ngit-grasp services, NOT in ngit-relay services." >&2 | ||
| 70 | echo "" >&2 | ||
| 71 | echo "Please use the ngit-grasp archive service instead." >&2 | ||
| 72 | echo "" >&2 | ||
| 73 | echo "To find the correct service name:" >&2 | ||
| 74 | echo " systemctl list-units 'ngit-grasp*' --all" >&2 | ||
| 75 | echo "" >&2 | ||
| 76 | echo "Common ngit-grasp service names:" >&2 | ||
| 77 | echo " - ngit-grasp.service" >&2 | ||
| 78 | echo " - ngit-grasp-relay-ngit-dev.service (NixOS multi-instance)" >&2 | ||
| 79 | echo " - ngit-grasp-archive.service" >&2 | ||
| 80 | return 1 | ||
| 81 | fi | ||
| 82 | |||
| 83 | # Check if service name looks like ngit-grasp (WARNING if not) | ||
| 84 | if [[ "$service_name" != *"ngit-grasp"* && "$service_name" != *"grasp"* ]]; then | ||
| 85 | echo -e "${_VS_YELLOW}WARNING: Service name doesn't contain 'ngit-grasp': $service_name${_VS_NC}" >&2 | ||
| 86 | echo "" >&2 | ||
| 87 | echo "Structured logging ([PARSE_FAIL], [PURGATORY_EXPIRED]) only exists in" >&2 | ||
| 88 | echo "ngit-grasp services." >&2 | ||
| 89 | echo "" >&2 | ||
| 90 | |||
| 91 | if [[ "$interactive" == "true" ]]; then | ||
| 92 | read -p "Continue anyway? (y/N) " -n 1 -r | ||
| 93 | echo | ||
| 94 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then | ||
| 95 | return 1 | ||
| 96 | fi | ||
| 97 | else | ||
| 98 | echo "Non-interactive mode: proceeding despite warning" >&2 | ||
| 99 | fi | ||
| 100 | fi | ||
| 101 | |||
| 102 | # Optionally check if structured logs actually exist | ||
| 103 | if [[ "$check_logs" == "true" ]]; then | ||
| 104 | # Check if journalctl is available | ||
| 105 | if ! command -v journalctl &> /dev/null; then | ||
| 106 | echo -e "${_VS_YELLOW}WARNING: journalctl not available, cannot verify logs exist${_VS_NC}" >&2 | ||
| 107 | return 0 | ||
| 108 | fi | ||
| 109 | |||
| 110 | # Check for structured log entries | ||
| 111 | # IMPORTANT: Use --no-pager to prevent hanging when run non-interactively (e.g., via SSH) | ||
| 112 | local has_parse_fail has_purgatory | ||
| 113 | has_parse_fail=$(journalctl --no-pager -u "$service_name" --since "7 days ago" 2>/dev/null | grep -c '\[PARSE_FAIL\]' || echo "0") | ||
| 114 | has_purgatory=$(journalctl --no-pager -u "$service_name" --since "7 days ago" 2>/dev/null | grep -c '\[PURGATORY_EXPIRED\]' || echo "0") | ||
| 115 | |||
| 116 | # Strip any non-numeric characters (grep -c can have trailing whitespace) | ||
| 117 | has_parse_fail="${has_parse_fail//[^0-9]/}" | ||
| 118 | has_purgatory="${has_purgatory//[^0-9]/}" | ||
| 119 | has_parse_fail="${has_parse_fail:-0}" | ||
| 120 | has_purgatory="${has_purgatory:-0}" | ||
| 121 | |||
| 122 | if [[ "$has_parse_fail" -eq 0 && "$has_purgatory" -eq 0 ]]; then | ||
| 123 | echo -e "${_VS_YELLOW}WARNING: No structured logs found in $service_name (last 7 days)${_VS_NC}" >&2 | ||
| 124 | echo "" >&2 | ||
| 125 | echo "This may indicate:" >&2 | ||
| 126 | echo " 1. Wrong service (should be ngit-grasp archive service, not ngit-relay)" >&2 | ||
| 127 | echo " 2. Structured logging not yet deployed to this ngit-grasp instance" >&2 | ||
| 128 | echo " 3. No parse failures or purgatory expiry events in the time window" >&2 | ||
| 129 | echo "" >&2 | ||
| 130 | echo "To verify you have the right service:" >&2 | ||
| 131 | echo " systemctl list-units 'ngit-grasp*' --all" >&2 | ||
| 132 | echo " journalctl -u <service> | grep -E '\\[PARSE_FAIL\\]|\\[PURGATORY_EXPIRED\\]' | head -5" >&2 | ||
| 133 | echo "" >&2 | ||
| 134 | |||
| 135 | if [[ "$interactive" == "true" ]]; then | ||
| 136 | read -p "Continue anyway? (y/N) " -n 1 -r | ||
| 137 | echo | ||
| 138 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then | ||
| 139 | return 1 | ||
| 140 | fi | ||
| 141 | else | ||
| 142 | echo "Non-interactive mode: proceeding despite warning" >&2 | ||
| 143 | fi | ||
| 144 | fi | ||
| 145 | fi | ||
| 146 | |||
| 147 | return 0 | ||
| 148 | } | ||
| 149 | |||
| 150 | # Export the function so it can be used after sourcing | ||
| 151 | export -f validate_service_for_structured_logging | ||