Add user filter and dimension to Pipelines aggregation engine

What does this MR do and why?

The DAP Impact Dashboard needs to let leaders filter and group dashboard data by an arbitrary team (a set of people), not only by GitLab group or project. Issue https://gitlab.com/gitlab-org/gitlab/-/issues/611201 is being delivered as four merge requests, one per ClickHouse aggregation engine that was missing by-user support. This MR covers the Pipelines engine.

The siphon_p_ci_pipelines table stores user_id as Nullable(Int64), and the engine had no way to filter or group by it. Without this, a team-scoped view of pipelines silently fell back to unfiltered data.

Changes:

  • Adds column :user_id, :integer, description: 'User who triggered the pipeline', association: true and exact_match :user_id, :string, description: 'Filter by one or many user Global IDs', formatter: gid_formatter to ee/app/models/analytics/aggregation_engines/pipelines.rb.
  • This adds a new userId argument on Analytics.pipelines and a new user field of type UserCore on PipelinesAggregationResponseDimensions, both generated from the engine declaration.
  • user_id is not part of the table's sort key, so the aggregation framework wraps it in argMax for deduplication, matching how the other non-key columns on this ReplacingMergeTree table are already handled.
  • Nullable column: pipelines started by a schedule, a trigger token, or an integration have no user_id. Those rows group under a null key and the user field resolves to null. Specs cover that case.
  • This is the engine's second association dimension, alongside the existing project_id. That is safe because BatchLoader::GraphQL.for(...).batch(key: dimension) already includes the key: fix from commit 890b49c3660c. Without that key, every association field on an engine would share one batch and ids would get looked up against the wrong model.
  • No migration, schema change, or feature flag: the column already existed in ClickHouse.
  • Regenerates doc/api/graphql/reference/_index.md and public/-/graphql/introspection_result.json.
  • Spec coverage: dimension examples for :user_id and the :user association alias (including a row with no user), a filter block for a single Global ID and an array of Global IDs, and a GraphQL request context that filters by a user Global ID and groups by the resolved association.

Out of scope

How to set up and validate locally

  1. Query the new argument and dimension in GraphiQL:

    query {
      group(fullPath: "gitlab-org") {
        analytics {
          pipelines(userId: ["gid://gitlab/User/1"]) {
            aggregated { nodes { dimensions { user { id username } } totalCount } }
          }
        }
      }
    }
  2. Run the specs for this engine:

    bundle exec rspec ee/spec/models/analytics/aggregation_engines/pipelines_spec.rb ee/spec/requests/api/graphql/analytics/pipelines_spec.rb
  3. Confirm the GraphQL docs are up to date:

    bundle exec rake gitlab:graphql:check_docs
  4. Confirm the introspection JSON is up to date:

    bundle exec rake gitlab:graphql:check_introspection_sync

References

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Merge request reports

Loading
Loading