Skip the Duo agent config lookup on an empty repository

What does this MR do and why?

Rendering the Duo section of the project settings page builds a Gitlab::DuoAgentPlatform::Config, which reads the agent config file from the repository. Both read paths pass project.default_branch to Repository#blob_data_at, and a project with an empty repository has no default branch. That nil reached Gitaly's CommitService/TreeEntry call, which answers a blank revision with GRPC::InvalidArgument: empty revision rather than reporting that no blob exists. Nothing in the chain rescued it, so /<namespace>/<project>/edit returned HTTP 500 for any project without commits.

Both readers are guarded, not just one. file_content calls candidate_file_content first, so guarding only file_content would leave the candidate lookup reaching Gitaly with the same blank revision and the 500 would remain whenever the candidate flag is on.

The class already handles this case one method away: cache_key falls back to 'empty' when there is no commit. Repository#ignore_revs_file_blob guards the same way before reading a blob, so this follows an existing pattern rather than introducing one.

References

  • Closes #628448
  • Follows the guard already used by Repository#ignore_revs_file_blob, which returns early unless the project has a default branch before reading a blob

Differences

Before: visiting the settings edit page for a project with an empty repository returned HTTP 500, so a newly created project without commits had no reachable settings page at all. The failure was raised from Gitaly rather than from the Duo code that caused it, which made the cause hard to see from the error alone. It was caught by the preprod QA smoke pipeline and confirmed on pre.gitlab.com.

After: both config lookups return early when the default branch is blank, so no request is made to Gitaly, the config loads as empty, and the settings page renders. Projects with a default branch are untouched and still read both the candidate and the main config file exactly as before.

How to set up and validate locally

bundle exec rspec spec/lib/gitlab/duo_agent_platform/config_spec.rb

The new context is "when the repository is empty". It sets the default branch to nil and asserts blob_data_at is never called, so the guard is verified by the absence of the Gitaly request rather than only by the returned value. That also covers the candidate path, since a single unguarded reader would still make the call and fail the expectation.

End to end, create a project without initializing a repository, so it has no commits and no default branch, then open its settings edit page. It renders instead of returning 500.

Edited by Jeston Singh

Merge request reports

Loading
Loading