upleb.uk

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

summaryrefslogtreecommitdiff
path: root/docs/how-to
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-23 11:44:14 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-27 20:37:59 +0000
commit4998ae6e575015f7d1a1cc75f2edd32369967bb2 (patch)
tree13bbf09c898f0d8d38156352f1cbe9e3babc309c /docs/how-to
parent323336c84613b74921ebc75bf46ccd2d8f9cd6cc (diff)
Add orchestration script for migration analysis pipeline
Adds run-migration-analysis.sh that orchestrates all 5 phases of the migration analysis with: - Parameterized inputs for relay URLs, git paths, and service name - Phase control (skip, only, from-phase options) - Dry-run mode to preview execution - Progress indicators and timing information - Error handling with continue-on-error option - Auto-detection of available features (git paths, journalctl) - Summary display with results overview
Diffstat (limited to 'docs/how-to')
-rwxr-xr-xdocs/how-to/migration-scripts/run-migration-analysis.sh716
1 files changed, 716 insertions, 0 deletions
diff --git a/docs/how-to/migration-scripts/run-migration-analysis.sh b/docs/how-to/migration-scripts/run-migration-analysis.sh
new file mode 100755
index 0000000..2ba25ab
--- /dev/null
+++ b/docs/how-to/migration-scripts/run-migration-analysis.sh
@@ -0,0 +1,716 @@
1#!/usr/bin/env bash
2#
3# run-migration-analysis.sh - Orchestrate the complete ngit-relay to ngit-grasp migration analysis
4#
5# This script runs all 5 phases of the migration analysis pipeline in sequence,
6# with proper error handling, progress reporting, and timing information.
7#
8# QUICK START:
9# # Basic usage (local analysis only - Phases 1, 3, 5)
10# ./run-migration-analysis.sh --prod-relay wss://relay.ngit.dev --archive-relay wss://archive.relay.ngit.dev
11#
12# # Full analysis including git sync check (requires VPS access)
13# ./run-migration-analysis.sh \
14# --prod-relay wss://relay.ngit.dev \
15# --archive-relay wss://archive.relay.ngit.dev \
16# --prod-git /var/lib/ngit-relay/git \
17# --archive-git /var/lib/ngit-relay-archive/git
18#
19# USAGE:
20# ./run-migration-analysis.sh [options]
21#
22# REQUIRED OPTIONS:
23# --prod-relay <url> Production relay WebSocket URL (e.g., wss://relay.ngit.dev)
24# --archive-relay <url> Archive relay WebSocket URL (e.g., wss://archive.relay.ngit.dev)
25#
26# OPTIONAL OPTIONS:
27# --prod-git <path> Git base directory for prod (enables Phase 2)
28# --archive-git <path> Git base directory for archive (enables Phase 2)
29# --service <name> Systemd service name for log extraction (enables Phase 4)
30# --output <dir> Output directory (default: work/migration-analysis-YYYYMMDD-HHMM)
31#
32# PHASE CONTROL:
33# --skip-phase-1 Skip event fetching (use existing data)
34# --skip-phase-2 Skip git sync check (use existing data)
35# --skip-phase-3 Skip categorization (use existing data)
36# --skip-phase-4 Skip log extraction (use existing data)
37# --skip-phase-5 Skip final classification
38# --only-phase-N Run only phase N (1-5)
39# --from-phase-N Start from phase N (skip earlier phases)
40#
41# OTHER OPTIONS:
42# --dry-run Show what would be executed without running
43# --continue-on-error Continue to next phase even if current phase fails
44# --help Show this help message
45#
46# PHASES:
47# Phase 1: Fetch events from both relays (~30s each, local)
48# Phase 2: Check git sync status (~20 min each, requires VPS)
49# Phase 3: Categorize and compare results (fast, local)
50# Phase 4: Extract logs from systemd (requires VPS)
51# Phase 5: Final classification (fast, local)
52#
53# EXAMPLES:
54# # Dry run to see what would happen
55# ./run-migration-analysis.sh --prod-relay wss://relay.ngit.dev --archive-relay wss://archive.relay.ngit.dev --dry-run
56#
57# # Run only Phase 1 (fetch events)
58# ./run-migration-analysis.sh --prod-relay wss://relay.ngit.dev --archive-relay wss://archive.relay.ngit.dev --only-phase-1
59#
60# # Resume from Phase 3 using existing Phase 1-2 data
61# ./run-migration-analysis.sh --prod-relay wss://relay.ngit.dev --archive-relay wss://archive.relay.ngit.dev --from-phase-3 --output work/migration-analysis-20260122-1430
62#
63# # Full analysis on VPS with all features
64# ./run-migration-analysis.sh \
65# --prod-relay wss://relay.ngit.dev \
66# --archive-relay wss://archive.relay.ngit.dev \
67# --prod-git /var/lib/ngit-relay/git \
68# --archive-git /var/lib/ngit-relay-archive/git \
69# --service ngit-grasp.service
70#
71# SEE ALSO:
72# docs/how-to/migrate-ngit-relay-to-ngit-grasp.md - Full migration guide
73#
74
75set -euo pipefail
76
77# Get script directory for finding other scripts
78SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
79
80# Colors for output (disabled if not a terminal)
81if [[ -t 1 ]]; then
82 RED='\033[0;31m'
83 GREEN='\033[0;32m'
84 YELLOW='\033[0;33m'
85 BLUE='\033[0;34m'
86 CYAN='\033[0;36m'
87 BOLD='\033[1m'
88 NC='\033[0m'
89else
90 RED=''
91 GREEN=''
92 YELLOW=''
93 BLUE=''
94 CYAN=''
95 BOLD=''
96 NC=''
97fi
98
99# Logging functions
100log_header() {
101 echo ""
102 echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${NC}"
103 echo -e "${BOLD}${CYAN} $*${NC}"
104 echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${NC}"
105 echo ""
106}
107
108log_phase() {
109 echo ""
110 echo -e "${BOLD}${BLUE}┌──────────────────────────────────────────────────────────────┐${NC}"
111 echo -e "${BOLD}${BLUE}│ $*${NC}"
112 echo -e "${BOLD}${BLUE}└──────────────────────────────────────────────────────────────┘${NC}"
113}
114
115log_info() {
116 echo -e "${BLUE}[INFO]${NC} $*" >&2
117}
118
119log_success() {
120 echo -e "${GREEN}[OK]${NC} $*" >&2
121}
122
123log_warn() {
124 echo -e "${YELLOW}[WARN]${NC} $*" >&2
125}
126
127log_error() {
128 echo -e "${RED}[ERROR]${NC} $*" >&2
129}
130
131log_step() {
132 echo -e "${CYAN} →${NC} $*" >&2
133}
134
135# Default values
136PROD_RELAY=""
137ARCHIVE_RELAY=""
138PROD_GIT=""
139ARCHIVE_GIT=""
140SERVICE_NAME=""
141OUTPUT_DIR=""
142DRY_RUN=false
143CONTINUE_ON_ERROR=false
144
145# Phase control
146SKIP_PHASE_1=false
147SKIP_PHASE_2=false
148SKIP_PHASE_3=false
149SKIP_PHASE_4=false
150SKIP_PHASE_5=false
151ONLY_PHASE=""
152FROM_PHASE=""
153
154# Timing
155declare -A PHASE_TIMES
156
157usage() {
158 head -80 "$0" | tail -n +3 | sed 's/^# //' | sed 's/^#//'
159 exit 0
160}
161
162# Parse command line arguments
163parse_args() {
164 while [[ $# -gt 0 ]]; do
165 case "$1" in
166 --prod-relay)
167 PROD_RELAY="$2"
168 shift 2
169 ;;
170 --archive-relay)
171 ARCHIVE_RELAY="$2"
172 shift 2
173 ;;
174 --prod-git)
175 PROD_GIT="$2"
176 shift 2
177 ;;
178 --archive-git)
179 ARCHIVE_GIT="$2"
180 shift 2
181 ;;
182 --service)
183 SERVICE_NAME="$2"
184 shift 2
185 ;;
186 --output)
187 OUTPUT_DIR="$2"
188 shift 2
189 ;;
190 --skip-phase-1)
191 SKIP_PHASE_1=true
192 shift
193 ;;
194 --skip-phase-2)
195 SKIP_PHASE_2=true
196 shift
197 ;;
198 --skip-phase-3)
199 SKIP_PHASE_3=true
200 shift
201 ;;
202 --skip-phase-4)
203 SKIP_PHASE_4=true
204 shift
205 ;;
206 --skip-phase-5)
207 SKIP_PHASE_5=true
208 shift
209 ;;
210 --only-phase-1|--only-phase-2|--only-phase-3|--only-phase-4|--only-phase-5)
211 ONLY_PHASE="${1#--only-phase-}"
212 shift
213 ;;
214 --from-phase-1|--from-phase-2|--from-phase-3|--from-phase-4|--from-phase-5)
215 FROM_PHASE="${1#--from-phase-}"
216 shift
217 ;;
218 --dry-run)
219 DRY_RUN=true
220 shift
221 ;;
222 --continue-on-error)
223 CONTINUE_ON_ERROR=true
224 shift
225 ;;
226 --help|-h)
227 usage
228 ;;
229 *)
230 log_error "Unknown option: $1"
231 echo "Use --help for usage information."
232 exit 1
233 ;;
234 esac
235 done
236}
237
238# Validate required arguments
239validate_args() {
240 local errors=0
241
242 if [[ -z "$PROD_RELAY" ]]; then
243 log_error "Missing required option: --prod-relay"
244 errors=1
245 fi
246
247 if [[ -z "$ARCHIVE_RELAY" ]]; then
248 log_error "Missing required option: --archive-relay"
249 errors=1
250 fi
251
252 # Validate relay URLs
253 if [[ -n "$PROD_RELAY" && ! "$PROD_RELAY" =~ ^wss?:// ]]; then
254 log_error "Invalid prod relay URL: $PROD_RELAY (must start with ws:// or wss://)"
255 errors=1
256 fi
257
258 if [[ -n "$ARCHIVE_RELAY" && ! "$ARCHIVE_RELAY" =~ ^wss?:// ]]; then
259 log_error "Invalid archive relay URL: $ARCHIVE_RELAY (must start with ws:// or wss://)"
260 errors=1
261 fi
262
263 # Validate git paths if provided
264 if [[ -n "$PROD_GIT" && ! -d "$PROD_GIT" ]]; then
265 log_warn "Prod git directory not found: $PROD_GIT"
266 log_warn "Phase 2 will fail unless running on VPS with access to this path."
267 fi
268
269 if [[ -n "$ARCHIVE_GIT" && ! -d "$ARCHIVE_GIT" ]]; then
270 log_warn "Archive git directory not found: $ARCHIVE_GIT"
271 log_warn "Phase 2 will fail unless running on VPS with access to this path."
272 fi
273
274 if [[ $errors -eq 1 ]]; then
275 echo ""
276 echo "Use --help for usage information."
277 exit 1
278 fi
279}
280
281# Check prerequisites
282check_prerequisites() {
283 local missing=0
284
285 log_info "Checking prerequisites..."
286
287 # Required tools
288 for tool in nak jq awk sort; do
289 if command -v "$tool" &> /dev/null; then
290 log_step "$tool: found"
291 else
292 log_error "$tool: NOT FOUND"
293 missing=1
294 fi
295 done
296
297 # Optional tools
298 if command -v journalctl &> /dev/null; then
299 log_step "journalctl: found (Phase 4 available)"
300 else
301 log_step "journalctl: not found (Phase 4 will be skipped)"
302 SKIP_PHASE_4=true
303 fi
304
305 if [[ $missing -eq 1 ]]; then
306 log_error "Missing required tools. Install them and try again."
307 exit 1
308 fi
309
310 # Check scripts exist
311 for script in 01-fetch-events.sh 10-check-git-sync.sh 20-categorize.sh 21-compare-relays.sh 30-extract-parse-failures.sh 31-extract-purgatory-expiry.sh 40-classify-actions.sh; do
312 if [[ ! -x "$SCRIPT_DIR/$script" ]]; then
313 log_error "Script not found or not executable: $SCRIPT_DIR/$script"
314 missing=1
315 fi
316 done
317
318 if [[ $missing -eq 1 ]]; then
319 exit 1
320 fi
321
322 log_success "All prerequisites satisfied"
323}
324
325# Determine which phases to run
326determine_phases() {
327 # Handle --only-phase-N
328 if [[ -n "$ONLY_PHASE" ]]; then
329 for i in 1 2 3 4 5; do
330 if [[ "$i" != "$ONLY_PHASE" ]]; then
331 eval "SKIP_PHASE_$i=true"
332 fi
333 done
334 fi
335
336 # Handle --from-phase-N
337 if [[ -n "$FROM_PHASE" ]]; then
338 for i in 1 2 3 4 5; do
339 if [[ "$i" -lt "$FROM_PHASE" ]]; then
340 eval "SKIP_PHASE_$i=true"
341 fi
342 done
343 fi
344
345 # Auto-skip Phase 2 if git paths not provided
346 if [[ -z "$PROD_GIT" && -z "$ARCHIVE_GIT" ]]; then
347 if [[ "$SKIP_PHASE_2" != "true" ]]; then
348 log_warn "No git paths provided. Phase 2 (git sync check) will be skipped."
349 log_warn "Use --prod-git and --archive-git to enable Phase 2."
350 SKIP_PHASE_2=true
351 fi
352 fi
353
354 # Auto-skip Phase 4 if service not provided
355 if [[ -z "$SERVICE_NAME" ]]; then
356 if [[ "$SKIP_PHASE_4" != "true" ]]; then
357 log_warn "No service name provided. Phase 4 (log extraction) will be skipped."
358 log_warn "Use --service to enable Phase 4."
359 SKIP_PHASE_4=true
360 fi
361 fi
362}
363
364# Setup output directory
365setup_output_dir() {
366 if [[ -z "$OUTPUT_DIR" ]]; then
367 OUTPUT_DIR="work/migration-analysis-$(date +%Y%m%d-%H%M)"
368 fi
369
370 log_info "Output directory: $OUTPUT_DIR"
371
372 if [[ "$DRY_RUN" == "true" ]]; then
373 log_info "[DRY RUN] Would create directory structure"
374 return
375 fi
376
377 mkdir -p "$OUTPUT_DIR"/{prod/raw,archive/raw,comparison,logs,results}
378
379 # Save configuration
380 cat > "$OUTPUT_DIR/config.txt" << EOF
381# Migration Analysis Configuration
382# Generated: $(date -Iseconds)
383
384PROD_RELAY=$PROD_RELAY
385ARCHIVE_RELAY=$ARCHIVE_RELAY
386PROD_GIT=$PROD_GIT
387ARCHIVE_GIT=$ARCHIVE_GIT
388SERVICE_NAME=$SERVICE_NAME
389OUTPUT_DIR=$OUTPUT_DIR
390EOF
391
392 log_success "Created output directory structure"
393}
394
395# Run a phase with timing and error handling
396run_phase() {
397 local phase_num="$1"
398 local phase_name="$2"
399 shift 2
400 local cmd=("$@")
401
402 local skip_var="SKIP_PHASE_$phase_num"
403 if [[ "${!skip_var}" == "true" ]]; then
404 log_phase "Phase $phase_num: $phase_name [SKIPPED]"
405 return 0
406 fi
407
408 log_phase "Phase $phase_num: $phase_name"
409
410 if [[ "$DRY_RUN" == "true" ]]; then
411 log_info "[DRY RUN] Would execute:"
412 for c in "${cmd[@]}"; do
413 echo " $c"
414 done
415 return 0
416 fi
417
418 local start_time
419 start_time=$(date +%s)
420
421 local exit_code=0
422
423 # Execute the command(s)
424 for c in "${cmd[@]}"; do
425 log_step "Running: $c"
426 if ! eval "$c"; then
427 exit_code=1
428 if [[ "$CONTINUE_ON_ERROR" == "true" ]]; then
429 log_warn "Command failed, continuing due to --continue-on-error"
430 else
431 log_error "Command failed"
432 break
433 fi
434 fi
435 done
436
437 local end_time
438 end_time=$(date +%s)
439 local duration=$((end_time - start_time))
440 PHASE_TIMES[$phase_num]=$duration
441
442 if [[ $exit_code -eq 0 ]]; then
443 log_success "Phase $phase_num completed in ${duration}s"
444 else
445 log_error "Phase $phase_num failed after ${duration}s"
446 if [[ "$CONTINUE_ON_ERROR" != "true" ]]; then
447 return 1
448 fi
449 fi
450
451 return $exit_code
452}
453
454# Phase 1: Fetch events
455run_phase_1() {
456 local cmds=()
457
458 # Fetch from prod relay
459 cmds+=("'$SCRIPT_DIR/01-fetch-events.sh' '$PROD_RELAY' '$OUTPUT_DIR/prod'")
460
461 # Fetch from archive relay
462 cmds+=("'$SCRIPT_DIR/01-fetch-events.sh' '$ARCHIVE_RELAY' '$OUTPUT_DIR/archive'")
463
464 run_phase 1 "Fetch Events (~30s each)" "${cmds[@]}"
465}
466
467# Phase 2: Git sync check
468run_phase_2() {
469 local cmds=()
470
471 if [[ -n "$PROD_GIT" ]]; then
472 cmds+=("'$SCRIPT_DIR/10-check-git-sync.sh' '$OUTPUT_DIR/prod/raw/state-events.json' '$PROD_GIT' '$OUTPUT_DIR/prod' --categorize")
473 else
474 log_warn "Skipping prod git sync check (no --prod-git provided)"
475 fi
476
477 if [[ -n "$ARCHIVE_GIT" ]]; then
478 cmds+=("'$SCRIPT_DIR/10-check-git-sync.sh' '$OUTPUT_DIR/archive/raw/state-events.json' '$ARCHIVE_GIT' '$OUTPUT_DIR/archive' --categorize")
479 else
480 log_warn "Skipping archive git sync check (no --archive-git provided)"
481 fi
482
483 if [[ ${#cmds[@]} -eq 0 ]]; then
484 log_warn "No git paths provided, skipping Phase 2"
485 return 0
486 fi
487
488 run_phase 2 "Git Sync Check (~20 min each)" "${cmds[@]}"
489}
490
491# Phase 3: Categorize and compare
492run_phase_3() {
493 local cmds=()
494
495 # Check if we have git-sync-status.tsv files (from Phase 2)
496 # If not, we can't run categorization
497 local has_prod_sync=false
498 local has_archive_sync=false
499
500 if [[ -f "$OUTPUT_DIR/prod/git-sync-status.tsv" ]]; then
501 has_prod_sync=true
502 fi
503
504 if [[ -f "$OUTPUT_DIR/archive/git-sync-status.tsv" ]]; then
505 has_archive_sync=true
506 fi
507
508 # Run categorization if we have sync data but no category files
509 if [[ "$has_prod_sync" == "true" && ! -f "$OUTPUT_DIR/prod/category1-complete-match.txt" ]]; then
510 cmds+=("'$SCRIPT_DIR/20-categorize.sh' '$OUTPUT_DIR/prod/git-sync-status.tsv' '$OUTPUT_DIR/prod'")
511 fi
512
513 if [[ "$has_archive_sync" == "true" && ! -f "$OUTPUT_DIR/archive/category1-complete-match.txt" ]]; then
514 cmds+=("'$SCRIPT_DIR/20-categorize.sh' '$OUTPUT_DIR/archive/git-sync-status.tsv' '$OUTPUT_DIR/archive'")
515 fi
516
517 # Run comparison if we have category files
518 if [[ -f "$OUTPUT_DIR/prod/category1-complete-match.txt" && -f "$OUTPUT_DIR/archive/category1-complete-match.txt" ]]; then
519 cmds+=("'$SCRIPT_DIR/21-compare-relays.sh' '$OUTPUT_DIR/prod' '$OUTPUT_DIR/archive' '$OUTPUT_DIR/comparison'")
520 else
521 log_warn "Missing category files for comparison."
522 log_warn "Phase 2 must complete successfully before Phase 3 can compare relays."
523
524 # Create placeholder comparison files if they don't exist
525 if [[ "$DRY_RUN" != "true" ]]; then
526 mkdir -p "$OUTPUT_DIR/comparison"
527 for f in complete-in-both.txt complete-prod-missing-archive.txt complete-prod-incomplete-archive.txt incomplete-in-both.txt in-archive-not-prod.txt; do
528 if [[ ! -f "$OUTPUT_DIR/comparison/$f" ]]; then
529 echo "# Placeholder - Phase 2 data not available" > "$OUTPUT_DIR/comparison/$f"
530 fi
531 done
532 echo "# Comparison not available - Phase 2 data missing" > "$OUTPUT_DIR/comparison/summary.txt"
533 fi
534 fi
535
536 if [[ ${#cmds[@]} -eq 0 ]]; then
537 log_warn "No categorization or comparison needed (already done or missing input)"
538 return 0
539 fi
540
541 run_phase 3 "Categorize & Compare (fast)" "${cmds[@]}"
542}
543
544# Phase 4: Extract logs
545run_phase_4() {
546 if [[ -z "$SERVICE_NAME" ]]; then
547 log_warn "No service name provided, skipping Phase 4"
548 return 0
549 fi
550
551 local cmds=()
552
553 cmds+=("'$SCRIPT_DIR/30-extract-parse-failures.sh' '$SERVICE_NAME' '$OUTPUT_DIR/logs'")
554 cmds+=("'$SCRIPT_DIR/31-extract-purgatory-expiry.sh' '$SERVICE_NAME' '$OUTPUT_DIR/logs'")
555
556 run_phase 4 "Extract Logs (VPS required)" "${cmds[@]}"
557}
558
559# Phase 5: Final classification
560run_phase_5() {
561 # Check if we have the minimum required files
562 local can_run=true
563
564 if [[ ! -d "$OUTPUT_DIR/prod" ]]; then
565 log_warn "Missing prod directory"
566 can_run=false
567 fi
568
569 if [[ ! -d "$OUTPUT_DIR/archive" ]]; then
570 log_warn "Missing archive directory"
571 can_run=false
572 fi
573
574 if [[ ! -d "$OUTPUT_DIR/comparison" ]]; then
575 log_warn "Missing comparison directory"
576 can_run=false
577 fi
578
579 # Create logs directory with empty files if missing
580 if [[ "$DRY_RUN" != "true" ]]; then
581 mkdir -p "$OUTPUT_DIR/logs"
582 for f in parse-failures.txt purgatory-expired.txt; do
583 if [[ ! -f "$OUTPUT_DIR/logs/$f" ]]; then
584 echo "# No data - Phase 4 not run" > "$OUTPUT_DIR/logs/$f"
585 fi
586 done
587 fi
588
589 if [[ "$can_run" == "false" ]]; then
590 log_error "Cannot run Phase 5 - missing required input directories"
591 return 1
592 fi
593
594 run_phase 5 "Final Classification (fast)" "'$SCRIPT_DIR/40-classify-actions.sh' '$OUTPUT_DIR'"
595}
596
597# Display summary
598display_summary() {
599 log_header "Migration Analysis Complete"
600
601 echo "Output Directory: $OUTPUT_DIR"
602 echo ""
603
604 # Phase timing summary
605 echo "Phase Timing:"
606 local total_time=0
607 for phase in 1 2 3 4 5; do
608 local skip_var="SKIP_PHASE_$phase"
609 if [[ "${!skip_var}" == "true" ]]; then
610 echo " Phase $phase: SKIPPED"
611 elif [[ -n "${PHASE_TIMES[$phase]:-}" ]]; then
612 local t="${PHASE_TIMES[$phase]}"
613 echo " Phase $phase: ${t}s"
614 total_time=$((total_time + t))
615 else
616 echo " Phase $phase: N/A"
617 fi
618 done
619 echo " ─────────────"
620 echo " Total: ${total_time}s"
621 echo ""
622
623 # Results summary
624 if [[ -f "$OUTPUT_DIR/results/summary.txt" ]]; then
625 echo "Results Summary:"
626 echo ""
627 # Extract key metrics from summary
628 if grep -q "No Action Required" "$OUTPUT_DIR/results/summary.txt"; then
629 grep -A1 "No Action Required" "$OUTPUT_DIR/results/summary.txt" | head -2
630 fi
631 if grep -q "Action Required" "$OUTPUT_DIR/results/summary.txt"; then
632 grep -A1 "Action Required" "$OUTPUT_DIR/results/summary.txt" | head -2
633 fi
634 if grep -q "Manual Investigation" "$OUTPUT_DIR/results/summary.txt"; then
635 grep -A1 "Manual Investigation" "$OUTPUT_DIR/results/summary.txt" | head -2
636 fi
637 echo ""
638 fi
639
640 # Output files
641 echo "Output Files:"
642 echo " $OUTPUT_DIR/results/no-action-required.txt"
643 echo " $OUTPUT_DIR/results/action-required.txt"
644 echo " $OUTPUT_DIR/results/manual-investigation.txt"
645 echo " $OUTPUT_DIR/results/summary.txt"
646 echo ""
647
648 # Next steps
649 echo "Next Steps:"
650 echo " 1. Review results/summary.txt for overview"
651 echo " 2. Address items in results/action-required.txt"
652 echo " 3. Investigate items in results/manual-investigation.txt"
653 echo " 4. Plan migration window when action items are resolved"
654 echo ""
655}
656
657# Main
658main() {
659 parse_args "$@"
660
661 log_header "ngit-relay to ngit-grasp Migration Analysis"
662
663 validate_args
664 check_prerequisites
665 determine_phases
666 setup_output_dir
667
668 # Show configuration
669 log_info "Configuration:"
670 log_step "Prod relay: $PROD_RELAY"
671 log_step "Archive relay: $ARCHIVE_RELAY"
672 [[ -n "$PROD_GIT" ]] && log_step "Prod git: $PROD_GIT"
673 [[ -n "$ARCHIVE_GIT" ]] && log_step "Archive git: $ARCHIVE_GIT"
674 [[ -n "$SERVICE_NAME" ]] && log_step "Service: $SERVICE_NAME"
675 log_step "Output: $OUTPUT_DIR"
676 echo ""
677
678 # Show phase plan
679 log_info "Phase Plan:"
680 for phase in 1 2 3 4 5; do
681 local skip_var="SKIP_PHASE_$phase"
682 if [[ "${!skip_var}" == "true" ]]; then
683 log_step "Phase $phase: SKIP"
684 else
685 log_step "Phase $phase: RUN"
686 fi
687 done
688 echo ""
689
690 if [[ "$DRY_RUN" == "true" ]]; then
691 log_warn "DRY RUN MODE - No changes will be made"
692 echo ""
693 fi
694
695 # Run phases
696 local overall_exit=0
697
698 run_phase_1 || overall_exit=1
699 run_phase_2 || overall_exit=1
700 run_phase_3 || overall_exit=1
701 run_phase_4 || overall_exit=1
702 run_phase_5 || overall_exit=1
703
704 # Display summary
705 if [[ "$DRY_RUN" != "true" ]]; then
706 display_summary
707 fi
708
709 if [[ $overall_exit -ne 0 ]]; then
710 log_warn "Some phases failed. Review output for details."
711 fi
712
713 exit $overall_exit
714}
715
716main "$@"