upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/docs/how-to/migration-scripts
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-23 16:12:03 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-27 20:38:04 +0000
commit2b21b807bdf6c0bab548ffceb5c41eee0902890c (patch)
treee3b17db923384dd512ae40f0f263de165d119f4f /docs/how-to/migration-scripts
parent6a6c8cf8b70bc387ea7241b5c9ec457cb525eb40 (diff)
Prevent Phase 4 from using wrong service (ngit-relay vs ngit-grasp)
Add validation to ensure Phase 4 scripts use ngit-grasp service (with structured logging) instead of ngit-relay service. Changes: - Add validate-service.sh helper for reusable service validation - Add validation to run-migration-analysis.sh before Phase 4 - Add validation to 30-extract-parse-failures.sh - Add validation to 31-extract-purgatory-expiry.sh - Update migration guide with clear warnings about service selection - Expand troubleshooting for 'Phase 4 finds no logs' issue - Emphasize lesson learned in relay.ngit.dev notes This prevents the issue where Phase 4 was run against ngit-relay.service and found no parse failures because structured logging only exists in ngit-grasp services.
Diffstat (limited to 'docs/how-to/migration-scripts')
-rwxr-xr-xdocs/how-to/migration-scripts/30-extract-parse-failures.sh34
-rwxr-xr-xdocs/how-to/migration-scripts/31-extract-purgatory-expiry.sh34
-rwxr-xr-xdocs/how-to/migration-scripts/run-migration-analysis.sh28
-rwxr-xr-xdocs/how-to/migration-scripts/validate-service.sh150
4 files changed, 244 insertions, 2 deletions
diff --git a/docs/how-to/migration-scripts/30-extract-parse-failures.sh b/docs/how-to/migration-scripts/30-extract-parse-failures.sh
index bc2049a..410fcbc 100755
--- a/docs/how-to/migration-scripts/30-extract-parse-failures.sh
+++ b/docs/how-to/migration-scripts/30-extract-parse-failures.sh
@@ -65,6 +65,14 @@
65 65
66set -euo pipefail 66set -euo pipefail
67 67
68# Get script directory for sourcing helpers
69SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
70
71# Source the service validation helper
72if [[ -f "$SCRIPT_DIR/validate-service.sh" ]]; then
73 source "$SCRIPT_DIR/validate-service.sh"
74fi
75
68# Colors for output (disabled if not a terminal) 76# Colors for output (disabled if not a terminal)
69if [[ -t 1 ]]; then 77if [[ -t 1 ]]; then
70 RED='\033[0;31m' 78 RED='\033[0;31m'
@@ -188,11 +196,35 @@ main() {
188 esac 196 esac
189 done 197 done
190 198
191 # Validate service name 199 # Validate service name format
192 if [[ ! "$service" =~ \.service$ ]]; then 200 if [[ ! "$service" =~ \.service$ ]]; then
193 service="${service}.service" 201 service="${service}.service"
194 fi 202 fi
195 203
204 # Validate service is appropriate for structured logging
205 # This prevents the common mistake of using ngit-relay instead of ngit-grasp
206 if type validate_service_for_structured_logging &>/dev/null; then
207 # Use non-interactive mode if not a terminal, skip log check (we'll do our own)
208 local interactive="true"
209 [[ ! -t 0 ]] && interactive="false"
210
211 if ! validate_service_for_structured_logging "$service" "false" "$interactive"; then
212 log_error "Service validation failed. Use an ngit-grasp service for structured logging."
213 exit 1
214 fi
215 else
216 # Fallback validation if helper not available
217 if [[ "$service" == *"ngit-relay"* ]]; then
218 log_error "Service name appears to be ngit-relay: $service"
219 log_error "Structured logging ([PARSE_FAIL]) only exists in ngit-grasp services."
220 log_error "Please use the ngit-grasp archive service instead."
221 log_error ""
222 log_error "To find the correct service:"
223 log_error " systemctl list-units 'ngit-grasp*' --all"
224 exit 1
225 fi
226 fi
227
196 log_info "Extracting parse failures from systemd logs" 228 log_info "Extracting parse failures from systemd logs"
197 log_info "Service: $service" 229 log_info "Service: $service"
198 log_info "Output: $output_dir" 230 log_info "Output: $output_dir"
diff --git a/docs/how-to/migration-scripts/31-extract-purgatory-expiry.sh b/docs/how-to/migration-scripts/31-extract-purgatory-expiry.sh
index 8cadad9..a20780e 100755
--- a/docs/how-to/migration-scripts/31-extract-purgatory-expiry.sh
+++ b/docs/how-to/migration-scripts/31-extract-purgatory-expiry.sh
@@ -76,6 +76,14 @@
76 76
77set -euo pipefail 77set -euo pipefail
78 78
79# Get script directory for sourcing helpers
80SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
81
82# Source the service validation helper
83if [[ -f "$SCRIPT_DIR/validate-service.sh" ]]; then
84 source "$SCRIPT_DIR/validate-service.sh"
85fi
86
79# Colors for output (disabled if not a terminal) 87# Colors for output (disabled if not a terminal)
80if [[ -t 1 ]]; then 88if [[ -t 1 ]]; then
81 RED='\033[0;31m' 89 RED='\033[0;31m'
@@ -195,11 +203,35 @@ main() {
195 esac 203 esac
196 done 204 done
197 205
198 # Validate service name 206 # Validate service name format
199 if [[ ! "$service" =~ \.service$ ]]; then 207 if [[ ! "$service" =~ \.service$ ]]; then
200 service="${service}.service" 208 service="${service}.service"
201 fi 209 fi
202 210
211 # Validate service is appropriate for structured logging
212 # This prevents the common mistake of using ngit-relay instead of ngit-grasp
213 if type validate_service_for_structured_logging &>/dev/null; then
214 # Use non-interactive mode if not a terminal, skip log check (we'll do our own)
215 local interactive="true"
216 [[ ! -t 0 ]] && interactive="false"
217
218 if ! validate_service_for_structured_logging "$service" "false" "$interactive"; then
219 log_error "Service validation failed. Use an ngit-grasp service for structured logging."
220 exit 1
221 fi
222 else
223 # Fallback validation if helper not available
224 if [[ "$service" == *"ngit-relay"* ]]; then
225 log_error "Service name appears to be ngit-relay: $service"
226 log_error "Structured logging ([PURGATORY_EXPIRED]) only exists in ngit-grasp services."
227 log_error "Please use the ngit-grasp archive service instead."
228 log_error ""
229 log_error "To find the correct service:"
230 log_error " systemctl list-units 'ngit-grasp*' --all"
231 exit 1
232 fi
233 fi
234
203 log_info "Extracting purgatory expiry events from systemd logs" 235 log_info "Extracting purgatory expiry events from systemd logs"
204 log_info "Service: $service" 236 log_info "Service: $service"
205 log_info "Output: $output_dir" 237 log_info "Output: $output_dir"
diff --git a/docs/how-to/migration-scripts/run-migration-analysis.sh b/docs/how-to/migration-scripts/run-migration-analysis.sh
index 65d9d17..b2ca142 100755
--- a/docs/how-to/migration-scripts/run-migration-analysis.sh
+++ b/docs/how-to/migration-scripts/run-migration-analysis.sh
@@ -548,6 +548,34 @@ run_phase_4() {
548 return 0 548 return 0
549 fi 549 fi
550 550
551 # Validate service name before running Phase 4
552 # Structured logging only exists in ngit-grasp, not ngit-relay
553 if [[ "$SERVICE_NAME" == *"ngit-relay"* ]]; then
554 log_error "SERVICE_NAME appears to be ngit-relay: $SERVICE_NAME"
555 log_error ""
556 log_error "Phase 4 requires an ngit-grasp service with structured logging."
557 log_error "Structured logging ([PARSE_FAIL], [PURGATORY_EXPIRED]) only exists"
558 log_error "in ngit-grasp services, NOT in ngit-relay services."
559 log_error ""
560 log_error "Please update --service to use the ngit-grasp archive service."
561 log_error ""
562 log_error "To find the correct service name:"
563 log_error " systemctl list-units 'ngit-grasp*' --all"
564 log_error ""
565 log_error "Common ngit-grasp service names:"
566 log_error " - ngit-grasp.service"
567 log_error " - ngit-grasp-relay-ngit-dev.service (NixOS multi-instance)"
568 log_error " - ngit-grasp-archive.service"
569 return 1
570 fi
571
572 # Warn if service name doesn't look like ngit-grasp
573 if [[ "$SERVICE_NAME" != *"ngit-grasp"* && "$SERVICE_NAME" != *"grasp"* ]]; then
574 log_warn "SERVICE_NAME doesn't contain 'ngit-grasp': $SERVICE_NAME"
575 log_warn "Structured logging only exists in ngit-grasp services."
576 log_warn "If this is not an ngit-grasp service, Phase 4 will find no logs."
577 fi
578
551 local cmds=() 579 local cmds=()
552 580
553 cmds+=("'$SCRIPT_DIR/30-extract-parse-failures.sh' '$SERVICE_NAME' '$OUTPUT_DIR/logs'") 581 cmds+=("'$SCRIPT_DIR/30-extract-parse-failures.sh' '$SERVICE_NAME' '$OUTPUT_DIR/logs'")
diff --git a/docs/how-to/migration-scripts/validate-service.sh b/docs/how-to/migration-scripts/validate-service.sh
new file mode 100755
index 0000000..2525a3f
--- /dev/null
+++ b/docs/how-to/migration-scripts/validate-service.sh
@@ -0,0 +1,150 @@
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)
33if [[ -t 1 ]]; then
34 _VS_RED='\033[0;31m'
35 _VS_YELLOW='\033[0;33m'
36 _VS_NC='\033[0m'
37else
38 _VS_RED=''
39 _VS_YELLOW=''
40 _VS_NC=''
41fi
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#
59validate_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 local has_parse_fail has_purgatory
112 has_parse_fail=$(journalctl -u "$service_name" --since "7 days ago" 2>/dev/null | grep -c '\[PARSE_FAIL\]' || echo "0")
113 has_purgatory=$(journalctl -u "$service_name" --since "7 days ago" 2>/dev/null | grep -c '\[PURGATORY_EXPIRED\]' || echo "0")
114
115 # Strip any non-numeric characters (grep -c can have trailing whitespace)
116 has_parse_fail="${has_parse_fail//[^0-9]/}"
117 has_purgatory="${has_purgatory//[^0-9]/}"
118 has_parse_fail="${has_parse_fail:-0}"
119 has_purgatory="${has_purgatory:-0}"
120
121 if [[ "$has_parse_fail" -eq 0 && "$has_purgatory" -eq 0 ]]; then
122 echo -e "${_VS_YELLOW}WARNING: No structured logs found in $service_name (last 7 days)${_VS_NC}" >&2
123 echo "" >&2
124 echo "This may indicate:" >&2
125 echo " 1. Wrong service (should be ngit-grasp archive service, not ngit-relay)" >&2
126 echo " 2. Structured logging not yet deployed to this ngit-grasp instance" >&2
127 echo " 3. No parse failures or purgatory expiry events in the time window" >&2
128 echo "" >&2
129 echo "To verify you have the right service:" >&2
130 echo " systemctl list-units 'ngit-grasp*' --all" >&2
131 echo " journalctl -u <service> | grep -E '\\[PARSE_FAIL\\]|\\[PURGATORY_EXPIRED\\]' | head -5" >&2
132 echo "" >&2
133
134 if [[ "$interactive" == "true" ]]; then
135 read -p "Continue anyway? (y/N) " -n 1 -r
136 echo
137 if [[ ! $REPLY =~ ^[Yy]$ ]]; then
138 return 1
139 fi
140 else
141 echo "Non-interactive mode: proceeding despite warning" >&2
142 fi
143 fi
144 fi
145
146 return 0
147}
148
149# Export the function so it can be used after sourcing
150export -f validate_service_for_structured_logging