Add ref argument to Commit.latestPipeline GraphQL field

What does this MR do and why?

Adds an optional ref argument to the Commit.latestPipeline GraphQL field.

Background. Commit.latestPipeline (added in !243957 (merged)) is ci_sources-scoped, so it excludes dangling-source pipelines (e.g. security_orchestration_policy scans) that could make the commits-list badge show a green check on a commit whose real CI pipeline failed (#579690). But the field was ref-agnostic: it returned the latest pipeline for a commit SHA across all refs.

Meanwhile, c416feed3356 made the commits-list badge ref-aware (pipelines(first: 1, ref: $pipelineRef)) so status is resolved per branch, because the same SHA can have pipelines on multiple refs. Switching the badge to latestPipeline would have regressed that per-ref resolution.

This MR reconciles the two: with the ref argument, callers get both dangling-source exclusion and per-ref scoping. The underlying Ci::Pipeline.latest_pipeline_per_commit(commits, ref = nil, …) already accepts a ref; the resolver now passes it through and includes ref in the batch-loader key so commits queried with different refs resolve in separate batches.

Query

The resolver batch-loads a page of commits with the existing current-partition-first path from !243957 (merged), now with an optional ref predicate:

EXPLAIN
SELECT DISTINCT ON (sha) *
FROM p_ci_pipelines
WHERE project_id = 278964
  AND partition_id = 113   -- current partition first
  AND (source IN (1,2,3,4,5,6,7,8,10,11) OR source IS NULL)
  AND ref = 'master'
  AND sha IN (
    '8b1c831c415227f2f21959d5f7fa882d0fc7826b', 'a18c1077e06763d54af15431fa322aaf65188c20',
    'ad931779d90d117c841eca6cdd569f748f826254', '9117eddda7c352a9d90d5fe13f1a474db66e0587',
    'e7fb3dc4b1b38fa16b39b7b106d2298b386d50d2', 'd63b339b8bb0da0fe80471d6703dc1137f428fd3',
    '5e351c99925ebef9cc7ec2d0c706e876e91ffc34', 'e17352d7aea8f56b9194af420d758bf47beb3575',
    '65be1f73b5d57d090ee05755a90d91b0ec8e49dc', 'fe8d33147909fa97604039524916753850256907',
    '4850b39a313b7207ab0fd14d60ef71616ab6d6ff', '4c702d721652850fe7c0335d8cbc0c4cae8312b9',
    'c2214384fdadf15002fbf90bdfe1d4abe280bd0b', '423ad1ed25266b0e53d533dba54edb3a4038fbc2',
    'bcd6c028b5e4109c7e9e01d86c7eba5987d06bb9', '0b4d4c1e64add719ae85ca95fd6f72a41995ec70',
    '32448c7802dd293c86525cf4fbded284edf39b39', 'ed7c52b6539029e6598dd8a7b807527b0a06d077',
    '8f452eab2547499ea609d15b5211325affc76771', 'd777101839a910064a48705b9806e8265915eddf'
  )
ORDER BY sha ASC, id DESC;

https://postgres.ai/console/gitlab/gitlab-production-main/sessions/54012/commands/156395:

Time: 1.402 ms  
  - planning: 1.313 ms  
  - execution: 0.089 ms  
    - I/O read: 0.000 ms  
    - I/O write: 0.000 ms  
  
Shared buffers:  
  - hits: 6 (~48.00 KiB) from the buffer pool  
  - reads: 0 from the OS file cache, including disk I/O  
  - dirtied: 0  
  - writes: 0  
 Unique  (cost=0.01..0.02 rows=1 width=1816) (actual time=0.039..0.039 rows=0 loops=1)
   Buffers: shared hit=6
   I/O Timings: read=0.000 write=0.000
   ->  Sort  (cost=0.01..0.02 rows=0 width=0) (actual time=0.038..0.039 rows=0 loops=1)
         Sort Key: p_ci_pipelines.sha, p_ci_pipelines.id DESC
         Sort Method: quicksort  Memory: 25kB
         Buffers: shared hit=6
         I/O Timings: read=0.000 write=0.000
         ->  Result  (cost=0.00..0.00 rows=0 width=0) (actual time=0.001..0.001 rows=0 loops=1)
               One-Time Filter: false
               I/O Timings: read=0.000 write=0.000
Settings: effective_cache_size = '472585MB', jit = 'off', random_page_cost = '1.5', work_mem = '230MB', seq_page_cost = '4'
Query ID: -2456647205469911070

The (project_id, sha) index still drives the lookup; ref is an additional filter on the returned rows.

Multi-version compatibility

The argument is optional and backwards-compatible, so this is a non-breaking schema change. Because @gl_introduced cannot gate an argument, the frontend switch (!243958 (merged)) sets the field-level @gl_introduced version to the milestone that includes this argument. Older backends then strip the entire latestPipeline { … } selection (degrading the badge gracefully) rather than erroring on an unknown argument. As with !243957 (merged) → !243958 (merged), this backend change is sequenced to deploy before the frontend uses it.

MR acceptance checklist

  • bundle exec rubocop on changed files.
  • Backend specs added: type spec (commit_type_spec.rb) and request spec (commits_spec.rb) covering ref-scoped, other-ref, and unscoped resolution.
  • GraphQL docs and introspection schema regenerated (gitlab:graphql:update_all).
Edited by Stan Hu

Merge request reports

Loading
Loading