Skip to content

Azure DevOps work items don't resolve when the build ran on a non-ADO build server, and AB# references can mis-link to GitHub issues #10176

Description

@NickJosevski

Severity

Not blocking, but there is no good workaround: any customer who tracks work items in Azure DevOps while building somewhere other than Azure DevOps (TeamCity, Jenkins, GitHub Actions, Bamboo…) gets no work items on their releases at all. Long-standing — originally reported by a customer in April 2021 and never triaged, because it was filed on the build-server plugin repo rather than here.

Originally raised as OctopusDeploy/Octopus-TeamCity#54, and in the customer thread https://help.octopus.com/t/work-item-link-missing-from-build-information/26490/17. The root cause is entirely in Octopus Server; the TeamCity plugin only pushes the build information payload, so that issue should be closed in favour of this one.

Version

Verified present on main as of 2026-08-12. Present since the Azure DevOps issue tracker extension was introduced — the guard described below has been in the code since the extension was consolidated into the server repo, and originally reported against 2020.6.4809 / 2021.1.6930.

Latest Version

I could reproduce the problem in the latest build

What happened?

There are two related defects here. They share a scenario — Azure DevOps for work items, some other build server, Git hosted outside ADO — so I'm filing them together, but they can be fixed independently.

1. The Azure DevOps issue tracker can only resolve work items for builds that ran in Azure DevOps

Unlike the Jira and GitHub issue trackers, the ADO tracker does not parse commit messages. It takes BuildUrl from the build information, parses it as an ADO build URL, and asks ADO's builds/{id}/workitems API which work items that build linked. Any build information from a non-ADO build server is filtered out before that happens:

// source/Octopus.Server.Extensibility.IssueTracker.AzureDevOps/WorkItems/WorkItemLinkMapper.cs
var filteredCommits = commitsToParse.Where(c => c.BuildEnvironment == "Azure DevOps" && !string.IsNullOrWhiteSpace(c.BuildUrl));

So with a TeamCity build and Azure Boards work items, WorkItems comes back empty and IssueTrackerName is null. IssueTrackerName is derived from whatever the mappers resolved (OctopusBuildInformationMapper), so it is always null when nothing resolves — there is no way to set it from the build information payload, and it isn't a field the build server plugins can populate.

This is deliberate — there's a comment to that effect on the mapper, a test named WhenNotFromAdoReturnsEmptyList, and the docs call it out ("Azure work items aren't currently supported unless the BuildEnvironment is Azure DevOps"). But it's an inconsistency customers reasonably don't expect: Jira and GitHub work item tracking both work fine from a TeamCity build because they parse commit messages. Only ADO is bound to its own build API.

Expected: ADO work item references in commit messages (Azure Boards AB#123 syntax, and ideally branch names as Jira already does) should resolve to ADO work items regardless of which build server produced the build information.

2. The GitHub issue tracker mis-resolves Azure Boards references, producing links to unrelated GitHub issues

If the GitHub issue tracker is enabled and the repo is on GitHub, a commit message like Fixes AB#123 matches GitHubWorkItemLinkMapper's comment parser regex. NormalizeLinkData then treats AB as the owner/repo segment and produces <github-base>/AB/issues/123, while GetGitHubOwnerAndRepo falls back to the commit's own repo and fetches issue 123 from that GitHub repo — which usually exists and has a real, completely unrelated title.

So the release gets a work item that looks legitimate, with a plausible description and a broken link. This is the "matched the work item to the wrong location" symptom from the original report. It's wrong data rather than missing data, so arguably the more urgent of the two.

The mapper already skips ADO-hosted repos (it looks for /_git/ in VcsRoot), but that check doesn't help when the code is on GitHub and only the work items are in ADO.

Reproduction

  1. Configure the Azure DevOps issue tracker in Configuration ➜ Settings with a connection to your ADO organisation.
  2. Host the repository on GitHub; create a work item in Azure Boards.
  3. Build in TeamCity (or any non-ADO build server) and push build information to Octopus, with a commit message referencing the work item.
  4. Inspect the build information for the package.

For defect 1, use a plain AB#<id> reference: WorkItems is [] and IssueTrackerName is null.

For defect 2, additionally enable the GitHub issue tracker and use Fixes AB#<id> where <id> is also a valid issue number in the GitHub repo: a work item appears pointing at the wrong GitHub issue.

Build information from the original report, showing the empty result:

"BuildEnvironment": "TeamCity",
"BuildUrl": "http://<teamcity>/viewLog.html?buildId=153",
"VcsType": "Git",
"VcsRoot": "https://github.com/<owner>/<repo>",
"IssueTrackerName": null,
"WorkItems": [],

More Information

Notes towards a fix — most of the machinery for defect 1 already exists:

  • AdoApiClient.GetWorkItemLink(AdoProjectUrls, workItemId) already builds a complete WorkItemLink (title, release note, browser URL) from just a project URL and an ID. It's private today and would need exposing on IAdoApiClient.
  • A comment parser for AB#123 modelled on the Jira and GitHub ones. Jira's also parses branch names, which is worth matching.
  • The commit-parsing path should be a fallback used when BuildEnvironment != "Azure DevOps", so it doesn't double up with the existing build-API path.
  • The main design question is which ADO project to query — an AB#123 reference carries no project. Candidate sources, in order: derive org/project from VcsRoot when it is an ADO /_git/ URL; use the connection's BaseUrl when it is already a project URL; otherwise a new optional "default project" field on the connection. The reported scenario (GitHub repo + ADO boards) needs the last one, which means a change to AzureDevOpsConnection / its resource and mapper, and to the bespoke ADO connection UI in the portal.
  • Correctness trap: AdoApiClient.GetWorkItem currently returns success with title = workItemId on a 404. That's harmless for the build API, where the IDs are known-good, but on a commit-parsing path it would fabricate a work item for every false-positive AB# match. It needs to skip not-found work items.

Defect 2 is a much smaller change — tighten the GitHub comment parser so link data whose prefix is neither empty nor a valid owner/repo is not treated as a GitHub issue reference.

Unrelated but found while tracing this, and the same class of bug if anyone wants to pick it up separately: TeamFoundationVersionControlCommitLinkMapper derives the ADO project by string-slicing BuildUrl (the code comment says "derive the ProjectName from the build Url and be wrecklessly optimistic it will 'Just Work TM'"). With TFVC plus a non-ADO build server, that yields commit links like http://<teamcity>/viewLog.html?buildId=153/_versionControl/changeset/123.

Workaround

None that's satisfying. Either move the build to Azure DevOps so the build-API path is used, or push build information from a small ADO pipeline in addition to the real build. Customers using ADO Boards with another build server can otherwise only link work items by hand.

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