🐛 Fixed orphaned Stripe prices when importing members by tier#28955
🐛 Fixed orphaned Stripe prices when importing members by tier#28955Aubaid12 wants to merge 1 commit into
Conversation
fixes TryGhost#22115 When importing members with an import_tier, the Stripe utils create a new price on the tier's product and then update the customer's subscription to use it. If that update threw (Stripe rejecting it, or a schedule-managed subscription), the just-created price was never recorded for archival and was left orphaned on the product, accumulating across imports. As suggested on the issue, the price is now archived if the subscription update fails, and the original error is surfaced regardless of whether archiving succeeds.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughIn 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 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. Comment |
fixes #22115
Why
@9larsons reproduced this on main and tagged it bug + help wanted. Importing members by tier could leave orphaned, unused prices piling up on a Stripe product.
What it does
When you import a member with an
import_tierand a Stripe customer,forceStripeSubscriptionToProduct()creates a new price on the tier's product, then updates the customer's subscription to use it. That new price is only recorded for archival (it gets cleaned up after the import) once the update succeeds. So if the update throws, for example because Stripe rejects it or the subscription is schedule-managed, the price is never archived and stays orphaned on the product, building up on every import.The subscription update is now wrapped so that on failure the just-created price is archived before the error propagates. The original error always surfaces, even if archiving itself fails (that's logged as a warning). This is what @9larsons suggested on the issue: "archive the just-created price if the update throws."
Why Ghost users/developers need it
Site owners and integrations that import paid members by tier end up with a growing list of unused prices on their Stripe products, which is confusing to manage. This keeps the price list clean.
Tests
5 unit cases covering the full create → update → archive path: a successful update does not archive; a failed update archives the new price; the original error still surfaces if archiving also fails; an existing-price update failure does not archive (nothing was created); and a createPrice failure does not update or archive. All 17 tests in the file pass.