You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为本地部署的CodeIgniter Web系统实现自动更新?

Absolutely, you can build an auto-update workflow for your CodeIgniter system that mirrors desktop app behavior—here's a practical, step-by-step guide tailored to your local deployment setup:

Core Concept

The idea is to replicate desktop app update logic with four key steps:

  • Check for updates: Compare your local code's latest commit hash with the remote Bitbucket repo's branch head
  • Auto-pull code: Use git to fetch the latest changes (with pre-configured auth to avoid manual login)
  • Run migrations: Trigger CodeIgniter's built-in migration system automatically
  • Safety guards: Add backups, access controls, and rollback logic to prevent downtime
Step-by-Step Implementation

1. Pre-requisites

First, set up the foundation for automated git access:

  • Generate an SSH key pair for your web server user (e.g., www-data on Linux) and add the public key to your Bitbucket repo's Access keys (under Repository Settings)
  • For private repos, create a Bitbucket App Password with only Repository Read permissions (avoid using your personal password)
  • Ensure the web server user has read/write permissions to your CodeIgniter project directory and can execute git commands

2. Build the Update Controller

Create a new controller (e.g., Update.php) in your CodeIgniter application to handle the update workflow:

Check for New Versions

This method compares your local commit hash with the remote Bitbucket branch:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Update extends CI_Controller {

    public function __construct() {
        parent::__construct();
        // Enforce security first
        $this->lock_down_access();
    }

    private function lock_down_access() {
        // Restrict to CLI or trusted internal IPs
        if (!$this->input->is_cli_request()) {
            $allowed_ips = ['192.168.1.0/24', '127.0.0.1']; // Replace with your office subnet
            $user_ip = $this->input->ip_address();
            if (!in_array($user_ip, $allowed_ips)) {
                show_404();
            }
        }
        // Optional: Add password protection for web access
        if (!$this->input->post('secure_key') || $this->input->post('secure_key') !== 'your_strong_update_password') {
            show_error("Unauthorized access to update system.");
        }
    }

    public function check_and_update() {
        // Get local latest commit hash
        $local_commit_path = FCPATH . '.git/refs/heads/main'; // Replace with your branch name
        if (!file_exists($local_commit_path)) {
            show_error("Local git repo not found.");
        }
        $local_commit = trim(file_get_contents($local_commit_path));

        // Fetch remote commit hash via Bitbucket API
        $repo_owner = 'your_bitbucket_username';
        $repo_slug = 'your_repo_name';
        $branch = 'main';
        $api_url = "https://api.bitbucket.org/2.0/repositories/{$repo_owner}/{$repo_slug}/refs/branches/{$branch}";

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $api_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        // For private repos, add App Password auth
        // curl_setopt($ch, CURLOPT_USERPWD, 'your_username:your_bitbucket_app_password');

        $response = curl_exec($ch);
        curl_close($ch);

        $remote_data = json_decode($response, true);
        if (empty($remote_data['target']['hash'])) {
            show_error("Failed to fetch remote repo info.");
        }
        $remote_commit = $remote_data['target']['hash'];

        // Compare hashes to trigger update
        if ($remote_commit !== $local_commit) {
            try {
                $this->run_update_workflow($remote_commit);
                echo "✅ Update successful! New commit: {$remote_commit}";
                // Optional: Alert admin via email
                $this->send_admin_alert("Success", "System updated to commit {$remote_commit}");
            } catch (Exception $e) {
                echo "❌ Update failed: " . $e->getMessage();
                $this->send_admin_alert("Failure", $e->getMessage());
            }
        } else {
            echo "ℹ️ System is already up to date.";
        }
    }

Execute the Update & Migrations

Add this private method to handle pulling code, backups, and migrations with rollback logic:

private function run_update_workflow($remote_commit) {
        $backup_dir = FCPATH . 'backups/' . date('YmdHis') . '_' . substr($remote_commit, 0, 7);
        mkdir($backup_dir, 0755, true);

        // 1. Backup code
        exec("cp -r " . escapeshellarg(FCPATH) . " " . escapeshellarg($backup_dir), $backup_output, $backup_code);
        if ($backup_code !== 0) {
            throw new Exception("Failed to backup code: " . implode("\n", $backup_output));
        }

        // 2. Backup database
        $db_config = $this->db->get_config();
        $db_backup = $backup_dir . '/db_backup.sql';
        $dump_cmd = sprintf(
            "mysqldump -u%s -p%s %s > %s",
            escapeshellarg($db_config['username']),
            escapeshellarg($db_config['password']),
            escapeshellarg($db_config['database']),
            escapeshellarg($db_backup)
        );
        exec($dump_cmd, $db_output, $db_code);
        if ($db_code !== 0) {
            throw new Exception("Failed to backup database: " . implode("\n", $db_output));
        }

        // 3. Pull latest code
        chdir(FCPATH);
        exec("git pull origin main", $pull_output, $pull_code); // Replace branch if needed
        if ($pull_code !== 0) {
            // Rollback code backup
            exec("cp -r " . escapeshellarg($backup_dir) . "/* " . escapeshellarg(FCPATH));
            throw new Exception("Git pull failed: " . implode("\n", $pull_output));
        }

        // 4. Run CodeIgniter migrations
        exec("php index.php migrate", $migrate_output, $migrate_code);
        if ($migrate_code !== 0) {
            // Rollback code and database
            exec("cp -r " . escapeshellarg($backup_dir) . "/* " . escapeshellarg(FCPATH));
            exec(sprintf(
                "mysql -u%s -p%s %s < %s",
                escapeshellarg($db_config['username']),
                escapeshellarg($db_config['password']),
                escapeshellarg($db_config['database']),
                escapeshellarg($db_backup)
            ));
            throw new Exception("Migration failed: " . implode("\n", $migrate_output));
        }

        // Optional: Clean up old backups (keep last 5)
        $this->prune_old_backups();
    }

    private function send_admin_alert($status, $message) {
        // Use CodeIgniter's email library to notify admins
        $this->load->library('email');
        $this->email->from('update-system@yourcompany.com', 'Auto-Update System');
        $this->email->to('admin@yourcompany.com');
        $this->email->subject("CodeIgniter System Update {$status}");
        $this->email->message($message);
        $this->email->send();
    }

    private function prune_old_backups() {
        $backup_dir = FCPATH . 'backups/';
        $backups = glob($backup_dir . '*');
        usort($backups, function($a, $b) {
            return filemtime($b) - filemtime($a);
        });
        // Keep only the last 5 backups
        foreach (array_slice($backups, 5) as $old_backup) {
            exec("rm -rf " . escapeshellarg($old_backup));
        }
    }
}

3. Schedule Automated Checks

Since CodeIgniter is request-driven, use your server's task scheduler to trigger the update check:

  • Linux/macOS: Add a cron job (run crontab -e as the web server user or root):
    # Check for updates daily at 2 AM
    0 2 * * * /usr/bin/php /path/to/your/codeigniter/index.php Update check_and_update
    
  • Windows: Use Task Scheduler to create a daily task that runs:
    php.exe C:\path\to\codeigniter\index.php Update check_and_update
    
Critical Safety Notes
  • Test first: Run the update workflow manually via CLI first to debug permission or auth issues
  • Restrict access: Never expose the update controller to the public internet—limit it to internal IPs only
  • Backup everything: The backup step is non-negotiable; it prevents data loss if updates fail
  • Avoid production surprises: Only merge tested code to your main branch, as this system will pull all changes automatically
  • Log everything: Add detailed logging to track update attempts, successes, and failures

内容的提问来源于stack exchange,提问作者Ronald Araújo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:02:50