2 Hooks
Niquel Mendoza edited this page 2026-04-30 22:12:07 +00:00

Hooks System Guide

Complete reference for the TSNDep hooks system for automating commands.


Overview

Hooks allow you to execute custom shell commands at specific points in the dependency lifecycle. Use them for:

  • Running tests after installation
  • Building projects automatically
  • Validating configurations
  • Triggering CI/CD pipelines
  • Sending notifications
  • Performing cleanup tasks

Hook Lifecycle

TSNDep executes hooks at four main points:

1. pre_install
   ↓
2. [Clone/Pull repositories]
   ↓
3. post_install (if post_install_only_on_success=true and all succeeded)
   ↓
4. pre_update (when running tsndep update)
   ↓
5. [Pull updates]
   ↓
6. post_update (if post_update_only_on_success=true and all succeeded)

Hook Types

pre_install

Executes before cloning/pulling any repositories.

Use cases:

  • Verify prerequisites (Git, Python, etc.)
  • Clean old installations
  • Set up environment variables
  • Create directories

Timing: Early in process, before any changes

Example:

{
  "hooks": {
    "pre_install": [
      {
        "command": "git --version",
        "permitir_fallo": false,
        "timeout_ms": 5000
      },
      {
        "command": "python --version",
        "permitir_fallo": false,
        "timeout_ms": 5000
      },
      {
        "command": "rm -rf old_deps/",
        "permitir_fallo": true,
        "timeout_ms": 10000
      }
    ]
  }
}

post_install

Executes after successfully installing all dependencies.

Use cases:

  • Install Python dependencies (pip install)
  • Run build scripts
  • Execute tests
  • Generate documentation
  • Setup databases

Timing: Only runs if post_install_only_on_success=true AND all installs succeeded

Example:

{
  "hooks": {
    "post_install": [
      {
        "command": "pip install -r requirements.txt",
        "permitir_fallo": true,
        "timeout_ms": 120000
      },
      {
        "command": "python -m pytest tests/",
        "permitir_fallo": true,
        "timeout_ms": 60000
      },
      {
        "command": "python setup.py build",
        "permitir_fallo": true,
        "timeout_ms": 120000
      }
    ],
    "post_install_only_on_success": true
  }
}

pre_update

Executes before updating repositories.

Use cases:

  • Backup current state
  • Stop running services
  • Notify team members
  • Log update reason

Timing: Runs before tsndep update pulls changes

Example:

{
  "hooks": {
    "pre_update": [
      {
        "command": "cp -r . ./backup_$(date +%Y%m%d_%H%M%S)/",
        "permitir_fallo": false,
        "timeout_ms": 30000
      },
      {
        "command": "echo 'Starting update: $(date)' >> update.log",
        "permitir_fallo": true,
        "timeout_ms": 5000
      }
    ]
  }
}

post_update

Executes after pulling all updates.

Use cases:

  • Rebuild after updates
  • Run new migrations
  • Restart services
  • Verify compatibility
  • Send completion notification

Timing: Controlled by post_update_only_on_success flag

Example:

{
  "hooks": {
    "post_update": [
      {
        "command": "pip install -r requirements.txt",
        "permitir_fallo": true,
        "timeout_ms": 120000
      },
      {
        "command": "python scripts/migrate.py",
        "permitir_fallo": true,
        "timeout_ms": 60000
      },
      {
        "command": "systemctl restart my-service",
        "permitir_fallo": true,
        "timeout_ms": 10000
      }
    ],
    "post_update_only_on_success": true
  }
}

Hook Configuration

Command Object

Each hook command requires:

{
  "command": "shell command to execute",
  "permitir_fallo": boolean,    // Optional: default false
  "timeout_ms": integer         // Optional: default 60000
}

command (String) - Required

The shell command to execute.

Rules:

  • Executed with /bin/sh on Unix-like systems
  • Executed with cmd.exe on Windows
  • Can include pipes, redirects, etc.
  • Has access to environment variables

Examples:

{
  "command": "echo 'Processing...'"
}
{
  "command": "python -m pip install -r requirements.txt"
}
{
  "command": "ls -la | grep -E '.*\\.py$'"
}

permitir_fallo (Boolean) - Optional

Whether to continue if this command fails.

Values:

  • true — Continue even if command fails (exit code ≠ 0)
  • false — Stop execution if command fails (default)

When to use:

  • true — For optional tasks (e.g., cleanup, logging)
  • false — For critical tasks (e.g., prerequisite checks)

Example:

{
  "hooks": {
    "pre_install": [
      {
        "command": "git --version",
        "permitir_fallo": false  // Stop if git not found
      },
      {
        "command": "rm -rf /tmp/old_files",
        "permitir_fallo": true   // Continue even if fails
      }
    ]
  }
}

timeout_ms (Integer) - Optional

Maximum time to wait for command completion in milliseconds.

Rules:

  • Minimum: 100ms
  • Maximum: 3600000ms (1 hour)
  • Default: 60000ms (60 seconds)
  • If exceeded, command is terminated

Examples:

