feat(stats): add --no-discord flag to stats:experiment-funnel (#606)

## What

Adds a `--no-discord` flag to `stats:experiment-funnel` so the
per-variant report can be run **on demand (e.g. in production) and only
printed to the console**, without posting to the Discord channel.

```bash
php artisan stats:experiment-funnel --no-discord
```

## Why

Handy for ad-hoc checks of the live experiment without spamming the
ops/Stripe Discord channel. The scheduled weekly run (and any run
without the flag) still posts to Discord exactly as before — default
behaviour is unchanged.

## Notes
- The console table already prints before the Discord step; the flag
just short-circuits the `->send()` and prints `Skipped Discord
(--no-discord).`
- Test added: with `--no-discord`, the command succeeds, prints the
table, and `Http::assertNothingSent()`.
- Pint + Larastan + the command's Pest suite green.

> Tip: the command queries the default DB connection, so to see
**production** numbers run it inside the prod container (e.g. via the
Coolify terminal).
This commit is contained in:
Víctor Falcón 2026-06-29 12:31:29 +02:00 committed by GitHub
parent 09d6e8ee6c
commit 1db2871398
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 1 deletions

View File

@ -10,7 +10,7 @@ use Illuminate\Console\Command;
class SendExperimentFunnelReportCommand extends Command
{
protected $signature = 'stats:experiment-funnel';
protected $signature = 'stats:experiment-funnel {--no-discord : Print the report to the console only, without posting to Discord}';
protected $description = 'Post the trial/pricing experiment funnel (per variant) to Discord';
@ -39,6 +39,12 @@ class SendExperimentFunnelReportCommand extends Command
$this->line($line);
}
if ($this->option('no-discord')) {
$this->info('Skipped Discord (--no-discord).');
return self::SUCCESS;
}
$webhookUrl = config('services.discord.ai_cohort_webhook_url')
?: config('services.discord.webhook_url');

View File

@ -168,3 +168,19 @@ it('does not post when the experiment has not started', function () {
Http::assertNothingSent();
});
it('prints the report without posting to discord when --no-discord is set', function () {
config(['services.discord.ai_cohort_webhook_url' => 'https://discord.test/hook']);
Http::fake(['discord.test/*' => Http::response('', 204)]);
experimentUser(SubscriptionExperiment::CONTROL, CarbonImmutable::parse('2026-06-05'), [
'status' => 'active',
'at' => CarbonImmutable::parse('2026-06-05'),
]);
artisan('stats:experiment-funnel', ['--no-discord' => true])
->expectsOutputToContain('control')
->assertSuccessful();
Http::assertNothingSent();
});