Author: Shivam Mathur (shivammathur)
Date: 2024-11-25T04:54:17+05:30
Commit: Refactor logic to move and configure files to commands · php/web-downloads@67eef44 · GitHub
Raw diff: https://github.com/php/web-downloads/commit/67eef4454300543be2fb009d2ae6d136ea8733b2.diff
Refactor logic to move and configure files to commands
Changed paths:
A autoloader.php
A runner.php
A src/Console/Command.php
A src/Console/Command/PeclCommand.php
A src/Console/Command/PhpCommand.php
A src/Console/Command/WinlibsCommand.php
M src/GetArtifacts.php
M src/PeclHandler.php
M src/PhpHandler.php
M src/WinlibsHandler.php
Diff:
diff --git a/autoloader.php b/autoloader.php
new file mode 100644
index 0000000..dcafefa
--- /dev/null
+++ b/autoloader.php
@@ -0,0 +1,18 @@
+<?php
+
+spl_autoload_register(function ($class) {
+ $prefix = 'App\\';
+ $base_dir = __DIR__ . '/src/';
+
+ $len = strlen($prefix);
+ if (strncmp($prefix, $class, $len) !== 0) {
+ return;
+ }
+
+ $relative_class = substr($class, $len);
+ $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
+
+ if (file_exists($file)) {
+ require $file;
+ }
+});
\ No newline at end of file
diff --git a/runner.php b/runner.php
new file mode 100644
index 0000000..ca3638d
--- /dev/null
+++ b/runner.php
@@ -0,0 +1,62 @@
+#!/usr/bin/env php
+<?php
+
+use App\Console\Command;
+
+require_once __DIR__ . '/autoloader.php';
+
+$consoleDirectory = __DIR__ . '/src/Console/Command';
+
+function getClassname($directory, $file): string
+{
+ $relativePath = str_replace($directory, '', $file->getPathname());
+ $relativePath = str_replace('/', '\\', $relativePath);
+ $relativePath = trim($relativePath, '\\');
+ $className = 'App\\Console\\Command\\' . $relativePath;
+ return str_replace('.php', '', $className);
+}
+
+function discoverCommands(string $directory, $argc, $argv): array
+{
+ $commands = ;
+ foreach (
+ new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS),
+ RecursiveIteratorIterator::LEAVES_ONLY
+ ) as $file) {
+ if ($file->isFile() && $file->getExtension() === 'php') {
+ $className = getClassName($directory, $file);
+ if (is_subclass_of($className, Command::class)) {
+ $instance = new $className($argc, $argv);
+ $commands[$instance->getSignature()] = $instance;
+ }
+ }
+ }
+ return $commands;
+}
+
+function listCommands(array $commands): void
+{
+ echo "Available commands:\n";
+ /** @var Command $command */
+ foreach ($commands as $signature => $command) {
+ echo $signature . " - " . $command->getDescription() . "\n";
+ }
+}
+
+$commands = discoverCommands($consoleDirectory, $argc, $argv);
+
+$commandInput = $argv[1] ?? 'help';
+
+if (in_array($commandInput, ['help', '--help', '-h', '?'], true)) {
+ listCommands($commands);
+ exit(Command::SUCCESS);
+}
+
+if (isset($commands[$commandInput])) {
+ $status = $commands[$commandInput]->handle($argc, $argv);
+ exit($status);
+} else {
+ echo "Command not found\n";
+ exit(Command::INVALID);
+}
diff --git a/src/Console/Command.php b/src/Console/Command.php
new file mode 100644
index 0000000..84e83d3
--- /dev/null
+++ b/src/Console/Command.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Console;
+
+abstract class Command
+{
+ public const SUCCESS = 0;
+ public const FAILURE = 1;
+ public const INVALID = 2;
+
+ protected string $signature = '';
+
+ protected string $description = '';
+
+ public function __construct(
+ protected ?int $argc = null,
+ protected ?array $argv = null,
+ protected array $arguments = ,
+ protected array $options = ,
+ ) {
+ if ($argc !== null && $argv !== null) {
+ $this->parse($argc, $argv);
+ }
+ }
+ abstract public function handle();
+
+
+ private function parse($argc, $argv): void {
+ $pattern = '/\{(\w+)}|\{--(\w+)}/';
+ $signatureParts = ;
+ if (preg_match_all($pattern, $this->signature, $matches, PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $signatureParts = $match[1] ?: $match[2];
+ }
+ }
+
+ $argCount = 0;
+ for ($i = 1; $i < $argc; $i++) {
+ if (preg_match('/^--([^=]+)=(.*)$/', $argv[$i], $matches)) {
+ $this->options[$matches[1]] = $matches[2];
+ } else {
+ if (isset($signatureParts[$argCount])) {
+ $this->arguments[$signatureParts[$argCount]] = $argv[$i];
+ } else {
+ $this->arguments[$argCount] = $argv[$i];
+ }
+ $argCount++;
+ }
+ }
+ }
+
+ public function getSignature(): string {
+ return explode(' ', $this->signature)[0];
+ }
+
+ public function getDescription(): string {
+ return $this->description;
+ }
+
+ public function getArgument($index) {
+ return $this->arguments[$index] ?? null;
+ }
+
+ public function getOption($name) {
+ return $this->options[$name] ?? null;
+ }
+}
\ No newline at end of file
diff --git a/src/Console/Command/PeclCommand.php b/src/Console/Command/PeclCommand.php
new file mode 100644
index 0000000..cd813e0
--- /dev/null
+++ b/src/Console/Command/PeclCommand.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace App\Console\Command;
+
+use App\Console\Command;
+use Exception;
+use ZipArchive;
+
+class PeclCommand extends Command
+{
+ protected string $signature = 'pecl:add --base-directory=';
+
+ protected string $description = 'Add pecl extensions';
+
+ public function handle(): int {
+ try {
+ $baseDirectory = $this->getOption('base-directory');
+ if(!$baseDirectory) {
+ throw new Exception('Base directory is required');
+ }
+
+ $files = glob(getenv('BUILDS_DIRECTORY') . '/php/*.zip');
+
+ // We lock the files we are working on
+ // so that we don't process them again if the command is run again
+ $filteredFiles = ;
+ foreach ($files as $filepath) {
+ $lockFile = $filepath . '.lock';
+ if(!file_exists($lockFile)) {
+ touch($lockFile);
+ $filteredFiles = $filepath;
+ }
+ }
+
+ foreach ($filteredFiles as $filepath) {
+
+ $destinationDirectory = $baseDirectory . "/pecl/releases";
+
+ if (!is_dir($destinationDirectory)) {
+ mkdir($destinationDirectory, 0755, true);
+ }
+
+ $zip = new ZipArchive();
+
+ if ($zip->open($filepath) === TRUE) {
+ if ($zip->extractTo($destinationDirectory) === FALSE) {
+ throw new Exception('Failed to extract the extension build');
+ }
+ $zip->close();
+ } else {
+ throw new Exception('Failed to extract the extension');
+ }
+
+ unlink($filepath);
+
+ unlink($filepath . '.lock');
+ }
+
+ return Command::SUCCESS;
+ } catch (Exception $e) {
+ echo $e->getMessage();
+ return Command::FAILURE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Console/Command/PhpCommand.php b/src/Console/Command/PhpCommand.php
new file mode 100644
index 0000000..def12e1
--- /dev/null
+++ b/src/Console/Command/PhpCommand.php
@@ -0,0 +1,284 @@
+<?php
+
+namespace App\Console\Command;
+
+use App\Console\Command;
+use DateTimeImmutable;
+use Exception;
+use ZipArchive;
+
+class PhpCommand extends Command
+{
+ protected string $signature = 'php:add --base-directory=';
+ protected string $description = 'Add php builds';
+
+ protected ?string $baseDirectory = null;
+
+ public function handle(): int {
+ try {
+ $this->baseDirectory = $this->getOption('base-directory');
+ if(!$this->baseDirectory) {
+ throw new Exception('Base directory is required');
+ }
+
+ $files = glob(getenv('BUILDS_DIRECTORY') . '/php/*.zip');
+
+ // We lock the files we are working on
+ // so that we don't process them again if the command is run again
+ $filteredFiles = ;
+ foreach ($files as $filepath) {
+ $lockFile = $filepath . '.lock';
+ if(!file_exists($lockFile)) {
+ touch($lockFile);
+ $filteredFiles = $filepath;
+ }
+ }
+
+ foreach ($filteredFiles as $filepath) {
+ $hash = hash('sha256', $filepath) . strtotime('now');
+ $tempDirectory = "/tmp/php-" . $hash;
+
+ if(is_dir($tempDirectory)) {
+ rmdir($tempDirectory);
+ }
+ mkdir($tempDirectory, 0755, true);
+
+ $zip = new ZipArchive();
+
+ if ($zip->open($filepath) === TRUE) {
+ if($zip->extractTo($tempDirectory) === FALSE) {
+ throw new Exception('Failed to extract the extension build');
+ }
+ $zip->close();
+ } else {
+ throw new Exception('Failed to extract the extension');
+ }
+
+ unlink($filepath);
+
+ $destinationDirectory = $this->getDestinationDirectory($tempDirectory);
+
+ $this->moveBuild($tempDirectory, $destinationDirectory);
+
+ $this->generateListing($destinationDirectory);
+
+ rmdir($tempDirectory);
+
+ unlink($filepath . '.lock');
+ }
+ return Command::SUCCESS;
+ } catch (Exception $e) {
+ echo $e->getMessage();
+ return Command::FAILURE;
+ }
+ }
+
+ private function getDestinationDirectory(string $tempDirectory): string
+ {
+ $testPackFile = basename(glob($tempDirectory . '/php-test-pack-*.zip')[0]);
+ $testPackFileName = str_replace('.zip', '', $testPackFile);
+ $version = explode('-', $testPackFileName)[3];
+ return $this->baseDirectory . (preg_match('/^\d+\.\d+\.\d+$/', $version) ? '/releases' : '/qa');
+ }
+
+ /**
+ * @throws Exception
+ */
+ private function moveBuild(string $tempDirectory, string $destinationDirectory): void
+ {
+ $files = glob($tempDirectory . '/*');
+ if($files) {
+ $version = $this->getFileVersion($files[0]);
+ foreach ($files as $file) {
+ $fileName = basename($file);
+ $destination = $destinationDirectory . '/' . $fileName;
+ rename($file, $destination);
+ }
+ rmdir($tempDirectory);
+ $this->copyBuildsToArchive($destinationDirectory, $version);
+ } else {
+ throw new Exception('No builds found in the artifact');
+ }
+ }
+
+ private function copyBuildsToArchive(string $directory, string $version): void
+ {
+ $version_short = substr($version, 0, 3);
+ $files = glob($directory . '/php*-' . $version_short . '-*.zip');
+ foreach ($files as $file) {
+ $fileVersion = $this->getFileVersion($file);
+ if($fileVersion) {
+ copy($directory . '/' . basename($file), $directory . '/archive/' . $file);
+ if(version_compare($fileVersion, $version) < 0) {
+ unlink($file);
+ }
+ }
+ }
+ }
+
+ private function getFileVersion(string $file): string
+ {
+ $file = preg_replace('/^php-((debug|devel|test)-pack)?/', '', $file);
+ return explode('-', $file)[0];
+ }
+
+ /**
+ * @throws Exception
+ */
+ private function generateListing(string $directory): void
+ {
+ $builds = glob($directory . '/php-[678].*[0-9]-latest.zip');
+ if (empty($builds)) {
+ $builds = glob($directory . '/php-[678].*[0-9].zip');
+ }
+
+ $releases = ;
+ $sha256sums = $this->getSha256Sums($directory);
+ foreach ($builds as $file) {
+ $file_ori = $file;
+ $mtime = date('Y-M-d H:i:s', filemtime($file));
+
+ $parts = $this->parseFileName(basename($file));
+ $key = ($parts['nts'] ? 'nts-' : 'ts-') . $parts['vc'] . '-' . $parts['arch'];
+ $version_short = $parts['version_short'];
+ if (!isset($releases['version'])) {
+ $releases[$version_short]['version'] = $parts['version'];
+ }
+ $releases[$version_short][$key]['mtime'] = $mtime;
+ $releases[$version_short][$key]['zip'] = [
+ 'path' => $file_ori,
+ 'size' => $this->bytes2string(filesize($file_ori)),
+ 'sha256' => $sha256sums[strtolower($file_ori)]
+ ];
+ $namingPattern = $parts['version'] . ($parts['nts'] ? '-' . $parts['nts'] : '') . '-Win32-' . $parts['vc'] . '-' . $parts['arch'] . ($parts['ts'] ? '-' . $parts['ts'] : '');
+ $build_types = [
+ 'source' => 'php-' . $parts['version'] . '-src.zip',
+ 'debug_pack' => 'php-debug-pack-' . $namingPattern . '.zip',
+ 'devel_pack' => 'php-devel-pack-' . $namingPattern . '.zip',
+ 'installer' => 'php-' . $namingPattern . '.msi',
+ 'test_pack' => 'php-test-pack-' . $parts['version'] . '.zip',
+ ];
+ foreach($build_types as $type => $fileName) {
+ $filePath = $directory . '/' . $fileName;
+ if (file_exists($filePath)) {
+ $releases[$version_short][$type] = [
+ 'path' => $fileName,
+ 'size' => $this->bytes2string(filesize($filePath))
+ ];
+ }
+ }
+ }
+
+ $this->updateReleasesJson($releases, $directory);
+ if($directory === $this->baseDirectory . '/releases') {
+ $this->updateLatestBuilds($releases, $directory);
+ }
+ }
+
+ /**
+ * @throws Exception
+ */
+ private function updateReleasesJson(array $releases, string $directory): void
+ {
+ foreach ($releases as &$release) {
+ foreach ($release as &$build_type) {
+ if (! is_array($build_type) || ! isset($build_type['mtime'])) {
+ continue;
+ }
+
+ try {
+ $date = new DateTimeImmutable($build_type['mtime']);
+ $build_type['mtime'] = $date->format('c');
+ } catch (Exception $exception) {
+ throw new Exception('Failed to generate releases.json: ' . $exception->getMessage());
+ }
+ }
+ unset($build_type);
+ }
+ unset($release);
+
+ file_put_contents(
+ $directory . '/releases.json',
+ json_encode($releases, JSON_PRETTY_PRINT)
+ );
+ }
+
+ private function updateLatestBuilds($releases, $directory): void
+ {
+ foreach ($releases as $versionShort => $release) {
+ $latestFileName = str_replace($release['version'], $versionShort, $release['path']);
+ $latestFileName = str_replace('.zip', '-latest.zip', $latestFileName);
+ copy($directory . '/' . $release['path'], $directory . '/latest/' . $latestFileName);
+ }
+ }
+
+ private function getSha256Sums($directory): array
+ {
+ $result = ;
+ $sha_file = fopen("$directory/sha256sum.txt", 'w');
+ foreach (scandir($directory) as $filename) {
+ if (pathinfo($filename, PATHINFO_EXTENSION) !== 'zip') {
+ continue;
+ }
+ $sha256 = hash_file('sha256', "$directory/$filename");
+ fwrite($sha_file, "$sha256 *$filename\n");
+ $result[strtolower(basename($filename))] = $sha256;
+ }
+ fclose($sha_file);
+ return $result;
+ }
+
+ private function bytes2string(int $size): float
+ {
+ $sizes = ['YB', 'ZB', 'EB', 'PB', 'TB', 'GB', 'MB', 'kB', 'B'];
+
+ $total = count($sizes);
+
+ while($total-- && $size > 1024) $size /= 1024;
+
+ return round($size, 2) . $sizes[$total];
+ }
+
+ private function parseFileName($fileName): array
+ {
+ $fileName = str_replace(['-Win32', '.zip'], ['', ''], $fileName);
+
+ $parts = explode('-', $fileName);
+ if (is_numeric($parts[2]) || $parts[2] == 'dev') {
+ $version = $parts[1] . '-' . $parts[2];
+ $nts = $parts[3] == 'nts' ? 'nts' : false;
+ if ($nts) {
+ $vc = $parts[4];
+ $arch = $parts[5];
+ } else {
+ $vc = $parts[3];
+ $arch = $parts[4];
+ }
+ } elseif ($parts[2] == 'nts') {
+ $nts = 'nts';
+ $version = $parts[1];
+ $vc = $parts[3];
+ $arch = $parts[4];
+ } else {
+ $nts = false;
+ $version = $parts[1];
+ $vc = $parts[2];
+ $arch = $parts[3];
+ }
+ if (is_numeric($vc)) {
+ $vc = 'VC6';
+ $arch = 'x86';
+ }
+ $t = count($parts) - 1;
+ $ts = is_numeric($parts[$t]) ? $parts[$t] : false;
+
+ return [
+ 'version' => $version,
+ 'version_short' => substr($version, 0, 3),
+ 'nts' => $nts,
+ 'vc' => $vc,
+ 'arch' => $arch,
+ 'ts' => $ts
+ ];
+ }
+}
\ No newline at end of file
diff --git a/src/Console/Command/WinlibsCommand.php b/src/Console/Command/WinlibsCommand.php
new file mode 100644
index 0000000..b0bbcb9
--- /dev/null
+++ b/src/Console/Command/WinlibsCommand.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace App\Console\Command;
+
+use App\Console\Command;
+use Exception;
+
+class WinlibsCommand extends Command
+{
+ protected string $signature = 'winlibs:add --base-directory=';
+ protected string $description = 'Add winlibs dependencies';
+
+ protected ?string $baseDirectory = null;
+
+ public function handle(): int {
+ try {
+ $this->baseDirectory = $this->getOption('base-directory');
+ if(!$this->baseDirectory) {
+ throw new Exception('Base directory is required');
+ }
+
+ $buildDirectories = glob($this->baseDirectory . '/winlibs/*', GLOB_ONLYDIR);
+
+ // We lock the Directories we are working on
+ // so that we don't process them again if the command is run again
+ $filteredDirectories = ;
+ foreach ($buildDirectories as $directoryPath) {
+ $lockFile = $directoryPath . '.lock';
+ if(!file_exists($lockFile)) {
+ touch($lockFile);
+ $filteredDirectories = $directoryPath;
+ }
+ }
+
+ foreach($filteredDirectories as $directoryPath) {
+ $data = json_decode(file_get_contents($directoryPath . '/data.json'), true);
+ extract($data);
+ $files = glob($directoryPath . '/*.zip');
+ $files = $this->parseFiles($files);
+ if($files) {
+ $this->copyFiles($files, $library, $ref, $vs_version_targets);
+ $this->updateSeriesFiles($files, $library, $ref, $php_versions, $vs_version_targets, $stability);
+ }
+
+ rmdir($directoryPath);
+
+ unlink($directoryPath . '.lock');
+ }
+ return Command::SUCCESS;
+ } catch (Exception $e) {
+ echo $e->getMessage();
+ return Command::FAILURE;
+ }
+ }
+
+ private function parseFiles(array $files): array
+ {
+ $data = ;
+ foreach ($files as $file) {
+ $fileName = basename($file);
+ $fileNameParts = explode('.', $fileName);
+ $parsedFileNameParts = explode('-', $fileNameParts[0]);
+ $data = [
+ 'file_path' => $file,
+ 'file_name' => $fileName,
+ 'extension' => $fileNameParts[1],
+ 'artifact_name' => $parsedFileNameParts[0],
+ 'vs_version' => $parsedFileNameParts[1],
+ 'arch' => $parsedFileNameParts[2],
+ ];
+ }
+ return $data;
+ }
+
+ private function copyFiles(array $files, $library, $ref, $vs_version_targets): void
+ {
+ $baseDirectory = $this->baseDirectory . "/php-sdk/deps";
+ if(!is_dir($baseDirectory)) {
+ mkdir($baseDirectory, 0755, true);
+ }
+ $vs_version_targets = explode(',', $vs_version_targets);
+ foreach($files as $file) {
+ foreach ($vs_version_targets as $vs_version_target) {
+ $destinationDirectory = $baseDirectory . '/' . $vs_version_target . '/' . $file['arch'];
+ $destinationFileName = str_replace($file['artifact_name'], $library . '-' . $ref, $file['file_name']);
+ copy($file['file_path'], $destinationDirectory . '/' . $destinationFileName);
+ }
+ }
+ }
+
+ private function updateSeriesFiles($files, $library, $ref, $php_versions, $vs_version_targets, $stability): void
+ {
+ $php_versions = explode(',', $php_versions);
+ $vs_version_targets = explode(',', $vs_version_targets);
+ $stability_values = explode(',', $stability);
+
+ $baseDirectory = $this->baseDirectory . "/php-sdk/deps/series";
+
+ foreach ($php_versions as $php_version) {
+ foreach ($vs_version_targets as $vs_version_target) {
+ foreach ($stability_values as $stability_value) {
+ foreach ($files as $file) {
+ $fileName = str_replace($file['artifact_name'], $library . '-' . $ref, $file['file_name']);
+ $arch = $file['arch'];
+ $seriesFile = $baseDirectory . "/packages-$php_version-$vs_version_target-$arch-$stability_value.txt";
+ $file_lines = file($seriesFile, FILE_IGNORE_NEW_LINES);
+ foreach($file_lines as $no => $line) {
+ if(str_starts_with($line, $library)) {
+ $file_lines[$no] = $fileName;
+ }
+ }
+ file_put_contents($seriesFile, implode("\n", $file_lines));
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/GetArtifacts.php b/src/GetArtifacts.php
index 2a18046..7a38e2d 100644
--- a/src/GetArtifacts.php
+++ b/src/GetArtifacts.php
@@ -4,7 +4,7 @@
class GetArtifacts
{
- public static function handle($workflow_run_id, $token): null|array
+ public static function handle($workflow_run_id, $token): void
{
$ch = curl_init();
@@ -29,16 +29,17 @@ public static function handle($workflow_run_id, $token): null|array
if ($err) {
echo "cURL Error #:" . $err;
- return null;
} else {
- $files = ;
$artifacts = json_decode($response, true);
+ $workflowRunDirectory = getenv('BUILDS_DIRECTORY') . "/winlibs/" . $workflow_run_id;
+ if (is_dir($workflowRunDirectory)) {
+ rmdir($workflowRunDirectory);
+ }
+ mkdir($workflowRunDirectory, 0755, true);
foreach ($artifacts['artifacts'] as $artifact) {
- $filepath = "/tmp/" . $artifact['name'] . ".zip";
- $files = $filepath;
+ $filepath = $workflowRunDirectory . "/" . $artifact['name'] . ".zip";
FetchArtifact::handle($artifact['archive_download_url'], $filepath, $token);
}
- return $files;
}
}
diff --git a/src/PeclHandler.php b/src/PeclHandler.php
index 4329f45..abba598 100644
--- a/src/PeclHandler.php
+++ b/src/PeclHandler.php
@@ -43,31 +43,12 @@ protected function execute(array $data): void
*/
private function fetchExtension(string $extension, string $ref, string $url, string $token): void
{
- $filepath = "/tmp/$extension-$ref-" . hash('sha256', $url) . strtotime('now') . ".zip";
+ $filepath = getenv('BUILDS_DIRECTORY') . "/pecl/$extension-$ref-" . hash('sha256', $url) . strtotime('now') . ".zip";
FetchArtifact::handle($url, $filepath, $token);
if(!file_exists($filepath) || mime_content_type($filepath) !== 'application/zip') {
throw new Exception('Failed to fetch the extension');
}
-
- $destinationDirectory = getenv('BUILDS_DIRECTORY') . "/pecl/releases";
-
- if(!is_dir($destinationDirectory)) {
- mkdir($destinationDirectory, 0755, true);
- }
-
- $zip = new ZipArchive();
-
- if ($zip->open($filepath) === TRUE) {
- if($zip->extractTo($destinationDirectory) === FALSE) {
- throw new Exception('Failed to extract the extension build');
- }
- $zip->close();
- } else {
- throw new Exception('Failed to extract the extension');
- }
-
- unlink($filepath);
}
}
\ No newline at end of file
diff --git a/src/PhpHandler.php b/src/PhpHandler.php
index 7c9a1d0..e3425e5 100644
--- a/src/PhpHandler.php
+++ b/src/PhpHandler.php
@@ -45,247 +45,12 @@ private function fetchPhpBuild(string $url, string $token): void
{
$hash = hash('sha256', $url) . strtotime('now');
- $filepath = "/tmp/php-" . $hash . ".tar.gz";
+ $filepath = getenv('BUILDS_DIRECTORY') . "/php/php-" . $hash . ".tar.gz";
FetchArtifact::handle($url, $filepath, $token);
if(!file_exists($filepath) || mime_content_type($filepath) !== 'application/zip') {
throw new Exception('Failed to fetch the PHP build');
}
-
- $tempDirectory = "/tmp/php-" . $hash;
-
- if(is_dir($tempDirectory)) {
- rmdir($tempDirectory);
- }
- mkdir($tempDirectory, 0755, true);
-
- $zip = new ZipArchive();
-
- if ($zip->open($filepath) === TRUE) {
- if($zip->extractTo($tempDirectory) === FALSE) {
- throw new Exception('Failed to extract the extension build');
- }
- $zip->close();
- } else {
- throw new Exception('Failed to extract the extension');
- }
-
- unlink($filepath);
-
- $destinationDirectory = $this->getDestinationDirectory($tempDirectory);
-
- $this->moveBuild($tempDirectory, $destinationDirectory);
-
- $this->generateListing($destinationDirectory);
- }
-
- private function getDestinationDirectory(string $tempDirectory): string
- {
- $testPackFile = basename(glob($tempDirectory . '/php-test-pack-*.zip')[0]);
- $testPackFileName = str_replace('.zip', '', $testPackFile);
- $version = explode('-', $testPackFileName)[3];
- return getenv('BUILDS_DIRECTORY') . (preg_match('/^\d+\.\d+\.\d+$/', $version) ? '/releases' : '/qa');
- }
-
- /**
- * @throws Exception
- */
- private function moveBuild(string $tempDirectory, string $destinationDirectory): void
- {
- $files = glob($tempDirectory . '/*');
- if($files) {
- $version = $this->getFileVersion($files[0]);
- foreach ($files as $file) {
- $fileName = basename($file);
- $destination = $destinationDirectory . '/' . $fileName;
- rename($file, $destination);
- }
- rmdir($tempDirectory);
- $this->copyBuildsToArchive($destinationDirectory, $version);
- } else {
- throw new Exception('No builds found in the artifact');
- }
- }
-
- private function copyBuildsToArchive(string $directory, string $version): void
- {
- $version_short = substr($version, 0, 3);
- $files = glob($directory . '/php*-' . $version_short . '-*.zip');
- foreach ($files as $file) {
- $fileVersion = $this->getFileVersion($file);
- if($fileVersion) {
- copy($directory . '/' . basename($file), $directory . '/archive/' . $file);
- if(version_compare($fileVersion, $version) < 0) {
- unlink($file);
- }
- }
- }
- }
-
- private function getFileVersion(string $file): string
- {
- $file = preg_replace('/^php-((debug|devel|test)-pack)?/', '', $file);
- return explode('-', $file)[0];
- }
-
- /**
- * @throws Exception
- */
- private function generateListing(string $directory): void
- {
- $builds = glob($directory . '/php-[678].*[0-9]-latest.zip');
- if (empty($builds)) {
- $builds = glob($directory . '/php-[678].*[0-9].zip');
- }
-
- $releases = ;
- $sha256sums = $this->getSha256Sums($directory);
- foreach ($builds as $file) {
- $file_ori = $file;
- $mtime = date('Y-M-d H:i:s', filemtime($file));
-
- $parts = $this->parseFileName(basename($file));
- $key = ($parts['nts'] ? 'nts-' : 'ts-') . $parts['vc'] . '-' . $parts['arch'];
- $version_short = $parts['version_short'];
- if (!isset($releases['version'])) {
- $releases[$version_short]['version'] = $parts['version'];
- }
- $releases[$version_short][$key]['mtime'] = $mtime;
- $releases[$version_short][$key]['zip'] = [
- 'path' => $file_ori,
- 'size' => $this->bytes2string(filesize($file_ori)),
- 'sha256' => $sha256sums[strtolower($file_ori)]
- ];
- $namingPattern = $parts['version'] . ($parts['nts'] ? '-' . $parts['nts'] : '') . '-Win32-' . $parts['vc'] . '-' . $parts['arch'] . ($parts['ts'] ? '-' . $parts['ts'] : '');
- $build_types = [
- 'source' => 'php-' . $parts['version'] . '-src.zip',
- 'debug_pack' => 'php-debug-pack-' . $namingPattern . '.zip',
- 'devel_pack' => 'php-devel-pack-' . $namingPattern . '.zip',
- 'installer' => 'php-' . $namingPattern . '.msi',
- 'test_pack' => 'php-test-pack-' . $parts['version'] . '.zip',
- ];
- foreach($build_types as $type => $fileName) {
- $filePath = $directory . '/' . $fileName;
- if (file_exists($filePath)) {
- $releases[$version_short][$type] = [
- 'path' => $fileName,
- 'size' => $this->bytes2string(filesize($filePath))
- ];
- }
- }
- }
-
- $this->updateReleasesJson($releases, $directory);
- if($directory === getenv('BUILDS_DIRECTORY') . '/releases') {
- $this->updateLatestBuilds($releases, $directory);
- }
- }
-
- /**
- * @throws Exception
- */
- private function updateReleasesJson(array $releases, string $directory): void
- {
- foreach ($releases as &$release) {
- foreach ($release as &$build_type) {
- if (! is_array($build_type) || ! isset($build_type['mtime'])) {
- continue;
- }
-
- try {
- $date = new DateTimeImmutable($build_type['mtime']);
- $build_type['mtime'] = $date->format('c');
- } catch (Exception $exception) {
- throw new Exception('Failed to generate releases.json: ' . $exception->getMessage());
- }
- }
- unset($build_type);
- }
- unset($release);
-
- file_put_contents(
- $directory . '/releases.json',
- json_encode($releases, JSON_PRETTY_PRINT)
- );
- }
-
- private function updateLatestBuilds($releases, $directory): void
- {
- foreach ($releases as $versionShort => $release) {
- $latestFileName = str_replace($release['version'], $versionShort, $release['path']);
- $latestFileName = str_replace('.zip', '-latest.zip', $latestFileName);
- copy($directory . '/' . $release['path'], $directory . '/latest/' . $latestFileName);
- }
- }
-
- private function getSha256Sums($directory): array
- {
- $result = ;
- $sha_file = fopen("$directory/sha256sum.txt", 'w');
- foreach (scandir($directory) as $filename) {
- if (pathinfo($filename, PATHINFO_EXTENSION) !== 'zip') {
- continue;
- }
- $sha256 = hash_file('sha256', "$directory/$filename");
- fwrite($sha_file, "$sha256 *$filename\n");
- $result[strtolower(basename($filename))] = $sha256;
- }
- fclose($sha_file);
- return $result;
- }
-
- private function bytes2string(int $size): float
- {
- $sizes = ['YB', 'ZB', 'EB', 'PB', 'TB', 'GB', 'MB', 'kB', 'B'];
-
- $total = count($sizes);
-
- while($total-- && $size > 1024) $size /= 1024;
-
- return round($size, 2) . $sizes[$total];
- }
-
- private function parseFileName($fileName): array
- {
- $fileName = str_replace(['-Win32', '.zip'], ['', ''], $fileName);
-
- $parts = explode('-', $fileName);
- if (is_numeric($parts[2]) || $parts[2] == 'dev') {
- $version = $parts[1] . '-' . $parts[2];
- $nts = $parts[3] == 'nts' ? 'nts' : false;
- if ($nts) {
- $vc = $parts[4];
- $arch = $parts[5];
- } else {
- $vc = $parts[3];
- $arch = $parts[4];
- }
- } elseif ($parts[2] == 'nts') {
- $nts = 'nts';
- $version = $parts[1];
- $vc = $parts[3];
- $arch = $parts[4];
- } else {
- $nts = false;
- $version = $parts[1];
- $vc = $parts[2];
- $arch = $parts[3];
- }
- if (is_numeric($vc)) {
- $vc = 'VC6';
- $arch = 'x86';
- }
- $t = count($parts) - 1;
- $ts = is_numeric($parts[$t]) ? $parts[$t] : false;
-
- return [
- 'version' => $version,
- 'version_short' => substr($version, 0, 3),
- 'nts' => $nts,
- 'vc' => $vc,
- 'arch' => $arch,
- 'ts' => $ts
- ];
}
}
\ No newline at end of file
diff --git a/src/WinlibsHandler.php b/src/WinlibsHandler.php
index 4625c10..f123d82 100644
--- a/src/WinlibsHandler.php
+++ b/src/WinlibsHandler.php
@@ -32,74 +32,8 @@ protected function validate(array $data): bool
protected function execute(array $data): void
{
extract($data);
- $files = GetArtifacts::handle($workflow_run_id, $token);
- $files = $this->parseFiles($files);
- if($files) {
- $this->copyFiles($files, $library, $ref, $vs_version_targets);
- $this->updateSeriesFiles($files, $library, $ref, $php_versions, $vs_version_targets, $stability);
- }
- }
-
- private function parseFiles(array $files): array
- {
- $data = ;
- foreach ($files as $file) {
- $fileName = basename($file);
- $fileNameParts = explode('.', $fileName);
- $parsedFileNameParts = explode('-', $fileNameParts[0]);
- $data = [
- 'file_path' => $file,
- 'file_name' => $fileName,
- 'extension' => $fileNameParts[1],
- 'artifact_name' => $parsedFileNameParts[0],
- 'vs_version' => $parsedFileNameParts[1],
- 'arch' => $parsedFileNameParts[2],
- ];
- }
- return $data;
- }
-
- private function copyFiles(array $files, $library, $ref, $vs_version_targets): void
- {
- $baseDirectory = getenv('BUILDS_DIRECTORY') . "/php-sdk/deps";
- if(!is_dir($baseDirectory)) {
- mkdir($baseDirectory, 0755, true);
- }
- $vs_version_targets = explode(',', $vs_version_targets);
- foreach($files as $file) {
- foreach ($vs_version_targets as $vs_version_target) {
- $destinationDirectory = $baseDirectory . '/' . $vs_version_target . '/' . $file['arch'];
- $destinationFileName = str_replace($file['artifact_name'], $library . '-' . $ref, $file['file_name']);
- copy($file['file_path'], $destinationDirectory . '/' . $destinationFileName);
- }
- }
- }
-
- private function updateSeriesFiles($files, $library, $ref, $php_versions, $vs_version_targets, $stability): void
- {
- $php_versions = explode(',', $php_versions);
- $vs_version_targets = explode(',', $vs_version_targets);
- $stability_values = explode(',', $stability);
-
- $baseDirectory = getenv('BUILDS_DIRECTORY') . "/php-sdk/deps/series";
-
- foreach ($php_versions as $php_version) {
- foreach ($vs_version_targets as $vs_version_target) {
- foreach ($stability_values as $stability_value) {
- foreach ($files as $file) {
- $fileName = str_replace($file['artifact_name'], $library . '-' . $ref, $file['file_name']);
- $arch = $file['arch'];
- $seriesFile = $baseDirectory . "/packages-$php_version-$vs_version_target-$arch-$stability_value.txt";
- $file_lines = file($seriesFile, FILE_IGNORE_NEW_LINES);
- foreach($file_lines as $no => $line) {
- if(strpos($line, $library) === 0) {
- $file_lines[$no] = $fileName;
- }
- }
- file_put_contents($seriesFile, implode("\n", $file_lines));
- }
- }
- }
- }
+ GetArtifacts::handle($workflow_run_id, $token);
+ $directory = getenv('BUILDS_DIRECTORY') . '/winlibs/'. $workflow_run_id;
+ file_put_contents( $directory . '/data.json', json_encode($data));
}
}
\ No newline at end of file