From 028aec1d451abe448d80fab593b1fd5d3e1ceca6 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Tue, 10 Dec 2024 08:34:42 +0000 Subject: [PATCH 1/5] wip --- config/nativephp-internal.php | 5 ++ src/Commands/BundleCommand.php | 130 +++++++++++++++++++++++++++++++++ src/NativeServiceProvider.php | 2 + 3 files changed, 137 insertions(+) create mode 100644 src/Commands/BundleCommand.php diff --git a/config/nativephp-internal.php b/config/nativephp-internal.php index 4210df9..1c2734f 100644 --- a/config/nativephp-internal.php +++ b/config/nativephp-internal.php @@ -29,4 +29,9 @@ * The URL to the NativePHP API. */ 'api_url' => env('NATIVEPHP_API_URL', 'http://localhost:4000/api/'), + + 'zephpyr' => [ + 'host' => env('ZEPHPYR_HOST', 'zephpyr.com'), + 'key' => env('ZEPHPYR_SECRET'), + ], ]; diff --git a/src/Commands/BundleCommand.php b/src/Commands/BundleCommand.php new file mode 100644 index 0000000..c5fe0ce --- /dev/null +++ b/src/Commands/BundleCommand.php @@ -0,0 +1,130 @@ +key = config('nativephp-internal.zephpyr.key'); + + if (!$this->key) { + $this->line(''); + $this->warn('No ZEPHPYR_SECRET found. Cannot bundle!'); + $this->line(''); + $this->line('Add this app\'s ZEPHPYR_SECRET to its .env file:'); + $this->line(base_path('.env')); + $this->line(''); + $this->info('Not set up with Zephpyr yet? Secure your NativePHP app builds and more!'); + $this->info('Check out https://zephpyr.com'); + $this->line(''); + + return static::FAILURE; + } + + // Package the app up into a zip + if (! $this->zipApplication()) { + $this->error("Failed to create zip archive at {$this->zipPath}."); + return static::FAILURE; + } + + // Send the zip file + if (! $this->sendToZephpyr()) { + $this->error("Failed to upload zip [{$this->zipPath}] to Zephpyr."); + return static::FAILURE; + } + + return static::SUCCESS; + } + + private function zipApplication(): bool + { + $this->zipName = 'app_' . str()->random(8) . '.zip'; + $this->zipPath = storage_path($this->zipName); + + $zip = new ZipArchive; + + if ($zip->open($this->zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) { + return false; + } + + $this->prepareNativeEnv(); + + $this->addFilesToZip($zip); + + $zip->close(); + + $this->restoreWebEnv(); + + return true; + } + + private function addFilesToZip(ZipArchive $zip): void + { + $app = (new Finder())->files() + ->followLinks() + ->ignoreVCSIgnored(true) + ->in(base_path()) + ->exclude([ + 'tests', + ...config('nativephp.cleanup_exclude_files', []), + ]); + + $this->finderToZip($app, $zip); + + $vendor = (new Finder())->files() + ->exclude([ + 'vendor/nativephp/php-bin', + ]) + ->in(base_path('vendor')); + + $this->finderToZip($vendor, $zip); + + $nodeModules = (new Finder())->files() + ->in(base_path('node_modules')); + + $this->finderToZip($nodeModules, $zip); + + $env = (new Finder())->files() + ->ignoreDotFiles(false) + ->name('.env') + ->in(base_path()); + + $this->finderToZip($env, $zip); + } + + private function finderToZip(Finder $finder, ZipArchive $zip): void + { + foreach ($finder as $file) { + dump([$file->getRealPath(), $file->getRelativePath()]); + $zip->addFile($file->getRealPath(), $file->getRelativePathname()); + } + } + + private function sendToZephpyr(): bool + { + return false; + $response = Http::attach('archive', fopen($this->zipPath, 'r'), $this->zipName) + ->post(config('nativephp-internal.zephpyr.host'), [ + 'key' => $this->key, + ]); + + return $response->successful(); + } +} diff --git a/src/NativeServiceProvider.php b/src/NativeServiceProvider.php index 9701766..997d982 100644 --- a/src/NativeServiceProvider.php +++ b/src/NativeServiceProvider.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\DB; use Native\Laravel\ChildProcess as ChildProcessImplementation; +use Native\Laravel\Commands\BundleCommand; use Native\Laravel\Commands\FreshCommand; use Native\Laravel\Commands\LoadPHPConfigurationCommand; use Native\Laravel\Commands\LoadStartupConfigurationCommand; @@ -36,6 +37,7 @@ public function configurePackage(Package $package): void FreshCommand::class, SeedDatabaseCommand::class, MinifyApplicationCommand::class, + BundleCommand::class, ]) ->hasConfigFile() ->hasRoute('api') From 110395d33635f2869253a4d00ec96ccf5dea21e9 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Tue, 10 Dec 2024 08:37:26 +0000 Subject: [PATCH 2/5] Remove the minify command --- src/Commands/MinifyApplicationCommand.php | 111 ---------------------- src/NativeServiceProvider.php | 2 - 2 files changed, 113 deletions(-) delete mode 100644 src/Commands/MinifyApplicationCommand.php diff --git a/src/Commands/MinifyApplicationCommand.php b/src/Commands/MinifyApplicationCommand.php deleted file mode 100644 index 37d8378..0000000 --- a/src/Commands/MinifyApplicationCommand.php +++ /dev/null @@ -1,111 +0,0 @@ -argument('app')); - - if (! is_dir($appPath)) { - $this->error('The app path is not a directory'); - - return; - } - - $this->info('Minifying application…'); - - $this->cleanUpEnvFile($appPath); - $this->removeIgnoredFilesAndFolders($appPath); - - $compactor = new Php; - - $phpFiles = Finder::create() - ->files() - ->name('*.php') - ->in($appPath); - - foreach ($phpFiles as $phpFile) { - $minifiedContent = $compactor->compact($phpFile->getRealPath(), $phpFile->getContents()); - file_put_contents($phpFile->getRealPath(), $minifiedContent); - } - } - - protected function cleanUpEnvFile(string $appPath): void - { - $envFile = $appPath.'/.env'; - - if (! file_exists($envFile)) { - return; - } - - $this->info('Cleaning up .env file…'); - - $cleanUpKeys = config('nativephp.cleanup_env_keys', []); - - $envContent = file_get_contents($envFile); - $envValues = collect(explode("\n", $envContent)) - ->filter(function (string $line) use ($cleanUpKeys) { - $key = Str::before($line, '='); - - return ! Str::is($cleanUpKeys, $key); - }) - ->join("\n"); - - file_put_contents($envFile, $envValues); - } - - protected function removeIgnoredFilesAndFolders(string $appPath): void - { - $this->info('Cleaning up ignored files and folders…'); - - $itemsToRemove = config('nativephp.cleanup_exclude_files', []); - - foreach ($itemsToRemove as $item) { - $fullPath = $appPath.'/'.$item; - - if (file_exists($fullPath)) { - if (is_dir($fullPath)) { - $this->deleteDirectoryRecursive($fullPath); - } else { - array_map('unlink', glob($fullPath)); - } - } else { - foreach (glob($item) as $pathFound) { - unlink($pathFound); - } - } - } - } - - private function deleteDirectoryRecursive(string $directory): bool - { - if (! file_exists($directory)) { - return true; - } - - if (! is_dir($directory)) { - return unlink($directory); - } - - foreach (scandir($directory) as $item) { - if ($item == '.' || $item == '..') { - continue; - } - - if (! $this->deleteDirectoryRecursive($directory.'/'.$item)) { - return false; - } - } - - return rmdir($directory); - } -} diff --git a/src/NativeServiceProvider.php b/src/NativeServiceProvider.php index 997d982..9d14d56 100644 --- a/src/NativeServiceProvider.php +++ b/src/NativeServiceProvider.php @@ -13,7 +13,6 @@ use Native\Laravel\Commands\LoadPHPConfigurationCommand; use Native\Laravel\Commands\LoadStartupConfigurationCommand; use Native\Laravel\Commands\MigrateCommand; -use Native\Laravel\Commands\MinifyApplicationCommand; use Native\Laravel\Commands\SeedDatabaseCommand; use Native\Laravel\Contracts\ChildProcess as ChildProcessContract; use Native\Laravel\Contracts\GlobalShortcut as GlobalShortcutContract; @@ -36,7 +35,6 @@ public function configurePackage(Package $package): void MigrateCommand::class, FreshCommand::class, SeedDatabaseCommand::class, - MinifyApplicationCommand::class, BundleCommand::class, ]) ->hasConfigFile() From 927da87cb314738837b3d07465e23ba343d2bfc3 Mon Sep 17 00:00:00 2001 From: simonhamp Date: Tue, 10 Dec 2024 08:41:03 +0000 Subject: [PATCH 3/5] Fix styling --- src/Commands/BundleCommand.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Commands/BundleCommand.php b/src/Commands/BundleCommand.php index c5fe0ce..3a282a8 100644 --- a/src/Commands/BundleCommand.php +++ b/src/Commands/BundleCommand.php @@ -4,7 +4,6 @@ use Illuminate\Console\Command; use Native\Electron\Traits\CleansEnvFile; -use Native\Laravel\NativeServiceProvider; use Symfony\Component\Finder\Finder; use ZipArchive; @@ -17,14 +16,16 @@ class BundleCommand extends Command protected $description = 'Bundle your application for distribution.'; private ?string $key; + private string $zipPath; + private string $zipName; public function handle() { $this->key = config('nativephp-internal.zephpyr.key'); - if (!$this->key) { + if (! $this->key) { $this->line(''); $this->warn('No ZEPHPYR_SECRET found. Cannot bundle!'); $this->line(''); @@ -41,12 +42,14 @@ public function handle() // Package the app up into a zip if (! $this->zipApplication()) { $this->error("Failed to create zip archive at {$this->zipPath}."); + return static::FAILURE; } // Send the zip file if (! $this->sendToZephpyr()) { $this->error("Failed to upload zip [{$this->zipPath}] to Zephpyr."); + return static::FAILURE; } @@ -55,7 +58,7 @@ public function handle() private function zipApplication(): bool { - $this->zipName = 'app_' . str()->random(8) . '.zip'; + $this->zipName = 'app_'.str()->random(8).'.zip'; $this->zipPath = storage_path($this->zipName); $zip = new ZipArchive; @@ -77,7 +80,7 @@ private function zipApplication(): bool private function addFilesToZip(ZipArchive $zip): void { - $app = (new Finder())->files() + $app = (new Finder)->files() ->followLinks() ->ignoreVCSIgnored(true) ->in(base_path()) @@ -88,7 +91,7 @@ private function addFilesToZip(ZipArchive $zip): void $this->finderToZip($app, $zip); - $vendor = (new Finder())->files() + $vendor = (new Finder)->files() ->exclude([ 'vendor/nativephp/php-bin', ]) @@ -96,12 +99,12 @@ private function addFilesToZip(ZipArchive $zip): void $this->finderToZip($vendor, $zip); - $nodeModules = (new Finder())->files() + $nodeModules = (new Finder)->files() ->in(base_path('node_modules')); $this->finderToZip($nodeModules, $zip); - $env = (new Finder())->files() + $env = (new Finder)->files() ->ignoreDotFiles(false) ->name('.env') ->in(base_path()); From 49b72147e7cc24356aa1f378989127fa78049618 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Thu, 19 Dec 2024 14:48:17 +0000 Subject: [PATCH 4/5] wip --- config/nativephp-internal.php | 3 +- config/nativephp.php | 3 +- src/Commands/BundleCommand.php | 80 ++++++++++++++++++++++++---------- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/config/nativephp-internal.php b/config/nativephp-internal.php index 1c2734f..a05783a 100644 --- a/config/nativephp-internal.php +++ b/config/nativephp-internal.php @@ -32,6 +32,7 @@ 'zephpyr' => [ 'host' => env('ZEPHPYR_HOST', 'zephpyr.com'), - 'key' => env('ZEPHPYR_SECRET'), + 'token' => env('ZEPHPYR_TOKEN'), + 'key' => env('ZEPHPYR_KEY'), ], ]; diff --git a/config/nativephp.php b/config/nativephp.php index b24afec..08b0099 100644 --- a/config/nativephp.php +++ b/config/nativephp.php @@ -6,7 +6,7 @@ * It is used to determine if the app needs to be updated. * Increment this value every time you release a new version of your app. */ - 'version' => env('NATIVEPHP_APP_VERSION', '1.0.0'), + 'version' => env('NATIVEPHP_APP_VERSION', 1), /** * The ID of your application. This should be a unique identifier @@ -47,6 +47,7 @@ 'AWS_*', 'GITHUB_*', 'DO_SPACES_*', + 'ZEPHPYR_*', '*_SECRET', 'NATIVEPHP_UPDATER_PATH', 'NATIVEPHP_APPLE_ID', diff --git a/src/Commands/BundleCommand.php b/src/Commands/BundleCommand.php index 3a282a8..0802e4c 100644 --- a/src/Commands/BundleCommand.php +++ b/src/Commands/BundleCommand.php @@ -3,6 +3,7 @@ namespace Native\Laravel\Commands; use Illuminate\Console\Command; +use Illuminate\Support\Facades\Http; use Native\Electron\Traits\CleansEnvFile; use Symfony\Component\Finder\Finder; use ZipArchive; @@ -11,7 +12,7 @@ class BundleCommand extends Command { use CleansEnvFile; - protected $name = 'native:bundle'; + protected $signature = 'native:bundle {--fetch}'; protected $description = 'Bundle your application for distribution.'; @@ -27,9 +28,9 @@ public function handle() if (! $this->key) { $this->line(''); - $this->warn('No ZEPHPYR_SECRET found. Cannot bundle!'); + $this->warn('No ZEPHPYR_KEY found. Cannot bundle!'); $this->line(''); - $this->line('Add this app\'s ZEPHPYR_SECRET to its .env file:'); + $this->line('Add this app\'s ZEPHPYR_KEY to its .env file:'); $this->line(base_path('.env')); $this->line(''); $this->info('Not set up with Zephpyr yet? Secure your NativePHP app builds and more!'); @@ -39,6 +40,16 @@ public function handle() return static::FAILURE; } + if ($this->option('fetch')) { + if (! $this->fetchLatestBundle()) { + $this->warn("Latest bundle not yet available. Try again soon."); + return static::FAILURE; + } + + $this->info("Latest bundle downloaded."); + return static::SUCCESS; + } + // Package the app up into a zip if (! $this->zipApplication()) { $this->error("Failed to create zip archive at {$this->zipPath}."); @@ -47,12 +58,19 @@ public function handle() } // Send the zip file - if (! $this->sendToZephpyr()) { + dd($result = $this->sendToZephpyr()); + + if ($result->failed()) { $this->error("Failed to upload zip [{$this->zipPath}] to Zephpyr."); return static::FAILURE; } + @unlink($this->zipPath); + + $this->info('Successfully uploaded to Zephpyr.'); + $this->line('Use native:bundle --fetch to retrieve the latest bundle.'); + return static::SUCCESS; } @@ -80,11 +98,17 @@ private function zipApplication(): bool private function addFilesToZip(ZipArchive $zip): void { + // TODO: Check the composer.json to make sure there are no symlinked or private packages as these will be a + // pain later + $app = (new Finder)->files() ->followLinks() ->ignoreVCSIgnored(true) ->in(base_path()) ->exclude([ + 'vendor', + 'dist', + 'build', 'tests', ...config('nativephp.cleanup_exclude_files', []), ]); @@ -93,41 +117,49 @@ private function addFilesToZip(ZipArchive $zip): void $vendor = (new Finder)->files() ->exclude([ - 'vendor/nativephp/php-bin', + 'nativephp/php-bin', + 'nativephp/electron/resources/js', + 'nativephp/*/vendor', ]) ->in(base_path('vendor')); - $this->finderToZip($vendor, $zip); + $this->finderToZip($vendor, $zip, 'vendor'); $nodeModules = (new Finder)->files() ->in(base_path('node_modules')); - $this->finderToZip($nodeModules, $zip); - - $env = (new Finder)->files() - ->ignoreDotFiles(false) - ->name('.env') - ->in(base_path()); - - $this->finderToZip($env, $zip); + $this->finderToZip($nodeModules, $zip, 'node_modules'); } - private function finderToZip(Finder $finder, ZipArchive $zip): void + private function finderToZip(Finder $finder, ZipArchive $zip, ?string $path = null): void { foreach ($finder as $file) { - dump([$file->getRealPath(), $file->getRelativePath()]); - $zip->addFile($file->getRealPath(), $file->getRelativePathname()); + if ($file->getRealPath() === false) { + continue; + } + + $zip->addFile($file->getRealPath(), str($path)->finish(DIRECTORY_SEPARATOR) . $file->getRelativePathname()); } } - private function sendToZephpyr(): bool + private function sendToZephpyr() { - return false; - $response = Http::attach('archive', fopen($this->zipPath, 'r'), $this->zipName) - ->post(config('nativephp-internal.zephpyr.host'), [ - 'key' => $this->key, - ]); + return Http::withToken(config('nativephp-internal.zephpyr.token')) + ->attach('archive', fopen($this->zipPath, 'r'), $this->zipName) + ->post(str(config('nativephp-internal.zephpyr.host'))->finish('/') . 'api/build/' . $this->key); + } - return $response->successful(); + private function fetchLatestBundle(): bool + { + $response = Http::withToken(config('nativephp-internal.zephpyr.token')) + ->get(str(config('nativephp-internal.zephpyr.host'))->finish('/') . 'api/download/' . $this->key); + + if ($response->failed()) { + return false; + } + + file_put_contents(base_path('build/__nativephp_app_bundle'), $response->body()); + + return true; } } From 24c9695a89b45e668e657e7ead178e0ca10b14af Mon Sep 17 00:00:00 2001 From: simonhamp Date: Sun, 29 Dec 2024 15:42:25 +0000 Subject: [PATCH 5/5] Fix styling --- src/Commands/BundleCommand.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Commands/BundleCommand.php b/src/Commands/BundleCommand.php index 0802e4c..e2e2e76 100644 --- a/src/Commands/BundleCommand.php +++ b/src/Commands/BundleCommand.php @@ -42,11 +42,13 @@ public function handle() if ($this->option('fetch')) { if (! $this->fetchLatestBundle()) { - $this->warn("Latest bundle not yet available. Try again soon."); + $this->warn('Latest bundle not yet available. Try again soon.'); + return static::FAILURE; } - $this->info("Latest bundle downloaded."); + $this->info('Latest bundle downloaded.'); + return static::SUCCESS; } @@ -138,7 +140,7 @@ private function finderToZip(Finder $finder, ZipArchive $zip, ?string $path = nu continue; } - $zip->addFile($file->getRealPath(), str($path)->finish(DIRECTORY_SEPARATOR) . $file->getRelativePathname()); + $zip->addFile($file->getRealPath(), str($path)->finish(DIRECTORY_SEPARATOR).$file->getRelativePathname()); } } @@ -146,13 +148,13 @@ private function sendToZephpyr() { return Http::withToken(config('nativephp-internal.zephpyr.token')) ->attach('archive', fopen($this->zipPath, 'r'), $this->zipName) - ->post(str(config('nativephp-internal.zephpyr.host'))->finish('/') . 'api/build/' . $this->key); + ->post(str(config('nativephp-internal.zephpyr.host'))->finish('/').'api/build/'.$this->key); } private function fetchLatestBundle(): bool { $response = Http::withToken(config('nativephp-internal.zephpyr.token')) - ->get(str(config('nativephp-internal.zephpyr.host'))->finish('/') . 'api/download/' . $this->key); + ->get(str(config('nativephp-internal.zephpyr.host'))->finish('/').'api/download/'.$this->key); if ($response->failed()) { return false;