• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NIT-Administrative-Systems / SysDev-laravel-soa / 21224384457

21 Jan 2026 08:19PM UTC coverage: 39.779% (+0.8%) from 38.99%
21224384457

push

github

web-flow
feat: conditional webhooks (#186)

11 of 13 new or added lines in 4 files covered. (84.62%)

1 existing line in 1 file now uncovered.

288 of 724 relevant lines covered (39.78%)

14.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Console/Commands/EventHub/WebhookConfiguration.php
1
<?php
2

3
namespace Northwestern\SysDev\SOA\Console\Commands\EventHub;
4

5
use Illuminate\Console\Command;
6
use Illuminate\Console\ConfirmableTrait;
7
use Northwestern\SysDev\SOA\Console\Commands\Concerns\ConfirmsEventHubChanges;
8
use Northwestern\SysDev\SOA\EventHub;
9
use Northwestern\SysDev\SOA\Routing\EventHubWebhookRegistration;
10

11
use function Laravel\Prompts\confirm;
12
use function Laravel\Prompts\spin;
13

14
class WebhookConfiguration extends Command
15
{
16
    use ConfirmableTrait, ConfirmsEventHubChanges;
17

18
    protected $signature = 'eventhub:webhook:configure {--force}';
19

20
    protected $description = 'Configure webhook routes in EventHub';
21

22
    public function __construct(
23
        protected EventHub\Webhook $webhook_api,
24
        protected EventHubWebhookRegistration $hook_registry
25
    ) {
26
        parent::__construct();
×
27
    }
28

29
    public function handle(): int
30
    {
31
        if (! $this->confirmWebhookConfiguration()) {
×
32
            $this->components->error('Command aborted.');
×
33

34
            return self::FAILURE;
×
35
        }
36

37
        $force_delete = $this->option('force');
×
38

39
        $registered_hooks = spin(
×
40
            fn () => collect($this->webhook_api->listAll()['webhooks']),
×
41
            'Fetching existing webhooks...'
×
42
        );
×
43

44
        $registered_hooks = $registered_hooks->map(fn ($hook) => $hook['topicName'])->all();
×
45

46
        // We can remove stuff from this one as we touch them -- that we we know which still exist.
47
        $existing_hooks_updated = $registered_hooks;
×
48

49
        $desired_hooks = $this->hook_registry->getHooks();
×
50
        foreach ($desired_hooks as $hook) {
×
51
            $hook = $hook->toArray();
×
52

53
            // Remove from unmanaged list
54
            $existing_hooks_updated = array_diff($existing_hooks_updated, [$hook['topicName']]);
×
55

56
            $this->createOrUpdate($hook, $registered_hooks);
×
57
        }
58

59
        if (count($existing_hooks_updated) > 0) {
×
60
            $this->newLine();
×
61
            $this->components->error('The following webhooks are configured in EventHub but do not have a corresponding entry in the routes file:');
×
62
            $this->newLine();
×
63
            $this->components->bulletList($existing_hooks_updated);
×
64
            $this->newLine();
×
65

66
            $delete_unmanaged = $force_delete ?: confirm(
×
67
                label: 'Would you like to delete these unmanaged webhooks?',
×
68
                default: false,
×
69
                hint: 'This will remove webhooks not defined in your routes file.'
×
70
            );
×
71

72
            if ($delete_unmanaged === true) {
×
73
                foreach ($existing_hooks_updated as $hook_to_delete) {
×
74
                    $this->delete($hook_to_delete);
×
75
                }
76
            }
77
        }
78

79
        // Display status after the changes are made.
80
        $this->call('eventhub:webhook:status');
×
81

82
        return self::SUCCESS;
×
83
    }
84

85
    protected function createOrUpdate($hook, $registered_hooks)
86
    {
87
        $topicName = $hook['topicName'];
×
88

89
        try {
UNCOV
90
            if (in_array($hook['topicName'], $registered_hooks) === false) {
×
91
                // For new webhooks, use the active state from the
92
                // DTO if set, otherwise default to true.
NEW
93
                if (! array_key_exists('active', $hook)) {
×
NEW
94
                    $hook['active'] = true;
×
95
                }
96

97
                // Not allowed in the POST/PUT body
98
                unset($hook['topicName']);
×
99

100
                spin(
×
101
                    fn () => $this->webhook_api->create($topicName, $hook),
×
102
                    "Creating webhook for {$topicName}..."
×
103
                );
×
104

105
                $this->components->info("Created webhook for <bg=magenta;fg=white;options=bold> {$topicName} </>");
×
106
            } else {
107
                // For existing webhooks, enforce the active state if specified.
108
                // This allows `eventHubWebhookActiveWhen()` to control state.
109

110
                // Not allowed in the POST/PUT body
111
                unset($hook['topicName']);
×
112

113
                spin(
×
114
                    fn () => $this->webhook_api->updateConfig($topicName, $hook),
×
115
                    "Updating webhook for {$topicName}..."
×
116
                );
×
117

118
                $this->components->info("Updated webhook for <bg=magenta;fg=white;options=bold> {$topicName} </>");
×
119
            }
120
        } catch (EventHub\Exception\EventHubError $e) {
×
121
            $this->newLine();
×
122
            $this->components->error("Failed to update {$topicName}: {$e->getMessage()}");
×
123
            $this->newLine();
×
124
        }
125
    }
126

127
    protected function delete($queue_name)
128
    {
129
        try {
130
            spin(
×
131
                fn () => $this->webhook_api->delete($queue_name),
×
132
                "Deleting webhook for {$queue_name}..."
×
133
            );
×
134

135
            $this->components->info("Deleted webhook for <bg=magenta;fg=white;options=bold> {$queue_name} </>");
×
136
        } catch (EventHub\Exception\EventHubError $e) {
×
137
            $this->newLine();
×
138
            $this->components->error("Failed to delete {$queue_name}: {$e->getMessage()}");
×
139
            $this->newLine();
×
140
        }
141
    }
142
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc