public function fire(Worker $worker, $message)
 {
     Log::info("--- Pull Request Build Start ---");
     $commit = $message['commit'];
     $pullNumber = $message['pullNumber'];
     $siteId = $message['siteId'];
     $pr = new PullRequest($siteId);
     $commitInfo = $pr->get($commit);
     $repoName = $commitInfo->repo;
     $gitOrigin = "git@github.com:{$repoName}.git";
     $dc = new DC($siteId);
     $branch = $commitInfo->branch;
     $root = (new SystemConfig())->get(SystemConfig::WORK_ROOT_FIELD) . '/' . $siteId;
     $ifContent = $dc->get(DC::IDENTIFYFILE);
     if (!empty($ifContent)) {
         $passphrase = $dc->get(DC::PASSPHRASE);
         $identifyfile = (new SystemConfig())->get(SystemConfig::WORK_ROOT_FIELD) . '/' . $siteId . '/identify.key';
         if (!File::exists($identifyfile)) {
             file_put_contents($identifyfile, $ifContent);
             chmod($identifyfile, 0600);
         }
     } else {
         $passphrase = null;
         $identifyfile = null;
     }
     $defaultBranch = "{$root}/branch/default";
     $prDefaultBranch = "{$root}/branch/pruse";
     $branchRoot = "{$root}/pull_requests/repo/{$repoName}";
     $commitPath = "{$root}/pull_requests/commit/{$commit}";
     $progress = 0;
     $cmd = '';
     $lock1 = null;
     $lock2 = null;
     try {
         $lock2 = new \Eleme\Rlock\Lock(app('redis')->connection(), JobLock::pullRequestBuildLock($prDefaultBranch), array('timeout' => 600000, 'blocking' => false));
         if (!$lock2->acquire()) {
             Log::info("Job locked, now {$worker->getJobId()} Release");
             $worker->release(30);
             return;
         }
         if (!File::exists($prDefaultBranch)) {
             // 可能跟build branch冲突
             $lock1 = new \Eleme\Rlock\Lock(app('redis')->connection(), JobLock::buildLock($defaultBranch), array('timeout' => 600000, 'blocking' => false));
             if (!$lock1->acquire()) {
                 Log::info("Job locked, now {$worker->getJobId()} Release");
                 $worker->release(30);
                 return;
             }
             Log::info('init pull request branch');
             $mcd = 'mkdir -p ' . $prDefaultBranch;
             (new Process($cmd))->mustRun();
             $cmd = "mkdir -p {$root}/pull_requests/commit/";
             (new Process($cmd))->mustRun();
             $progress = 1;
             $cmd = "cp -r {$defaultBranch} {$prDefaultBranch}";
             (new Process($cmd))->mustRun();
             $progress = 2;
             $lock1->release();
             $lock1 = null;
         }
         if (!File::exists($commitPath)) {
             $cmd = "git fetch -f origin +refs/pull/{$pullNumber}/head";
             Log::info($cmd . "  " . $prDefaultBranch);
             (new GitProcess($cmd, $prDefaultBranch, $identifyfile, $passphrase, 600))->setTimeout(600)->mustRun();
             $progress = 3;
             $cmd = "cp -r {$prDefaultBranch} {$commitPath}";
             Log::info($cmd);
             (new Process($cmd))->mustRun();
         }
         $lock2->release();
         $lock2 = null;
         $cmd = "git checkout -qf FETCH_HEAD";
         Log::info($cmd);
         (new Process($cmd, $commitPath))->mustRun();
         $commitInfo->buildStatus = 'Building';
         $pr->save($commitInfo);
         $progress = 4;
         $cmd = $dc->get(DC::BUILD_COMMAND) ?: 'make deploy';
         Log::info($cmd);
         (new Process($cmd, $commitPath))->setTimeout(600)->mustRun();
         $commitInfo->buildStatus = 'Success';
         $pr->save($commitInfo);
         try {
             $progress = 5;
             $commitInfo->testStatus = 'Testing';
             $pr->save($commitInfo);
             $cmd = $dc->get(DC::TEST_COMMAND);
             if (!empty($cmd)) {
                 Log::info($cmd);
                 (new Process($cmd, $commitPath))->setTimeout(600)->mustRun();
             }
         } catch (Exception $e) {
             $this->sendStatus($siteId, $dc->get(DC::GITHUB_TOKEN), $dc->get(DC::GIT_ORIGIN), $commit, 'failure', 'Test Failure');
             throw new Exception($e->getMessage(), 1379);
         }
         $commitInfo->testStatus = 'Success';
         $pr->save($commitInfo);
         $this->sendStatus($siteId, $dc->get(DC::GITHUB_TOKEN), $dc->get(DC::GIT_ORIGIN), $commit, 'success', 'Build and Test Success');
     } catch (Exception $e) {
         if ($e->getCode() != 1379) {
             $this->sendStatus($siteId, $dc->get(DC::GITHUB_TOKEN), $dc->get(DC::GIT_ORIGIN), $commit, 'error', 'Job Error');
         }
         if ($lock1 !== null) {
             $lock1->release();
         }
         if ($lock2 !== null) {
             $lock2->release();
         }
         Log::info("ERROR!!! : " . $e->getMessage());
         $commitInfo->buildStatus = 'Error';
         $commitInfo->testStatus = 'Error';
         $commitInfo->errorMsg = "Command : {$cmd}\nError Message : {$e->getMessage()}";
         switch ($progress) {
             case 5:
                 $commitInfo->buildStatus = 'Success';
                 break;
             case 4:
                 (new Process("rm -rf {$commitPath}"))->run();
             case 3:
             case 2:
                 $commitInfo->testStatus = 'Abort';
                 break;
             case 1:
                 $cmd = "rm -rf {$root}/pull_requests/commit/";
                 (new Process($cmd))->run();
                 (new Process("rm -rf {$prDefaultBranch}"))->run();
                 $commitInfo->testStatus = 'Abort';
                 break;
         }
         $pr->save($commitInfo);
     }
     Log::info("progress : {$progress}");
     Log::info("worker id : {$worker->getJobId()} finish");
     //if (!empty($identifyfile)) (new Process('rm -f ' . $identifyfile))->run();
 }
    public function fire(Worker $worker, $message)
    {
        $this->warnings = array();
        $commit = $message['commit'];
        $hostType = $message['hostType'];
        $siteId = $message['siteId'];
        $dc = new DC($siteId);
        $staticDir = $dc->get(DC::STATIC_DIR);
        $gitOrigin = $dc->get(DC::GIT_ORIGIN);
        if (isset($message['type']) && $message['type'] == self::TYPE_PULL_REQUEST) {
            $id = $message['id'];
            $this->type = self::TYPE_PULL_REQUEST;
            $this->pr = new PullRequestDeploy($siteId);
            $this->prDeployInfo = $this->pr->get($id);
            $operateUser = $this->prDeployInfo->operateUser;
            $root = (new SystemConfig())->get(SystemConfig::WORK_ROOT_FIELD) . '/' . $siteId . '/pull_requests';
            $commitPath = "{$root}/commit/{$commit}";
        } else {
            $this->type = self::TYPE_NORMAL_DEPLOY;
            $this->dfManger = new DeployInfo($siteId);
            $id = $message['id'];
            $this->deployInfo = $this->dfManger->get($id);
            $operateUser = $this->deployInfo['user'];
            $root = (new SystemConfig())->get(SystemConfig::WORK_ROOT_FIELD) . '/' . $siteId . '/commit';
            $commitPath = "{$root}/{$commit}";
        }
        $LOCAL_STATIC_DIR = "{$commitPath}/{$staticDir}/";
        $LOCAL_DIR = $commitPath . '/';
        $remoteUser = $dc->get(DC::REMOTE_USER);
        $remoteOwner = $dc->get(DC::REMOTE_OWNER);
        $ifContent = $dc->get(DC::IDENTIFYFILE);
        if (!empty($ifContent)) {
            $passphrase = $dc->get(DC::PASSPHRASE);
            $identifyfile = (new SystemConfig())->get(SystemConfig::WORK_ROOT_FIELD) . '/' . $siteId . '/identify.key';
            file_put_contents($identifyfile, $ifContent);
            chmod($identifyfile, 0600);
        } else {
            $passphrase = null;
            $identifyfile = null;
        }
        $RSYNC_EXCLUDE = "{$commitPath}/" . $dc->get(DC::RSYNC_EXCLUDE);
        $REMOTE_STATIC_DIR = $dc->get(DC::REMOTE_STATIC_DIR) . '/';
        $REMOTE_DIR = $dc->get(DC::REMOTE_APP_DIR) . '/';
        $staticScript = ScriptCommand::complie($dc->get(DC::DEPLOY_STATIC_SCRIPT), $siteId);
        $webScript = ScriptCommand::complie($dc->get(DC::DEPLOY_WEB_SCRIPT), $siteId);
        Log::info("--- {$worker->getJobId()} ---");
        Log::info("Commit deploy: {$commit}");
        //本地同步锁
        $redis = app('redis')->connection();
        $commitLock = new \Eleme\Rlock\Lock($redis, JobLock::buildLock($siteId . $hostType), array('timeout' => 600000, 'blocking' => false));
        if (!$commitLock->acquire()) {
            Log::info("worker : {$worker->getJobId()} Release");
            $worker->release(30);
            return;
        }
        $this->updateStatus('Deploying');
        $rsyLock = NULL;
        try {
            $REMOTE_DIR = $this->clearDirString($REMOTE_DIR);
            $REMOTE_STATIC_DIR = $this->clearDirString($REMOTE_STATIC_DIR);
            $hosts = (new SiteHost($siteId, $hostType, SiteHost::STATIC_HOST))->getList();
            $staticHosts = new SplQueue();
            foreach ($hosts as $h) {
                $staticHosts->push($h);
            }
            $hosts = (new SiteHost($siteId, $hostType, SiteHost::WEB_HOST))->getList();
            $webHosts = new SplQueue();
            foreach ($hosts as $h) {
                $webHosts->push($h);
            }
            /*****************************************
             *
             *  执行静态文件同步
             *
             *****************************************/
            $worker->report('');
            //执行同步前本地命令
            $this->processCommands($staticScript['before']['handle']);
            while (!$staticHosts->isEmpty()) {
                $host = $staticHosts->shift();
                $rsyLock = new \Eleme\Rlock\Lock($redis, JobLock::rsyLock($host['hostip']), array('timeout' => 180000, 'blocking' => false));
                $worker->report('');
                if ($rsyLock->acquire()) {
                    try {
                        $HOST_NAME = $host['hostname'];
                        $PORT = $host['hostport'];
                        //执行同步前每次都执行的本地命令
                        $this->processCommands($staticScript['before']['local']);
                        //执行同步前每次都执行的远端命令
                        $this->processCommands($staticScript['before']['remote'], $HOST_NAME, $host['hostip'], $remoteUser, $identifyfile, $passphrase, $PORT);
                        Log::info("deploying static files to {$HOST_NAME}.");
                        $this->sshProcess($HOST_NAME, $host['hostip'], $remoteUser, "sudo mkdir -p {$REMOTE_STATIC_DIR}", $identifyfile, $passphrase, null, $PORT);
                        $this->sshProcess($HOST_NAME, $host['hostip'], $remoteUser, "sudo chown {$remoteUser} -R {$REMOTE_STATIC_DIR}", $identifyfile, $passphrase, null, $PORT);
                        $this->rsyncProcess($HOST_NAME, $host['hostip'], $remoteUser, $RSYNC_EXCLUDE, $LOCAL_STATIC_DIR, $REMOTE_STATIC_DIR, RsyncProcess::KEEP_FILES, $identifyfile, $passphrase, $commitPath, $PORT);
                        $this->sshProcess($HOST_NAME, $host['hostip'], $remoteUser, "sudo chown {$remoteOwner} -R {$REMOTE_STATIC_DIR}", $identifyfile, $passphrase, null, $PORT);
                        //执行同步后每次都执行的本地命令
                        $this->processCommands($staticScript['after']['local']);
                        //执行同步后每次都执行的远端命令
                        $this->processCommands($staticScript['after']['remote'], $HOST_NAME, $host['hostip'], $remoteUser, $identifyfile, $passphrase, $PORT);
                        $rsyLock->release();
                    } catch (Exception $e) {
                        $rsyLock->release();
                        throw $e;
                    }
                } else {
                    // 正在同步,重新放回队列
                    $staticHosts->push($host);
                }
            }
            //执行同步后本地命令
            $this->processCommands($staticScript['after']['handle']);
            /*****************************************
             *
             *  执行WEB应用同步
             *
             *****************************************/
            //执行同步前本地命令
            $this->processCommands($webScript['before']['handle']);
            while (!$webHosts->isEmpty()) {
                $host = $webHosts->shift();
                $worker->report('');
                $rsyLock = new \Eleme\Rlock\Lock($redis, JobLock::rsyLock($host['hostip']), array('timeout' => 180000, 'blocking' => false));
                if ($rsyLock->acquire()) {
                    try {
                        $HOST_NAME = $host['hostname'];
                        $PORT = $host['hostport'];
                        //执行同步前每次都执行的本地命令
                        $this->processCommands($webScript['before']['local']);
                        //执行同步前每次都执行的远端命令
                        $this->processCommands($webScript['before']['remote'], $HOST_NAME, $host['hostip'], $remoteUser, $identifyfile, $passphrase, $PORT);
                        Log::info("deploying web apps to {$HOST_NAME}.");
                        $this->sshProcess($HOST_NAME, $host['hostip'], $remoteUser, "sudo mkdir -p {$REMOTE_DIR}", $identifyfile, $passphrase, null, $PORT);
                        $this->sshProcess($HOST_NAME, $host['hostip'], $remoteUser, "sudo chown {$remoteUser} -R {$REMOTE_DIR}", $identifyfile, $passphrase, null, $PORT);
                        $this->rsyncProcess($HOST_NAME, $host['hostip'], $remoteUser, $RSYNC_EXCLUDE, $LOCAL_DIR, $REMOTE_DIR, RsyncProcess::FORCE_DELETE, $identifyfile, $passphrase, $commitPath, $PORT);
                        $this->sshProcess($HOST_NAME, $host['hostip'], $remoteUser, "sudo chown {$remoteOwner} -R {$REMOTE_DIR}", $identifyfile, $passphrase, null, $PORT);
                        //执行同步后每次都执行的本地命令
                        $this->processCommands($webScript['after']['local']);
                        //执行同步后每次都执行的远端命令
                        $this->processCommands($webScript['after']['remote'], $HOST_NAME, $host['hostip'], $remoteUser, $identifyfile, $passphrase, $PORT);
                        $rsyLock->release();
                    } catch (Exception $e) {
                        $rsyLock->release();
                        throw $e;
                    }
                } else {
                    $webHosts->push($host);
                }
            }
            $worker->report('');
            //执行同步后本地命令
            $this->processCommands($webScript['after']['handle']);
            $errMsg = '';
            foreach ($this->warnings as $w) {
                $errMsg .= "{$w}\n";
            }
            $errMsg = empty($errMsg) ? null : $errMsg;
            $this->updateStatus('Deploy Success', $errMsg);
            Log::info($worker->getJobId() . " finish");
            $pc = new \PrevCommit($siteId, $hostType);
            $prevCommit = $pc->get();
            try {
                preg_match('/github\\.com:(.+?)\\.git$/i', $gitOrigin, $matchs);
                $repoName = $matchs[1];
                $token = $dc->get(DC::HIPCHAT_TOKEN);
                $room = $dc->get(DC::HIPCHAT_ROOM);
                if (!empty($token) && !empty($room)) {
                    $client = new HipChat($token, $room);
                    $diffUrl = '';
                    if (!empty($prevCommit) && $prevCommit != $commit) {
                        $diffUrl = "Diff: https://github.com/{$repoName}/compare/{$prevCommit}...{$commit}";
                    }
                    $notify = <<<EOT
Message: Deploy {$siteId} to {$hostType} Success
Deploy Id: {$id}
Operater: {$operateUser}
Status: Success
Host Type: {$hostType}
Commit: {$commit}
{$diffUrl}
EOT;
                    $client->notify($notify);
                    Log::info('Hipchat Notify Send Sucess');
                }
                $logins = Watch::allUserWatching($siteId);
                $emails = array();
                foreach ($logins as $login) {
                    $user = GithubUser::loadFromRedis($login);
                    $emails[] = $user->email;
                }
                if (count($emails) > 0) {
                    $mailer = Mail::getSwiftMailer();
                    $transport = $mailer->getTransport();
                    $transport->stop();
                    $transport->start();
                    Mail::send('emails.deploy', array('siteId' => $siteId, 'status' => 'Success', 'hostType' => $hostType, 'commit' => $commit, 'repoName' => $matchs[1], 'user' => $operateUser, 'id' => $id, 'prevCommit' => $prevCommit), function ($message) use($emails) {
                        $email = array_pop($emails);
                        $message->to($email)->subject('Deploy Success!');
                        foreach ($emails as $email) {
                            $message->cc($email);
                        }
                    });
                    Log::info('Email Notify Send Success');
                }
            } catch (Exception $e) {
                Log::error("Notify Error:\n" . $e);
            }
            $rmpath = app_path() . '/storage/views/*';
            $this->process('sudo rm -rf ' . $rmpath, null, false);
            $rmpath = app_path() . '/storage/cache/*';
            $this->process('sudo rm -rf ' . $rmpath, null, false);
            $rmpath = app_path() . '/storage/meta/*';
            $this->process('sudo rm -rf ' . $rmpath, null, false);
            $pc->set($commit);
        } catch (Exception $e) {
            //if ($rsyLock != null) $rsyLock->release();
            $errMsg = $worker->getJobId() . " error : " . $e->getMessage() . "\n";
            $this->updateStatus('Error', $errMsg, null, $errMsg);
            Log::error($e);
            Log::info($worker->getJobId() . " Error Finish\n---------------------------");
        }
        $commitLock->release();
        //if (!empty($identifyfile)) $this->process('rm -f ' . $identifyfile, false);
    }
 public function fire(Worker $worker, $message)
 {
     Log::info("--- BuildBranchJob Start ---");
     $siteId = $message['siteId'];
     $buildId = $message['id'];
     $branch = $message['branch'];
     $dc = new DC($siteId);
     $this->infoManage = new DeployInfo($siteId);
     $root = (new SystemConfig())->get(SystemConfig::WORK_ROOT_FIELD) . '/' . $siteId;
     $commitRoot = "{$root}/commit/";
     $branchPath = "{$commitRoot}/{$branch}";
     $gitOrigin = $dc->get(DC::GIT_ORIGIN);
     $buildCommand = $dc->get(DC::BUILD_COMMAND) ?: 'make deploy';
     $defaultBranch = 'default';
     $developRoot = "{$root}/branch/{$defaultBranch}";
     $progress = 0;
     $redis = app('redis')->connection();
     $lock = new \Eleme\Rlock\Lock($redis, JobLock::buildLock($developRoot), array('timeout' => 600000, 'blocking' => false));
     if (!$lock->acquire()) {
         Log::info("Job locked, now {$worker->getJobId()} Release");
         $worker->release(30);
         return;
     }
     try {
         $this->deployInfo = $this->infoManage->get($buildId);
         $ifContent = $dc->get(DC::IDENTIFYFILE);
         if (!empty($ifContent)) {
             $passphrase = $dc->get(DC::PASSPHRASE);
             $sitePath = (new SystemConfig())->get(SystemConfig::WORK_ROOT_FIELD) . '/' . $siteId;
             if (!File::exists($sitePath)) {
                 $this->process('mkdir -p ' . $sitePath);
             }
             $identifyfile = $sitePath . '/identify.key';
             file_put_contents($identifyfile, $ifContent);
             chmod($identifyfile, 0600);
         } else {
             $passphrase = null;
             $identifyfile = null;
         }
         if (!File::exists($developRoot)) {
             $this->refreshStatus('Clone Repo');
             $worker->report('');
             $createWait = 1;
             $this->process('mkdir -p ' . $commitRoot);
             $this->process('mkdir -p ' . $developRoot);
             $this->gitProcess('git clone ' . $gitOrigin . ' ' . $developRoot, $developRoot, $identifyfile, $passphrase);
             unset($createWait);
         }
         $this->refreshStatus('Fetch Origin');
         $worker->report('');
         $this->gitProcess("git fetch origin", $developRoot, $identifyfile, $passphrase);
         $progress = 1;
         $this->process("cp -r {$developRoot} {$branchPath}", $commitRoot);
         $revParseProcess = $this->process("git rev-parse origin/{$branch}", $branchPath);
         $commit = trim($revParseProcess->getOutput());
         $commitPath = "{$commitRoot}/{$commit}";
         $needBuild = true;
         if ($commit !== $branch) {
             if (File::exists($commitPath)) {
                 File::deleteDirectory($branchPath);
                 $needBuild = false;
             } else {
                 $progress = 2;
                 File::move($branchPath, $commitPath);
             }
         }
         if ($needBuild) {
             $this->refreshStatus('Building', false);
             Log::info("Build {$siteId} branch:  {$branch}");
             $this->process("git checkout {$commit}", $commitPath);
             $worker->report('');
             $this->process($buildCommand, $commitPath);
         }
         (new CommitVersion($siteId))->add($commit);
         $this->deployInfo['commit'] = $commit;
         $this->refreshStatus('Build Success');
         Log::info('--- ' . $worker->getJobId() . " finish ---");
     } catch (Exception $e) {
         Log::error($e);
         Log::info('--- ' . $worker->getJobId() . " ERROR ---");
         //$this->deployInfo['errMsg'] = $e->getFile() . '  '. $e->getLine() . ' : ' . $e->getMessage();
         $this->deployInfo['errOut'] = $worker->getJobId() . " error : " . $e->getMessage() . "\n";
         $this->refreshStatus('Error', false);
         switch ($progress) {
             case 2:
                 $this->process('rm -rf ' . $commitPath);
             case 1:
                 $this->process('rm -rf ' . $branchPath);
         }
         if (isset($createWait) && $createWait == 1) {
             $this->process('rm -rf ' . $developRoot);
             $this->process('rm -rf ' . $commitRoot);
         }
     }
     $lock->release();
     Log::info("--- BuildBranchJob End ---");
     //if (!empty($identifyfile)) $this->process('rm -f ' . $identifyfile, false);
 }