Add failedJobsCount field to Pipeline GraphQL type

What does this MR do and why?

This MR adds a new failedBuildsCount field to the Ci::PipelineType GraphQL type to support the migration of the MR Pipelines page from REST to GraphQL.

As part of MR Pipelines migration to GraphQL (&14144) • Sahil Sharma • 18.7, we need to implement the Failed Jobs expandable widget that currently exists in the REST-based MR Pipelines page. This widget displays a count badge showing the number of failed jobs for each pipeline, allowing users to quickly identify and expand pipelines with failures.

The REST API already provides failed_builds_count via Ci::PipelineEntity, but this data was not available in GraphQL. This MR bridges that gap by exposing the same information through the GraphQL API.

References

Closes #581323

How to set up and validate locally

  1. Enable the feature flag for GraphQL-based MR Pipelines:

    Feature.enable(:mr_pipelines_graphql)
  2. Create a pipeline with multiple stages and failed builds across stages:

    Sample `.gitlab-ci.yml` configuration (click to expand)
     workflow:
       rules:
         - if: $CI_PIPELINE_SOURCE == "merge_request_event"
         - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
         
     stages:
       - build
       - test
       - deploy
    
     build_job_1:
       stage: build
       script:
         - echo "Building..."
         - exit 0
    
     build_job_2:
       stage: build
       script:
         - echo "Building..."
         - exit 0  
    
     test_job_1:
       stage: test
       script:
         - echo "Testing..."
         - exit 1  # This will fail
    
     test_job_2:
       stage: test
       script:
         - echo "Testing..."
         - exit 1  # This will fail
    
     deploy_job:
       stage: deploy
       script:
         - echo "Deploying..."
         - exit 0
       when: manual
       allow_failure: true
  3. Push this configuration to trigger a pipeline, or create one manually via the UI

  4. Query the new field in GraphQL Explorer (/-/graphql-explorer):

    {
      project(fullPath: "your-namespace/your-project") {
        pipelines(last: 5) {
          nodes {
            iid
            status
            failedBuildsCount
          }
        }
      }
    }
  5. Verify the failedBuildsCount returns 2 (matching the number of failed builds in the pipeline)

Database Review

Query Analysis

The failedBuildsCount field uses the existing Ci::Pipeline#limited_failed_builds association.

Raw SQL

SELECT
    "p_ci_builds ". "status ", "p_ci_builds ". "finished_at ", "p_ci_builds ". "created_at ", "p_ci_builds ". "updated_at ", "p_ci_builds ". "started_at ", "p_ci_builds ". "coverage ", "p_ci_builds ". "name ", "p_ci_builds ". "options ", "p_ci_builds ". "allow_failure ", "p_ci_builds ". "stage_idx ", "p_ci_builds ". "tag ", "p_ci_builds ". "ref ", "p_ci_builds ". "type ", "p_ci_builds ". "target_url ", "p_ci_builds ". "description ", "p_ci_builds ". "erased_at ", "p_ci_builds ". "artifacts_expire_at ", "p_ci_builds ". "environment ", "p_ci_builds ". "when ", "p_ci_builds ". "yaml_variables ", "p_ci_builds ". "queued_at ", "p_ci_builds ". "lock_version ", "p_ci_builds ". "coverage_regex ", "p_ci_builds ". "retried ", "p_ci_builds ". "protected ", "p_ci_builds ". "failure_reason ", "p_ci_builds ". "scheduled_at ", "p_ci_builds ". "token_encrypted ", "p_ci_builds ". "resource_group_id ", "p_ci_builds ". "waiting_for_resource_at ", "p_ci_builds ". "processed ", "p_ci_builds ". "scheduling_type ", "p_ci_builds ". "id ", "p_ci_builds ". "stage_id ", "p_ci_builds ". "partition_id ", "p_ci_builds ". "auto_canceled_by_partition_id ", "p_ci_builds ". "auto_canceled_by_id ", "p_ci_builds ". "commit_id ", "p_ci_builds ". "erased_by_id ", "p_ci_builds ". "project_id ", "p_ci_builds ". "runner_id ", "p_ci_builds ". "upstream_pipeline_id ", "p_ci_builds ". "user_id ", "p_ci_builds ". "execution_config_id ", "p_ci_builds ". "upstream_pipeline_partition_id ", "p_ci_builds ". "scoped_user_id ", "p_ci_builds ". "timeout ", "p_ci_builds ". "timeout_source ", "p_ci_builds ". "exit_code ", "p_ci_builds ". "debug_trace_enabled "
FROM
    "p_ci_builds "
WHERE
    "p_ci_builds ". "type " = 'Ci::Build'
    AND "p_ci_builds ". "commit_id " = 637
    AND "p_ci_builds ". "partition_id " = 100
    AND ("p_ci_builds ". "retried " = FALSE
        OR "p_ci_builds ". "retried " IS NULL)
    AND ("p_ci_builds ". "status " IN ('failed'))
LIMIT 101

Query Plan

Limit  (cost=0.00..0.00 rows=1 width=612) (actual time=0.003..0.003 rows=0 loops=1)
  ->  Seq Scan on ci_builds_100 p_ci_builds  (cost=0.00..0.00 rows=1 width=612) (actual time=0.003..0.003 rows=0 loops=1)
        Filter: (((NOT retried) OR (retried IS NULL)) AND ((type)::text = 'Ci::Build'::text) AND (commit_id = 637) AND (partition_id = 100) AND ((status)::text = 'failed'::text))
Planning:
  Buffers: shared hit=1085 read=43
Planning Time: 6.727 ms
Execution Time: 0.012 ms

Screenshots or screen recordings

No visual changes.

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.

Edited by Sahil Sharma

Merge request reports

Loading