예제 #1
0
파일: Svn.php 프로젝트: ShuangRen/walle-web
 /**
  * 更新到指定commit版本
  *
  * @param string $commit
  * @return bool
  */
 public function updateToVersion($task)
 {
     $copy = GlobalHelper::str2arr($task->file_list);
     $fileAndVersion = [];
     foreach ($copy as $file) {
         $fileAndVersion[] = StringHelper::explode($file, " ", true, true);
     }
     $branch = $task->branch == 'trunk' ? $task->branch : ($this->getConfig()->repo_mode == Project::REPO_BRANCH ? 'branches/' : 'tags/') . $task->branch;
     // 先更新
     $versionSvnDir = sprintf('%s-svn', rtrim(Project::getDeployWorkspace($task->link_id), '/'));
     $cmd[] = sprintf('cd %s ', $versionSvnDir);
     $cmd[] = $this->_getSvnCmd(sprintf('svn checkout %s/%s .', $this->getConfig()->repo_url, $branch));
     // 更新指定文件到指定版本,并复制到同步目录
     foreach ($fileAndVersion as $assign) {
         if (in_array($assign[0], ['.', '..'])) {
             continue;
         }
         $cmd[] = $this->_getSvnCmd(sprintf('svn up %s %s', $assign[0], empty($assign[1]) ? '' : ' -r ' . $assign[1]));
         // 多层目录需要先新建父目录,否则复制失败
         if (strpos($assign[0], '/') !== false) {
             $cmd[] = sprintf('mkdir -p %s/%s', Project::getDeployWorkspace($task->link_id), dirname($assign[0]));
         }
         $cmd[] = sprintf('cp -rf %s %s/%s', rtrim($assign[0], '/'), Project::getDeployWorkspace($task->link_id), dirname($assign[0]));
     }
     $command = join(' && ', $cmd);
     return $this->runLocalCommand($command);
 }
예제 #2
0
파일: Task.php 프로젝트: netstao/walle-web
 /**
  * 获取远程服务器要操作的任务命令
  *
  * @param $task    string
  * @param $version string
  * @return string string
  */
 public static function getRemoteTaskCommand($task, $version)
 {
     $tasks = GlobalHelper::str2arr($task);
     if (empty($tasks)) {
         return '';
     }
     $cmd = [];
     $workspace = rtrim(Project::getDeployWorkspace($version), '/');
     $version = Project::getReleaseVersionDir($version);
     $pattern = ['#{WORKSPACE}#', '#{VERSION}#'];
     $replace = [$workspace, $version];
     foreach ($tasks as $task) {
         $cmd[] = preg_replace($pattern, $replace, $task);
     }
     return join(' && ', $cmd);
 }
예제 #3
0
 /**
  * 同步代码之后触发任务
  * 所有目标机器都部署完毕之后,做一些清理工作,如删除缓存、重启服务(nginx、php、task)
  *
  * @return bool
  */
 public function postRelease($version)
 {
     $tasks = GlobalHelper::str2arr($this->getConfig()->post_release);
     if (empty($tasks)) {
         return true;
     }
     $cmd = [];
     $workspace = rtrim(Project::getDeployWorkspace($version), '/');
     $version = Project::getReleaseVersionDir($version);
     $pattern = ['#{WORKSPACE}#', '#{VERSION}#'];
     $replace = [$workspace, $version];
     foreach ($tasks as $task) {
         $cmd[] = preg_replace($pattern, $replace, $task);
     }
     $command = join(' && ', $cmd);
     return $this->runRemoteCommand($command);
 }
예제 #4
0
 protected final function runRemoteCommand($command)
 {
     $this->log = '';
     $needs_tty = '';
     foreach (GlobalHelper::str2arr($this->getConfig()->hosts) as $remoteHost) {
         $localCommand = 'ssh ' . $needs_tty . ' -p ' . $this->getHostPort($remoteHost) . ' -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ' . $this->getConfig()->release_user . '@' . $this->getHostName($remoteHost);
         $remoteCommand = str_replace('"', '\\"', trim($command));
         $localCommand .= ' "sh -c \\"' . $remoteCommand . '\\"" ';
         static::log('Run remote command ' . $remoteCommand);
         $log = $this->log;
         $this->status = $this->runLocalCommand($localCommand);
         $this->log = $log . (($log ? PHP_EOL : '') . $remoteHost . ' : ' . $this->log);
         if (!$this->status) {
             return false;
         }
     }
     return true;
 }
