Hooks & Automation
Customize your workflow with pre-run and post-run hooks for automated testing, formatting, and deployment.
Hook Types
Pre-Run Hook
Executed before any git operations. Perfect for:
- • Code formatting and linting
- • Running tests
- • Build verification
- • Security scans
Location: .lfg/pre-run.sh
Post-Run Hook
Executed after successful completion. Ideal for:
- • Opening PR in browser
- • Sending notifications
- • Triggering deployments
- • Updating project management tools
Location: .lfg/post-run.sh
Pre-Run Hook Examples
Node.js/JavaScript Project
#!/usr/bin/env bash
# Pre-run hook for Node.js projects
set -e # Exit on any error
echo "🔍 Running pre-commit checks..."
# Format code with Prettier
echo "📝 Formatting code..."
npm run format || exit 1
# Lint code
echo "🔍 Linting code..."
npm run lint || exit 1
# Run tests
echo "🧪 Running tests..."
npm run test || exit 1
# Type checking (if using TypeScript)
if [ -f "tsconfig.json" ]; then
echo "🔍 Type checking..."
npm run type-check || exit 1
fi
echo "✅ All pre-commit checks passed!"
exit 0
Python Project
#!/usr/bin/env bash
# Pre-run hook for Python projects
set -e
echo "🐍 Running Python pre-commit checks..."
# Format with Black
echo "📝 Formatting with Black..."
black . --check || {
echo "❌ Code formatting issues found. Run 'black .' to fix."
exit 1
}
# Sort imports with isort
echo "📦 Checking import sorting..."
isort . --check-only || {
echo "❌ Import sorting issues found. Run 'isort .' to fix."
exit 1
}
# Lint with flake8
echo "🔍 Linting with flake8..."
flake8 . || exit 1
# Type checking with mypy
echo "🔍 Type checking with mypy..."
mypy . || exit 1
# Run tests with pytest
echo "🧪 Running tests..."
pytest || exit 1
echo "✅ All Python checks passed!"
exit 0
Go Project
#!/usr/bin/env bash
# Pre-run hook for Go projects
set -e
echo "🐹 Running Go pre-commit checks..."
# Format code
echo "📝 Formatting Go code..."
gofmt -l . | grep -q . && {
echo "❌ Code formatting issues found. Run 'gofmt -w .' to fix."
exit 1
}
# Vet code
echo "🔍 Vetting Go code..."
go vet ./... || exit 1
# Run golint if available
if command -v golint >/dev/null 2>&1; then
echo "🔍 Linting Go code..."
golint -set_exit_status ./... || exit 1
fi
# Build to check for compilation errors
echo "🔨 Building project..."
go build ./... || exit 1
# Run tests
echo "🧪 Running tests..."
go test ./... || exit 1
echo "✅ All Go checks passed!"
exit 0
Laravel/PHP Project
#!/usr/bin/env bash
# Pre-run hook for Laravel/PHP projects
set -e
echo "🐘 Running PHP/Laravel pre-commit checks..."
# Format code with Laravel Pint
echo "📝 Formatting PHP code..."
./vendor/bin/pint --test || {
echo "❌ Code formatting issues found. Run './vendor/bin/pint' to fix."
exit 1
}
# Static analysis with PHPStan
if [ -f "phpstan.neon" ] || [ -f "phpstan.neon.dist" ]; then
echo "🔍 Running PHPStan analysis..."
./vendor/bin/phpstan analyse || exit 1
fi
# Run tests
echo "🧪 Running PHPUnit tests..."
./vendor/bin/phpunit || exit 1
# Check for security vulnerabilities
if command -v composer >/dev/null 2>&1; then
echo "🔒 Checking for security vulnerabilities..."
composer audit || exit 1
fi
echo "✅ All PHP/Laravel checks passed!"
exit 0
Post-Run Hook Examples
Open PR in Browser
#!/usr/bin/env bash
# Post-run hook to open PR in browser
# PR_URL is provided by LFG when a PR is created
if [ -n "$PR_URL" ]; then
echo "🌐 Opening PR in browser..."
# macOS
if command -v open >/dev/null 2>&1; then
open "$PR_URL" >/dev/null 2>&1 || true
# Linux
elif command -v xdg-open >/dev/null 2>&1; then
xdg-open "$PR_URL" >/dev/null 2>&1 || true
# Windows (WSL)
elif command -v cmd.exe >/dev/null 2>&1; then
cmd.exe /c start "$PR_URL" >/dev/null 2>&1 || true
fi
echo "✅ PR opened in browser"
fi
exit 0
Slack Notification
#!/usr/bin/env bash
# Post-run hook for Slack notifications
# Load environment variables (including SLACK_WEBHOOK_URL)
if [ -f ".lfg/.env" ]; then
source .lfg/.env
fi
# Only send notification if PR was created
if [ -n "$PR_URL" ] && [ -n "$SLACK_WEBHOOK_URL" ]; then
BRANCH=$(git rev-parse --abbrev-ref HEAD)
AUTHOR=$(git config user.name)
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || echo "repository")
# Get commit message
COMMIT_MSG=$(git log -1 --pretty=format:"%s")
# Send Slack notification
curl -X POST -H 'Content-type: application/json' \
--data "{
\"text\": \"🚀 New PR created by $AUTHOR\",
\"blocks\": [
{
\"type\": \"section\",
\"text\": {
\"type\": \"mrkdwn\",
\"text\": \"*New Pull Request*\n*Repository:* $REPO\n*Branch:* \`$BRANCH\`\n*Author:* $AUTHOR\n*Commit:* $COMMIT_MSG\"
}
},
{
\"type\": \"actions\",
\"elements\": [
{
\"type\": \"button\",
\"text\": {
\"type\": \"plain_text\",
\"text\": \"View PR\"
},
\"url\": \"$PR_URL\"
}
]
}
]
}" \
"$SLACK_WEBHOOK_URL" >/dev/null 2>&1 || true
echo "📢 Slack notification sent"
fi
exit 0
Deployment Trigger
#!/usr/bin/env bash
# Post-run hook for deployment triggers
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# Trigger staging deployment for develop branch
if [ "$BRANCH" = "develop" ]; then
echo "🚀 Triggering staging deployment..."
# Example: GitHub Actions workflow dispatch
if command -v gh >/dev/null 2>&1; then
gh workflow run deploy-staging.yml \
--field branch="$BRANCH" \
--field environment="staging" >/dev/null 2>&1 || true
fi
echo "✅ Staging deployment triggered"
fi
# Trigger production deployment for main branch
if [ "$BRANCH" = "main" ]; then
echo "🚀 Triggering production deployment..."
# Example: Call deployment webhook
if [ -n "$DEPLOY_WEBHOOK_URL" ]; then
curl -X POST -H "Content-Type: application/json" \
-d "{\"branch\": \"$BRANCH\", \"environment\": \"production\"}" \
"$DEPLOY_WEBHOOK_URL" >/dev/null 2>&1 || true
fi
echo "✅ Production deployment triggered"
fi
exit 0
Project Management Integration
#!/usr/bin/env bash
# Post-run hook for project management integration
# Extract ticket number from branch name (e.g., PROJ-123-feature-name)
BRANCH=$(git rev-parse --abbrev-ref HEAD)
TICKET=$(echo "$BRANCH" | sed -nE 's/^([A-Z]+-[0-9]+).*$/\1/p')
if [ -n "$TICKET" ] && [ -n "$PR_URL" ]; then
echo "🎫 Updating ticket $TICKET..."
# Example: Update Jira ticket
if [ -n "$JIRA_API_TOKEN" ] && [ -n "$JIRA_BASE_URL" ]; then
COMMIT_MSG=$(git log -1 --pretty=format:"%s")
# Add comment to Jira ticket
curl -X POST \
-H "Authorization: Bearer $JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"body\": \"Pull request created: $PR_URL\n\nCommit: $COMMIT_MSG\"
}" \
"$JIRA_BASE_URL/rest/api/3/issue/$TICKET/comment" >/dev/null 2>&1 || true
echo "✅ Jira ticket $TICKET updated"
fi
# Example: Update Linear issue
if [ -n "$LINEAR_API_TOKEN" ]; then
curl -X POST \
-H "Authorization: $LINEAR_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"mutation { commentCreate(input: { issueId: \\\"$TICKET\\\", body: \\\"PR created: $PR_URL\\\" }) { success } }\"
}" \
"https://api.linear.app/graphql" >/dev/null 2>&1 || true
echo "✅ Linear issue $TICKET updated"
fi
fi
exit 0
Hook Configuration
Configuration Options
hooks:
pre: .lfg/pre-run.sh # Path to pre-run hook (relative to repo root)
post: .lfg/post-run.sh # Path to post-run hook (relative to repo root)
Hook Permissions
Make sure your hook scripts are executable:
Environment Variables
Store sensitive information in .lfg/.env
:
# Slack integration
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
# Jira integration
JIRA_API_TOKEN=your_jira_token
JIRA_BASE_URL=https://yourcompany.atlassian.net
# Linear integration
LINEAR_API_TOKEN=your_linear_token
# Deployment webhooks
DEPLOY_WEBHOOK_URL=https://deploy.yourcompany.com/webhook
Hook Best Practices
Exit Codes Matter
Pre-run hooks should exit with non-zero code to block commits on failure
Use 'set -e' and 'exit 1' for failures, 'exit 0' for success
Fast Feedback
Keep pre-run hooks fast to avoid slowing down the development workflow
Run quick checks first, skip slow tests in pre-hooks
Error Handling
Post-run hooks should be resilient and not fail the entire process
Use '|| true' for non-critical operations in post-hooks
Environment Detection
Check for required tools and environment variables before using them
Use 'command -v tool >/dev/null 2>&1' to check if tools exist
Logging
Provide clear feedback about what the hooks are doing
Use echo statements to show progress and results
Conditional Logic
Make hooks smart about when to run certain operations
Check branch names, file changes, or environment variables
Hook Troubleshooting
Problem: Hook script not executing
Solution: Check file permissions with 'ls -la .lfg/' and set executable with 'chmod +x .lfg/pre-run.sh .lfg/post-run.sh'
Problem: Pre-run hook blocking commits
Solution: Check the exit code of your hook script. Use 'bash -x .lfg/pre-run.sh' to debug step by step.
Problem: Environment variables not available
Solution: Source .lfg/.env in your hook script or check that variables are exported properly.
Problem: Hook script path not found
Solution: Verify the path in hooks.pre and hooks.post in config.yml. Paths are relative to repository root.
Problem: Post-run hook not receiving PR_URL
Solution: PR_URL is only available when --pr flag is used and PR creation succeeds. Check GitHub CLI authentication.
Problem: Hook script syntax errors
Solution: Test your hook scripts independently with 'bash .lfg/pre-run.sh' to check for syntax issues.