-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·1607 lines (1325 loc) · 44 KB
/
install.sh
File metadata and controls
executable file
·1607 lines (1325 loc) · 44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
#
# Script Name: install.sh
# Description: AI Command Auditor Installer - One-command installation and setup
# Author: Etherisc
# Date: 2024
# Version: 1.0
#
# Usage: curl -fsSL https://raw.githubusercontent.com/etherisc/ai-command-auditor/main/install.sh | sh
# Example: curl -fsSL https://raw.githubusercontent.com/etherisc/ai-command-auditor/main/install.sh | sh -s -- --template python --verbose
#
set -euo pipefail # Exit on error, undefined vars, pipe failures
# Constants
readonly SCRIPT_NAME="$(basename "$0")"
readonly LOG_FILE="/tmp/ai-auditor-install.log"
readonly PACKAGE_NAME="ai-command-auditor"
readonly GITHUB_REPO="etherisc/ai-command-auditor"
readonly MIN_PYTHON_VERSION="3.8"
# Global variables
VERBOSE=false
QUIET=false
DRY_RUN=false
FORCE=false
CONFIG_DIR=".ai-auditor"
TEMPLATE="general"
INSTALL_HOOKS=true
INSTALL_CI=true
SYSTEM_WIDE=false
PYTHON_CMD=""
PIP_CMD=""
INSTALL_LOG=""
# Color codes for output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m' # No Color
# Logging functions
log() {
local level="$1"
shift
local message="$*"
local timestamp
timestamp="$(date +'%Y-%m-%d %H:%M:%S')"
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
if [[ "$level" == "ERROR" ]]; then
echo -e "${RED}ERROR: $message${NC}" >&2
elif [[ "$level" == "WARN" ]]; then
echo -e "${YELLOW}WARNING: $message${NC}" >&2
elif [[ "$level" == "INFO" ]]; then
if [[ "$QUIET" != true ]]; then
echo -e "${BLUE}INFO: $message${NC}"
fi
elif [[ "$level" == "SUCCESS" ]]; then
if [[ "$QUIET" != true ]]; then
echo -e "${GREEN}✓ $message${NC}"
fi
elif [[ "$level" == "DEBUG" ]]; then
if [[ "$VERBOSE" == true ]]; then
echo -e "${BLUE}DEBUG: $message${NC}"
fi
fi
}
info() {
log "INFO" "$@"
}
success() {
log "SUCCESS" "$@"
}
warn() {
log "WARN" "$@"
}
error() {
log "ERROR" "$@"
}
debug() {
log "DEBUG" "$@"
}
# Progress indicator
show_progress() {
local current="$1"
local total="$2"
local task="$3"
if [[ "$QUIET" != true ]]; then
echo -e "${BLUE}[$current/$total] $task${NC}"
fi
}
# Usage information
usage() {
cat << EOF
Usage: $SCRIPT_NAME [OPTIONS]
AI Command Auditor Installer - One-command installation and setup
OPTIONS:
-h, --help Show this help message
-v, --verbose Enable verbose output
-q, --quiet Minimal output mode
-d, --dry-run Show what would be done without executing
-f, --force Force installation even if already installed
--config-dir=PATH Custom config directory (default: .ai-auditor)
--template=TYPE Template selection: python, node, rust, general, security (default: general)
--no-hooks Skip git hooks setup
--no-ci Skip GitHub Actions setup
--system-wide Install globally for all projects
EXAMPLES:
# Basic installation
$SCRIPT_NAME
# Python project with verbose output
$SCRIPT_NAME --template python --verbose
# Install without git hooks
$SCRIPT_NAME --no-hooks --template general
# Dry run to see what would happen
$SCRIPT_NAME --dry-run --verbose
For more information, visit: https://github.com/$GITHUB_REPO
EOF
}
# Error cleanup
cleanup_on_error() {
local exit_code=$?
error "Installation failed with exit code $exit_code"
error "Rolling back changes..."
# Rollback logic
if [[ -n "${INSTALL_LOG:-}" ]] && [[ -f "$INSTALL_LOG" ]]; then
debug "Installation log available at: $INSTALL_LOG"
fi
# Remove partially created config directory
if [[ -d "$CONFIG_DIR" ]] && [[ "$DRY_RUN" != true ]]; then
warn "Removing partially created config directory: $CONFIG_DIR"
rm -rf "$CONFIG_DIR" || true
fi
error "Installation failed. Check the log file: $LOG_FILE"
error "For help, visit: https://github.com/$GITHUB_REPO/issues"
exit $exit_code
}
# Set up error trap
trap cleanup_on_error ERR
# Command validation
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Version comparison
version_compare() {
# Compare versions in format x.y.z
# Returns 0 if version1 >= version2, 1 otherwise
local version1="$1"
local version2="$2"
# Convert to comparable format
local v1_major v1_minor v1_patch
local v2_major v2_minor v2_patch
IFS='.' read -r v1_major v1_minor v1_patch <<< "$version1"
IFS='.' read -r v2_major v2_minor v2_patch <<< "$version2"
# Default patch versions to 0 if not provided
v1_patch=${v1_patch:-0}
v2_patch=${v2_patch:-0}
# Compare major version
if [[ $v1_major -gt $v2_major ]]; then
return 0
elif [[ $v1_major -lt $v2_major ]]; then
return 1
fi
# Compare minor version
if [[ $v1_minor -gt $v2_minor ]]; then
return 0
elif [[ $v1_minor -lt $v2_minor ]]; then
return 1
fi
# Compare patch version
if [[ $v1_patch -ge $v2_patch ]]; then
return 0
else
return 1
fi
}
# Parse command line arguments
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
exit 0
;;
-v|--verbose)
VERBOSE=true
shift
;;
-q|--quiet)
QUIET=true
shift
;;
-d|--dry-run)
DRY_RUN=true
shift
;;
-f|--force)
FORCE=true
shift
;;
--config-dir=*)
CONFIG_DIR="${1#*=}"
shift
;;
--config-dir)
CONFIG_DIR="$2"
shift 2
;;
--template=*)
TEMPLATE="${1#*=}"
shift
;;
--template)
TEMPLATE="$2"
shift 2
;;
--no-hooks)
INSTALL_HOOKS=false
shift
;;
--no-ci)
INSTALL_CI=false
shift
;;
--system-wide)
SYSTEM_WIDE=true
shift
;;
*)
error "Unknown option: $1"
usage
exit 1
;;
esac
done
# Validate template option
case "$TEMPLATE" in
python|node|rust|general|security)
debug "Using template: $TEMPLATE"
;;
*)
error "Invalid template: $TEMPLATE"
error "Valid templates: python, node, rust, general, security"
exit 1
;;
esac
# Validate config directory
if [[ -z "$CONFIG_DIR" ]]; then
error "Config directory cannot be empty"
exit 1
fi
debug "Parsed arguments:"
debug " CONFIG_DIR: $CONFIG_DIR"
debug " TEMPLATE: $TEMPLATE"
debug " INSTALL_HOOKS: $INSTALL_HOOKS"
debug " INSTALL_CI: $INSTALL_CI"
debug " SYSTEM_WIDE: $SYSTEM_WIDE"
debug " VERBOSE: $VERBOSE"
debug " QUIET: $QUIET"
debug " DRY_RUN: $DRY_RUN"
debug " FORCE: $FORCE"
}
# Print banner
print_banner() {
if [[ "$QUIET" != true ]]; then
cat << 'EOF'
╔═══════════════════════════════════════════════════════════╗
║ AI Command Auditor Installer ║
║ ║
║ Secure command validation and analysis for your ║
║ development workflow ║
╚═══════════════════════════════════════════════════════════╝
EOF
fi
info "Starting AI Command Auditor installation..."
if [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN MODE - No changes will be made"
fi
}
# Check prerequisites
check_prerequisites() {
show_progress 1 7 "Checking prerequisites"
debug "Checking system prerequisites..."
# Check for required commands
local required_commands=("curl" "python3")
local missing_commands=()
for cmd in "${required_commands[@]}"; do
if ! command_exists "$cmd"; then
missing_commands+=("$cmd")
fi
done
if [[ ${#missing_commands[@]} -gt 0 ]]; then
error "Missing required commands: ${missing_commands[*]}"
error "Please install the missing commands and try again"
exit 1
fi
success "Prerequisites check completed"
}
# Python environment detection
detect_python_environment() {
debug "Detecting Python environment..."
# Find available Python commands
local python_candidates=("python3" "python")
local found_python=""
for cmd in "${python_candidates[@]}"; do
if command_exists "$cmd"; then
local version
version=$($cmd --version 2>&1 | grep -oE '[0-9]+\.[0-9]+' | head -1)
debug "Found $cmd with version: $version"
if version_compare "$version" "$MIN_PYTHON_VERSION"; then
found_python="$cmd"
PYTHON_CMD="$cmd"
debug "Selected Python command: $PYTHON_CMD"
break
else
debug "$cmd version $version is below minimum required $MIN_PYTHON_VERSION"
fi
fi
done
if [[ -z "$found_python" ]]; then
error "Python $MIN_PYTHON_VERSION or higher is required"
error "Please install Python $MIN_PYTHON_VERSION+ and try again"
exit 1
fi
# Check for pip
local pip_candidates=("pip3" "pip")
local found_pip=""
for cmd in "${pip_candidates[@]}"; do
if command_exists "$cmd"; then
# Verify this pip works with our Python
if $cmd --version >/dev/null 2>&1; then
found_pip="$cmd"
PIP_CMD="$cmd"
debug "Selected pip command: $PIP_CMD"
break
fi
fi
done
if [[ -z "$found_pip" ]]; then
error "pip is required but not found"
error "Please install pip and try again"
exit 1
fi
# Check if we're in a virtual environment
if [[ -n "${VIRTUAL_ENV:-}" ]]; then
info "Virtual environment detected: $VIRTUAL_ENV"
debug "Will install to virtual environment"
elif [[ -n "${CONDA_DEFAULT_ENV:-}" ]]; then
info "Conda environment detected: $CONDA_DEFAULT_ENV"
debug "Will install to conda environment"
else
debug "No virtual environment detected"
if [[ "$SYSTEM_WIDE" != true ]]; then
warn "Installing to system Python - consider using a virtual environment"
fi
fi
success "Python environment detection completed"
}
# Check if package is already installed
check_existing_installation() {
debug "Checking for existing installation..."
if $PYTHON_CMD -c "import $PACKAGE_NAME" >/dev/null 2>&1; then
local installed_version
installed_version=$($PYTHON_CMD -c "import $PACKAGE_NAME; print(getattr($PACKAGE_NAME, '__version__', 'unknown'))" 2>/dev/null || echo "unknown")
if [[ "$FORCE" == true ]]; then
warn "Package $PACKAGE_NAME is already installed (version: $installed_version) - forcing reinstall"
return 1 # Not installed (force reinstall)
else
success "Package $PACKAGE_NAME is already installed (version: $installed_version)"
return 0 # Already installed
fi
else
debug "Package $PACKAGE_NAME is not installed"
return 1 # Not installed
fi
}
# Install the package
install_ai_command_auditor() {
debug "Installing AI Command Auditor package..."
local install_cmd="$PIP_CMD install"
# Add additional options based on configuration
if [[ "$VERBOSE" == true ]]; then
install_cmd="$install_cmd --verbose"
fi
if [[ "$FORCE" == true ]]; then
install_cmd="$install_cmd --force-reinstall"
fi
# For now, we'll install from the local directory (development mode)
# In production, this would be: install_cmd="$install_cmd $PACKAGE_NAME"
if [[ -f "setup.py" ]] || [[ -f "pyproject.toml" ]]; then
info "Installing from local development package..."
install_cmd="$install_cmd -e ."
else
# Fallback to PyPI (when package is published)
info "Installing from PyPI..."
install_cmd="$install_cmd $PACKAGE_NAME"
fi
debug "Installation command: $install_cmd"
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would execute: $install_cmd"
return 0
fi
# Execute installation
if $install_cmd; then
success "Package installation completed"
else
error "Package installation failed"
exit 1
fi
}
# Verify CLI installation
verify_cli_installation() {
debug "Verifying CLI installation..."
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would verify CLI installation"
return 0
fi
# Check if ai-auditor command is available
if command_exists "ai-auditor"; then
local version
version=$(ai-auditor --version 2>/dev/null || echo "unknown")
success "AI Command Auditor CLI is available (version: $version)"
else
error "AI Command Auditor CLI not found in PATH"
error "You may need to restart your terminal or add the installation directory to PATH"
exit 1
fi
}
# Main package installation function
install_package() {
show_progress 2 7 "Installing AI Command Auditor package"
detect_python_environment
# Check if already installed
if check_existing_installation; then
if [[ "$FORCE" != true ]]; then
info "Package already installed, skipping installation"
return 0
fi
fi
install_ai_command_auditor
verify_cli_installation
success "Package installation completed successfully"
}
# Check for existing configuration
check_existing_configuration() {
debug "Checking for existing configuration..."
if [[ -d "$CONFIG_DIR" ]]; then
if [[ "$FORCE" == true ]]; then
warn "Configuration directory $CONFIG_DIR exists - forcing recreation"
return 1 # Recreate config
else
info "Configuration directory $CONFIG_DIR already exists"
if [[ -f "$CONFIG_DIR/config/auditor.yml" ]]; then
success "Configuration appears to be complete"
return 0 # Config exists
else
warn "Configuration directory exists but appears incomplete"
return 1 # Recreate config
fi
fi
else
debug "Configuration directory $CONFIG_DIR does not exist"
return 1 # Create config
fi
}
# Create configuration directory structure
create_config_directory() {
debug "Creating configuration directory structure..."
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would create directory: $CONFIG_DIR"
return 0
fi
# Create main config directory
if ! mkdir -p "$CONFIG_DIR"; then
error "Failed to create configuration directory: $CONFIG_DIR"
exit 1
fi
# Create subdirectories
local subdirs=("config" "config/rules" "config/prompts" "hooks" "workflows" "logs")
for subdir in "${subdirs[@]}"; do
local full_path="$CONFIG_DIR/$subdir"
if ! mkdir -p "$full_path"; then
error "Failed to create directory: $full_path"
exit 1
fi
debug "Created directory: $full_path"
done
success "Configuration directory structure created"
}
# Apply template using AI Command Auditor CLI
apply_configuration_template() {
debug "Applying configuration template: $TEMPLATE"
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would apply template: $TEMPLATE to $CONFIG_DIR"
return 0
fi
# Check if CLI is available
if ! command_exists "ai-auditor"; then
warn "AI Command Auditor CLI not available - using fallback configuration"
create_fallback_configuration
return 0
fi
# Use the CLI to initialize with template
local init_cmd="ai-auditor init"
init_cmd="$init_cmd --template $TEMPLATE"
init_cmd="$init_cmd --config-dir $CONFIG_DIR"
# Add environment and security level if specified in template
case "$TEMPLATE" in
python)
init_cmd="$init_cmd --environment development --security-level standard"
;;
security)
init_cmd="$init_cmd --environment production --security-level strict"
;;
*)
init_cmd="$init_cmd --environment development --security-level standard"
;;
esac
debug "Template application command: $init_cmd"
# Execute template application
if $init_cmd; then
success "Template application completed"
else
warn "Template application failed - using fallback configuration"
create_fallback_configuration
fi
}
# Create fallback configuration if template application fails
create_fallback_configuration() {
debug "Creating fallback configuration..."
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would create fallback configuration"
return 0
fi
# Create basic auditor.yml
cat > "$CONFIG_DIR/config/auditor.yml" << 'EOF'
# AI Command Auditor Configuration
# This is a fallback configuration - customize as needed
# AI Configuration
ai:
model: "gpt-4o"
timeout: 30
max_retries: 3
temperature: 0.1
max_tokens: 1000
# Security Configuration
security:
max_command_length: 1000
allow_multiline: false
strict_mode: false
blocked_commands: []
# Logging Configuration
logging:
level: "INFO"
file: ".ai-auditor/logs/auditor.log"
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# Validation Configuration
validation:
enable_ai_check: true
enable_rule_check: true
require_context: false
cache_results: true
# Integration Configuration
integration:
git_hooks: true
ci_integration: true
pre_commit: true
pre_push: true
# Policy Configuration
policy:
block_on_critical: true
warn_on_high: true
log_all_matches: true
require_approval_for: ["critical", "high"]
EOF
# Create basic security rules
cat > "$CONFIG_DIR/config/rules/security-rules.yml" << 'EOF'
# Security Rules Configuration
# Customize these rules for your project needs
dangerous_patterns:
- pattern: "rm\\s+-rf\\s+/"
severity: "critical"
message: "Attempting to delete root directory"
- pattern: "sudo\\s+chmod\\s+777"
severity: "high"
message: "Setting dangerous file permissions"
- pattern: "curl.*\\|.*sh"
severity: "medium"
message: "Downloading and executing scripts from internet"
- pattern: "wget.*\\|.*sh"
severity: "medium"
message: "Downloading and executing scripts from internet"
EOF
# Create basic OpenAI prompts
cat > "$CONFIG_DIR/config/prompts/openai-prompts.yml" << 'EOF'
# OpenAI Prompts Configuration
# Customize these prompts for your analysis needs
security_analysis_prompt: |
Analyze this command for security risks:
Command: {command}
Context: {context}
Rate from 1-10 and explain any concerns:
code_review_prompt: |
Review this code change for:
- Security vulnerabilities
- Code quality issues
- Best practice violations
Code: {code}
EOF
# Create README
cat > "$CONFIG_DIR/README.md" << 'EOF'
# AI Command Auditor Configuration
This directory contains your AI Command Auditor configuration files.
## Structure
- `config/auditor.yml` - Main configuration file
- `config/rules/` - Security and validation rules
- `config/prompts/` - AI prompts for analysis
- `hooks/` - Git hook scripts (if enabled)
- `workflows/` - GitHub Actions workflows (if enabled)
- `logs/` - Application logs
## Customization
All files in this directory can be customized for your project needs.
See the documentation for details on configuration options.
## Getting Started
1. Review and customize `config/auditor.yml`
2. Add project-specific rules in `config/rules/`
3. Customize AI prompts in `config/prompts/`
4. Test your setup: `ai-auditor validate-setup`
For more information, visit: https://github.com/etherisc/ai-command-auditor
EOF
success "Fallback configuration created"
}
# Set proper file permissions
set_config_permissions() {
debug "Setting configuration file permissions..."
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would set file permissions on $CONFIG_DIR"
return 0
fi
# Set directory permissions
find "$CONFIG_DIR" -type d -exec chmod 755 {} \; 2>/dev/null || true
# Set file permissions
find "$CONFIG_DIR" -type f -exec chmod 644 {} \; 2>/dev/null || true
# Make hook scripts executable if they exist
if [[ -d "$CONFIG_DIR/hooks" ]]; then
find "$CONFIG_DIR/hooks" -name "*.sh" -exec chmod 755 {} \; 2>/dev/null || true
fi
success "File permissions set"
}
# Main configuration setup function
setup_configuration() {
show_progress 3 7 "Setting up configuration"
# Check if configuration already exists
if check_existing_configuration; then
if [[ "$FORCE" != true ]]; then
info "Configuration already exists, skipping setup"
return 0
fi
fi
create_config_directory
apply_configuration_template
set_config_permissions
success "Configuration setup completed successfully"
}
# Check if we're in a git repository and setup hooks
check_git_repository() {
debug "Checking git repository status..."
if ! git rev-parse --git-dir >/dev/null 2>&1; then
warn "Not in a git repository - git hooks will be skipped"
return 1
fi
local git_dir
git_dir=$(git rev-parse --git-dir)
debug "Git directory: $git_dir"
if [[ ! -d "$git_dir/hooks" ]]; then
debug "Creating git hooks directory"
if [[ "$DRY_RUN" != true ]]; then
mkdir -p "$git_dir/hooks"
fi
fi
return 0
}
# Check for existing git hooks
check_existing_hooks() {
local hook_name="$1"
local git_dir
git_dir=$(git rev-parse --git-dir)
local hook_file="$git_dir/hooks/$hook_name"
if [[ -f "$hook_file" ]] && [[ -s "$hook_file" ]]; then
debug "Existing $hook_name hook found"
return 0
else
debug "No existing $hook_name hook found"
return 1
fi
}
# Backup existing git hook
backup_existing_hook() {
local hook_name="$1"
local git_dir
git_dir=$(git rev-parse --git-dir)
local hook_file="$git_dir/hooks/$hook_name"
local backup_file
backup_file="$hook_file.backup.$(date +%Y%m%d_%H%M%S)"
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would backup $hook_name hook to $backup_file"
return 0
fi
if cp "$hook_file" "$backup_file"; then
success "Backed up existing $hook_name hook to $backup_file"
return 0
else
error "Failed to backup existing $hook_name hook"
return 1
fi
}
# Check for pre-commit framework
check_precommit_framework() {
debug "Checking for pre-commit framework..."
# Check if pre-commit is installed
if command_exists "pre-commit"; then
debug "pre-commit command found"
# Check if .pre-commit-config.yaml exists
if [[ -f ".pre-commit-config.yaml" ]]; then
info "Pre-commit framework detected with configuration"
return 0
else
debug "pre-commit installed but no configuration found"
return 1
fi
else
debug "pre-commit framework not found"
return 1
fi
}
# Install hooks using AI Command Auditor CLI
install_hooks_via_cli() {
debug "Installing hooks using AI Command Auditor CLI..."
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would execute: ai-auditor setup-hooks --config-dir $CONFIG_DIR"
return 0
fi
# Check if CLI is available
if ! command_exists "ai-auditor"; then
warn "AI Command Auditor CLI not available - using manual hook setup"
install_hooks_manually
return $?
fi
# Use the CLI to setup hooks
local setup_cmd="ai-auditor setup-hooks"
setup_cmd="$setup_cmd --config-dir $CONFIG_DIR"
if [[ "$VERBOSE" == true ]]; then
setup_cmd="$setup_cmd --verbose"
fi
debug "Hook setup command: $setup_cmd"
# Execute hook setup
if $setup_cmd; then
success "Hooks installed successfully via CLI"
return 0
else
warn "CLI hook setup failed - falling back to manual setup"
install_hooks_manually
return $?
fi
}
# Manual hook installation as fallback
install_hooks_manually() {
debug "Installing hooks manually..."
local git_dir
git_dir=$(git rev-parse --git-dir)
local hooks_dir="$git_dir/hooks"
# Define hooks to install
local hooks=("pre-commit" "pre-push")
for hook in "${hooks[@]}"; do
debug "Installing $hook hook..."
local hook_file="$hooks_dir/$hook"
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would create $hook hook at $hook_file"
continue
fi
# Create the hook script
cat > "$hook_file" << EOF
#!/bin/bash
#
# AI Command Auditor Git Hook: $hook
# Auto-generated by installer
#
# Exit on any error
set -e
# Get the config directory
CONFIG_DIR="\$(git rev-parse --show-toplevel)/$CONFIG_DIR"
# Check if ai-auditor is available
if ! command -v ai-auditor >/dev/null 2>&1; then
echo "Warning: ai-auditor command not found - skipping validation"
exit 0
fi
# Check if config directory exists
if [[ ! -d "\$CONFIG_DIR" ]]; then
echo "Warning: AI Command Auditor config not found at \$CONFIG_DIR - skipping validation"
exit 0
fi
# Run the appropriate validation
case "$hook" in
pre-commit)
echo "Running AI Command Auditor pre-commit validation..."
ai-auditor validate-commit --config-dir "\$CONFIG_DIR"
;;
pre-push)
echo "Running AI Command Auditor pre-push validation..."
ai-auditor validate-push --config-dir "\$CONFIG_DIR"
;;
esac
exit 0
EOF
# Make the hook executable
if chmod +x "$hook_file"; then
success "Created $hook hook"
else
error "Failed to make $hook hook executable"
return 1
fi
done
success "Manual hook installation completed"
return 0
}
# Setup pre-commit framework integration
setup_precommit_integration() {
debug "Setting up pre-commit framework integration..."
if [[ "$DRY_RUN" == true ]]; then
info "DRY RUN: Would setup pre-commit integration"