public function execute(AMQPMessage $message) { $logger = $this->logger; $redis = $this->redis; $body = json_decode($message->body, true); if (!array_key_exists('BUILD_ID', $body['env'])) { $logger->warn('no build information', ['container' => $body['container'], 'message' => $body]); return true; } $buildId = $body['env']['BUILD_ID']; $logger->debug('processing log fragment', ['build' => $buildId, 'container' => isset($body['container']) ? $body['container'] : null, 'keys' => array_keys($body)]); $build = new Build(); $build->setId($buildId); $redis->rpush($build->getLogsList(), json_encode(['type' => Build::LOG_OUTPUT, 'message' => $body['content'], 'stream' => $this->getStreamType($body['type']), 'microtime' => $body['timestamp'], 'fragment_id' => $body['fragment_id'], 'build_id' => $buildId])); }
public function build(Build $build, BuildScript $script, $timeout) { $logger = $this->logger; $docker = $this->docker; $websocketProducer = $this->websocketProducer; $redis = $this->redis; $publish = function ($content) use($build, $websocketProducer, $redis) { static $fragment = 0; $message = new BuildMessage($build, $content); $websocketProducer->publish((string) $message); $redis->rpush($build->getLogsList(), json_encode(['type' => Build::LOG_OUTPUT, 'message' => $content, 'stream' => 'stdout', 'microtime' => microtime(true), 'fragment_id' => $fragment++, 'build_id' => $build->getId()])); }; $project = $build->getProject(); $options = $build->getOptions(); $workdir = sys_get_temp_dir() . '/stage1/workdir/' . $build->getId(); if (is_dir($workdir)) { $fs = new Filesystem(); $fs->remove($workdir); } mkdir($workdir, 0777, true); $logger->info('using workdir', ['workdir' => $workdir]); mkdir($workdir . '/ssh', 0755, true); $project->dumpSshKeys($workdir . '/ssh', 'root'); file_put_contents($workdir . '/ssh/config', $project->getSshConfig($workdir . '/ssh')); file_put_contents($workdir . '/git_ssh', "#!/bin/bash\nexec /usr/bin/ssh -F {$workdir}/ssh/config \"\$@\""); chmod($workdir . '/git_ssh', 0777); $GIT_SSH = $workdir . '/git_ssh'; if ($build->isPullRequest()) { $clone = ProcessBuilder::create(['git', 'clone', '--quiet', '--depth', '1', $project->getGitUrl(), $workdir . '/source'])->setEnv('GIT_SSH', $GIT_SSH)->getProcess(); $commandLine = $clone->getCommandLine(); $logger->info('cloning repository', ['command_line' => $commandLine]); $publish('$ ' . substr($commandLine, 0, strrpos($commandLine, ' ')) . PHP_EOL); $clone->run(); $fetch = ProcessBuilder::create(['git', 'fetch', '--quiet', 'origin', 'refs/' . $build->getRef()])->setEnv('GIT_SSH', $GIT_SSH)->setWorkingDirectory($workdir . '/source')->getProcess(); $logger->info('fecthing pull request', ['command_line' => $fetch->getCommandLine()]); $publish('$ ' . $fetch->getCommandLine() . PHP_EOL); $fetch->run(); $checkout = ProcessBuilder::create(['git', 'checkout', '--quiet', '-b', 'pull_request', 'FETCH_HEAD'])->setEnv('GIT_SSH', $GIT_SSH)->setWorkingDirectory($workdir . '/source')->getProcess(); $logger->info('checkouting pull request', ['command_line' => $checkout->getCommandLine()]); $publish('$ ' . $checkout->getCommandLine() . PHP_EOL); $checkout->run(); } else { $clone = ProcessBuilder::create(['git', 'clone', '--quiet', '--depth', '1', '--branch', $build->getRef(), $project->getGitUrl(), $workdir . '/source'])->setEnv('GIT_SSH', $GIT_SSH)->getProcess(); $commandLine = $clone->getCommandLine(); $logger->info('cloning repository', ['command_line' => $commandLine]); $publish('$ ' . substr($commandLine, 0, strrpos($commandLine, ' ')) . PHP_EOL); $clone->run(); } $contextPath = $workdir . '/source/' . $options['dockerfile']['path']; $logger->info('creating docker build context from path', ['context_path' => $contextPath]); $context = new Context($contextPath); $logger->info('starting actual build', ['build' => $build->getId(), 'timeout' => $timeout]); $response = $docker->build($context, $build->getImageName(), false, false, true, false); $error = false; $response->read(function ($output) use($logger, $response, $publish, &$error) { if ($response->headers->get('content-type') === 'application/json') { $output = json_decode($output, true); $logger->info('got data chunk', ['output' => $output]); if (isset($output['stream'])) { $publish($output['stream']); } } else { $message = $output; } }); }