Expose opt-in tagger dates in ListRefs

What does this MR do and why?

This MR supplies the missing tagger timestamp needed to migrate the Tags REST API to ListRefs while preserving its existing created_at response.

Why this change is needed

GitLab #630430 reports that offset pages 2 and above fetch all tags from Gitaly before Rails selects the requested page. This repeatedly transfers detailed tag data and builds the full tag list in Rails memory.

The migration proposed in GitLab #614152 would fetch the first page * per_page refs through ListRefs, select the requested page, and batch-fetch commits and messages only for those selected tags.

A preliminary local benchmark found 61% lower median retrieval time with this approach than with limited FindAllTags. However, ListRefs lacks the tagger date needed for API created_at, and the existing commit/message batch RPCs do not expose it. Individual FindTag lookups would add per-tag RPC overhead.

What changes

  • Adds include_tagger_date to the existing ListRefs request, disabled by default.
  • Adds Reference.tagger_date, using google.protobuf.Timestamp like the existing Tag.tagger.date field.
  • Requests %(taggerdate:unix) from the existing Git command when enabled; no new RPC is introduced.
  • Returns the referenced tag's own timestamp. Lightweight tags and missing tagger dates leave the field absent; Unix epoch zero remains present.
  • Uses ParseDateSeconds to preserve existing FindTag behavior for overflowing dates.

This is a prerequisite for the Rails migration. It does not switch the Tags API to ListRefs or fix the incident by itself.

Coverage and remaining validation

Tests cover date inclusion and peeling off/on, annotated and lightweight tags, branches and HEAD, missing dates, epoch zero, nested tags retaining their own timestamp, paginated creation-date ordering, and overflow parity with FindTag.

Performance with the new field has not been measured. The earlier Rails retrieval benchmark excluded creation dates and does not establish this field's overhead. Naming and the opt-in API are ready for Gitaly team review.

References

Screenshots or screen recordings

Not applicable; no UI changes.

How to set up and validate locally

  1. Prepare a repository with annotated, lightweight, and nested tags with distinct tagger timestamps.
  2. Using a server and client bindings built from this branch, call ListRefs with include_tagger_date disabled, then enabled.
  3. Verify annotated tags return their own timestamps and lightweight tags have no timestamp. Repeat with peel_tags: true.
  4. Follow pagination cursors and verify the dates remain attached to the same refs.

Validation

  • Passed: GITALY_TESTING_GIT_BINARY="$(command -v git)" go test ./internal/gitaly/service/ref -count=1.
  • Passed: protobuf regeneration and make lint-proto, using the matching prebuilt protoc 30.2 and Go 1.26 toolchain.
  • The local source build of protoc failed on Abseil compatibility. Local bundled Git lacks the MVCC binary, so tests used system Git 2.51 via the supported test override.

MR acceptance checklist

  • Reference-service tests pass.
  • Protobuf lint passes and generated bindings are updated.
  • API fields are documented in the protobuf definition.
  • Changelog trailer included.
  • Benchmark the new field enabled versus disabled.
Edited by Emma Park

Merge request reports

Loading
Loading