README

This is a set of scripts to automatically update from a remote git repository via a trigger using incron file system event monitoring.

Ideal for keeping development and production systems synchronized with git commits without manual intervention. An external webhook or cron job triggers deployment, and the system automatically pulls the latest code from a specified remote branch.

Features

  • Automatic Deployments: Monitor directories for trigger events and auto-sync code from git
  • Multi-Branch Support: Deploy different branches to different directories (e.g., master to production, dev to staging)
  • Lightweight: Simple bash script with minimal dependencies - just incron and bash
  • Permission Handling: Automatically sets correct ownership for web server access
  • Notification Integration: Hooks for Slack notifications on deployment start/completion
  • CI/CD Ready: Example integration with Bitbucket Pipelines and Gitea Actions

How It Works

External Trigger (webhook/cron)
    ↓
Creates git.flag file
    ↓
incron detects IN_CREATE event
    ↓
Executes git.sh script
    ↓
git fetch --all && git reset --hard origin/<branch>
    ↓
Fixes file ownership for web server
    ↓
Sends Slack notification
    ↓
Cleans up git.flag

Quick Start

1. Clone Repository with Pre-Authentication

Clone your git repository with SSH keys configured for unattended access:

cd /var/www
git clone git@bitbucket.org:your-org/your-repo.git .

2. Install Dependencies

# Install incron (Linux/Debian)
sudo apt-get install incron

# Make deployment script executable
chmod +x git.sh

3. Configure incron Rule

Edit /etc/incron.d/www-deploy (or create it):

/var/www/ IN_CREATE /var/www/git.sh $@ $# master

Replace:

  • /var/www/ with your deployment directory
  • master with your target branch (dev, staging, etc.)

For multiple environments:

/var/www/ IN_CREATE /var/www/git.sh $@ $# master
/var/www-dev/ IN_CREATE /var/www-dev/git.sh $@ $# dev
/var/www-staging/ IN_CREATE /var/www-staging/git.sh $@ $# staging

4. Set Up External Trigger

Create a webhook endpoint that triggers deployment. See example-trigger/ for PHP and shell implementations:

PHP Webhook:

<?php
// Endpoint that receives POST from Bitbucket/GitLab
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Verify webhook secret here
    touch("git.flag");
    echo "Deployment triggered";
}

Shell Script (for cron jobs):

#!/bin/bash
cd /var/www
touch git.flag

5. Configure Slack Notifications (Optional)

Define the slackecho function in your shell environment:

slackecho() {
  local message="$1"
  curl -X POST -H 'Content-type: application/json' \
    --data "{\"text\":\"$message\"}" \
    https://hooks.slack.com/services/YOUR/WEBHOOK/URL
}
export -f slackecho

Or add to /etc/environment for system-wide access.

Directory Structure

git-incron-deploy/
├── git.sh                      # Main deployment script
├── bitbucket-pipelines.yml     # CI/CD example (Bitbucket)
├── .gitea/workflows/           # Gitea Actions workflows
├── example-trigger/
│   ├── deploy.php             # PHP webhook example
│   └── deploy.sh              # Bash trigger example
├── incron.d/
│   └── www-deploy             # incron rule template
└── .github/
    └── copilot-instructions.md # AI coding agent guidelines

Script Parameters

git.sh accepts three required parameters:

./git.sh <folder> <file> <branch>
  • <folder>: Deployment directory path (e.g., /var/www)
  • <file>: Trigger filename (should always be git.flag)
  • <branch>: Remote branch to deploy from (e.g., master, dev)

Example:

./git.sh /var/www git.flag master

Manual Deployment (Debugging)

To manually trigger deployment without a webhook:

cd /var/www
touch git.flag
# incron detects the file and runs git.sh automatically

Monitor the process:

# Check incron logs
tail -f /var/log/syslog | grep incron

# Verify file permissions
ls -la /var/www/ | head -5

Troubleshooting

Deployment Not Triggering

  1. Verify incron is running:

    sudo systemctl status incron
    
  2. Check incron rule syntax:

    sudo incrontab -l
    
  3. Test manually:

    cd /var/www
    touch git.flag
    # Should trigger immediately
    
  4. Monitor logs:

    tail -f /var/log/syslog | grep incron
    

Git Authentication Failures

Incron runs as system user and doesn't inherit SSH keys from your shell. Configure SSH keys for the www-data user:

# Generate SSH key for www-data
sudo -u www-data ssh-keygen -t rsa -f /var/www/.ssh/id_rsa

# Add public key to Bitbucket/GitHub
# Then test
sudo -u www-data git fetch --all

Permission Issues After Deployment

Web server user must own all deployed files. git.sh handles this automatically by running:

chown www-data:www-data /var/www -R

For different web servers, modify this line:

  • Apache: apache:apache
  • nginx: nginx:nginx
  • Custom user: youruser:youruser

Integration Examples

Bitbucket Webhooks

Configure webhook in Bitbucket repository settings:

  • URL: https://your-server.com/webhook/deploy.php
  • Trigger: "Push"

The webhook should POST to your trigger endpoint, which creates git.flag.

GitLab/GitHub Webhooks

Similar setup - configure push webhook to hit your trigger endpoint.

Cron-Based Deployment

For scheduled deployments without webhooks:

# /etc/cron.d/deploy-cron
0 2 * * * www-data touch /var/www/git.flag

CI/CD Integration

Bitbucket Pipelines

Example pipeline that validates script syntax:

pipelines:
  default:
    - step:
        script:
          - chmod +x git.sh
          - ./git.sh ./ git.flag master

Gitea Actions

Syntax checking workflow in .gitea/workflows/syntax-check.yml:

  • ShellCheck validation for bash scripts
  • PHP lint for PHP files
  • YAML validation for configuration files

Important Notes

  • Linux/Unix Only: Requires incron for file system event monitoring
  • Pre-Authentication: Git repository must be cloned with SSH keys or credentials configured
  • No Concurrent Locking: Multiple simultaneous triggers could cause race conditions
  • Single Branch Per Directory: Each monitored directory deploys one specific branch
  • Root or Elevated Privileges: chown requires sufficient privileges to change file ownership

Support

For issues, questions, or improvements:

Description
No description provided
Readme 43 KiB
Languages
Shell 96.5%
PHP 3.5%