Inline blame: "View blame prior to this change" link drops the relative URL root

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Summary

On instances installed under a relative URL (for example https://example.com/gitlab), the "View blame prior to this change" button in the inline blame view links to a URL without the relative URL root. The link 404s.

The standalone blame page (/-/blame/) is not affected because it builds the same link on the server with project_blame_path.

Steps to reproduce

  1. Run GitLab with a relative URL root, for example relative_url_root: /gitlab in GDK (gdk.yml) or external_url "https://example.com/gitlab" in gitlab.rb.
  2. Open any text file that has more than one commit in its history.
  3. In the file header, select Blame to enable inline blame.
  4. Hover a blame entry and copy the link address of the View blame prior to this change button (icon doc-versions).

Example project

Reproducible on any project on a relative-URL instance. Not reproducible on GitLab.com because it has no relative URL root.

What is the current bug behavior?

The link is https://example.com/<group>/<project>/-/blob/<parent-sha>/<path>?blame=1. The /gitlab prefix is missing and the link returns 404.

What is the expected correct behavior?

The link is https://example.com/gitlab/<group>/<project>/-/blob/<parent-sha>/<path>?blame=1.

Relevant logs and/or screenshots

No server-side logs. The URL is assembled in the browser.

Output of checks

Reproduced by reading the source at v19.2.4-ee and master.

Possible fixes

app/assets/javascripts/vue_shared/components/source_viewer/components/blame_commit_info.vue, computed previousBlameUrl:

const blobPath = joinPaths(
  '/',
  this.projectPath,
  '-/blob',
  this.commit.parentSha,
  this.previousPath,
);
return `${blobPath}?blame=1`;

joinPaths('/', ...) produces a root-relative path with no gon.relative_url_root. Two options, in line with URLs in GitLab:

  • Preferred: have the backend return the path. The blame GraphQL groups already return previousPath and commit.parentSha; adding a previousBlamePath (or similar) field lets Rails build it with project_blob_path.
  • Minimal: prepend gon.relative_url_root (or use the path_helpers js-routes helper for project_blob_path) in previousBlameUrl.

Note that .eslint_todo/gitlab-no-hardcoded-urls.mjs does not list this file, so the no-hardcoded-urls sweep in !245993 (merged) did not catch it. The joinPaths('/', ...) pattern slips past that rule.

Additional context

  • Introduced with the compact inline blame refactor in 6ffae9aa (18.9), implementing #576393 (closed). The spec in that issue hardcodes the <project>/-/blob/<prev-sha>/<prev-file>?blame=1 shape, so the missing root was baked in from design.
  • Became visible to self-managed users in 19.1 when inline_blame was enabled by default (#501539 (closed)). On 19.1+ there is no UI path to the standalone blame page: the header Blame button and the gutter blame icons both open inline blame (chunk.vue handleBlameClick).
  • Same class of bug as the snippet-delete redirect fixed in !245993 (merged) (19.3). That MR does not touch this component.
  • Docs follow-up: Git file blame still says "To open the full blame page, in the upper-right corner, select Blame." That button does not exist in 19.1+.
  • !248531 (closed) moves blame rendering into chunk.vue and passes projectPath down. If still open, the fix could ride along.

Workarounds for affected admins:

  • Edit the URL, /-/blob/ to /-/blame/, and use the button on the standalone blame page.
  • Feature.disable(:inline_blame) to restore the pre-19.1 behaviour.

Affected versions: 18.9 (behind flag), 19.1 and later (flag default on). Confirmed on 19.2.4. Still present on master.

Parent epic: &11471

Edited by 🤖 GitLab Bot 🤖