-
Notifications
You must be signed in to change notification settings - Fork 8
feat(localhost): add port management and loop-mode auto-branch #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,9 +15,13 @@ YELLOW='\033[1;33m' | |
| RED='\033[0;31m' | ||
| NC='\033[0m' # No Color | ||
|
|
||
| # Error message constants | ||
| readonly ERROR_UNKNOWN_COMMAND="Unknown command:" | ||
| readonly HELP_USAGE_INFO="Use '$0 help' for usage information" | ||
| # Error message constants (use shared-constants.sh if available, otherwise define locally) | ||
| if [[ -z "${ERROR_UNKNOWN_COMMAND:-}" ]]; then | ||
| readonly ERROR_UNKNOWN_COMMAND="Unknown command:" | ||
| fi | ||
| if [[ -z "${HELP_USAGE_INFO:-}" ]]; then | ||
| readonly HELP_USAGE_INFO="Use '$0 help' for usage information" | ||
| fi | ||
|
|
||
| print_info() { | ||
| local msg="$1" | ||
|
|
@@ -46,6 +50,145 @@ print_error() { | |
| # Configuration file | ||
| CONFIG_FILE="../configs/localhost-config.json" | ||
|
|
||
| # ============================================================================= | ||
| # Port Management Functions | ||
| # ============================================================================= | ||
| # These functions ensure port conflicts are avoided and services use available ports. | ||
| # This is critical for: | ||
| # 1. Avoiding "port already in use" errors | ||
| # 2. Enabling SSL via reverse proxy (password managers require HTTPS) | ||
| # 3. Consistent .local domain access across all local services | ||
|
|
||
| # Default port range for auto-assignment | ||
| readonly PORT_RANGE_START=3000 | ||
| readonly PORT_RANGE_END=9999 | ||
|
|
||
| # Check if a port is in use | ||
| # Returns 0 if port is FREE, 1 if port is IN USE | ||
| is_port_free() { | ||
| local port="$1" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤖 Was this useful? React with 👍 or 👎 |
||
| if [[ -z "$port" ]]; then | ||
| print_error "Port number required" | ||
| return 1 | ||
| fi | ||
|
|
||
| # Check using lsof (works on macOS and Linux) | ||
| if lsof -i :"$port" >/dev/null 2>&1; then | ||
| return 1 # Port is in use | ||
| fi | ||
|
|
||
| # Double-check with nc if available | ||
| if command -v nc >/dev/null 2>&1; then | ||
| if nc -z 127.0.0.1 "$port" 2>/dev/null; then | ||
| return 1 # Port is in use | ||
| fi | ||
| fi | ||
|
|
||
| return 0 # Port is free | ||
| } | ||
|
|
||
| # Find the next available port starting from a given port | ||
| # Usage: find_available_port [start_port] | ||
| # Returns: Prints the first available port | ||
| find_available_port() { | ||
| local start_port="${1:-$PORT_RANGE_START}" | ||
| local port="$start_port" | ||
|
|
||
| while [[ $port -le $PORT_RANGE_END ]]; do | ||
| if is_port_free "$port"; then | ||
| echo "$port" | ||
| return 0 | ||
| fi | ||
| ((port++)) | ||
| done | ||
|
|
||
| print_error "No available ports found in range $start_port-$PORT_RANGE_END" | ||
| return 1 | ||
| } | ||
|
|
||
| # Check port and suggest alternative if in use | ||
| # Usage: check_port_or_suggest [port] | ||
| # Returns: 0 if port is free, 1 if in use (prints suggestion) | ||
| check_port_or_suggest() { | ||
| local port="$1" | ||
|
|
||
| if [[ -z "$port" ]]; then | ||
| print_error "Port number required" | ||
| return 1 | ||
| fi | ||
|
|
||
| if is_port_free "$port"; then | ||
| print_success "Port $port is available" | ||
| return 0 | ||
| else | ||
| local process_info | ||
| process_info=$(lsof -i :"$port" 2>/dev/null | tail -1 | awk '{print $1, $2}') | ||
| print_warning "Port $port is in use by: $process_info" | ||
|
|
||
| local suggested_port | ||
| suggested_port=$(find_available_port "$((port + 1))") | ||
| if [[ -n "$suggested_port" ]]; then | ||
| print_info "Suggested alternative: $suggested_port" | ||
| echo "SUGGESTED_PORT=$suggested_port" | ||
| fi | ||
| return 1 | ||
| fi | ||
| } | ||
|
Comment on lines
+62
to
+136
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's verify the current state of the file and examine lines 62-136
cat -n .agent/scripts/localhost-helper.sh | head -150Repository: marcusquinn/aidevops Length of output: 5547 🏁 Script executed: # Check if there's any bootstrap or setup script that documents tool availability
fd -t f -e sh -e bash | head -20Repository: marcusquinn/aidevops Length of output: 776 🏁 Script executed: # Look for any environment setup or requirements documentation
git ls-files | grep -E "(README|setup|bootstrap|requirements|install)" | head -10Repository: marcusquinn/aidevops Length of output: 421 🏁 Script executed: # Check if there are other scripts that validate tool availability
rg -t sh "lsof|command -v" --max-count=20 -A 2 -B 2Repository: marcusquinn/aidevops Length of output: 50376 Add input validation and tool availability guards to port helper functions The port management functions assume Three instances require fixing:
Add numeric port validation (1–65535) in 🤖 Prompt for AI Agents |
||
|
|
||
| # List all ports currently in use by local development services | ||
| list_dev_ports() { | ||
| print_info "Ports in use by local development services:" | ||
| echo "" | ||
|
|
||
| # Common development port ranges | ||
| local dev_ports=(3000 3001 3002 3003 4000 5000 5173 5174 8000 8080 8085 8888 9000 9222 11235) | ||
|
|
||
| for port in "${dev_ports[@]}"; do | ||
| if ! is_port_free "$port"; then | ||
| local process_info | ||
| process_info=$(lsof -i :"$port" 2>/dev/null | tail -1 | awk '{print $1}') | ||
| echo " :$port - $process_info" | ||
| fi | ||
| done | ||
|
|
||
| echo "" | ||
| print_info "Use 'lsof -i :<port>' for detailed process info" | ||
| return 0 | ||
| } | ||
|
|
||
| # Kill process on a specific port | ||
| kill_port() { | ||
| local port="$1" | ||
|
|
||
| if [[ -z "$port" ]]; then | ||
| print_error "Port number required" | ||
| return 1 | ||
| fi | ||
|
|
||
| local pids | ||
| pids=$(lsof -ti :"$port" 2>/dev/null) | ||
|
|
||
| if [[ -z "$pids" ]]; then | ||
| print_info "No process found on port $port" | ||
| return 0 | ||
| fi | ||
|
|
||
| print_warning "Killing process(es) on port $port: $pids" | ||
| echo "$pids" | xargs kill -9 2>/dev/null | ||
|
|
||
| # Wait up to 3 seconds for the port to become free | ||
| for _ in {1..6}; do | ||
| if is_port_free "$port"; then | ||
| print_success "Port $port is now free" | ||
| return 0 | ||
| fi | ||
| sleep 0.5 | ||
| done | ||
|
|
||
| print_error "Failed to free port $port" | ||
| return 1 | ||
| } | ||
|
|
||
| # Check if config file exists | ||
| check_config() { | ||
| if [[ ! -f "$CONFIG_FILE" ]]; then | ||
|
|
@@ -534,6 +677,18 @@ main() { | |
| "stop-mcp") | ||
| stop_localwp_mcp | ||
| ;; | ||
| "check-port") | ||
| check_port_or_suggest "$param2" | ||
| ;; | ||
| "find-port") | ||
| find_available_port "$param2" | ||
| ;; | ||
| "list-ports") | ||
| list_dev_ports | ||
| ;; | ||
| "kill-port") | ||
| kill_port "$param2" | ||
| ;; | ||
| "help"|"-h"|"--help"|"") | ||
| echo "Localhost Development Helper Script" | ||
| echo "Usage: $0 [command] [options]" | ||
|
|
@@ -553,6 +708,12 @@ main() { | |
| echo " start-mcp - Start LocalWP MCP server for AI database access" | ||
| echo " stop-mcp - Stop LocalWP MCP server" | ||
| echo "" | ||
| echo "Port Management Commands:" | ||
| echo " check-port [port] - Check if port is available, suggest alternative" | ||
| echo " find-port [start] - Find next available port from start (default: 3000)" | ||
| echo " list-ports - List common dev ports in use" | ||
| echo " kill-port [port] - Kill process using specified port" | ||
| echo "" | ||
| echo "Examples:" | ||
| echo " $0 setup-dns" | ||
| echo " $0 setup-proxy" | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,13 +7,72 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Usage: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ~/.aidevops/agents/scripts/pre-edit-check.sh | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ~/.aidevops/agents/scripts/pre-edit-check.sh --loop-mode --task "description" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Exit codes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 0 - OK to proceed (on feature branch, or docs-only on main in loop mode) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 1 - STOP (on protected branch, interactive mode) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 2 - Create worktree (loop mode detected code task on main) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # AI assistants should call this before any Edit/Write tool and STOP if it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # returns a warning about being on main branch. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Loop Mode Support | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # When --loop-mode is passed, the script auto-decides based on task description: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - Docs-only tasks (README, CHANGELOG, docs/) -> stay on main (exit 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - Code tasks (feature, fix, implement, etc.) -> signal worktree needed (exit 2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LOOP_MODE=false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TASK_DESC="" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| while [[ $# -gt 0 ]]; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case $1 in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --loop-mode) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LOOP_MODE=true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shift | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --task) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TASK_DESC="$2" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shift 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| *) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shift | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+33
to
+47
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Harden
Proposed fix --task)
- TASK_DESC="$2"
- shift 2
+ if [[ $# -lt 2 ]]; then
+ echo "ERROR: --task requires a value" >&2
+ exit 1
+ fi
+ TASK_DESC="$2"
+ shift 2
;;
*)
- shift
+ echo "WARNING: ignoring unknown arg: $1" >&2
+ shift
;;As per coding guidelines, automation scripts should fail deterministically with clear feedback. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Function to detect if task is docs-only | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| is_docs_only() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local task="$1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Use bash 4.0+ parameter expansion for lowercase (more efficient than tr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local task_lower="${task,,}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Code change indicators (negative match - if present, NOT docs-only) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # These take precedence over docs patterns | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local code_patterns="feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance|port|ssl|helper" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Docs-only indicators (positive match) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local docs_patterns="^readme|^changelog|^documentation|docs/|typo|spelling|comment only|license only|^update readme|^update changelog|^update docs" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Check for code patterns first (takes precedence) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if echo "$task_lower" | grep -qE "$code_patterns"; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 1 # Not docs-only | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Check for docs patterns | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if echo "$task_lower" | grep -qE "$docs_patterns"; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 # Is docs-only | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Default: not docs-only (safer to create branch) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+49
to
+74
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, check the shebang and overall structure of the script
head -20 .agent/scripts/pre-edit-check.shRepository: marcusquinn/aidevops Length of output: 958 🏁 Script executed: # Search for any documentation about Bash version requirements
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "README*" \) | xargs grep -l "bash" -i | head -10Repository: marcusquinn/aidevops Length of output: 457 🏁 Script executed: # Check other scripts in the .agent/scripts directory for patterns
ls -la .agent/scripts/*.sh | head -20Repository: marcusquinn/aidevops Length of output: 1776 🏁 Script executed: # Examine shebang lines across all scripts
for script in .agent/scripts/*.sh; do
echo "=== $script ==="
head -1 "$script"
doneRepository: marcusquinn/aidevops Length of output: 6876 🏁 Script executed: # Look for Bash version checks or requirements in the codebase
rg "bash.*4|version.*bash|BASH_VERSION" --type sh -A 2 -B 2Repository: marcusquinn/aidevops Length of output: 921 🏁 Script executed: # Check CI configuration files for environment specifications
find . -type f \( -name ".github" -o -name "*.yml" -o -name "*.yaml" \) -path "*/.github/*" | head -20Repository: marcusquinn/aidevops Length of output: 342 🏁 Script executed: # Check CI workflow configurations for Bash/runner specifications
cat .github/workflows/code-quality.yml | head -50Repository: marcusquinn/aidevops Length of output: 1829 🏁 Script executed: # Get the full pre-edit-check.sh script to understand context
cat -n .agent/scripts/pre-edit-check.shRepository: marcusquinn/aidevops Length of output: 7744 🏁 Script executed: # Look for any Bash version checks or requirements in documentation
rg "bash.*version|minimum.*bash|bash.*3|bash.*4" -i --type md -A 2 -B 2Repository: marcusquinn/aidevops Length of output: 5889 🏁 Script executed: # Test the regex patterns with example task descriptions
python3 << 'EOF'
import re
import subprocess
# Simulate the is_docs_only function
def test_is_docs_only(task):
task_lower = task.lower()
code_patterns = "feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance|port|ssl|helper"
docs_patterns = "^readme|^changelog|^documentation|docs/|typo|spelling|comment only|license only|^update readme|^update changelog|^update docs"
# Check code patterns first
if re.search(code_patterns, task_lower):
return "NOT docs-only (code pattern match)"
# Check docs patterns
if re.search(docs_patterns, task_lower):
return "IS docs-only (docs pattern match)"
# Default
return "NOT docs-only (default)"
# Test cases
test_tasks = [
"Update docs/localhost.md for SSL", # Review's example
"Update README.md with SSL configuration",
"Fix SSL certificate docs",
"Add helper script for SSL",
"Update docs/ssl-setup.md",
"Document SSL port configuration",
"Fix typo in docs/ssl.md",
"Add SSL section to docs/README",
"Refactor SSL helper function",
"Update changelog for SSL fix",
]
print("Testing regex patterns:")
print("-" * 70)
for task in test_tasks:
result = test_is_docs_only(task)
print(f"Task: {task:<45} -> {result}")
EOFRepository: marcusquinn/aidevops Length of output: 150 🏁 Script executed: # Also check if there's any documentation about Bash version requirements
rg "bash.*3\.|bash.*4\.|compatibility|version.*requirement" -i --type mdRepository: marcusquinn/aidevops Length of output: 5395 🏁 Script executed: # Check how pre-edit-check.sh is invoked in the codebase
rg "pre-edit-check\.sh" -B 2 -A 2Repository: marcusquinn/aidevops Length of output: 4315 🏁 Script executed: # Manually test the regex patterns with grep
echo "Testing regex patterns:"
echo ""
# Test tasks
echo "Test 1: 'Update docs/localhost.md for SSL'"
echo "update docs/localhost.md for ssl" | grep -qE "feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance|port|ssl|helper" && echo " → Matches CODE_PATTERNS (NOT docs-only)" || echo " → No code pattern"
echo ""
echo "Test 2: 'Update README.md with SSL configuration'"
echo "update readme.md with ssl configuration" | grep -qE "feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance|port|ssl|helper" && echo " → Matches CODE_PATTERNS (NOT docs-only)" || echo " → No code pattern"
echo ""
echo "Test 3: 'Add helper script for SSL'"
echo "add helper script for ssl" | grep -qE "feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance|port|ssl|helper" && echo " → Matches CODE_PATTERNS (NOT docs-only)" || echo " → No code pattern"
echo ""
echo "Test 4: 'Update docs/port-configuration.md (pure docs)'"
echo "update docs/port-configuration.md" | grep -qE "feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance|port|ssl|helper" && echo " → Matches CODE_PATTERNS (NOT docs-only - FALSE POSITIVE)" || echo " → No code pattern"
echo ""
echo "Test 5: 'Fix localhost helper (code change)'"
echo "fix localhost helper" | grep -qE "feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance|port|ssl|helper" && echo " → Matches CODE_PATTERNS (NOT docs-only - CORRECT)" || echo " → No code pattern"Repository: marcusquinn/aidevops Length of output: 559 🏁 Script executed: # Check if pre-edit-check.sh is tested and what the test expectations are
find . -name "*test*" -o -name "*spec*" | xargs grep -l "pre-edit-check\|is_docs_only" 2>/dev/null | head -10Repository: marcusquinn/aidevops Length of output: 46 🏁 Script executed: # Look for any Bash 3 vs 4 compatibility workarounds in the codebase
rg "tr.*lower|tolower|parameter.*expansion" -i --type shRepository: marcusquinn/aidevops Length of output: 2129 Fix Bash 4+ incompatibility and tighten regex to eliminate false positives. Two confirmed issues:
Proposed fixReplace is_docs_only() {
local task="$1"
- # Use bash 4.0+ parameter expansion for lowercase (more efficient than tr)
- local task_lower="${task,,}"
+ # Use tr for bash 3.2+ compatibility (consistent with other scripts in framework)
+ local task_lower="$(echo "$task" | tr '[:upper:]' '[:lower:]')"
# Code change indicators (negative match - if present, NOT docs-only)
# These take precedence over docs patterns
- local code_patterns="feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance|port|ssl|helper"
+ local code_patterns="feature|fix|bug|implement|refactor|add.*function|update.*code|create.*script|modify.*config|change.*logic|new.*api|endpoint|enhance"
# Docs-only indicators (positive match)
local docs_patterns="^readme|^changelog|^documentation|docs/|typo|spelling|comment only|license only|^update readme|^update changelog|^update docs"📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Colors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RED='\033[0;31m' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GREEN='\033[0;32m' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -37,6 +96,21 @@ fi | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Check if on main or master | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Loop mode: auto-decide based on task description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$LOOP_MODE" == "true" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if is_docs_only "$TASK_DESC"; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo -e "${YELLOW}LOOP-AUTO${NC}: Docs-only task detected, staying on $current_branch" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "LOOP_DECISION=stay" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Auto-create worktree for code changes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo -e "${YELLOW}LOOP-AUTO${NC}: Code task detected, worktree required" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "LOOP_DECISION=worktree" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 2 # Special exit code for "create worktree" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Interactive mode: show warning and exit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo -e "${RED}${BOLD}======================================================${NC}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo -e "${RED}${BOLD} STOP - ON PROTECTED BRANCH: $current_branch${NC}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fallback constants are incomplete (shared-constants absent => confusing errors).
You added fallbacks for
ERROR_UNKNOWN_COMMAND/HELP_USAGE_INFO, but the script also uses other constants (e.g.,ERROR_CONFIG_NOT_FOUNDincheck_config()). Ifshared-constants.shisn’t present, error output becomes blank-ish.Proposed fix
if [[ -z "${ERROR_UNKNOWN_COMMAND:-}" ]]; then readonly ERROR_UNKNOWN_COMMAND="Unknown command:" fi if [[ -z "${HELP_USAGE_INFO:-}" ]]; then readonly HELP_USAGE_INFO="Use '$0 help' for usage information" fi +if [[ -z "${ERROR_CONFIG_NOT_FOUND:-}" ]]; then + readonly ERROR_CONFIG_NOT_FOUND="Config file not found:" +fiAs per coding guidelines, automation scripts should fail with clear, actionable messaging.
📝 Committable suggestion
🤖 Prompt for AI Agents