예제 #5
0
파일: Task.php 프로젝트: 9618211/walle-web
 /**
  * 获取远程服务器要操作的任务命令
  *
  * @param $task    string
  * @param $version string
  * @return string string
  */
 public static function getRemoteTaskCommand($task, $version)
 {
     $tasks = GlobalHelper::str2arr($task);
     if (empty($tasks)) {
         return '';
     }
     // 可能要做一些依赖环境变量的命令操作
     $cmd = ['source /etc/profile'];
     $workspace = Project::getTargetWorkspace();
     $version = Project::getReleaseVersionDir($version);
     $pattern = ['#{WORKSPACE}#', '#{VERSION}#'];
     $replace = [$workspace, $version];
     // 简化用户切换目录,直接切换到当前的版本目录:{release_library}/{project}/{version}
     $cmd[] = "cd {$version}";
     foreach ($tasks as $task) {
         $cmd[] = preg_replace($pattern, $replace, $task);
     }
     return join(' && ', $cmd);
 }
예제 #6
0
 /**
  * 将多个文件/目录通过ansible传输到指定的多个目标机
  *
  * ansible 不支持 rsync模块, 改用宿主机 tar 打包, ansible 并发传输到目标机临时目录, 目标机解压
  *
  * @param $version
  * @param string $files 相对仓库文件/目录路径, 空格分割
  * @param array $remoteHosts
  */
 public function copyFiles($version, $files = '*', $remoteHosts = [])
 {
     // 1. 打包
     $excludes = GlobalHelper::str2arr($this->getConfig()->excludes);
     $packagePath = Project::getDeployPackagePath($version);
     $packageCommand = sprintf('cd %s && tar -p %s -cz -f %s %s', escapeshellarg(rtrim(Project::getDeployWorkspace($version), '/') . '/'), $this->excludes($excludes), escapeshellarg($packagePath), $files);
     $ret = $this->runLocalCommand($packageCommand);
     if (!$ret) {
         return false;
     }
     // 2. 传输文件
     $releasePackage = Project::getReleaseVersionPackage($version);
     $ret = $this->copyFilesByAnsibleCopy($packagePath, $releasePackage);
     if (!$ret) {
         return false;
     }
     // 3. 解压
     $releasePath = Project::getReleaseVersionDir($version);
     $unpackageCommand = sprintf('cd %1$s && tar --no-same-owner -pm -C %1$s -xz -f %2$s', $releasePath, $releasePackage);
     $ret = $this->runRemoteCommandByAnsibleShell($unpackageCommand);
     return $ret;
 }
예제 #7
0
 public function diffWithOnline($file)
 {
     $localSourceDir = $this->config->getDeployFromDir();
     $remoteSourceDir = $this->config->getTargetWorkspace();
     $cmd[] = "cat {$remoteSourceDir}/{$file}";
     $command = implode(' && ', $cmd);
     $host = GlobalHelper::str2arr($this->config->hosts)[0];
     if ($this->runRemoteCommand($command, 0, $host)) {
         $contentOld = explode(PHP_EOL, substr($this->log, strlen($host . ' : ')));
         array_walk($contentOld, function (&$line) {
             $line = rtrim($line, "\r\n");
         });
     } else {
         $contentOld = [];
     }
     $contentNew = file("{$localSourceDir}/{$file}");
     array_walk($contentNew, function (&$line) {
         $line = rtrim($line, "\r\n");
     });
     $diff = new \Diff($contentOld, $contentNew);
     return $diff->render(new \Diff_Renderer_Html_Array());
 }
예제 #8
0
 /**
  * 获取当前进程配置的目标机器host列表
  */
 public static function getHosts()
 {
     return GlobalHelper::str2arr(static::$CONF->hosts);
 }
