Loading
Stamp deploy timestamps on CD rollout environments
What does this MR do and why?
The organization CD environments page (route /o/:organization_path/-/deploy/environments) rendered placeholder dashes for the Release, Last deploy, and By fields on every environment card, even after rollouts completed.
The cause: the cd_rollout_environments columns started_at and finished_at were never written by any code path. This MR adds timestamp stamping when a rollout environment changes state, mirroring what Cd::Rollout and Cd::Deployment already do.
This is behind the existing ai_native_deploy experimental feature flag. No new flag, no migration.
Root cause analysis
- The environment card (
ee/app/assets/javascripts/cd/components/environment_card.vue) only attributes deploy metadata to rollout environments that havefinishedAtset. With none set, it renders the placeholder for all three fields. - Querying
/api/graphqlexactly as the page does confirmed the API returned the release name (versionSet.name) and deploying user correctly, butfinishedAt: nullon every rollout environment. This ruled out the frontend. - In the database, completed
cd_rollout_environmentsrows had NULLstarted_atandfinished_at, while the parentCd::Rolloutrow and the childCd::Deploymentrows both had timestamps. The gap was exactly this one model. Cd::RolloutandCd::Deploymentstamp their timestamps instate_machinesbefore_transitioncallbacks.Cd::RolloutEnvironmentuses a plain Rails enum, and nothing in the codebase wrote its timestamp columns.- Both of the model's state writers only wrote state. The
EnvironmentTransitionclass in the AutoFlow workflow-event path (added by !250702 (merged)) calledupdate!(state: target_state), and the model's ownsync_state_from_deployments!did the same. - !249670 (merged) (moves latest-finished selection to the backend) selects on the same
finished_atcolumn (scope :finished, -> { where.not(finished_at: nil) }), so it returns nothing until this column is populated. Its specs pass because factories setfinished_atexplicitly.
Solution
- New
Cd::RolloutEnvironment#transition_state!method: no-op when state is unchanged, setsstarted_at ||= Time.currenton enteringin_progress, setsfinished_at = Time.currenton entering a terminal state (completed,failed,cancelled). This mirrors thebefore_transitioncallbacks onCd::RolloutandCd::Deployment. - Both state writers now route through it:
sync_state_from_deployments!andCd::Rollouts::WorkflowEvents::EnvironmentTransition(previouslyupdate!(state: target_state)). - Specs cover
started_atstamping,started_atpreservation across re-entry,finished_atfor each terminal state, no-op on unchanged state, and both writer paths. - Deliberately no backfill. Rows finished before this change keep NULL
finished_at, and their cards keep the placeholder until the next rollout. The feature is behind the experimentalai_native_deployflag. If reviewers think existing data warrants it, a post-deployment data migration could derivefinished_atfrom each row's deployments or parent rollout.
References
In chronological order of the findings:
- !244679 (merged) introduced the environment card with client-side latest-finished selection filtering on
finishedAt. - !250702 (merged) (merged) added the AutoFlow workflow-event transitions that update rollout environment state but not timestamps, which is where the gap lives.
- https://gitlab.com/gitlab-org/gitlab/-/work_items/617189 reported environment data not rendering on the environments index page during the CD demo on 2026-08-14.
- !249670 (merged) (open) moves the latest-finished selection to the backend using the same
finished_atcriterion, so it depends on this fix to return data.
How to set up and validate locally
- Enable the
ai_native_deployfeature flag:Feature.enable(:ai_native_deploy) - Set up a deploy driver and seed data. For example, use the simulated driver from !250187 (closed), or the Argo Rollouts driver with a real cluster.
- Run a rollout to completion.
- Check the rollout environment rows:
Cd::Rollout.last.rollout_environments.pluck(:state, :started_at, :finished_at)shows timestamps. - Open the organization environments page and confirm the environment cards show Release, Last deploy, and By for the deployed environments.