Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions config/nativephp-internal.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
'api_url' => env('NATIVEPHP_API_URL', 'http://localhost:4000/api/'),

/**
* Configuration for the Zephpyr API.
* Configuration for the Bifrost API.
*/
'zephpyr' => [
'host' => env('ZEPHPYR_HOST', 'https://zephpyr.com'),
'token' => env('ZEPHPYR_TOKEN'),
'key' => env('ZEPHPYR_KEY'),
'bifrost' => [
'host' => env('BIFROST_HOST', 'https://bifrost.nativephp.com'),
'token' => env('BIFROST_TOKEN'),
'project' => env('BIFROST_PROJECT'),
],

/**
Expand Down
2 changes: 1 addition & 1 deletion config/nativephp.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
'GITHUB_*',
'DO_SPACES_*',
'*_SECRET',
'ZEPHPYR_*',
'BIFROST_*',
'NATIVEPHP_UPDATER_PATH',
'NATIVEPHP_APPLE_ID',
'NATIVEPHP_APPLE_ID_PASS',
Expand Down
14 changes: 6 additions & 8 deletions src/Builder/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,35 @@

namespace Native\Desktop\Builder;

use Native\Desktop\Builder\Concerns\CleansEnvFile;
use Native\Desktop\Builder\Concerns\CopiesBundleToBuildDirectory;
use Native\Desktop\Builder\Concerns\CopiesCertificateAuthority;
use Native\Desktop\Builder\Concerns\CopiesToBuildDirectory;
use Native\Desktop\Builder\Concerns\HasPreAndPostProcessing;
use Native\Desktop\Builder\Concerns\LocatesPhpBinary;
use Native\Desktop\Builder\Concerns\ManagesEnvFile;
use Native\Desktop\Builder\Concerns\PrunesVendorDirectory;
use Symfony\Component\Filesystem\Path;

class Builder
{
use CleansEnvFile;
use CopiesBundleToBuildDirectory;
use CopiesCertificateAuthority;
use CopiesToBuildDirectory;
use HasPreAndPostProcessing;
use LocatesPhpBinary;
use ManagesEnvFile;
use PrunesVendorDirectory;

public function __construct(
private string $buildPath,
private ?string $buildPath = null,
private ?string $sourcePath = null,
) {

$this->sourcePath = $sourcePath
? $sourcePath
: base_path();
$this->buildPath = $buildPath ?? base_path('build');
$this->sourcePath = $sourcePath ?? base_path();
}

public static function make(
string $buildPath,
?string $buildPath = null,
?string $sourcePath = null
) {
return new self($buildPath, $sourcePath);
Expand Down
45 changes: 0 additions & 45 deletions src/Builder/Concerns/CleansEnvFile.php

This file was deleted.

115 changes: 115 additions & 0 deletions src/Builder/Concerns/ManagesEnvFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php

/**
* This trait is responsible for managing .env file operations including:
* - Cleaning sensitive information during builds
* - Updating/removing individual environment variables
* - Reading environment values
*/

namespace Native\Desktop\Builder\Concerns;

trait ManagesEnvFile
{
abstract public function buildPath(string $path = ''): string;

public array $overrideKeys = [
'LOG_CHANNEL',
'LOG_STACK',
'LOG_DAILY_DAYS',
'LOG_LEVEL',
];

/**
* Clean sensitive information from .env file for production builds
*/
public function cleanEnvFile(?string $envPath = null): void
{
$envFile = $envPath ?? $this->getEnvPath();
$cleanUpKeys = array_merge($this->overrideKeys, config('nativephp.cleanup_env_keys', []));

$contents = collect(file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES))
// Remove cleanup keys
->filter(function (string $line) use ($cleanUpKeys) {
$key = str($line)->before('=');

return ! $key->is($cleanUpKeys)
&& ! $key->startsWith('#');
})
// Set defaults (other config overrides are handled in the NativeServiceProvider)
// The Log channel needs to be configured before anything else.
->push('LOG_CHANNEL=stack')
->push('LOG_STACK=daily')
->push('LOG_DAILY_DAYS=3')
->push('LOG_LEVEL=warning')
->join("\n");

file_put_contents($envFile, $contents);
}

/**
* Update or add an environment variable
*/
public function updateEnvFile(string $key, string $value, ?string $envPath = null): void
{
$envPath = $envPath ?? $this->getEnvPath();
$envContent = file_get_contents($envPath);

$pattern = "/^{$key}=.*$/m";

if (preg_match($pattern, $envContent)) {
$envContent = preg_replace($pattern, "{$key}={$value}", $envContent);
} else {
$envContent = rtrim($envContent, "\n")."\n{$key}={$value}\n";
}

file_put_contents($envPath, $envContent);
}

/**
* Remove environment variables
*/
public function removeFromEnvFile(array $keys, ?string $envPath = null): void
{
$envPath = $envPath ?? $this->getEnvPath();
$envContent = file_get_contents($envPath);

foreach ($keys as $key) {
$envContent = preg_replace("/^{$key}=.*$/m", '', $envContent);
}

// Clean up extra newlines
$envContent = preg_replace('/\n\n+/', "\n\n", $envContent);
$envContent = trim($envContent)."\n";

file_put_contents($envPath, $envContent);
}

/**
* Get an environment variable value
*/
public function getEnvValue(string $key, ?string $envPath = null): ?string
{
$envPath = $envPath ?? $this->getEnvPath();

if (! file_exists($envPath)) {
return null;
}

$envContent = file_get_contents($envPath);

if (preg_match("/^{$key}=(.*)$/m", $envContent, $matches)) {
return trim($matches[1]);
}

return null;
}

/**
* Get the appropriate .env file path based on context
*/
private function getEnvPath(): string
{
return $this->buildPath('app/'.app()->environmentFile());
}
}
68 changes: 68 additions & 0 deletions src/Commands/Bifrost/ClearBundleCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Native\Desktop\Commands\Bifrost;

use Illuminate\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;

use function Laravel\Prompts\intro;

#[AsCommand(
name: 'bifrost:clear-bundle',
description: 'Remove the downloaded bundle from the build directory.',
)]
class ClearBundleCommand extends Command
{
protected $signature = 'bifrost:clear-bundle';

public function handle(): int
{
intro('Clearing downloaded bundle...');

$bundlePath = base_path('build/__nativephp_app_bundle');
$signaturePath = $bundlePath.'.asc';

$bundleExists = file_exists($bundlePath);
$signatureExists = file_exists($signaturePath);

if (! $bundleExists && ! $signatureExists) {
$this->warn('No bundle or signature files found to clear.');

return static::SUCCESS;
}

$cleared = [];
$failed = [];

if ($bundleExists) {
if (unlink($bundlePath)) {
$cleared[] = 'bundle';
} else {
$failed[] = 'bundle';
}
}

if ($signatureExists) {
if (unlink($signaturePath)) {
$cleared[] = 'GPG signature';
} else {
$failed[] = 'GPG signature';
}
}

if (! empty($cleared)) {
$clearedText = implode(' and ', $cleared);
$this->info("Cleared {$clearedText} successfully!");
$this->line('Note: Building in this state would be unsecure without a valid bundle.');
}

if (! empty($failed)) {
$failedText = implode(' and ', $failed);
$this->error("Failed to remove {$failedText}.");

return static::FAILURE;
}

return static::SUCCESS;
}
}
Loading
Loading