# Git-based Deployment in BYOP Engine

## Overview

The BYOP Engine now supports Git-based deployments using Git hooks for continuous deployment. This allows developers to deploy applications by simply pushing to a Git repository.

## How It Works

1. **Initial Setup**: When a VM is initialized:
   - Creates a bare Git repository on the VM
   - Sets up a working directory for the component
   - Configures Git hooks for automatic deployment

2. **Continuous Deployment**: After initial setup, developers can:
   - Add the remote repository to their local Git config
   - Push changes to trigger automatic deployment
   - Monitor deployment progress through the BYOP dashboard

3. **Component-Specific Deployment**: Different components are handled appropriately:
   - **Frontend**: Built and served via Nginx
   - **Backend**: Built and managed via systemd or PM2
   - **Database**: Configuration files applied and services restarted

## Usage

### Adding a Remote Repository

After a component is deployed, add the remote repository to your Git config:

```bash
git remote add production ssh://root@<vm-ip>/opt/byop/repos/<component-id>.git
```

### Deploying Changes

Push to the remote repository to trigger a deployment:

```bash
git push production <branch>
```

The post-receive hook will automatically:
1. Check out the code to the working directory
2. Install dependencies
3. Build the application
4. Restart or reload services as needed

### Monitoring Deployments

You can monitor deployment status through:
- The BYOP dashboard
- SSH access to the VM to check logs
- Component status indicators

## Security Considerations

- SSH access is controlled through credentials managed by BYOP
- Deploy keys can be configured for secure repository access
- All operations use secure SSH connections

## Future Enhancements

- Support for deployment rollbacks
- Automated testing before deployment
- Multi-stage deployment environments (dev, staging, production)
- Notification system for deployment status updates

## Post script hooks example

```golang

// createFrontendPostReceiveHook generates a Git hook for frontend components
func createFrontendPostReceiveHook(component models.Component, deployPath string) string {
	return fmt.Sprintf(`#!/bin/bash
echo "Deploying frontend component: %s"

# Get the target branch (usually main or master)
TARGET="%s"
while read oldrev newrev ref
do
    # Check if the pushed branch is our target branch
    if [[ $ref = refs/heads/$TARGET ]]; 
    then
        echo "Deploying $TARGET branch..."
        
        # Checkout code to the deployment directory
        GIT_WORK_TREE=%s git checkout -f $TARGET
        cd %s
        
        # Update environment variables
        echo '%s' > %s/.env
        
        # Install dependencies
        echo "Installing dependencies..."
        npm install
        
        # Build the application
        echo "Building application..."
        %s
        
        # Notify about completion
        echo "Frontend deployment completed successfully"
    fi
done
`, component.Name, component.Branch, deployPath, deployPath, component.EnvVariables, deployPath, component.BuildCommand)
}

// createGoPostReceiveHook generates a Git hook for Go components
func createGoPostReceiveHook(component models.Component, deployPath string) string {
	return fmt.Sprintf(`#!/bin/bash
echo "Deploying Go component: %s"

# Get the target branch (usually main or master)
TARGET="%s"
while read oldrev newrev ref
do
    # Check if the pushed branch is our target branch
    if [[ $ref = refs/heads/$TARGET ]]; 
    then
        echo "Deploying $TARGET branch..."
        
        # Checkout code to the deployment directory
        GIT_WORK_TREE=%s git checkout -f $TARGET
        cd %s
        
        # Update environment variables
        echo '%s' > %s/.env
        
        # Build the application
        echo "Building Go application..."
        go build -o app
        
        # Restart the service
        echo "Restarting service..."
        systemctl restart byop-%s
        
        # Notify about completion
        echo "Go deployment completed successfully"
    fi
done
`, component.Name, component.Branch, deployPath, deployPath, component.EnvVariables, deployPath, component.ID)
}

// createNodePostReceiveHook generates a Git hook for Node.js components
func createNodePostReceiveHook(component models.Component, deployPath string) string {
	return fmt.Sprintf(`#!/bin/bash
echo "Deploying Node.js component: %s"

# Get the target branch (usually main or master)
TARGET="%s"
while read oldrev newrev ref
do
    # Check if the pushed branch is our target branch
    if [[ $ref = refs/heads/$TARGET ]]; 
    then
        echo "Deploying $TARGET branch..."
        
        # Checkout code to the deployment directory
        GIT_WORK_TREE=%s git checkout -f $TARGET
        cd %s
        
        # Update environment variables
        echo '%s' > %s/.env
        
        # Install dependencies
        echo "Installing dependencies..."
        npm install
        
        # Build the application if there's a build command
        if [[ "%s" != "" ]]; then
            echo "Building application..."
            %s || true
        fi
        
        # Restart the PM2 process
        echo "Restarting PM2 process..."
        pm2 restart byop-%s || pm2 start npm --name "byop-%s" -- start
        pm2 save
        
        # Notify about completion
        echo "Node.js deployment completed successfully"
    fi
