Make Wiki operations target default branch instead of HEAD
What does this MR do and why?
For #373182 (closed), #360651 (closed)
In the above issues, we noticed some quirky behaviors with Wiki features. They form a common pattern that the problems occur after the default branch of Wiki repository is updated. There are multiple actions can lead to this change, for example:
- Force push via direct Wiki git access
- Import a repository from another source
- Transfer a repository to another group having a different default branch.
After such actions, the HEAD ref of such repositories are not updated accordingly. Normal project repositories never face this concern because in Gitaly, we have a complicated heuristic to determine the default branch and fallback in case HEAD does not exist. I wrote an in-depth analysis here. Unfortunately, the wiki feature groups use HEAD
directly for many operations, such as version such as versions management, file collision check, etc. All file updates/creations are committed to the default branch (repository.default_branch
). This inconsistency causes many quirky behaviors.
This MR is to force them to use the default branch, instead of HEAD
ref from Rails side.
Side note: the default branch of wiki repository is a big confusion. It is independent of the container project's default branch. We can consider adding more documentation, or add a place on the UI to state it out explicitly. I don't think we should add the ability to change the default branch of Wiki, though.
How to set up and validate locally
Here's a simple scenario that can reproduce:
- Initialize Wiki feature for a project
- Clone Wiki repository to local environment
- Rename/delete the default branch, assuming it's recently
main
, and push to remote
git checkout -b master
git push origin --delete main
git branch -D main
- Confirming the HEAD ref of that repository
[6] pry(main)> p = Project.find_by_full_path("flightjs/test-wiki-project"); wiki = p.wiki; wiki.default_branch
=> "master"
[7] pry(main)> Gitlab::Git::Commit.find_commit(p.wiki.repository, 'HEAD')
=> nil
[8] pry(main)> Gitlab::Git::Commit.find_commit(p.wiki.repository, 'main')
=> nil
[9] pry(main)> Gitlab::Git::Commit.find_commit(p.wiki.repository, 'master')
=> <Gitaly::GitCommit: id: "558ce4f10c203cb00596a7356d6295b38ea0a1d6", subject: "Create x", body: "Create x", author: <Gitaly::CommitAuthor: name: "Administrator", email: "admin@example.com", date: <Google::Protobuf::Timestamp: seconds: 1662828689, nanos: 0>, timezone: "+0000">, committer: <Gitaly::CommitAuthor: name: "Administrator", email: "admin@example.com", date: <Google::Protobuf::Timestamp: seconds: 1662828689, nanos: 0>, timezone: "+0000">, parent_ids: ["4e487a1f7f536c61c4525b3943d0f14414375080"], body_size: 8, signature_type: :NONE, tree_id: "f16a30b6f4a6aa34fff3005384dd654e0409b9f9", trailers: []>
- Access the storage of repository, check the HEAD ref
❯ cat @hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c301
7bb5b7.wiki.git/HEAD
ref: refs/heads/main
wiki_find_page_with_normal_repository_rpcs
flag is on
When - Accessing a random page, we'll face page creation form, while the sidebar shows it exists:
- Click
Create page
, we'll see file duplication error
- Sometimes, it would show an error page, matching the experience of user in the bug report:
wiki_find_page_with_normal_repository_rpcs
flag is off
When - Edit a random page, we'll face conflict error:
- Visit the history page of a wiki page, there is no visible histories while that page has many prior versions, including the first initial one.
After this fix, all features on the UIs work as normal.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.