diff options
Diffstat (limited to 'quickbuild/src/Builder.php')
-rw-r--r-- | quickbuild/src/Builder.php | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/quickbuild/src/Builder.php b/quickbuild/src/Builder.php new file mode 100644 index 00000000..5568d725 --- /dev/null +++ b/quickbuild/src/Builder.php @@ -0,0 +1,237 @@ +<?php +declare(strict_types=1); +/** + * RoadRunner. + * + * @license MIT + * @author Anton Titov (Wolfy-J) + */ + +namespace Spiral\RoadRunner\QuickBuild; + +final class Builder +{ + const DOCKER = 'spiralscout/rr-build'; + + /** + * Coloring. + * + * @var array + */ + protected static $colors = [ + "reset" => "\e[0m", + "white" => "\033[1;38m", + "red" => "\033[0;31m", + "green" => "\033[0;32m", + "yellow" => "\033[1;93m", + "gray" => "\033[0;90m" + ]; + + /** @var array */ + private $config; + + /** + * @param array $config + */ + protected function __construct(array $config) + { + $this->config = $config; + } + + /** + * Validate the build configuration. + * + * @return array + */ + public function configErrors(): array + { + $errors = []; + if (!isset($this->config["commands"])) { + $errors[] = "Directive 'commands' missing"; + } + + if (!isset($this->config["packages"])) { + $errors[] = "Directive 'packages' missing"; + } + + if (!isset($this->config["register"])) { + $errors[] = "Directive 'register' missing"; + } + + return $errors; + } + + /** + * Build the application. + * + * @param string $directory + * @param string $template + * @param string $output + * @param string $version + */ + public function build(string $directory, string $template, string $output, string $version) + { + $filename = $directory . "/main.go"; + $output = $output . ($this->getOS() == 'windows' ? '.exe' : ''); + + // step 1, generate template + $this->generate($template, $filename); + + $command = sprintf( + 'docker run --rm -v "%s":/mnt -e RR_VERSION=%s -e GOARCH=amd64 -e GOOS=%s %s /bin/bash -c "mv /mnt/main.go main.go; bash compile.sh; cp rr /mnt/%s;"', + $directory, + $version, + $this->getOS(), + self::DOCKER, + $output + ); + + self::cprintf("<yellow>%s</reset>\n", $command); + + // run the build + $this->run($command, true); + + if (!file_exists($directory . '/' . $output)) { + self::cprintf("<red>Build has failed!</reset>"); + return; + } + + self::cprintf("<green>Build complete!</reset>\n"); + $this->run($directory . '/' . $output, false); + } + + /** + * @param string $command + * @param bool $shadow + */ + protected function run(string $command, bool $shadow = false) + { + $shadow && self::cprintf("<gray>"); + passthru($command); + $shadow && self::cprintf("</reset>"); + } + + /** + * @param string $template + * @param string $filename + */ + protected function generate(string $template, string $filename) + { + $body = file_get_contents($template); + + $replace = [ + '// -packages- //' => '"' . join("\"\n\"", $this->config['packages']) . '"', + '// -commands- //' => '_ "' . join("\"\n_ \"", $this->config['commands']) . '"', + '// -register- //' => join("\n", $this->config['register']) + ]; + + // compile the template + $result = str_replace(array_keys($replace), array_values($replace), $body); + file_put_contents($filename, $result); + } + + /** + * @return string + */ + protected function getOS(): string + { + $os = strtolower(PHP_OS); + + if (strpos($os, 'win') !== false) { + return 'windows'; + } + + if (strpos($os, 'darwin') !== false) { + return 'darwin'; + } + + return "linux"; + } + + /** + * Create new builder using given config. + * + * @param string $config + * @return Builder|null + */ + public static function loadConfig(string $config): ?Builder + { + if (!file_exists($config)) { + return null; + } + + $configData = json_decode(file_get_contents($config), true); + if (!is_array($configData)) { + return null; + } + + return new Builder($configData); + } + + /** + * Make colored output. + * + * @param string $format + * @param mixed ...$args + */ + public static function cprintf(string $format, ...$args) + { + if (self::isColorsSupported()) { + $format = preg_replace_callback("/<\/?([^>]+)>/", function ($value) { + return self::$colors[$value[1]]; + }, $format); + } else { + $format = preg_replace("/<[^>]+>/", "", $format); + } + + echo sprintf($format, ...$args); + } + + /** + * @return bool + */ + public static function isWindows(): bool + { + return \DIRECTORY_SEPARATOR === '\\'; + } + + /** + * Returns true if the STDOUT supports colorization. + * + * @codeCoverageIgnore + * @link https://github.com/symfony/Console/blob/master/Output/StreamOutput.php#L94 + * @param mixed $stream + * @return bool + */ + public static function isColorsSupported($stream = STDOUT): bool + { + if ('Hyper' === getenv('TERM_PROGRAM')) { + return true; + } + + try { + if (\DIRECTORY_SEPARATOR === '\\') { + return ( + function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($stream) + ) || getenv('ANSICON') !== false + || getenv('ConEmuANSI') == 'ON' + || getenv('TERM') == 'xterm'; + } + + if (\function_exists('stream_isatty')) { + return (bool)@stream_isatty($stream); + } + + if (\function_exists('posix_isatty')) { + return (bool)@posix_isatty($stream); + } + + $stat = @fstat($stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + } catch (\Throwable $e) { + return false; + } + } +}
\ No newline at end of file |