Add Organizations::Stateful concern with state machine
What does this MR do and why?
This MR does two things:
1. Introduce Organizations::Stateful
Introduces an Organizations::Stateful concern modelled after Namespaces::Stateful, but stripped of concepts that don't apply to organizations (ancestor hierarchy, archival, transfers, state preservation).
States
| Value | Name | Description |
|---|---|---|
| 0 | active |
Default. Organization is fully operational. |
| 1 | deletion_scheduled |
Soft-deleted. Invisible to non-admins. Reversible. |
| 2 | deletion_in_progress |
Hard-deletion worker is running. |
Events
| Event | From | To |
|---|---|---|
schedule_deletion |
active |
deletion_scheduled |
start_deletion |
deletion_scheduled |
deletion_in_progress |
cancel_deletion |
deletion_scheduled / deletion_in_progress |
active |
reschedule_deletion |
deletion_in_progress |
deletion_scheduled |
Key differences from Namespaces::Stateful
- No ancestor hierarchy, archival, state preservation, or transfer
deletion_scheduled_atstored in a dedicated typed column (not JSONB)- Cancel always returns to
active
Model changes
Organizations::OrganizationincludesOrganizations::Statefuland delegatesdeletion_error/deletion_error=toorganization_detail
2. Extract shared Stateful:: concerns
Namespaces::Stateful and Organizations::Stateful share significant identical logic. This extracts the common parts into a top-level Stateful namespace under app/models/concerns/stateful/ so both domain concerns include it, eliminating the duplication.
What was extracted
| Module | Extracted methods |
|---|---|
Stateful::TransitionContext |
transition_args, transition_user |
Stateful::TransitionCallbacks |
update_state_metadata, set_deletion_schedule_data, clear_deletion_schedule_data, set_deletion_error_data, update_state_metadata_on_failure, build_transition_error_message |
Stateful::TransitionValidation |
ensure_transition_user |
Stateful::TransitionLogging |
log_transition, log_transition_failure |
Template methods
The two places where domain-specific knowledge is needed are bridged by two template methods that each including concern defines:
stateful_detail— returns the associated detail record (namespace_detailsororganization_detail)stateful_log_metadata— returns the base log hash (e.g.{ message: 'Namespace state transition', namespace_id: id })
Side-effect: standardised logging key in Namespaces::Stateful
Namespaces::Stateful::TransitionLogging was using the deprecated user_id: log key. The shared Stateful::TransitionLogging uses Labkit::Fields::GL_USER_ID consistently, fixing this as part of the extraction.
Files changed
New (shared concerns)
app/models/concerns/stateful/transition_context.rbapp/models/concerns/stateful/transition_callbacks.rbapp/models/concerns/stateful/transition_validation.rbapp/models/concerns/stateful/transition_logging.rb
New (Organizations::Stateful main concern)
app/models/concerns/organizations/stateful.rb— includes all 4 shared modules directly; definesstateful_detailandstateful_log_metadata
Modified (Namespaces::Stateful)
app/models/concerns/namespaces/stateful.rb— replacesinclude TransitionContext/include TransitionLoggingwith the shared modules; addsstateful_detailandstateful_log_metadataapp/models/concerns/namespaces/stateful/transition_callbacks.rb— nowinclude ::Stateful::TransitionCallbacks; retains transfer-only methodsapp/models/concerns/namespaces/stateful/transition_validation.rb— nowinclude ::Stateful::TransitionValidation; retainsvalidate_ancestors_state
Deleted (replaced by shared modules)
app/models/concerns/namespaces/stateful/transition_context.rbapp/models/concerns/namespaces/stateful/transition_logging.rbapp/models/concerns/organizations/stateful/transition_context.rbapp/models/concerns/organizations/stateful/transition_callbacks.rbapp/models/concerns/organizations/stateful/transition_logging.rbapp/models/concerns/organizations/stateful/transition_validation.rb
Config
config/bounded_contexts.yml— registersStatefulunderplatform:(required byGitlab/BoundedContextsRuboCop cop)
Specs
spec/models/concerns/organizations/stateful_spec.rb— enum, state machine states, valid/rejected transitionsspec/models/concerns/stateful/transition_context_spec.rbspec/models/concerns/stateful/transition_validation_spec.rbspec/models/concerns/stateful/transition_callbacks_spec.rbspec/models/concerns/stateful/transition_logging_spec.rbspec/models/concerns/namespaces/stateful/transition_logging_spec.rb— updated toLabkit::Fields::GL_USER_ID
Depends on Add state to organizations and organization_det... (!230540 - merged) • Rémy Coutable • 19.0 (adds state, deletion_scheduled_at, state_metadata columns).
Part of Add Organizations::Stateful concern with state ... (#594306 - closed) • Rémy Coutable • 19.0
MR acceptance checklist
- I have evaluated the MR acceptance checklist for this MR.