Respect num_context_lines in exact code search

🤖 AI-authored change.

What does this MR do and why?

The Zoekt client hardcoded num_context_lines to 1 and discarded the API parameter, so a documented parameter was accepted and silently ignored (issue 599116). The REST declaration already admits 0..MAX_NUM_CONTEXT_LINES and advanced search already honours it; only the Zoekt path did not.

The value is now read from the search filters and clamped to the same 0-20 range advanced search admits, so an unbounded value cannot reach the webserver, which expands every match by this much. The default stays 1 rather than advanced search's 2: exact code search renders a caller-controlled number of chunks per file, so the larger default would multiply the payload by the chunk count.

Two consequences the plumbing change carries with it:

  • The rendered start line was the match line less one, which was correct only while the context was fixed at 1. It is now derived from the context the webserver actually returned, which is fewer than requested near the start of a file.
  • The language aggregation cache key excludes the value. The indexer forces it to 0 on an aggregation-only request, so keying on it would fragment one tally into one entry per context setting.

References

  • Closes #599116
  • Spec: specs/exact-code-search-result-limits/SPEC.md in gitlab-org/search-team/artifacts, at merged commit 44921f0e (artifacts!118). That amendment also settled a contradiction between two specs about what the parameter means for exact code search.

Screenshots or screen recordings

Before After

How to set up and validate locally

With a GDK running Zoekt and a project indexed:

curl -s --header "PRIVATE-TOKEN: <token>" \
  "http://gdk.test:3000/api/v4/projects/<id>/search?scope=blobs&search=<term>&search_type=zoekt&num_context_lines=7"

Each result's data carries 7 lines either side of the match, and startline names the first of them. num_context_lines=50 is rejected with 400 by the REST parameter declaration; 0 yields the matching line alone.

MR acceptance checklist

Verification

With the five production files reverted to the parent commit and both spec files kept, the two spec files report 50 examples, 10 failures — the ten being exactly the new examples, with no infrastructure failures. With the change in place the same command reports 50 examples, 0 failures.

That the webserver honours a caller-supplied value above 1 was measured rather than assumed, because a Rails-side fix against a backend that ignored the field would be a no-op. A gitlab-zoekt webserver was run over a purpose-built one-file index and sent the v2 payload this code sends, varying only num_context_lines. Returned context lines either side of a match at line 15 of a 30-line file:

requested before after
0 0 0
1 1 1
2 2 2
5 5 5
20 14 15

The last row is the file boundary, which is what the start_line derivation exists to handle.

What I did not verify

The GraphQL blobSearch resolver does not build a num_context_lines argument, so that surface is unchanged by this MR and was not exercised. The web search page passes the parameter through the same filter path but was not driven end to end. The probe used a locally built single-shard index, not a multi-node production corpus, so fan-out and dedup behaviour under a non-zero context setting is untested here.


🤖 Automated change — mention me to get a response. Feedback welcome. Ask to speak to John directly anytime.

Edited by John Mason

Merge request reports

Loading
Loading