[PHP-WEBMASTER] [web-downloads] main: Add support to upload PECL deps

[email protected] (Shivam Mathur)
Newsgroups php.webmaster
Message-ID <[email protected]>
Author: Shivam Mathur (shivammathur)
Date: 2025-11-19T00:04:04+05:30

Commit: https://github.com/php/web-downloads/commit/7b294549bbf926ba6c8620ea93e1959634f574de
Raw diff: https://github.com/php/web-downloads/commit/7b294549bbf926ba6c8620ea93e1959634f574de.diff

Add support to upload PECL deps

Changed paths:
  M  .github/workflows/winlibs.yml
  M  API.md
  M  src/Console/Command/WinlibsCommand.php
  M  src/Http/Controllers/WinlibsController.php
  M  tests/Console/Command/WinlibsCommandTest.php


Diff:

diff --git a/.github/workflows/winlibs.yml b/.github/workflows/winlibs.yml
index f6c981a..8ead945 100644
--- a/.github/workflows/winlibs.yml
+++ b/.github/workflows/winlibs.yml
@@ -9,6 +9,10 @@ on:
       ref:
         description: 'Library Ref'
         required: true
+      type:
+        description: 'Library Type (php or pecl)'
+        required: true
+        default: 'php'
       workflow_run_id:
         description: 'Workflow Run ID'
         required: true
@@ -32,4 +36,4 @@ jobs:
           --request POST \
           --location https://downloads.php.net/api/winlibs \
           --header 'Authorization: Bearer ${{ secrets.AUTH_TOKEN }}' \
-          --data '{ "library": "${{ inputs.library }}", "ref": "${{ inputs.ref }}", "workflow_run_id": "${{ inputs.workflow_run_id }}", "php_versions": "${{ inputs.php_versions }}", "vs_version": "${{ inputs.vs_version }}", "vs_version_targets": "${{ inputs.vs_version_targets }}", "stability": "${{ inputs.stability }}", "token": "${{ secrets.TOKEN }}" }'
+          --data '{ "library": "${{ inputs.library }}", "ref": "${{ inputs.ref }}", "type": "${{ inputs.type }}", "workflow_run_id": "${{ inputs.workflow_run_id }}", "php_versions": "${{ inputs.php_versions }}", "vs_version": "${{ inputs.vs_version }}", "vs_version_targets": "${{ inputs.vs_version_targets }}", "stability": "${{ inputs.stability }}", "token": "${{ secrets.TOKEN }}" }'
diff --git a/API.md b/API.md
index b5dacb2..9240bff 100644
--- a/API.md
+++ b/API.md
@@ -138,6 +138,7 @@ curl -i -X POST \
 - Request body (JSON):
     - `library` (string, required)
     - `ref` (string, required)
+    - `type` (string, required): `php`, or `pecl`.
     - `workflow_run_id` (string, required)
     - `php_versions` (string, required): Comma-separated list matching `^(?:\d+\.\d+|master)(?:,\s*(?:\d+\.\d+|master))*$`.
     - `vs_version_targets` (string, required): Comma-separated list matching `^(v[c|s]\d{2})(,v[c|s]\d{2})*$`.
diff --git a/src/Console/Command/WinlibsCommand.php b/src/Console/Command/WinlibsCommand.php
index 4ddac95..1edc3a7 100644
--- a/src/Console/Command/WinlibsCommand.php
+++ b/src/Console/Command/WinlibsCommand.php
@@ -45,14 +45,18 @@ public function handle(): int
                 $files = glob($directoryPath . '/*.zip');
                 $files = $this->parseFiles($files);
                 if ($files) {
-                    $this->copyFiles($files, $data['library'], $data['vs_version_targets']);
-                    $this->updateSeriesFiles(
-                        $files,
-                        $data['library'],
-                        $data['php_versions'],
-                        $data['vs_version_targets'],
-                        $data['stability']
-                    );
+                    if($data['type'] === 'php') {
+                        $this->copyPhpFiles($files, $data['library'], $data['vs_version_targets']);
+                        $this->updateSeriesFiles(
+                            $files,
+                            $data['library'],
+                            $data['php_versions'],
+                            $data['vs_version_targets'],
+                            $data['stability']
+                        );
+                    } else {
+                        $this->copyPeclFiles($files, $data['library']);
+                    }
                 }
 
                 (new Helpers)->rmdirr($directoryPath);
@@ -85,7 +89,7 @@ public function parseFiles(array $files): array
         return $data;
     }
 
