Skip to content

fix: support arbitrary-depth issue hierarchy in fetchMissingAncestorIssues - #1887

Open
tstandish-tnsk wants to merge 2 commits into
atlassian:mainfrom
tstandish-tnsk:fix/fetch-ancestor-issues-deep-hierarchy
Open

fix: support arbitrary-depth issue hierarchy in fetchMissingAncestorIssues#1887
tstandish-tnsk wants to merge 2 commits into
atlassian:mainfrom
tstandish-tnsk:fix/fetch-ancestor-issues-deep-hierarchy

Conversation

@tstandish-tnsk

@tstandish-tnsk tstandish-tnsk commented Jun 29, 2026

Copy link
Copy Markdown

Summary

fetchMissingAncestorIssues made exactly two rounds of ancestor fetching — parents, then grandparents — designed for the standard subtask → task → epic chain. Projects using deeper Jira hierarchy levels (e.g. Sub-Initiative → Epic → Task → Root) exceed this limit.

When constructIssueTree then tries to attach the unresolved top-level ancestor to its parent, the parent isn't in the combined list, so the issue is silently dropped along with its entire subtree. This means issues that match the JQL filter never appear in the tree view when "Group issues by epic" is enabled.

Change

Replace the two-round approach with an iterative loop that keeps fetching missing ancestor keys until none remain, with a depth cap of 10 to prevent runaway requests.

Before:

const missingParentKeys = this.calculateMissingParentKeys(newIssues);
const parentIssues = await this.fetchIssuesForKeys(site, missingParentKeys);

// If a jqlIssue is a sub-task we make a second call to make sure we get its parent's epic.
const missingGrandparentKeys = this.calculateMissingParentKeys([...newIssues, ...parentIssues]);
const grandparentIssues = await this.fetchIssuesForKeys(site, missingGrandparentKeys);

return [...parentIssues, ...grandparentIssues];

After:

const fetched: TreeViewIssue[] = [];
let allIssues = [...newIssues];
for (let depth = 0; depth < 10; depth++) {
    const missingKeys = this.calculateMissingParentKeys(allIssues);
    if (!missingKeys.length) {
        break;
    }
    const batch = await this.fetchIssuesForKeys(site, missingKeys);
    fetched.push(...batch);
    allIssues = [...allIssues, ...batch];
}
return fetched;

Behaviour

  • For standard 2-level hierarchies (subtask → epic) behaviour is identical — the loop exits after 2 iterations as before.
  • For deeper hierarchies the loop continues until the root is found.
  • The depth cap of 10 prevents runaway API calls in pathological cases.

Rovo Dev code review: Rovo Dev couldn't review this pull request
The pull request author does not have access to Rovo Dev.

…ssues

The previous implementation made exactly two rounds of ancestor fetching
(parents, then grandparents), which was designed for the standard
subtask -> task -> epic chain. Projects that use deeper Jira hierarchy
levels (e.g. Sub-Initiative -> Epic -> Task -> Root) exceed this limit,
causing the top-level ancestor to go unresolved. When constructIssueTree
then tries to attach it to its parent, the parent isn't in the combined
list, so the issue is silently dropped along with its entire subtree.

Replace the two-round approach with an iterative loop that keeps fetching
missing ancestor keys until none remain or a depth cap of 10 is reached.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@atlassian-cla-bot

atlassian-cla-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

Hooray! All contributors have signed the CLA.

@tstandish-tnsk

Copy link
Copy Markdown
Author

I can't share images due to potential sensitive data but I can confirm that a local patch to the vs code extension with this update shows equivalent counts and expected tasks as compared to the main JIRA Filter view, which was originally how I found this discrepancy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant