Fix trial widget delayed on initial landing after registration

Summary

After a user completes trial registration, the trial is provisioned asynchronously. This causes a brief flash where the free-tier UI (free namespace icon, "Free" tier badge) is shown before the real trial data arrives from CustomersDot.

This MR implements Solution 3 from the issue discussion: a short-lived Rails.cache presence marker that allows in-scope surfaces to render the trial state optimistically until real data lands.

What Changed

Surface 1: Left-nav trial widget (StatusWidgetPresenter)

Added optimistic_trial_active? predicate:

  • Returns true only when (a) marker is active AND (b) no real trial yet exists
  • Real data always wins — the moment eligible_trial_active? is true, the optimistic branch is never taken
  • When active, trial_status derives dates from TrialDurationService (start = now, end = now + trial duration days)

Surface 2: Project/group home page free-tier badge (TrialsHelper#show_tier_badge_for_new_trial?)

Returns false when the pending trial marker is active, suppressing the badge during the window.

Guardrails

  • Marker written only on successful trial submission (never written on failure)
  • Optimistic branch taken only when marker active AND no real trial row exists
  • Real data always wins over fake data
  • Marker self-expires at 5 minutes — no cleanup code needed
  • Provisioning flow is completely unchanged

Screenshots/videos

Note that billing page is out of scope. We only care about landing page right after trial application, which is the project page

How to reproduce locally

Verifying that in-scope surfaces render trial state optimistically while the trial is still being provisioned. The natural race is a brief window between trial submission and CustomersDot returning real trial data, so it is impractical to catch by hand — instead, simulate the marker directly.

Setup

These are SaaS-only code paths. Enable SaaS simulation in your GDK:

echo 'GITLAB_SIMULATE_SAAS=1' >> env.runit
gdk restart

Fast path: simulate the marker

Pick a group you own that has no trial and no paid subscription. From rails console:

group = Group.find_by_full_path('your-group-path')

GitlabSubscriptions::Trials::PendingTrialMarker.set(group.id)
GitlabSubscriptions::Trials::PendingTrialMarker.active?(group.id)
# => true

Then load the group's home page and observe:

  1. The left-nav trial widget appears, showing roughly 30 days remaining (dates come from GitlabSubscriptions::TrialDurationService — start is today, end is today + duration days).
  2. The "Free" tier badge on the group/project home page is gone.

The marker TTL is CACHE_TTL = 5.minutes, so it self-expires. Reload after five minutes (or clear it manually with Rails.cache.delete("gitlab_subscriptions:trials:pending_trial_marker:#{group.id}")) and confirm the UI reverts to free-tier: badge returns, widget disappears.

What are the relevant issue numbers?

Related to https://gitlab.com/gitlab-org/gitlab/-/issues/587952

Edited by Doug Stull

Merge request reports

Loading
Loading