Skip to content

Commit 1ecb12c

Browse files
committed
Octane wrapper
1 parent 064a969 commit 1ecb12c

File tree

8 files changed

+274
-3
lines changed

8 files changed

+274
-3
lines changed

.gitignore

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
composer.phar
2+
composer.lock
23
/vendor/
34

4-
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
5-
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
6-
# composer.lock
5+
/.idea

bin/file-watcher.cjs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const chokidar = require('chokidar');
2+
3+
const paths = JSON.parse(process.argv[2]);
4+
const poll = process.argv[3] ? true : false;
5+
6+
const watcher = chokidar.watch(paths, {
7+
ignoreInitial: true,
8+
usePolling: poll,
9+
});
10+
11+
watcher
12+
.on('add', () => console.log('File added...'))
13+
.on('change', () => console.log('File changed...'))
14+
.on('unlink', () => console.log('File deleted...'))
15+
.on('unlinkDir', () => console.log('Directory deleted...'));

composer.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "programic/laravel-kubernetes",
3+
"description": "Programic Laravel Kubernetes",
4+
"autoload": {
5+
"psr-4": {
6+
"Programic\\LaravelKubernetes\\": "src/"
7+
}
8+
},
9+
"authors": [
10+
{
11+
"name": "Nick Verschoor",
12+
"email": "[email protected]"
13+
}
14+
],
15+
"require": {
16+
"php": "^8.2",
17+
"laravel/octane": "^2.6"
18+
},
19+
"extra": {
20+
"laravel": {
21+
"providers": [
22+
"Programic\\LaravelKubernetes\\KubernetesServiceProvider"
23+
]
24+
}
25+
},
26+
"minimum-stability": "stable",
27+
"prefer-stable": true
28+
}

config/kubernetes.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
return [
4+
/*
5+
|--------------------------------------------------------------------------
6+
| File Watching
7+
|--------------------------------------------------------------------------
8+
|
9+
| The following list of files and directories will be watched when using
10+
| the --watch option offered by Octane. If any of the directories and
11+
| files are changed, Octane will automatically reload your workers.
12+
|
13+
*/
14+
'watch' => [
15+
'enabled' => env('KUBERNETES_WATCH_ENABLED', env('APP_ENV') === 'local'),
16+
'paths' => [
17+
'app',
18+
'bootstrap',
19+
'config/**/*.php',
20+
'database/**/*.php',
21+
'public/**/*.php',
22+
'resources/**/*.php',
23+
'routes',
24+
'composer.lock',
25+
'.env',
26+
],
27+
],
28+
29+
/*
30+
|--------------------------------------------------------------------------
31+
| Maximum Execution Time
32+
|--------------------------------------------------------------------------
33+
|
34+
| The following setting configures the maximum execution time for requests
35+
| being handled by Octane. You may set this value to 0 to indicate that
36+
| there isn't a specific time limit on Octane request execution time.
37+
|
38+
*/
39+
'max_execution_time' => env('MAX_EXECUTION_TIME', 60),
40+
];

src/Commands/InstallCommand.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Programic\LaravelKubernetes\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use function Laravel\Prompts\spin;
7+
8+
class InstallCommand extends Command
9+
{
10+
protected $signature = 'kubernetes:install
11+
{--force : Overwrite any existing configuration files}';
12+
13+
protected $description = 'Install components and resources';
14+
15+
public function handle(): int
16+
{
17+
$this->callSilent('vendor:publish', [
18+
'--tag' => 'kubernetes-config',
19+
'--force' => $this->option('force'),
20+
]);
21+
22+
spin(
23+
function (): void {
24+
$this->callSilent(InstallOctaneCommand::class, ['--server' => 'frankenphp']);
25+
},
26+
'Installing Octane components and resources'
27+
);
28+
29+
$this->components->info('Laravel kubernetes installed successfully.');
30+
31+
return 0;
32+
}
33+
}

src/Commands/InstallOctaneCommand.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Programic\LaravelKubernetes\Commands;
4+
5+
use Laravel\Octane\Commands\InstallCommand;
6+
use function Laravel\Prompts\select;
7+
8+
class InstallOctaneCommand extends InstallCommand
9+
{
10+
public function handle()
11+
{
12+
return (int) ! tap(
13+
$this->installFrankenPhpServer()
14+
);
15+
}
16+
}

