-
Notifications
You must be signed in to change notification settings - Fork 245
fix: keep catalog push alive when deletion checks fail #2314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6f31c2e
a4f8bf6
6380543
ecf6f0f
222be1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -179,9 +179,19 @@ export async function checkFeatureDeleteInfo( | |
| } | ||
|
|
||
| // Check API for product references | ||
| const response = await getFeatureDeletionInfo({ secretKey, featureId }); | ||
| let response; | ||
| try { | ||
| response = await getFeatureDeletionInfo({ secretKey, featureId }); | ||
| } catch { | ||
| return { | ||
| id: featureId, | ||
| canDelete: false, | ||
| reason: "deletion_check_failed", | ||
| featureType, | ||
| }; | ||
| } | ||
|
|
||
| if (response && response.totalCount > 0) { | ||
| if (response && response.totalCount > 0) { | ||
| return { | ||
| id: featureId, | ||
| canDelete: false, | ||
|
|
@@ -204,22 +214,27 @@ export async function checkFeatureDeleteInfo( | |
| // Check if a plan can be deleted | ||
| async function checkPlanDeleteInfo(planId: string): Promise<PlanDeleteInfo> { | ||
| const secretKey = getSecretKey(); | ||
| const response = await getPlanDeletionInfo({ secretKey, planId }); | ||
| try { | ||
| const response = await getPlanDeletionInfo({ secretKey, planId }); | ||
|
|
||
| if (response && response.totalCount > 0) { | ||
| return { | ||
| id: planId, | ||
| canDelete: false, | ||
| customerCount: response.totalCount, | ||
| firstCustomerName: response.customerName, | ||
| }; | ||
| } | ||
|
|
||
| if (response && response.totalCount > 0) { | ||
| return { id: planId, canDelete: true, customerCount: 0 }; | ||
| } catch { | ||
| return { | ||
| id: planId, | ||
| canDelete: false, | ||
| customerCount: response.totalCount, | ||
| firstCustomerName: response.customerName, | ||
| customerCount: 0, | ||
| deletionCheckFailed: true, | ||
| }; | ||
| } | ||
|
Comment on lines
+230
to
237
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Prompt To Fix With AIThis is a comment left during a code review.
Path: packages/atmn/src/commands/push/push.ts
Line: 230-237
Comment:
**`deletionCheckFailed` flag is never read — fail-closed intent is not enforced**
When `getPlanDeletionInfo` throws, the catch block returns `canDelete: false, customerCount: 0, deletionCheckFailed: true`. Because `customerCount === 0`, `createPlanDeletePrompt` routes to `createPlanDeleteNoCustomersPrompt`, which presents **"Delete permanently"** as the default option. Nothing in `usePush.ts` (or anywhere else) reads `deletionCheckFailed` to override this behaviour, so if the user accepts the default the push will attempt to delete a plan whose customer status is genuinely unknown. The same pattern appears in `checkFeatureDeleteInfo`: `reason: "deletion_check_failed"` falls through `createFeatureDeletePrompt` to `createFeatureDeleteNoDepsPrompt`, again defaulting to "Delete permanently" as though the feature has no dependencies. Both cases contradict the PR's stated "fail closed and defer deletion" goal. At minimum the prompt should default to "Skip (keep as is)" when `deletionCheckFailed` is true; alternatively the failed-check entries could be excluded from `plansToDelete` / `featuresToDelete` entirely and silently deferred.
How can I resolve this? If you propose a fix, please make it concise. |
||
|
|
||
| return { | ||
| id: planId, | ||
| canDelete: true, | ||
| customerCount: 0, | ||
| }; | ||
| } | ||
|
|
||
| // Check if updating a plan will create a new version | ||
|
|
@@ -572,6 +587,8 @@ function normalizePlanForCompare( | |
| version: | ||
| license.version ?? licenseVersionFallbacks?.get(license.licensePlanId), | ||
| included: license.included ?? 0, | ||
| prepaidOnly: license.prepaidOnly ?? true, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: License comparison does not actually observe the new Prompt for AI agents |
||
| customize: license.customize, | ||
| })); | ||
|
|
||
| return result; | ||
|
|
@@ -644,6 +661,12 @@ function toApiCustomizePlan(customize: CustomizePlan): Record<string, unknown> { | |
| ...(customize.price.intervalCount !== undefined | ||
| ? { interval_count: customize.price.intervalCount } | ||
| : {}), | ||
| ...(customize.price.additionalCurrencies | ||
| ? { | ||
| additional_currencies: | ||
| customize.price.additionalCurrencies, | ||
| } | ||
| : {}), | ||
| } | ||
| : null, | ||
| } | ||
|
|
@@ -668,6 +691,15 @@ function toApiCustomizePlan(customize: CustomizePlan): Record<string, unknown> { | |
| : null, | ||
| } | ||
| : {}), | ||
| ...(customize.upsertLicenses !== undefined | ||
| ? { | ||
| upsert_licenses: transformPlanToApi({ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Variant license customization loses its optional fields and changes the meaning of omitted Prompt for AI agents |
||
| id: "license-customize", | ||
| name: "License customize", | ||
| licenses: customize.upsertLicenses, | ||
| }).licenses, | ||
| } | ||
| : {}), | ||
| }; | ||
| } | ||
|
|
||
|
|
@@ -678,6 +710,7 @@ function toCatalogVariantParams( | |
| ): Record<string, unknown> { | ||
| return { | ||
| variant_plan_id: variant.id, | ||
| ...(variant.version !== undefined ? { version: variant.version } : {}), | ||
| name: variant.name, | ||
| customize: toApiCustomizePlan(variant.customize ?? {}), | ||
| ...(intent === "create_version" ? { force_version: true } : {}), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ifstatement — it is left over from the refactor and the surrounding code is at a single-tab indent level.Prompt To Fix With AI
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!