Skip to content

Commit 53961e1

Browse files
committed
Remove binaries from repo and download based on os and arch
1 parent a2f94fb commit 53961e1

File tree

3 files changed

+160
-66
lines changed

3 files changed

+160
-66
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
],
2525
"require": {
2626
"php": "^8.0",
27-
"ext-json": "*"
27+
"ext-json": "*",
28+
"ext-curl": "*"
2829
},
2930
"suggest": {
3031
"ext-pcntl": "For signal handling support on Unix-like systems"

src/Platform.php

Lines changed: 156 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,71 +5,73 @@
55
class Platform
66
{
77
private const BINARY_NAME = 'volt-test';
8+
9+
private const CURRENT_VERSION = 'v0.0.1-beta';
10+
private const BASE_DOWNLOAD_URL = 'https://github.com/volt-test/binaries/releases/download';
811
private const SUPPORTED_PLATFORMS = [
9-
'linux-amd64' => 'linux-amd64/volt-test',
10-
'darwin-amd64' => 'darwin-amd64/volt-test',
11-
'darwin-arm64' => 'darwin-arm64/volt-test',
12-
'windows-amd64' => 'windows-amd64/volt-test.exe',
13-
'windows-AMD64' => 'windows-amd64/volt-test.exe',
12+
'linux-amd64' => 'volt-test-linux-amd64',
13+
'darwin-amd64' => 'volt-test-darwin-amd64',
14+
'darwin-arm64' => 'volt-test-darwin-arm64',
15+
'windows-amd64' => 'volt-test-windows-amd64.exe'
1416
];
1517

16-
public static function installBinary($testing = false): void
18+
private static function getVendorDir(): string
1719
{
18-
$platform = self::detectPlatform($testing);
19-
20-
if (! array_key_exists($platform, self::SUPPORTED_PLATFORMS)) {
21-
throw new \RuntimeException("Platform $platform is not supported");
22-
}
23-
24-
$sourceFile = __DIR__ . '/../bin/platforms/' . self::SUPPORTED_PLATFORMS[$platform];
25-
$targetDir = self::getBinaryDir();
26-
$targetFile = $targetDir . '/' . basename(self::SUPPORTED_PLATFORMS[$platform]);
27-
28-
if (! file_exists($sourceFile)) {
29-
throw new \RuntimeException("Binary not found for platform: $platform");
20+
// First try using Composer's environment variable
21+
if (getenv('COMPOSER_VENDOR_DIR')) {
22+
return rtrim(getenv('COMPOSER_VENDOR_DIR'), '/\\');
3023
}
3124

32-
if (! is_dir($targetDir)) {
33-
if (! mkdir($targetDir, 0755, true)) {
34-
throw new \RuntimeException("Failed to create directory: $targetDir");
25+
// Then try using Composer's home directory
26+
if (getenv('COMPOSER_HOME')) {
27+
$vendorDir = rtrim(getenv('COMPOSER_HOME'), '/\\') . '/vendor';
28+
if (is_dir($vendorDir)) {
29+
return $vendorDir;
3530
}
3631
}
3732

38-
if (! copy($sourceFile, $targetFile)) {
39-
throw new \RuntimeException("Failed to copy binary to: $targetFile");
33+
// Try to find vendor directory relative to current file
34+
$paths = [
35+
__DIR__ . '/../../../', // From src/VoltTest to vendor
36+
__DIR__ . '/vendor/', // Direct vendor subdirectory
37+
dirname(__DIR__, 2) . '/vendor/', // Two levels up
38+
dirname(__DIR__, 3) . '/vendor/', // Three levels up
39+
dirname(__DIR__) . '/vendor/',
40+
];
41+
42+
foreach ($paths as $path) {
43+
if (file_exists($path . 'autoload.php')) {
44+
return rtrim($path, '/\\');
45+
}
4046
}
4147

42-
chmod($targetFile, 0755);
43-
44-
// Create symlink in vendor/bin
45-
$vendorBinDir = self::getVendorBinDir();
46-
if (! is_dir($vendorBinDir)) {
47-
if (! mkdir($vendorBinDir, 0755, true)) {
48-
throw new \RuntimeException("Failed to create vendor bin directory: $vendorBinDir");
48+
// If running as a Composer script, use the working directory
49+
if (getenv('COMPOSER')) {
50+
$path = getcwd() . '/vendor';
51+
if (is_dir($path)) {
52+
return $path;
4953
}
5054
}
5155

52-
$symlinkPath = $vendorBinDir . '/' . self::BINARY_NAME;
53-
if (file_exists($symlinkPath)) {
54-
unlink($symlinkPath);
55-
}
56+
throw new \RuntimeException(
57+
'Could not locate Composer vendor directory. ' .
58+
'Please ensure you are installing through Composer.'
59+
);
60+
}
5661

57-
if (PHP_OS_FAMILY === 'Windows') {
58-
// Windows doesn't support symlinks by default, so we'll copy the file
59-
if (! copy($targetFile, $symlinkPath)) {
60-
throw new \RuntimeException("Failed to copy binary to vendor/bin: $symlinkPath");
61-
}
62-
} else {
63-
if (! symlink($targetFile, $symlinkPath)) {
64-
throw new \RuntimeException("Failed to create symlink in vendor/bin: $symlinkPath");
65-
}
66-
}
62+
private static function getBinaryDir(): string
63+
{
64+
return self::getVendorDir() . '/bin';
65+
}
6766

67+
private static function getCurrentVersion(): string
68+
{
69+
return self::CURRENT_VERSION;
6870
}
6971

7072
private static function detectPlatform($testing = false): string
7173
{
72-
if ($testing === true) {
74+
if ($testing) {
7375
return 'unsupported-platform';
7476
}
7577
$os = strtolower(PHP_OS);
@@ -82,40 +84,131 @@ private static function detectPlatform($testing = false): string
8284
} elseif (strpos($os, 'linux') === 0) {
8385
$os = 'linux';
8486
}
87+
8588
if ($arch === 'x86_64') {
8689
$arch = 'amd64';
90+
} elseif ($arch === 'arm64' || $arch === 'aarch64') {
91+
$arch = 'arm64';
8792
}
8893

8994
return "$os-$arch";
9095
}
9196

92-
private static function getBinaryDir(): string
97+
public static function installBinary($testing = false): void
9398
{
94-
return self::getVendorDir() . '/volt-test/bin';
95-
}
99+
$platform = self::detectPlatform($testing);
96100

97-
private static function getVendorBinDir(): string
98-
{
99-
return self::getVendorDir() . '/bin';
100-
}
101+
if (!array_key_exists($platform, self::SUPPORTED_PLATFORMS)) {
102+
throw new \RuntimeException("Platform $platform is not supported");
103+
}
101104

102-
private static function getVendorDir(): string
103-
{
104-
// Traverse up from current directory until we find vendor directory
105-
$dir = __DIR__;
106-
while ($dir !== '/' && ! is_dir($dir . '/vendor')) {
107-
$dir = dirname($dir);
105+
$version = self::getCurrentVersion();
106+
$binaryName = self::SUPPORTED_PLATFORMS[$platform];
107+
$downloadUrl = sprintf('%s/%s/%s', self::BASE_DOWNLOAD_URL, $version, $binaryName);
108+
109+
$binDir = self::getBinaryDir();
110+
$targetFile = $binDir . '/' . self::BINARY_NAME;
111+
if (PHP_OS_FAMILY === 'Windows') {
112+
$targetFile .= '.exe';
108113
}
109114

110-
if (! is_dir($dir . '/vendor')) {
111-
throw new \RuntimeException('Could not locate vendor directory');
115+
if (!is_dir($binDir)) {
116+
if (!mkdir($binDir, 0755, true)) {
117+
throw new \RuntimeException("Failed to create directory: $binDir");
118+
}
112119
}
113120

114-
return $dir . '/vendor';
121+
echo "Downloading VoltTest binary $version for platform: $platform\n";
122+
123+
$tempFile = tempnam(sys_get_temp_dir(), 'volt-test-download-');
124+
if ($tempFile === false) {
125+
throw new \RuntimeException("Failed to create temporary file");
126+
}
127+
128+
try {
129+
$ch = curl_init($downloadUrl);
130+
if ($ch === false) {
131+
throw new \RuntimeException("Failed to initialize cURL");
132+
}
133+
134+
$fp = fopen($tempFile, 'w');
135+
if ($fp === false) {
136+
curl_close($ch);
137+
throw new \RuntimeException("Failed to open temporary file for writing");
138+
}
139+
140+
curl_setopt_array($ch, [
141+
CURLOPT_FILE => $fp,
142+
CURLOPT_FOLLOWLOCATION => true,
143+
CURLOPT_SSL_VERIFYPEER => true,
144+
CURLOPT_FAILONERROR => true,
145+
CURLOPT_TIMEOUT => 300,
146+
CURLOPT_CONNECTTIMEOUT => 30,
147+
CURLOPT_HTTPHEADER => ['User-Agent: volt-test-php-sdk']
148+
]);
149+
150+
if (curl_exec($ch) === false) {
151+
throw new \RuntimeException("Download failed: " . curl_error($ch));
152+
}
153+
154+
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
155+
if ($httpCode !== 200) {
156+
throw new \RuntimeException("HTTP request failed with status $httpCode");
157+
}
158+
159+
curl_close($ch);
160+
fclose($fp);
161+
162+
if (!file_exists($tempFile) || filesize($tempFile) === 0) {
163+
throw new \RuntimeException("Downloaded file is empty or missing");
164+
}
165+
166+
if (!rename($tempFile, $targetFile)) {
167+
throw new \RuntimeException("Failed to move downloaded binary to: $targetFile");
168+
}
169+
170+
if (!chmod($targetFile, 0755)) {
171+
throw new \RuntimeException("Failed to set executable permissions on binary");
172+
}
173+
174+
file_put_contents($binDir . '/.volt-test-version', $version);
175+
176+
echo "Successfully installed VoltTest binary $version to: $targetFile\n";
177+
} catch (\Exception $e) {
178+
if (file_exists($tempFile)) {
179+
unlink($tempFile);
180+
}
181+
throw $e;
182+
}
115183
}
116184

117185
public static function getBinaryPath(): string
118186
{
119-
return self::getBinaryDir() . '/' . basename(self::SUPPORTED_PLATFORMS[self::detectPlatform()]);
187+
$binDir = self::getBinaryDir();
188+
$binaryName = self::BINARY_NAME;
189+
if (PHP_OS_FAMILY === 'Windows') {
190+
$binaryName .= '.exe';
191+
}
192+
193+
$binaryPath = $binDir . '/' . $binaryName;
194+
$versionFile = $binDir . '/.volt-test-version';
195+
196+
$needsInstall = true;
197+
198+
if (file_exists($binaryPath) && file_exists($versionFile)) {
199+
try {
200+
$currentVersion = trim(file_get_contents($versionFile));
201+
$latestVersion = self::getCurrentVersion();
202+
$needsInstall = $currentVersion !== $latestVersion;
203+
} catch (\Exception $e) {
204+
$needsInstall = true;
205+
}
206+
}
207+
208+
if ($needsInstall) {
209+
self::installBinary();
210+
}
211+
212+
return $binaryPath;
120213
}
121-
}
214+
}

tests/Units/PlatformTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function testGetBinaryPath()
7171

7272
// Assert that the binary path contains the expected directory structure
7373
$this->assertStringContainsString(
74-
'volt-test/bin',
74+
'/bin',
7575
$binaryPath,
7676
"Binary path does not contain the expected directory structure"
7777
);
@@ -94,7 +94,7 @@ public function testInstallBinary()
9494
$vendorDir = $getVendorDirMethod->invoke($platform);
9595

9696
// Assert that the binary directory is created
97-
$binaryDir = $vendorDir . '/volt-test/bin';
97+
$binaryDir = $vendorDir . '/bin';
9898
$this->assertDirectoryExists($binaryDir, "Binary directory was not created");
9999

100100
// Assert that the binary file exists

0 commit comments

Comments
 (0)