src/Commands/StartCommand.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
namespace Programic\LaravelKubernetes\Commands;
4+
5+
use Illuminate\Support\Str;
6+
use Laravel\Octane\Commands\StartFrankenPhpCommand;
7+
use Symfony\Component\Console\Attribute\AsCommand;
8+
use Symfony\Component\Process\ExecutableFinder;
9+
use Symfony\Component\Process\Process;
10+
11+
#[AsCommand(name: 'kubernetes:start')]
12+
class StartCommand extends StartFrankenPhpCommand
13+
{
14+
protected $hidden = false;
15+
16+
/**
17+
* The command's signature.
18+
*
19+
* @var string
20+
*/
21+
public $signature = 'kubernetes:start
22+
{--host=127.0.0.1 : The IP address the server should bind to}
23+
{--port=80 : The port the server should be available on}
24+
{--admin-host=localhost : The host the admin server should be available on}
25+
{--admin-port=2019 : The port the admin server should be available on}
26+
{--workers=auto : The number of workers that should be available to handle requests}
27+
{--max-requests=500 : The number of requests to process before reloading the server}
28+
{--caddyfile= : The path to the FrankenPHP Caddyfile file}
29+
{--https : Enable HTTPS, HTTP/2, and HTTP/3, and automatically generate and renew certificates}
30+
{--http-redirect : Enable HTTP to HTTPS redirection (only enabled if --https is passed)}
31+
{--watch : Automatically reload the server when the application is modified (enable by default if APP_ENV is local)}
32+
{--poll : Use file system polling while watching in order to watch files over a network}
33+
{--log-level=INFO : Log messages at or above the specified log level}';
34+
35+
public $description = 'Start the server';
36+
37+
protected function writeServerOutput($server): void
38+
{
39+
[$output, $errorOutput] = $this->getServerOutput($server);
40+
41+
Str::of($output)
42+
->explode("\n")
43+
->filter()
44+
->each(function ($output): void {
45+
$this->output->writeln($output);
46+
});
47+
48+
Str::of($errorOutput)
49+
->explode("\n")
50+
->filter()
51+
->each(function ($output): void {
52+
$debug = json_decode($output, true);
53+
54+
if (! is_array($debug)) {
55+
$this->components->info($output);
56+
57+
return;
58+
}
59+
60+
if (isset($debug['logger']) && Str::startsWith($debug['logger'], 'http.log.access.log')) {
61+
$this->output->writeln($output);
62+
}
63+
});
64+
}
65+
66+
protected function startServerWatcher()
67+
{
68+
$watch = config('kubernetes.watch.enabled') || $this->option('watch');
69+
70+
if (! $watch) {
71+
return new class
72+
{
73+
public function __call($method, $parameters)
74+
{
75+
return null;
76+
}
77+
};
78+
}
79+
80+
if (empty($paths = config('octane.watch'))) {
81+
throw new InvalidArgumentException(
82+
'List of directories/files to watch not found. Please update your "config/octane.php" configuration file.',
83+
);
84+
}
85+
86+
return tap(new Process([
87+
(new ExecutableFinder)->find('node'),
88+
'file-watcher.cjs',
89+
json_encode(collect(config('octane.watch'))->map(fn ($path) => base_path($path))),
90+
$this->option('poll'),
91+
], realpath(__DIR__.'/../../bin'), null, null, null))->start();
92+
}
93+
}

src/KubernetesServiceProvider.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace Programic\LaravelKubernetes;
4+
5+
use Illuminate\Support\Facades\Config;
6+
use Illuminate\Support\ServiceProvider;
7+
8+
class KubernetesServiceProvider extends ServiceProvider
9+
{
10+
public function register()
11+
{
12+
$this->mergeConfigFrom(__DIR__.'/../config/kubernetes.php', 'kubernetes');
13+
}
14+
15+
public function boot()
16+
{
17+
$this->registerPublishing();
18+
$this->setOctaneConfig();
19+
$this->registerCommands();
20+
}
21+
22+
protected function registerCommands(): void
23+
{
24+
if ($this->app->runningInConsole()) {
25+
$this->commands([
26+
Commands\InstallCommand::class,
27+
Commands\StartCommand::class,
28+
]);
29+
}
30+
}
31+
32+
protected function setOctaneConfig(): void
33+
{
34+
config()->set('octane.server', 'frankenphp');
35+
config()->set('octane.watch', config('kubernetes.watch.paths'));
36+
config()->set('octane.max_execution_time', config('kubernetes.max_execution_time'));
37+
}
38+
39+
protected function registerPublishing()
40+
{
41+
if ($this->app->runningInConsole()) {
42+
$this->publishes([
43+
__DIR__.'/../config/kubernetes.php' => config_path('kubernetes.php'),
44+
], 'kubernetes-config');
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)