Deployments AE: add group dimension
Background
The EI dashboard needs deployment counts broken down per group ("Deployment frequency by group").
Analytics::AggregationEngines::Deployments already provides the deployment count and monthly
trends, but has no group dimension — today a per-group breakdown costs one scoped request per
group, since prepare_base_aggregation_scope ORs the requested objects into a single result set
instead of breaking it down.
Deployments are bound to projects, so "group" is defined here as the immediate parent namespace
of the deployment's project. The siphon_deployments table carries no group column, but its
traversal_path column is the full path including the organization —
{organization_id}/{root_ns_id}/.../{parent_group_id}/{project_namespace_id}/ — so the immediate
parent id is extractable in-query. Engine only; no schema or MV changes.
Proposal
group dimension (engine only)
Extract the second-to-last path segment (the segment before the project namespace id) and resolve
the Group association by id:
column :group_id, :integer, -> {
sql("toUInt64(splitByChar('/', traversal_path)[-3])")
}, description: 'Immediate parent group of the deployment project', association: {
finder: ->(ids) { Group.where(id: ids).index_by(&:id) }
}[-3] because the path is /-terminated (the last split element is the empty string and [-2]
is the project namespace id). The organization prefix in traversal_path does not affect the
extraction — only a fixed offset from the end is read.
The dimension complements (not replaces) scoping: scoping restricts the data set to the requested
groups/projects, while the dimension breaks that result down per immediate parent group in one
query (count per group id, combinable with the existing finished_at/created_at date buckets
and the rate metrics).
Caveats
- Personal-namespace projects: for a project directly under a user namespace the path is
{organization_id}/{user_namespace_id}/{project_namespace_id}/, so[-3]extracts a user namespace id that resolves to noGroup— the association finder returns nil. Decide whether to surface these rows as a nil bucket or exclude them from the dimension, and cover the choice with a spec. - No rollup: "immediate parent" means a project in a nested subgroup is attributed to that
subgroup, not to its top-level group. This matches the metric definition; a depth-parameterized
rollup is the shared
groupdimension helper planned for theMergeRequests/AiUsageEventsengines (#605525, #605518) and can be adopted here in a follow-up if rollup semantics are needed.
Acceptance criteria
-
group_iddimension extracting the immediate parent namespace id fromtraversal_path, with theGroupassociation finder. - Specs: per-group deployment count breakdown with association resolution; subgroup projects
attributed to the subgroup (not the root group); personal-namespace rows behave as decided
above; dimension combined with the existing monthly
date_bucketand range filters.
Metrics unblocked
Deployment frequency by group; per-group breakdowns of the existing deployment metrics (success/failure/canceled rates, duration quantiles).