{
  "command": "git --version",
  "timeout_ms": 5000          // 5 seconds
}
{
  "command": "pip install -r requirements.txt",
  "timeout_ms": 300000        // 5 minutes
}

Conditional Execution

post_install_only_on_success

Type: Boolean
Default: true

Only execute post_install hooks if all repositories installed successfully.

Behavior:

  • true — Run post_install only if no errors occurred during install
  • false — Always run post_install, even if some clones failed

Use case:

{
  "hooks": {
    "post_install": [
      {
        "command": "python -m pytest tests/",
        "permitir_fallo": false
      }
    ],
    "post_install_only_on_success": true  // Only test if all cloned
  }
}

post_update_only_on_success

Type: Boolean
Default: false

Only execute post_update hooks if all repositories updated successfully.

Behavior:

  • true — Run post_update only if no errors during update
  • false — Always run post_update (default, useful for cleanup)

Use case:

{
  "hooks": {
    "post_update": [
      {
        "command": "systemctl restart my-service",
        "permitir_fallo": false
      }
    ],
    "post_update_only_on_success": true  // Only restart if all updated
  }
}

Practical Examples

Example 1: Python Project Setup

{
  "hooks": {
    "pre_install": [
      {
        "command": "python --version",
        "permitir_fallo": false,
        "timeout_ms": 5000
      }
    ],
    "post_install": [
      {
        "command": "pip install -r requirements.txt",
        "permitir_fallo": true,
        "timeout_ms": 120000
      },
      {
        "command": "python -m pytest tests/ -v",
        "permitir_fallo": true,
        "timeout_ms": 60000
      }
    ],
    "post_install_only_on_success": true
  }
}

Example 2: CI/CD Pipeline Integration

{
  "hooks": {
    "pre_install": [
      {
        "command": "echo '===== Starting CI Pipeline =====' && date",
        "permitir_fallo": false,
        "timeout_ms": 5000
      }
    ],
    "post_install": [
      {
        "command": "pip install -r requirements.txt",
        "permitir_fallo": false,
        "timeout_ms": 120000
      },
      {
        "command": "python -m pylint src/",
        "permitir_fallo": true,
        "timeout_ms": 60000
      },
      {
        "command": "python -m pytest tests/ --cov=src/",
        "permitir_fallo": false,
        "timeout_ms": 120000
      }
    ],
    "post_install_only_on_success": true
  }
}

Example 3: Backup and Recovery

{
  "hooks": {
    "pre_update": [
      {
        "command": "cp -r . backup_$(date +%s)/ && echo 'Backup created'",
        "permitir_fallo": false,
        "timeout_ms": 60000
      }
    ],
    "post_update": [
      {
        "command": "find backup_* -mtime +7 -exec rm -rf {} \\; 2>/dev/null",
        "permitir_fallo": true,
        "timeout_ms": 30000
      }
    ],
    "post_update_only_on_success": false  // Always cleanup
  }
}

Example 4: Service Restart

{
  "hooks": {
    "post_update": [
      {
        "command": "systemctl stop my-trading-system",
        "permitir_fallo": true,
        "timeout_ms": 10000
      },
      {
        "command": "pip install -r requirements.txt",
        "permitir_fallo": false,
        "timeout_ms": 120000
      },
      {
        "command": "systemctl start my-trading-system",
        "permitir_fallo": false,
        "timeout_ms": 10000
      }
    ],
    "post_update_only_on_success": true
  }
}

Error Handling

Command Fails with permitir_fallo: false

[INSTALL:my-repo] Cloning from ...
Error: Command failed
Installation halted

Solution: Check command syntax, ensure tool is installed, or set permitir_fallo: true


Command Timeout

[INSTALL:my-repo] Timeout after 30s
Installation halted

Solution: Increase timeout_ms or optimize command


Command Not Found

Error: command not found: python3

Solution: Ensure tool is installed and in PATH, or use absolute path


Best Practices

Do:

  • Set permitir_fallo: false for critical checks
  • Use reasonable timeouts (5s for checks, 120s+ for builds)
  • Test hooks manually before adding them
  • Keep commands simple and focused
  • Use meaningful output messages
  • Log important events to files

Don't:

  • Use interactive commands (require user input)
  • Assume absolute paths (use relative or $PATH)
  • Set very long timeouts (avoid stalling)
  • Run unrelated tasks in hooks
  • Ignore error codes
  • Execute dangerous cleanup commands

Debugging Hooks

Test Command Manually

Before adding to hooks, test the command:

# Test single command
python -m pytest tests/

# Check exit code
echo $?  # 0 = success, non-zero = failure

Enable Verbose Output

Add debugging to your hook:

{
  "command": "set -x && python -m pytest tests/",  // 'set -x' for debugging",
  "permitir_fallo": true
}

Check Hook Execution

Monitor logs during execution:

tsndep install <url> <branch>  # Watch console output

Environment Variables

Hooks inherit parent process environment:

{
  "command": "echo $HOME && echo $PATH",
  "permitir_fallo": false
}

You can also set variables:

{
  "command": "export MY_VAR=value && python script.py",
  "permitir_fallo": false
}

Variables

View: Variables