Table of Contents
- Hooks System Guide
- Overview
- Hook Lifecycle
- Hook Types
- Hook Configuration
- Command Object
- command (String) - Required
- permitir_fallo (Boolean) - Optional
- timeout_ms (Integer) - Optional
- Conditional Execution
- Practical Examples
- Example 1: Python Project Setup
- Example 2: CI/CD Pipeline Integration
- Example 3: Backup and Recovery
- Example 4: Service Restart
- Error Handling
- Best Practices
- Debugging Hooks
- Environment Variables
- Variables
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/shon Unix-like systems - Executed with
cmd.exeon 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 installfalse— 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 updatefalse— 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: falsefor 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