done
`, component.Name, component.Branch, deployPath, deployPath, component.EnvVariables, deployPath, component.BuildCommand, component.BuildCommand, component.ID, component.ID)
}

// createPythonPostReceiveHook generates a Git hook for Python components
func createPythonPostReceiveHook(component models.Component, deployPath string) string {
	return fmt.Sprintf(`#!/bin/bash
echo "Deploying Python component: %s"

# Get the target branch (usually main or master)
TARGET="%s"
while read oldrev newrev ref
do
    # Check if the pushed branch is our target branch
    if [[ $ref = refs/heads/$TARGET ]]; 
    then
        echo "Deploying $TARGET branch..."
        
        # Checkout code to the deployment directory
        GIT_WORK_TREE=%s git checkout -f $TARGET
        cd %s
        
        # Update environment variables
        echo '%s' > %s/.env
        
        # Update dependencies
        echo "Updating Python dependencies..."
        source venv/bin/activate
        pip install -r requirements.txt
        
        # Restart the service
        echo "Restarting service..."
        systemctl restart byop-%s
        
        # Notify about completion
        echo "Python deployment completed successfully"
    fi
done
`, component.Name, component.Branch, deployPath, deployPath, component.EnvVariables, deployPath, component.ID)
}

// createDatabasePostReceiveHook generates a Git hook for database components
func createDatabasePostReceiveHook(component models.Component, deployPath string, dbType string) string {
	var configUpdate, restartCmd string

	switch dbType {
	case "postgresql":
		configUpdate = fmt.Sprintf(`
        # Apply configuration changes if available
        if [ -f %s/postgresql.conf ]; then
            cp %s/postgresql.conf /etc/postgresql/*/main/
            echo "Updated PostgreSQL configuration"
        fi`, deployPath, deployPath)
		restartCmd = "systemctl restart postgresql"
	case "mariadb", "mysql":
		configUpdate = fmt.Sprintf(`
        # Apply configuration changes if available
        if [ -f %s/my.cnf ]; then
            cp %s/my.cnf /etc/mysql/
            echo "Updated MariaDB configuration"
        fi`, deployPath, deployPath)
		restartCmd = "systemctl restart mariadb"
	case "mongodb":
		configUpdate = fmt.Sprintf(`
        # Apply configuration changes if available
        if [ -f %s/mongodb.conf ]; then
            cp %s/mongodb.conf /etc/mongodb.conf
            echo "Updated MongoDB configuration"
        fi`, deployPath, deployPath)
		restartCmd = "systemctl restart mongodb"
	}

	return fmt.Sprintf(`#!/bin/bash
echo "Deploying database component: %s"

# Get the target branch (usually main or master)
TARGET="%s"
while read oldrev newrev ref
do
    # Check if the pushed branch is our target branch
    if [[ $ref = refs/heads/$TARGET ]]; 
    then
        echo "Deploying $TARGET branch..."
        
        # Checkout code to the deployment directory
        GIT_WORK_TREE=%s git checkout -f $TARGET
        cd %s
        
        # Update environment variables
        echo '%s' > %s/.env
        %s
        
        # Run any database migrations if available
        if [ -f %s/migrations/run.sh ]; then
            echo "Running database migrations..."
            bash %s/migrations/run.sh
        fi
        
        # Restart database service
        echo "Restarting database service..."
        %s
        
        # Notify about completion
        echo "Database component deployment completed successfully"
    fi
done
`, component.Name, component.Branch, deployPath, deployPath, component.EnvVariables, deployPath, configUpdate, deployPath, deployPath, restartCmd)
}

// createSystemdServiceCommand creates a systemd service file for the component
func createSystemdServiceCommand(component models.Component, deploymentPath string) string {
	var execStart string
	var workingDir string

	workingDir = deploymentPath

	switch component.Language {
	case "golang":
		execStart = fmt.Sprintf("%s/app", deploymentPath)
	case "python":
		execStart = fmt.Sprintf("%s/venv/bin/python %s/main.py", deploymentPath, deploymentPath)
	default:
		execStart = component.BuildCommand
	}

	serviceFile := fmt.Sprintf(`[Unit]
Description=BYOP Component %s
After=network.target

[Service]
ExecStart=%s
WorkingDirectory=%s
Restart=always
User=root
Group=root
Environment=PATH=/usr/bin:/usr/local/bin
EnvironmentFile=%s/.env

[Install]
WantedBy=multi-user.target
`, component.Name, execStart, workingDir, deploymentPath)

	return fmt.Sprintf("echo '%s' > /etc/systemd/system/byop-%s.service", serviceFile, component.ID)
}
```