[4.x] Create pending tenants with pending_since, improve --with-pending#1458
[4.x] Create pending tenants with pending_since, improve --with-pending#1458
Conversation
Pasing --with-pending, --with-pending=1 or --with-pending=true now makes tenant commands include pending tenants regardless of the include_in_queries config, and passing --with-pending=false, --with-pending=0 or --with-pending=foo makes the commands exclude pending tenants.
Cover that --with-pending can now accept values, and that the option takes precedence over include_in_queries config. Also simplify/improve existing assertions.
Instead of creating pending tenants without pending_since, letting job pipelines (e.g. TenantCreated) run, and only after that, setting the tenant's pending_since, set it while creating. This allows checking tenant's pending status accurately e.g. in the CreateDatabase job pipeline.
Now that tenants are created with pending_since right away, the migrate and seed database jobs need to include pending tenants for creating pending tenants to work fully. The jobs can still exclude pending tenants if $includePending is set to false. Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthrough
Changes
Sequence DiagramsequenceDiagram
participant CLI
participant Job as JobPipeline
participant Model as TenantModel
participant Migrate as MigrateDatabase Job
participant Seed as SeedDatabase Job
participant DB as Database
CLI->>Job: dispatch tenant lifecycle (with --with-pending)
Job->>Model: create tenant (attributes include pending_since when pending)
Model-->>Job: created (creating/created events fire if pending)
Job->>Migrate: run (--with-pending = Migrate::$includePending)
Migrate->>DB: run migrations
Job->>Seed: run (--with-pending = Seed::$includePending)
Seed->>DB: run seeders
DB-->>CLI: tenant DB ready
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1458 +/- ##
============================================
+ Coverage 85.84% 85.89% +0.04%
- Complexity 1163 1165 +2
============================================
Files 185 185
Lines 3399 3409 +10
============================================
+ Hits 2918 2928 +10
Misses 481 481 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/PendingTenantsTest.php (1)
195-239: 🧹 Nitpick | 🔵 TrivialConsider adding test coverage for invalid
--with-pendingvalues.The current tests cover truthy (
--with-pending,=true,=1) and falsy (=false,=0) values. Per the PR description, "invalid values treated as false" viafilter_var. Consider adding a test case with an invalid value like--with-pending=invalidto document this behavior.📝 Suggested test addition
test('commands exclude pending tenants when invalid --with-pending value is passed', function () { config(['tenancy.pending.include_in_queries' => true]); $pendingTenant = Tenant::createPending(); $normalTenant = Tenant::create(); // Invalid values are treated as false per filter_var behavior $command = pest()->artisan("tenants:run 'bar testing testing@test.test password foo' --with-pending=invalid"); $command->expectsOutputToContain("Tenant: {$normalTenant->getTenantKey()}"); $command->doesntExpectOutputToContain("Tenant: {$pendingTenant->getTenantKey()}"); $command->assertSuccessful(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/PendingTenantsTest.php` around lines 195 - 239, Add a new test in PendingTenantsTest.php that verifies invalid --with-pending values are treated as false: create one pending and one normal Tenant, set config(['tenancy.pending.include_in_queries' => true]), run the tenants:run command with the flag "--with-pending=invalid" (use pest()->artisan as in the existing tests), and assert that the normal tenant appears in output while the pending tenant does not; name the test similar to test('commands exclude pending tenants when invalid --with-pending value is passed') to match existing test style.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/Database/Concerns/HasPending.php`:
- Around line 52-60: The CreatingPendingTenant event is being dispatched before
the model is persisted, so listeners (especially with the GeneratesIds trait)
see a tenant without an ID; move the event dispatch to after the model is saved
so the ID is generated first: create the tenant with static::make(...) and call
$tenant->save(), then call event(new CreatingPendingTenant($tenant));
references: static::make, static::getPendingAttributes, $tenant->save(), and the
CreatingPendingTenant event.
---
Outside diff comments:
In `@tests/PendingTenantsTest.php`:
- Around line 195-239: Add a new test in PendingTenantsTest.php that verifies
invalid --with-pending values are treated as false: create one pending and one
normal Tenant, set config(['tenancy.pending.include_in_queries' => true]), run
the tenants:run command with the flag "--with-pending=invalid" (use
pest()->artisan as in the existing tests), and assert that the normal tenant
appears in output while the pending tenant does not; name the test similar to
test('commands exclude pending tenants when invalid --with-pending value is
passed') to match existing test style.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 73bb6188-dcf8-449c-82e3-b0795c3952ca
📒 Files selected for processing (5)
src/Concerns/HasTenantOptions.phpsrc/Database/Concerns/HasPending.phpsrc/Jobs/MigrateDatabase.phpsrc/Jobs/SeedDatabase.phptests/PendingTenantsTest.php
Include --with-pending=foo as the fasly option in the falsy --with-pending test.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/Database/Concerns/HasPending.php`:
- Around line 64-68: The createPending() method currently uses array_merge([...
'pending_since' => now()->timestamp], static::getPendingAttributes($attributes),
$attributes) which allows callers to override 'pending_since' (e.g., passing
null) and produce a non-pending tenant; modify createPending() so the enforced
'pending_since' cannot be overwritten—either remove 'pending_since' from the
incoming $attributes before merging, or perform the merge so the timestamp is
applied last (or use array union + to prefer the existing timestamp), ensuring
createPending() always sets a non-null pending_since and thus always creates a
pending tenant; update any references to getPendingAttributes(...) if needed to
avoid reintroducing the override.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 208319f4-ed48-45b1-a11f-9a4cf977ffb7
📒 Files selected for processing (2)
src/Database/Concerns/HasPending.phptests/PendingTenantsTest.php
Reverting the HasPending changes (in createPending(), create tenant without pending_since, and only after that, update the tenant to give it pending_since) makes the test fail.
…reation Ensures that createPending always creates tenants with pending_since set to the current timestamp.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/Database/Concerns/HasPending.php (1)
32-35:⚠️ Potential issue | 🟠 Major
CreatingPendingTenantnow fires before the tenant is persisted.Line 32 moves this public event into Eloquent’s
creatingphase, so listeners now run before the tenant row exists in storage. That is a behavioral break for any listener that queries the tenant, depends on DB-populated state, or expects the record to be readable by key. Please either keep this dispatch on the post-save path or document the timing change as a breaking change.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Database/Concerns/HasPending.php` around lines 32 - 35, The CreatingPendingTenant event is now dispatched during Eloquent’s creating phase (static::creating) which runs before the tenant row is persisted; to restore previous behavior move the dispatch into the post-save lifecycle (e.g., static::created or static::saved) so listeners see a persisted record, i.e. replace the static::creating(...) handler with a static::created(...) or static::saved(...) handler that checks $tenant->pending() and fires event(new CreatingPendingTenant($tenant)); if this timing change is intentional instead update documentation/changelog to mark it as a breaking change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/Database/Concerns/HasPending.php`:
- Around line 32-35: The CreatingPendingTenant event is now dispatched during
Eloquent’s creating phase (static::creating) which runs before the tenant row is
persisted; to restore previous behavior move the dispatch into the post-save
lifecycle (e.g., static::created or static::saved) so listeners see a persisted
record, i.e. replace the static::creating(...) handler with a
static::created(...) or static::saved(...) handler that checks
$tenant->pending() and fires event(new CreatingPendingTenant($tenant)); if this
timing change is intentional instead update documentation/changelog to mark it
as a breaking change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 1e6c14c2-cc7b-4baf-b8a6-44fa8e7f29db
📒 Files selected for processing (2)
src/Database/Concerns/HasPending.phptests/PendingTenantsTest.php
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/Concerns/HasTenantOptions.php`:
- Line 21: Remove or resolve the inline TODO comment on the InputOption
declaration for '--with-pending' in HasTenantOptions.php: either delete the "//
todo@pending mention in docs" comment, replace it with a reference to the
documentation page or issue tracker (e.g., "see docs:
<doc-path-or-issue-number>"), or open and reference a new issue tracking the
docs update so the reminder is not left in source; update the comment text to
include the issue/PR number or documentation path next to the
InputOption('with-pending', ...) declaration.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7d952e8d-aafd-440e-93c9-215d054af511
📒 Files selected for processing (5)
src/Concerns/HasTenantOptions.phpsrc/Database/Concerns/HasPending.phpsrc/Jobs/MigrateDatabase.phpsrc/Jobs/SeedDatabase.phptests/PendingTenantsTest.php
Resolved in archtechx/tenancy-docs#5
Pending tenants aren't getting their
pending_sinceset until they're created completely (e.g. their DB was created, migrated and seeded -- first, the tenant is created fully, and only after that, the tenant is updated to havepending_since). This is a problem if someone wants to e.g. add a job to theDatabaseCreatedjob pipeline that would check$this->tenant->pending(). Since at the point ofDatabaseCreated, the tenant'spending_sinceisn't set yet,$this->tenant->pending()returnsfalse, even for tenants created usingcreatePending(). So instead of letting the pending tenant get fully created, and only after that, setting itspending_since(usingupdate()), we now setpending_sinceincreate().CreatingPendingTenantis now dispatched from thestatic::creatinghook, andPendingTenantCreatedis dispatched fromstatic::createdfor consistency.Setting
pending_sinceright increate()made theMigrateDatabaseandSeedDatabasejobs exclude the pending tenants during their creation if thetenancy.pending.include_in_queriesconfig was set tofalse-- in that case, these jobs would never migrate or seed the databases of pending tenants. So these jobs now pass--with-pendingto their underlying commands, with the value set in their$includePendingstatic property (trueby default). This overrides thetenancy.pending.include_in_queriesconfig -- unless the$includePendingproperties are set tofalse, these jobs will always include pending tenants.The
--with-pendingtenant command option originally worked just to opt-in for including pending tenants in the command. Now,--with-pendingcan accept values (true/1orfalse/0), so e.g.tenants:run foowith--with-pending/--with-pending=true/--with-pending=1includes pending tenantstenants:run foowith--with-pending=false/--with-pending=0excludes pending tenants (also--with-pending=foobar-- invalid input, consideredfalse)Passing
--with-pendingmakes the command bypass thetenancy.pending.include_in_queriesconfig (so e.g. iftenancy.pending.include_in_queriesis set totrue, and--with-pending=falseis passed to a command, the command will exclude pending tenants). When--with-pendingis not passed, the command will include or exclude pending tenants based on thetenancy.pending.include_in_queriesconfig.In tenancy-docs, I opened a PR with a note about the
--with-pendingand job changes (https://github.com/archtechx/tenancy-docs/pull/5).// todo@pending mention in docsfromHasTenantOptionsafter the docs PR gets reviewed/mergedSummary by CodeRabbit
New Features
--with-pendingaccepts explicit boolean-like values; when omitted, existing configuration is usedTests
--with-pendingparsing, job-driven migration/seeding for pending tenants, and lifecycle/job integration tests