Remove webhook maintenance mode replay feature

This feature stored incoming webhooks during maintenance mode and replayed them
when maintenance ended. The behavior adds unnecessary complexity without clear
value. Standard approach is to let webhooks fail during maintenance and let
senders retry.

Removes:
- Listener classes that handled maintenance mode events and webhook replay
- Maintenance mode checks from all webhook controllers (Github, Gitea, Gitlab, Bitbucket, Stripe)
- webhooks-during-maintenance filesystem disk configuration
- Feature mention from CHANGELOG

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai 2025-12-02 13:36:32 +01:00
parent 2302a70a44
commit 158d54712f
10 changed files with 0 additions and 233 deletions

View file

@ -5389,7 +5389,6 @@ ### 🚀 Features
- Add static ipv4 ipv6 support - Add static ipv4 ipv6 support
- Server disabled by overflow - Server disabled by overflow
- Preview deployment logs - Preview deployment logs
- Collect webhooks during maintenance
- Logs and execute commands with several servers - Logs and execute commands with several servers
### 🐛 Bug Fixes ### 🐛 Bug Fixes

View file

@ -3,7 +3,6 @@
namespace App\Http\Controllers\Webhook; namespace App\Http\Controllers\Webhook;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Livewire\Project\Service\Storage;
use App\Models\Application; use App\Models\Application;
use App\Models\ApplicationPreview; use App\Models\ApplicationPreview;
use Exception; use Exception;
@ -15,23 +14,6 @@ class Bitbucket extends Controller
public function manual(Request $request) public function manual(Request $request)
{ {
try { try {
if (app()->isDownForMaintenance()) {
$epoch = now()->valueOf();
$data = [
'attributes' => $request->attributes->all(),
'request' => $request->request->all(),
'query' => $request->query->all(),
'server' => $request->server->all(),
'files' => $request->files->all(),
'cookies' => $request->cookies->all(),
'headers' => $request->headers->all(),
'content' => $request->getContent(),
];
$json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Bitbicket::manual_bitbucket", $json);
return;
}
$return_payloads = collect([]); $return_payloads = collect([]);
$payload = $request->collect(); $payload = $request->collect();
$headers = $request->headers->all(); $headers = $request->headers->all();

View file

@ -7,7 +7,6 @@
use App\Models\ApplicationPreview; use App\Models\ApplicationPreview;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
@ -18,30 +17,6 @@ public function manual(Request $request)
try { try {
$return_payloads = collect([]); $return_payloads = collect([]);
$x_gitea_delivery = request()->header('X-Gitea-Delivery'); $x_gitea_delivery = request()->header('X-Gitea-Delivery');
if (app()->isDownForMaintenance()) {
$epoch = now()->valueOf();
$files = Storage::disk('webhooks-during-maintenance')->files();
$gitea_delivery_found = collect($files)->filter(function ($file) use ($x_gitea_delivery) {
return Str::contains($file, $x_gitea_delivery);
})->first();
if ($gitea_delivery_found) {
return;
}
$data = [
'attributes' => $request->attributes->all(),
'request' => $request->request->all(),
'query' => $request->query->all(),
'server' => $request->server->all(),
'files' => $request->files->all(),
'cookies' => $request->cookies->all(),
'headers' => $request->headers->all(),
'content' => $request->getContent(),
];
$json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Gitea::manual_{$x_gitea_delivery}", $json);
return;
}
$x_gitea_event = Str::lower($request->header('X-Gitea-Event')); $x_gitea_event = Str::lower($request->header('X-Gitea-Event'));
$x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256='); $x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256=');
$content_type = $request->header('Content-Type'); $content_type = $request->header('Content-Type');

View file

@ -14,7 +14,6 @@
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
@ -25,30 +24,6 @@ public function manual(Request $request)
try { try {
$return_payloads = collect([]); $return_payloads = collect([]);
$x_github_delivery = request()->header('X-GitHub-Delivery'); $x_github_delivery = request()->header('X-GitHub-Delivery');
if (app()->isDownForMaintenance()) {
$epoch = now()->valueOf();
$files = Storage::disk('webhooks-during-maintenance')->files();
$github_delivery_found = collect($files)->filter(function ($file) use ($x_github_delivery) {
return Str::contains($file, $x_github_delivery);
})->first();
if ($github_delivery_found) {
return;
}
$data = [
'attributes' => $request->attributes->all(),
'request' => $request->request->all(),
'query' => $request->query->all(),
'server' => $request->server->all(),
'files' => $request->files->all(),
'cookies' => $request->cookies->all(),
'headers' => $request->headers->all(),
'content' => $request->getContent(),
];
$json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::manual_{$x_github_delivery}", $json);
return;
}
$x_github_event = Str::lower($request->header('X-GitHub-Event')); $x_github_event = Str::lower($request->header('X-GitHub-Event'));
$x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256='); $x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256=');
$content_type = $request->header('Content-Type'); $content_type = $request->header('Content-Type');
@ -310,30 +285,6 @@ public function normal(Request $request)
$return_payloads = collect([]); $return_payloads = collect([]);
$id = null; $id = null;
$x_github_delivery = $request->header('X-GitHub-Delivery'); $x_github_delivery = $request->header('X-GitHub-Delivery');
if (app()->isDownForMaintenance()) {
$epoch = now()->valueOf();
$files = Storage::disk('webhooks-during-maintenance')->files();
$github_delivery_found = collect($files)->filter(function ($file) use ($x_github_delivery) {
return Str::contains($file, $x_github_delivery);
})->first();
if ($github_delivery_found) {
return;
}
$data = [
'attributes' => $request->attributes->all(),
'request' => $request->request->all(),
'query' => $request->query->all(),
'server' => $request->server->all(),
'files' => $request->files->all(),
'cookies' => $request->cookies->all(),
'headers' => $request->headers->all(),
'content' => $request->getContent(),
];
$json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::normal_{$x_github_delivery}", $json);
return;
}
$x_github_event = Str::lower($request->header('X-GitHub-Event')); $x_github_event = Str::lower($request->header('X-GitHub-Event'));
$x_github_hook_installation_target_id = $request->header('X-GitHub-Hook-Installation-Target-Id'); $x_github_hook_installation_target_id = $request->header('X-GitHub-Hook-Installation-Target-Id');
$x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256='); $x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256=');
@ -624,23 +575,6 @@ public function install(Request $request)
{ {
try { try {
$installation_id = $request->get('installation_id'); $installation_id = $request->get('installation_id');
if (app()->isDownForMaintenance()) {
$epoch = now()->valueOf();
$data = [
'attributes' => $request->attributes->all(),
'request' => $request->request->all(),
'query' => $request->query->all(),
'server' => $request->server->all(),
'files' => $request->files->all(),
'cookies' => $request->cookies->all(),
'headers' => $request->headers->all(),
'content' => $request->getContent(),
];
$json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::install_{$installation_id}", $json);
return;
}
$source = $request->get('source'); $source = $request->get('source');
$setup_action = $request->get('setup_action'); $setup_action = $request->get('setup_action');
$github_app = GithubApp::where('uuid', $source)->firstOrFail(); $github_app = GithubApp::where('uuid', $source)->firstOrFail();

View file

@ -7,7 +7,6 @@
use App\Models\ApplicationPreview; use App\Models\ApplicationPreview;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
@ -16,24 +15,6 @@ class Gitlab extends Controller
public function manual(Request $request) public function manual(Request $request)
{ {
try { try {
if (app()->isDownForMaintenance()) {
$epoch = now()->valueOf();
$data = [
'attributes' => $request->attributes->all(),
'request' => $request->request->all(),
'query' => $request->query->all(),
'server' => $request->server->all(),
'files' => $request->files->all(),
'cookies' => $request->cookies->all(),
'headers' => $request->headers->all(),
'content' => $request->getContent(),
];
$json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Gitlab::manual_gitlab", $json);
return;
}
$return_payloads = collect([]); $return_payloads = collect([]);
$payload = $request->collect(); $payload = $request->collect();
$headers = $request->headers->all(); $headers = $request->headers->all();

View file

@ -6,7 +6,6 @@
use App\Jobs\StripeProcessJob; use App\Jobs\StripeProcessJob;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class Stripe extends Controller class Stripe extends Controller
{ {
@ -20,23 +19,6 @@ public function events(Request $request)
$signature, $signature,
$webhookSecret $webhookSecret
); );
if (app()->isDownForMaintenance()) {
$epoch = now()->valueOf();
$data = [
'attributes' => $request->attributes->all(),
'request' => $request->request->all(),
'query' => $request->query->all(),
'server' => $request->server->all(),
'files' => $request->files->all(),
'cookies' => $request->cookies->all(),
'headers' => $request->headers->all(),
'content' => $request->getContent(),
];
$json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Stripe::events_stripe", $json);
return response('Webhook received. Cool cool cool cool cool.', 200);
}
StripeProcessJob::dispatch($event); StripeProcessJob::dispatch($event);
return response('Webhook received. Cool cool cool cool cool.', 200); return response('Webhook received. Cool cool cool cool cool.', 200);

View file

@ -1,48 +0,0 @@
<?php
namespace App\Listeners;
use Illuminate\Foundation\Events\MaintenanceModeDisabled as EventsMaintenanceModeDisabled;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
class MaintenanceModeDisabledNotification
{
public function __construct() {}
public function handle(EventsMaintenanceModeDisabled $event): void
{
$files = Storage::disk('webhooks-during-maintenance')->files();
$files = collect($files);
$files = $files->sort();
foreach ($files as $file) {
$content = Storage::disk('webhooks-during-maintenance')->get($file);
$data = json_decode($content, true);
$symfonyRequest = new SymfonyRequest(
$data['query'],
$data['request'],
$data['attributes'],
$data['cookies'],
$data['files'],
$data['server'],
$data['content']
);
foreach ($data['headers'] as $key => $value) {
$symfonyRequest->headers->set($key, $value);
}
$request = Request::createFromBase($symfonyRequest);
$endpoint = str($file)->after('_')->beforeLast('_')->value();
$class = "App\Http\Controllers\Webhook\\".ucfirst(str($endpoint)->before('::')->value());
$method = str($endpoint)->after('::')->value();
try {
$instance = new $class;
$instance->$method($request);
} catch (\Throwable $th) {
} finally {
Storage::disk('webhooks-during-maintenance')->delete($file);
}
}
}
}

View file

@ -1,21 +0,0 @@
<?php
namespace App\Listeners;
use Illuminate\Foundation\Events\MaintenanceModeEnabled as EventsMaintenanceModeEnabled;
class MaintenanceModeEnabledNotification
{
/**
* Create the event listener.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*/
public function handle(EventsMaintenanceModeEnabled $event): void {}
}

View file

@ -2,10 +2,6 @@
namespace App\Providers; namespace App\Providers;
use App\Listeners\MaintenanceModeDisabledNotification;
use App\Listeners\MaintenanceModeEnabledNotification;
use Illuminate\Foundation\Events\MaintenanceModeDisabled;
use Illuminate\Foundation\Events\MaintenanceModeEnabled;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use SocialiteProviders\Authentik\AuthentikExtendSocialite; use SocialiteProviders\Authentik\AuthentikExtendSocialite;
use SocialiteProviders\Azure\AzureExtendSocialite; use SocialiteProviders\Azure\AzureExtendSocialite;
@ -19,12 +15,6 @@
class EventServiceProvider extends ServiceProvider class EventServiceProvider extends ServiceProvider
{ {
protected $listen = [ protected $listen = [
MaintenanceModeEnabled::class => [
MaintenanceModeEnabledNotification::class,
],
MaintenanceModeDisabled::class => [
MaintenanceModeDisabledNotification::class,
],
SocialiteWasCalled::class => [ SocialiteWasCalled::class => [
AzureExtendSocialite::class.'@handle', AzureExtendSocialite::class.'@handle',
AuthentikExtendSocialite::class.'@handle', AuthentikExtendSocialite::class.'@handle',

View file

@ -35,13 +35,6 @@
'throw' => false, 'throw' => false,
], ],
'webhooks-during-maintenance' => [
'driver' => 'local',
'root' => storage_path('app/webhooks-during-maintenance'),
'visibility' => 'private',
'throw' => false,
],
'public' => [ 'public' => [
'driver' => 'local', 'driver' => 'local',
'root' => storage_path('app/public'), 'root' => storage_path('app/public'),