예제 #9
0
 /**
  * rsync 同步文件
  *
  * @param $remoteHost 远程host,格式:host 、host:port
  * @return bool
  */
 public function syncFiles($remoteHost, $version)
 {
     $excludes = GlobalHelper::str2arr($this->getConfig()->excludes);
     $command = sprintf('rsync -avzq --rsh="ssh -p %s" %s %s %s%s:%s', $this->getHostPort($remoteHost), $this->excludes($excludes), rtrim(Project::getDeployWorkspace($version), '/') . '/', $this->getConfig()->release_user . '@', $this->getHostName($remoteHost), Project::getReleaseVersionDir($version));
     return $this->runLocalCommand($command);
 }
예제 #10
0
 /**
  * @param Project $project
  * @param TaskModel $task
  * @return bool
  * @throws \Exception
  */
 protected function _packageFiles(Project $project, TaskModel $task)
 {
     $version = $task->link_id;
     $files = $task->getCommandFiles();
     $excludes = GlobalHelper::str2arr($project->excludes);
     $packagePath = Project::getDeployPackagePath($version);
     $packageCommand = sprintf('cd %s && tar -p %s -cz -f %s %s', escapeshellarg(rtrim(Project::getDeployWorkspace($version), '/') . '/'), $this->excludes($excludes), escapeshellarg($packagePath), $files);
     $ret = $this->runLocalCommand($packageCommand);
     if (!$ret) {
         throw new \Exception(yii::t('walle', 'package error'));
     }
     return true;
 }
예제 #11
0
 /**
  * 获取文件和版本号列表
  *
  * @param TaskModel $task
  * @return array
  */
 public function getFileAndVersionList(TaskModel $task)
 {
     $fileList = GlobalHelper::str2arr($task->file_list);
     $fileAndVersion = [];
     foreach ($fileList as $file) {
         list($file, $version) = array_pad(StringHelper::explode($file, ' ', true, true), 2, null);
         $fileAndVersion[] = ['file' => $file, 'version' => $version];
     }
     return $fileAndVersion;
 }
예제 #12
0
파일: Task.php 프로젝트: ashehui/walle-web
 /**
  * 获取要发布的文件列表
  *
  * @return array|string
  */
 public function getCommandFiles()
 {
     if ($this->file_transmission_mode == static::FILE_TRANSMISSION_MODE_FULL) {
         return '.';
     } elseif ($this->file_transmission_mode == static::FILE_TRANSMISSION_MODE_PART && $this->file_list) {
         $fileList = GlobalHelper::str2arr($this->file_list);
         $commandFiles = join(' ', $fileList);
         return trim($commandFiles);
     } else {
         throw new \InvalidArgumentException('file list empty');
     }
 }
예제 #13
0
파일: Git.php 프로젝트: ashehui/walle-web
 /**
  * 获取两个版本的差异
  *
  * @ return array
  */
 public function getVersionDiff($old, $new)
 {
     $destination = Project::getDeployFromDir();
     $cmd[] = sprintf('cd %s ', $destination);
     $cmd[] = sprintf('/usr/bin/env git reset -q --hard %s', $new);
     $cmd[] = sprintf('/usr/bin/env git diff %s %s --name-status', $old, $new);
     $command = implode(' && ', $cmd);
     $result = $this->runLocalCommand($command);
     $output = explode(PHP_EOL, $this->getExeLog());
     $diff = [];
     $excludes = GlobalHelper::str2arr($this->config->excludes);
     array_push($excludes, '*.git*');
     array_push($excludes, '.svn*');
     array_walk($excludes, function (&$item) {
         $item = '~^([A-Z])\\s+' . str_replace('\\*', '.*', preg_quote($item)) . '~Ui';
     });
     foreach ($output as $line) {
         if (!preg_filter($excludes, 'exclude', $line) && preg_match('~^([A-Z])\\s+(\\S+)$~', $line, $match)) {
             if ($file = realpath("{$destination}/{$match[2]}")) {
                 $diff[$file] = ['status' => $match[1], 'file' => $file];
             }
         }
     }
     return $diff;
 }