-    private function copyFiles(array $files, string $library, string $vs_version_targets): void
+    private function copyPhpFiles(array $files, string $library, string $vs_version_targets): void
     {
         $baseDirectory = $this->baseDirectory . "/php-sdk/deps";
         if (!is_dir($baseDirectory)) {
@@ -104,6 +108,22 @@ private function copyFiles(array $files, string $library, string $vs_version_tar
         }
     }
 
+    private function copyPeclFiles(array $files, string $library): void
+    {
+        $baseDirectory = $this->baseDirectory . "/pecl/deps";
+        if (!is_dir($baseDirectory)) {
+            mkdir($baseDirectory, 0755, true);
+        }
+        foreach ($files as $file) {
+            $destinationDirectory = $baseDirectory;
+            if (!is_dir($destinationDirectory)) {
+                mkdir($destinationDirectory, 0755, true);
+            }
+            $destinationFileName = str_replace($file['artifact_name'], $library, $file['file_name']);
+            copy($file['file_path'], $destinationDirectory . '/' . $destinationFileName);
+        }
+    }
+
     private function updateSeriesFiles(
         array  $files,
         string $library,
diff --git a/src/Http/Controllers/WinlibsController.php b/src/Http/Controllers/WinlibsController.php
index a997f5a..2679c20 100644
--- a/src/Http/Controllers/WinlibsController.php
+++ b/src/Http/Controllers/WinlibsController.php
@@ -14,6 +14,7 @@ protected function validate(array $data): bool
         $validator = new Validator([
             'library' => 'required|string',
             'ref' => 'required|string',
+            'type' => 'required|string|regex:/^(php|pecl)$/',
             'workflow_run_id' => 'required|string',
             'php_versions' => 'required|string|regex:/^(?:\d+\.\d+|master)(?:,\s*(?:\d+\.\d+|master))*$/',
             'vs_version_targets' => 'required|string|regex:/^(v[c|s]\d{2})(,v[c|s]\d{2})*$/',
diff --git a/tests/Console/Command/WinlibsCommandTest.php b/tests/Console/Command/WinlibsCommandTest.php
index 720e0db..c2127c9 100644
--- a/tests/Console/Command/WinlibsCommandTest.php
+++ b/tests/Console/Command/WinlibsCommandTest.php
@@ -15,6 +15,8 @@ class WinlibsCommandTest extends TestCase
     
     private string $winlibsDirectory;
 
+    private string $buildsDirectory;
+
     protected function setUp(): void
     {
         parent::setUp();
@@ -42,6 +44,7 @@ public function testSuccessfulFileOperations($phpVersion, $vsVersion, $arch, $st
         $seriesFilePath = $this->baseDirectory . "/php-sdk/deps/series/packages-$phpVersion-$vsVersion-$arch-$stability.txt";
 
         file_put_contents($this->winlibsDirectory . '/lib/data.json', json_encode([
+            'type' => 'php',
             'library' => $library,
             'ref' => $ref,
             'vs_version_targets' => $vsVersion,
@@ -77,6 +80,7 @@ public function testSuccessfulFileOperationsWithExistingSeriesFile($phpVersion,
         $seriesFilePath = $this->baseDirectory . "/php-sdk/deps/series/packages-$phpVersion-$vsVersion-$arch-$stability.txt";
 
         file_put_contents($this->winlibsDirectory . '/lib/data.json', json_encode([
+            'type' => 'php',
             'library' => $library,
             'ref' => $ref,
             'vs_version_targets' => $vsVersion,
@@ -114,6 +118,7 @@ public function testSuccessfulFileOperationsWithExistingOldLibraryInSeriesFile($
         $seriesFilePath = $this->baseDirectory . "/php-sdk/deps/series/packages-$phpVersion-$vsVersion-$arch-$stability.txt";
 
         file_put_contents($this->winlibsDirectory . '/lib/data.json', json_encode([
+            'type' => 'php',
             'library' => $library,
             'ref' => $ref,
             'vs_version_targets' => $vsVersion,
@@ -141,6 +146,42 @@ public function testSuccessfulFileOperationsWithExistingOldLibraryInSeriesFile($
         $this->assertStringNotContainsString("lib-1.0.0-$vsVersion-$arch.zip", file_get_contents($seriesFilePath), "Series file should be updated correctly.");
     }
 
+    public function testSuccessfulPeclFileOperations(): void
+    {
+        mkdir($this->winlibsDirectory . '/redis', 0755, true);
+        mkdir($this->baseDirectory . '/pecl/deps', 0755, true);
+
+        $library = 'phpredis';
+        $ref = '5.3.7';
+        $vsVersion = 'vs16';
+        $arch = 'x64';
+
+        file_put_contents($this->winlibsDirectory . '/redis/data.json', json_encode([
+            'type' => 'pecl',
+            'library' => $library,
+            'ref' => $ref,
+            'vs_version_targets' => $vsVersion,
+            'php_versions' => '8.2',
+            'stability' => 'stable'
+        ]));
+
+        $zipPath = $this->winlibsDirectory . "/redis/redis-$ref-$vsVersion-$arch.zip";
+        $zip = new ZipArchive();
+        if ($zip->open($zipPath, ZipArchive::CREATE) === TRUE) {
+            $zip->addFromString('dummy_file.txt', 'dummy content');
+            $zip->close();
+        }
+
+        $command = new WinlibsCommand();
+        $command->setOption('base-directory', $this->baseDirectory);
+        $command->setOption('builds-directory', $this->buildsDirectory);
+
+        $result = $command->handle();
+
+        $this->assertEquals(0, $result, 'Command should return success.');
+        $this->assertFileExists($this->baseDirectory . "/pecl/deps/$library-$ref-$vsVersion-$arch.zip");
+    }
+
     public static function versionProvider(): array
     {
         return [
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.