Thread resolved parameters through codegen and sort
What does this MR do and why?
This is MR 4 of 5 for parameterised field syntax.
MR 3 (!408 (merged)) added analyzer-level resolution that converts FieldFunction("finished", [Positional("daily")]) to ParameterizedField(Finished, [("granularity", "daily")]) and applies default parameter values to bare parameterisable fields. But the codegen layer completely ignored those resolved parameters: render_display_field dropped the Vec<(String, String)> by calling display_field.name(), then render_query_field matched on the bare string and always substituted hardcoded defaults. Similarly, graphql_sort_parameters always returned hardcoded {granularity: "weekly"} or {quantile: 0.95} regardless of what the user specified.
This MR threads the resolved parameters through both field codegen and sort codegen, giving users actual control over granularity and quantile values for the first time.
Field codegen
render_display_field now matches on ParameterizedField variants and renders the field name with its resolved parameters directly (e.g. finishedAt(granularity: "daily"), durationQuantile(quantile: 0.5)), recursing through AliasedDisplayField wrappers. For non-parameterised variants, rendering delegates to render_query_field as before.
The hardcoded startedAt, finishedAt, and durationQuantile match arms in PipelinesAnalyticsAnalyzer::render_query_field are removed since these fields are always ParameterizedField after resolution.
Sort parameter inheritance
Sort inherits parameters from the matching resolved dimension or metric rather than relying on per-source hardcoded values. For each sort field, build_aggregated_params looks up the corresponding ParameterizedField in dimensions/metrics by comparing base_field().dealias(), then passes the inherited (key, value) pairs through the graphql_sort_parameters trait method for source-level customisation.
The trait method signature changes from fn graphql_sort_parameters(&self, sort: &Sort) -> Option<&'static str> to fn graphql_sort_parameters(&self, sort: &Sort, inherited_params: &[(String, String)]) -> Vec<(String, String)>, returning structured data rather than a pre-formatted GraphQL string. The default passes inherited parameters through unchanged; sources can override to filter, transform, or extend parameters if needed. The PipelinesAnalyticsAnalyzer override is removed since the default does the right thing.
Code suggestions fix
This MR also fixes a latent bug where code suggestions sort by timestamp silently omitted the required granularity parameter because graphql_sort_parameters returned None for code suggestions. The backend requires parameters: {granularity: "monthly"} in the sort orderBy entry, and the new inheritance mechanism provides it automatically from the resolved dimension.
What this MR does NOT do
Compile output metadata (exposing resolved parameters per field in the serialised output) is deferred to MR 5.
References
- Parent issue: #130 (closed)
- MR 3 (depends on): !408 (merged)
- MR 2: !407 (merged)
- MR 1: !406 (merged)
- Design resolution: comment
How to set up and validate locally
cargo test-- all 696 tests should passcargo clippy-- should be cleancargo fmt --check-- should be clean
Manual testing via the Ruby extension
Build the native extension (re-run after any Rust changes):
cd glql_rb
bundle install
bundle exec rake compileUser-specified granularity flows through to GraphQL
mode: analytics
query: type = Pipeline and project = "gitlab-org/gitlab" and finished > -30d
dimensions: finished(daily), status
metrics: totalCount, successRate
sort: finished descTest via ruby extension
GLQL_QUERY='type = Pipeline and project = "gitlab-org/gitlab" and finished > -30d'
echo "q = Glql.compile('${GLQL_QUERY}', { mode: 'analytics', dimensions: 'finished(daily), status', metrics: 'totalCount, successRate', sort: 'finished desc' })[\"output\"]; puts q; exit" | bundle exec rake consoleExpected: The GraphQL output should contain finishedAt(granularity: "daily") in the dimensions block and parameters: {granularity: "daily"} in the orderBy entry.
Default granularity still works for bare dimensions
mode: analytics
query: type = Pipeline and project = "gitlab-org/gitlab" and finished > -30d
dimensions: finished, status
metrics: totalCount
sort: finished descTest via ruby extension
GLQL_QUERY='type = Pipeline and project = "gitlab-org/gitlab" and finished > -30d'
echo "q = Glql.compile('${GLQL_QUERY}', { mode: 'analytics', dimensions: 'finished, status', metrics: 'totalCount', sort: 'finished desc' })[\"output\"]; puts q; exit" | bundle exec rake consoleExpected: The GraphQL output should contain finishedAt(granularity: "weekly") (the default) and parameters: {granularity: "weekly"} in the orderBy.
Custom quantile value
mode: analytics
query: type = Pipeline and project = "gitlab-org/gitlab" and finished > -30d
dimensions: ref
metrics: totalCount, durationQuantile(0.5)
sort: durationQuantile descTest via ruby extension
GLQL_QUERY='type = Pipeline and project = "gitlab-org/gitlab" and finished > -30d'
echo "q = Glql.compile('${GLQL_QUERY}', { mode: 'analytics', dimensions: 'ref', metrics: 'totalCount, durationQuantile(0.5)', sort: 'durationQuantile desc' })[\"output\"]; puts q; exit" | bundle exec rake consoleExpected: The GraphQL output should contain durationQuantile(quantile: 0.5) in the metrics and parameters: {quantile: 0.5} in the orderBy.
Code suggestions timestamp renders with granularity
mode: analytics
query: type = CodeSuggestion and timestamp >= -3m
dimensions: timestamp, language
metrics: totalCount
sort: timestamp descTest via ruby extension
GLQL_QUERY='type = CodeSuggestion and group = "gitlab-duo" and timestamp >= -3m'
echo "q = Glql.compile('${GLQL_QUERY}', { mode: 'analytics', dimensions: 'timestamp, language', metrics: 'totalCount', sort: 'timestamp desc' })[\"output\"]; puts q; exit" | bundle exec rake consoleExpected: The GraphQL output should contain timestamp(granularity: "monthly") in the dimensions block and parameters: {granularity: "monthly"} in the orderBy. Previously, timestamp rendered as a bare field name and sort had no parameters block.