upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/how-to/migrate-to-ngit-grasp.md69
-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
5 files changed, 304 insertions, 11 deletions
diff --git a/docs/how-to/migrate-to-ngit-grasp.md b/docs/how-to/migrate-to-ngit-grasp.md
index 9b812a5..00af6c8 100644
--- a/docs/how-to/migrate-to-ngit-grasp.md
+++ b/docs/how-to/migrate-to-ngit-grasp.md
@@ -122,19 +122,36 @@ ls /path/to/git/npub1*/ # Should show *.git directories
122 122
123### Phase 4 Needs the Correct Service Name 123### Phase 4 Needs the Correct Service Name
124 124
125Phase 4 extracts structured logs (`[PARSE_FAIL]`, `[PURGATORY_EXPIRED]`) from journald. You must specify the service that has these logs - typically the **archive** service (ngit-grasp), not the production service (ngit-relay). 125> **CRITICAL:** Phase 4 extracts structured logs (`[PARSE_FAIL]`, `[PURGATORY_EXPIRED]`) from journald. These logs **ONLY exist in ngit-grasp services**, NOT in ngit-relay services.
126
127If you specify an ngit-relay service (like `ngit-relay.service`), Phase 4 will find **zero logs** and produce empty results. This is a common mistake that wastes time and produces misleading analysis.
128
129**Correct service names (ngit-grasp):**
130- `ngit-grasp.service`
131- `ngit-grasp-relay-ngit-dev.service` (NixOS multi-instance)
132- `ngit-grasp-archive.service`
133
134**Incorrect service names (ngit-relay - NO structured logging):**
135- `ngit-relay.service`
136- `relay-ngit-dev.service`
126 137
127```bash 138```bash
128# Find all ngit-related services 139# Find all ngit-related services
129systemctl list-units 'ngit-*' --all 140systemctl list-units 'ngit-*' --all
130 141
131# Check which service has structured logging 142# Check which service has structured logging (should be ngit-grasp)
132journalctl -u ngit-grasp-*.service | grep -E '\[PARSE_FAIL\]|\[PURGATORY_EXPIRED\]' | head -5 143journalctl -u ngit-grasp-*.service | grep -E '\[PARSE_FAIL\]|\[PURGATORY_EXPIRED\]' | head -5
133 144
145# Verify ngit-relay does NOT have structured logging
146journalctl -u ngit-relay.service | grep -E '\[PARSE_FAIL\]|\[PURGATORY_EXPIRED\]' | head -5
147# ^ This should return nothing
148
134# Use the archive service name for Phase 4 149# Use the archive service name for Phase 4
135./run-migration-analysis.sh ... --service ngit-grasp-relay-ngit-dev.service 150./run-migration-analysis.sh ... --service ngit-grasp-relay-ngit-dev.service
136``` 151```
137 152
153The migration scripts now validate the service name and will **error** if you specify an ngit-relay service, preventing this common mistake.
154
138### Permission Issues with Service-Owned Directories 155### Permission Issues with Service-Owned Directories
139 156
140Git data directories are typically owned by the service user and may require elevated permissions to read. 157Git data directories are typically owned by the service user and may require elevated permissions to read.
@@ -273,7 +290,7 @@ Skip or run specific phases:
273| `--archive-relay <url>` | Target relay WebSocket URL (required) | 290| `--archive-relay <url>` | Target relay WebSocket URL (required) |
274| `--prod-git <path>` | Git base directory for prod (enables Phase 2) | 291| `--prod-git <path>` | Git base directory for prod (enables Phase 2) |
275| `--archive-git <path>` | Git base directory for archive (enables Phase 2) | 292| `--archive-git <path>` | Git base directory for archive (enables Phase 2) |
276| `--service <name>` | Systemd service name (enables Phase 4) | 293| `--service <name>` | Systemd service name for Phase 4 log extraction. **MUST be an ngit-grasp service** (not ngit-relay). Structured logging only exists in ngit-grasp. |
277| `--output <dir>` | Output directory (default: auto-generated) | 294| `--output <dir>` | Output directory (default: auto-generated) |
278| `--skip-phase-N` | Skip phase N (1-5) | 295| `--skip-phase-N` | Skip phase N (1-5) |
279| `--only-phase-N` | Run only phase N | 296| `--only-phase-N` | Run only phase N |
@@ -427,16 +444,50 @@ The analysis will continue without log data.
427 444
428### Phase 4 finds no structured logs 445### Phase 4 finds no structured logs
429 446
430Structured logging (`[PARSE_FAIL]`, `[PURGATORY_EXPIRED]`) is only available in ngit-grasp. If checking an ngit-relay service, no structured logs will be found. 447**Symptom:** Phase 4 completes but `parse-failures.txt` and `purgatory-expired.txt` are empty or contain only header comments.
448
449**Most common cause:** You're querying the wrong service (ngit-relay instead of ngit-grasp).
450
451Structured logging (`[PARSE_FAIL]`, `[PURGATORY_EXPIRED]`) **only exists in ngit-grasp services**. If you specify an ngit-relay service, Phase 4 will find zero logs.
452
453**How to diagnose:**
431 454
432```bash 455```bash
433# Verify you're checking the right service (should be ngit-grasp) 456# 1. Check what service you configured
434journalctl -u ngit-grasp-*.service | grep -E '\[PARSE_FAIL\]|\[PURGATORY_EXPIRED\]' | head -5 457cat /path/to/output/config.txt | grep SERVICE_NAME
435 458
436# If checking ngit-relay, structured logs won't exist 459# 2. If it contains "ngit-relay", that's the problem!
437# Use --service with the ngit-grasp archive service name instead 460# ngit-relay does NOT have structured logging
461
462# 3. Find the correct ngit-grasp service
463systemctl list-units 'ngit-grasp*' --all
464
465# 4. Verify the ngit-grasp service has structured logs
466journalctl -u ngit-grasp-relay-ngit-dev.service --since "7 days ago" | \
467 grep -E '\[PARSE_FAIL\]|\[PURGATORY_EXPIRED\]' | head -5
438``` 468```
439 469
470**How to fix:**
471
472```bash
473# Update SERVICE_NAME to the ngit-grasp archive service and re-run
474./run-migration-analysis.sh \
475 --prod-relay wss://relay.ngit.dev \
476 --archive-relay ws://localhost:7443 \
477 --service ngit-grasp-relay-ngit-dev.service \
478 --from-phase-4 # Skip phases 1-3, just re-run phase 4
479```
480
481**Other possible causes:**
482
4831. **Structured logging not deployed:** If the ngit-grasp instance doesn't have the logging improvements deployed, no structured logs will exist. Check the ngit-grasp version.
484
4852. **No events in time window:** If there genuinely were no parse failures or purgatory expiry events, the files will be empty. This is valid - it means everything parsed successfully.
486
4873. **Wrong time range:** The default is 30 days. If your archive has been running longer, you may need `--since` to extend the range.
488
489**Prevention:** The migration scripts now validate the service name and will error if you specify an ngit-relay service.
490
440### Event counts are multiples of 250 491### Event counts are multiples of 250
441 492
442This suggests pagination may have failed. The scripts use `--paginate` by default, but if you see exactly 250, 500, 750 events, verify the relay is responding correctly. 493This suggests pagination may have failed. The scripts use `--paginate` by default, but if you see exactly 250, 500, 750 events, verify the relay is responding correctly.
@@ -645,7 +696,7 @@ This section documents the specific configuration and lessons learned from migra
645 696
6462. **Check archive accessibility**: We initially tried to run analysis remotely, but the archive relay was localhost-only. Had to SSH to VPS. 6972. **Check archive accessibility**: We initially tried to run analysis remotely, but the archive relay was localhost-only. Had to SSH to VPS.
647 698
6483. **Use archive service for Phase 4**: Structured logging (`[PARSE_FAIL]`, `[PURGATORY_EXPIRED]`) is in the ngit-grasp archive service, not the ngit-relay production service. 6993. **Use archive service for Phase 4 (CRITICAL)**: Structured logging (`[PARSE_FAIL]`, `[PURGATORY_EXPIRED]`) is **ONLY** in the ngit-grasp archive service, NOT the ngit-relay production service. Running Phase 4 against `ngit-relay.service` produces zero results because ngit-relay doesn't emit structured logs. The scripts now validate this and error if you specify an ngit-relay service.
649 700
6504. **Install git on VPS**: Git wasn't installed on the minimal VPS. The scripts now check for this in prerequisites. 7014. **Install git on VPS**: Git wasn't installed on the minimal VPS. The scripts now check for this in prerequisites.
651 702
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