Bug: BillingAccountGitlabInstance last_used_license not updated when instance re-activates under a different BillingAccount
Problem
When a self-managed instance activates with subscription A (under BillingAccount X) and later re-activates with subscription B (under a different BillingAccount Y), the existing BillingAccountGitlabInstance record is not updated. Instead, a new record is created with a random cdot_gitlab_instance_uid, leaving the original record stale — still pointing to the old/cancelled subscription.
This causes the Consumer Resolver to fail with:
Unable to find billing source for the instance <uuid>
because SubscriptionsFinder looks up the BillingAccountGitlabInstance by cdot_gitlab_instance_uid (which matches the original instance_identifier), finds the stale record, and resolves a cancelled Zuora subscription — returning {}.
Root Cause
In AccountGitlabInstance#find_or_create_from_instance_identifier (app/models/concerns/account_gitlab_instance.rb):
def find_or_create_from_instance_identifier(account:, instance_identifier:, last_used_license:)
instance = create_with(cdot_gitlab_instance_uid: instance_identifier)
.find_or_initialize_by(**find_or_init_params(account, instance_identifier))
instance.last_used_license = last_used_license
begin
return instance if instance.save
raise ActiveRecord::RecordNotUnique if instance.errors.details[:cdot_gitlab_instance_uid].any? do |e|
e[:error] == :taken
end
rescue ActiveRecord::RecordNotUnique
instance.cdot_gitlab_instance_uid = SecureRandom.uuid # <-- new random UID assigned!
instance.save
end
instance
end
find_or_init_params for BillingAccountGitlabInstance scopes the lookup by billing_account + instance_identifier. When the billing account changes, no existing record is found, so a new one is initialized. Saving fails on the cdot_gitlab_instance_uid uniqueness constraint (the old record still holds the original UID). The rescue path then assigns a random UUID and saves a new record — leaving the old record untouched with a stale last_used_license.
Impact
- Customers who have re-activated their instance under a new/different subscription (e.g. after a subscription renewal that changed the Zuora account, or after activating a $0 trial subscription and then a paid one) cannot use their credits.
- Re-activating the activation code does not fix the issue because the stale
BillingAccountGitlabInstancerecord is never updated. - The
SubscriptionsFinderresolves the old cancelled subscription and returns no billing source.
Steps to Reproduce
- Instance activates with subscription A under BillingAccount X →
BillingAccountGitlabInstancecreated withcdot_gitlab_instance_uid = instance_identifier. - Instance re-activates with subscription B under BillingAccount Y (different account).
- A new
BillingAccountGitlabInstanceis created with a randomcdot_gitlab_instance_uid. - The old record (BillingAccount X,
cdot_gitlab_instance_uid = instance_identifier) remains withlast_used_licensepointing to the cancelled subscription A. - Consumer Resolver looks up by
cdot_gitlab_instance_uid = instance_identifier, finds the stale record, fails to resolve an active subscription → credits unavailable.
Proposed Fix
When saving a new BillingAccountGitlabInstance fails due to a cdot_gitlab_instance_uid uniqueness conflict, instead of creating a new record with a random UID, find the existing record by cdot_gitlab_instance_uid and update its last_used_license (and billing_account if changed).
References
- Related (but different) issue: #14626 (instance_id disambiguation for shared subscriptions)
app/models/concerns/account_gitlab_instance.rbapp/finders/billing/usage/self_managed/subscriptions_finder.rbapp/models/consumer/resolver.rb
Support Priority Score: (1, 0, 0, 2, 3, 3, 3, 2, 3, 2, 3) => 22