Skip to content

GitHub issue tracker builds a broken link for GH-1234 style work item references #10186

Description

@NickJosevski

Severity

Low. Cosmetic but user-visible: the work item shows the correct title, so it looks fine until someone clicks the link and lands on a 404. Only affects commit messages using the GH-1234 reference form; the far more common #1234 and owner/repo#1234 forms are unaffected. No data corruption, no workaround needed beyond using a different reference syntax.

Found while investigating #10176 (Azure DevOps work item tracking); unrelated to that issue's cause, filed separately so it doesn't widen the decision being made there.

Version

Verified on main as of 2026-08-18, in GitHubWorkItemLinkMapper.NormalizeLinkData. Present since the GitHub issue tracker was introduced — the GH- reference form has always been accepted by the comment parser and has never been handled by the link builder.

Latest Version

I could reproduce the problem in the latest build

What happened?

A commit message of the form Fixes GH-1234 is recognised by the GitHub issue tracker's comment parser, which produces IssueNumber = "1234" and LinkData = "GH-1234". The work item's description resolves correctlyGetGitHubOwnerAndRepo falls back to the owner/repo of the commit's own repository and Octokit fetches issue 1234 from it, giving the real issue title.

But NormalizeLinkData builds a nonsensical URL. Because "GH-1234" contains no #, Split('#') yields a single component ["GH-1234"], which is non-empty, so the method takes the "we have org/repo formatted" branch:

var linkDataComponents = linkData.Split('#').ToList();
if (!string.IsNullOrEmpty(linkDataComponents[0]))
{
    // we have org/repo or user/repo formatted, insert "issues" between that and the issueId
    linkDataComponents.Insert(1, "issues");

    // switch to the baseUrl, rather than calc relative to the vscRoot
    baseToUse = baseUrl;
}

"GH-1234" is treated as if it were an owner/repo segment, issues is appended after it, and the base switches from the VCS root to the configured base URL. The result is:

<baseUrl>/GH-1234/issues

Note that the issue number is absent from the URL entirely1234 was never a separate component to begin with, so it is silently dropped rather than merely misplaced. With the default base URL this yields https://github.com/GH-1234/issues, which is not a valid GitHub path.

Expected: the same URL the equivalent bare reference produces. Fixes #1234 correctly yields <vcsRoot>/issues/1234, and GH-1234 is just an alternative spelling of the same same-repo reference, so it should resolve identically — relative to the VCS root, not the base URL.

Reproduction

  1. Enable the GitHub issue tracker in Configuration ➜ Settings.
  2. Commit to a GitHub-hosted repo with the message Fixes GH-1234, where 1234 is a real issue in that repo.
  3. Push build information to Octopus and create a release.
  4. The work item shows the correct issue title, but its link points at https://github.com/GH-1234/issues instead of <repo>/issues/1234.

More Information

The fix is confined to NormalizeLinkData in source/Octopus.Core/Features/IssueTrackers/GitHub/WorkItems/GitHubWorkItemLinkMapper.cs — strip a leading GH- (case-insensitive, as the parser matches case-insensitively) and treat the remainder as a bare same-repo issue id, i.e. take the same path as the else branch that handles #1234.

Two things to be careful of:

  • baseToUse must stay as the VCS root for this form, not switch to the base URL. The switch to baseUrl only makes sense for genuine owner/repo#id references, where the target repo differs from the one being built.
  • No existing test asserts the broken URL, so nothing needs updating to accommodate the fix. The only current GH- coverage is CommentParserScenarios, which asserts parser output (LinkData == "GH-1234") and is correct as-is. A NormalizeLinkData test for this form should be added alongside the existing link-building tests in source/Octopus.Core.UnitTests/Features/IssueTrackers/GitHub/WorkItemLinkMapperScenarios.cs.

Worth confirming as a product question while fixing: whether GH- should keep being accepted at all. It is a GitHub-supported shorthand, so presumably yes, but it is rare enough in practice that it has gone unnoticed since the integration shipped.

Workaround

Use #1234 or owner/repo#1234 in commit messages instead of GH-1234.

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature/workitemskind/bugThis issue represents a verified problem we are committed to solving

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions