Add vue3_migrate_refs_management flag and migrate branches pages

What does this MR do and why?

Adds the vue3_migrate_refs_management feature flag and opts the two branches page entrypoints into the Vue 3 migration.

With status: rollout, the bundler builds both a Vue 2 and a Vue 3 chunk for each entrypoint. Gitlab::Vue3Migration.entrypoint_for then picks between them per request, using current_user as the actor. That gives us a gradual ramp and instant rollback.

The flag ships disabled, so merging this changes nothing for users. The same components render, just on a different Vue runtime.

The tags entrypoints (tags/index, tags/show, tags/new) follow in a separate MR under this same flag.

Entrypoints in this MR

Entrypoint Vue apps mounted
projects/branches/index DivergenceGraphRoot (one per diverged branch), SortBranchesDropdownApp, DeleteMergedBranchesRoot, DeleteBranchButtonRoot (one per branch), DeleteBranchModalRoot, SourceCodeDropdown{N}
projects/branches/new RefSelectorRoot

Neither entrypoint is shadowed under ee/app/assets/javascripts/pages, so no EE counterparts are required by spec/lib/gitlab/vue3_migration_files_spec.rb.

Testing

Run with the flag enabled, after gdk restart rails-web and gdk restart vite. Vite builds its page entry map at startup, so it will not serve a new entrypoint without a restart.

Verify a page is on Vue 3 with document.querySelectorAll('[data-gitlab-vue3-app]'). initVueApp also logs [V] Using Vue.js 3 ... once per named app, so the notice count should match the app list above.

/-/branches, on a project with several branches including merged, unmerged, protected, and the default branch:

  • Divergence graph renders per diverged branch, ahead/behind counts correct, bar widths proportional (no feature spec covers this)
  • Sort dropdown renders and changes order on select
  • Delete merged branches modal opens, confirms, and leaves the default branch untouched (no feature spec covers this)
  • More-actions dropdown renders per row, with no delete item on default branch
  • Delete a branch from the more-actions dropdown: the singleton modal opens prefilled with the right branch, confirms, and the row is removed
  • Protected branch delete requires typing the branch name before the confirm button enables
  • Source-code archive dropdown lists zip and tar.gz links
  • Commit SHA popover renders on hover

/-/branches/new:

  • Ref selector populates with branches and tags
  • Selecting a non-default ref creates the branch from that ref
  • Invalid branch name still triggers NewBranchForm validation

Scope check:

  • With the flag enabled, /-/tags still reports zero [data-gitlab-vue3-app] elements, confirming the yml is what moves a page rather than the flag alone
  • bundle exec rspec spec/lib/gitlab/vue3_migration_files_spec.rb passes

Known warnings

Two expected @vue/compat warnings, neither a regression from this MR:

  1. Missing required prop target when hovering a commit SHA. This comes from the Vue.extend() and detached $mount() pattern in ~/issuable/popover/index.js. Prop validation runs before compat applies propsData, so it warns about a prop that is supplied moments later. The popover renders correctly. Follow-up issue to convert those call sites to initVueApp: TODO, link before merge.
  2. destroyed() deprecation from branches/components/delete_branch_modal.vue. Vue 3 renames the hook to unmounted() and compat shims it. Happy to rename here if reviewers prefer, but it felt out of scope for a flag-only MR.

Notes for reviewers

No changelog entry: there is no user-facing change, and the flag ships disabled.

No new tests: spec/lib/gitlab/vue3_migration_files_spec.rb already validates the yml schema, that the referenced flag exists, and CE/EE consistency. Component behaviour is covered by the existing Jest suite, which runs under VUE_VERSION=3.

The one pattern worth a second pair of eyes is RefSelector, which creates a per-instance Vuex store by assigning this.$store in beforeCreate(). It behaved correctly locally, and the component already carries glListenersMixin and declares emits, so it has had prior Vue 3 preparation.

Rollout

Enable for gitlab-org and dogfood for at least a week, exercising the deletion flows, then 10%, 50%, and 100% with a soak between steps. Then default_enabled: true, then a cleanup MR flipping both ymls to status: migrated and removing the flag.

A Sentry alert query needs defining before ramping past gitlab-org, since chunk switching has no runtime fallback. Tracked on the issue.

References

Edited by Jacques Erasmus

Merge request reports

Loading
Loading