Skip to content

fix(success): associatedPR and relatedIssue/PR handling - #1340

Merged
babblebey merged 2 commits into
masterfrom
fix/success
Nov 12, 2026
Merged

babblebey merged 2 commits into
masterfrom
fix/success

Conversation

@babblebey

@babblebey babblebey commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

This pull request improves the robustness and accuracy of the release automation logic, particularly in how associated pull requests and issues are identified and handled. The changes ensure that only relevant pull requests from the current repository are processed, gracefully handle missing or non-existent issues, and update the test suite to cover these scenarios.

  • Added filtering to ensure only pull requests from the current repository are considered when associating PRs with release commits, preventing actions on PRs from forks or other repositories.
  • Implemented a helper function getAssociatedPRsOfCommit to efficiently fetch all associated pull requests for a commit, handling pagination.
  • Updated the logic for resolving related issues to gracefully handle missing or non-existent issues/PRs by catching NOT_FOUND errors and logging them, instead of failing the process.
  • Refactored GraphQL queries to use a shared prFields fragment, reducing duplication and ensuring consistent PR data is fetched.
  • Removed the unused flatten import from lodash-es.
  • Updated and expanded tests to verify that comments and labels are only added to PRs/issues in the current repository, and that missing issues/PRs do not cause failures. This includes new tests for ignoring PRs from forks and gracefully handling non-existent issues.

These changes make the release process more reliable and prevent accidental actions on unrelated repositories or missing data.

Fixes #1339
Fixes #1092
Fixes #1032

aerodeval and others added 2 commits November 12, 2026 18:27
<!-- added by https://github.com/apps/hearts --><a
href='https://hearts.dev/projects/3/users/aerodeval'><img width='50'
alt='' align='right'
src='https://hearts.dev/projects/3/users/aerodeval/tally.svg'></a>

## Problem

When a release is cut from a branch that is not the default branch (e.g.
releases from `main` while `develop` is the default), the `success` step
crashes and posts no comment at all:

```
HttpError: Not Found
GET /repos/frappe/helpdesk/pulls/66/commits
```

Root cause: the GraphQL field `associatedPullRequests` returns every
pull request that contains the commit, including pull requests opened in
**other repositories**. For commits on the default branch GitHub only
returns the merged PR, but for commits on other branches it also returns
open PRs from forks (for example a fork's `pull[bot]` sync PR
`fork-owner/fork#66`). The plugin then calls `GET
/repos/<owner>/<repo>/pulls/66/commits` on the released repository,
where `#66` is an unrelated issue, gets a 404, and the `pFilter` over
all associated PRs rejects.

Verified with the GraphQL API on frappe/helpdesk commit `c295efa8e`:
`associatedPullRequests` returns `#66` (repository
`jango-blockchained/desk`, a fork) next to `#3882`, `#3897` and `#3931`
(repository `frappe/helpdesk`). This happens on every release while such
a fork PR stays open.

Same bug as reported in #1032 and #1092. #1292 proposed the same
approach but was closed by its author before review; this PR adds the
regression test and the pagination fix below.

## Fix

- Request `repository { nameWithOwner }` for each associated PR and drop
PRs whose repository is not the released one. The comparison uses the
`owner/repo` the plugin already resolves via `GET
/repos/{owner}/{repo}`, so renamed repositories keep working.
- The filter runs before `uniqBy(…, "number")`, so a foreign PR can no
longer shadow a same-numbered PR of this repository.
- While touching the loop: the pagination branch for commits with more
than 100 associated PRs referenced an undefined variable
(`response.commit.oid`) and threw a `ReferenceError`. The per-commit
pagination now lives in a small `loadAllAssociatedPRs` helper (`while
(pageInfo.hasNextPage)`) that passes the commit's `oid`, which also
removes the manual `cursor`/`hasNextPage` flags and the duplicated push
site. The existing "multipaged associatedPRs" test never reached that
branch because its second `postOnce` on the same URL used
`overwriteRoutes: true` and replaced the first mock; it now matches on
the query name and asserts the `sha` and `cursor` variables.
- The PR field selection was copied in all three queries; it is now one
`prFields` fragment, so `repository` cannot be present on page 1 but
missing on page 2. The two `flatten()` calls on already-flat arrays are
gone with it.

Note: the pagination path is live for the first time. On a heavily
forked repository a non-default-branch commit can carry hundreds of fork
PRs, which now means a few sequential 100-node pages per commit instead
of a crash.

## Edge cases considered

- PRs opened from a fork **into** this repository have `repository` =
this repository (only `headRepository` is the fork), so contributor PRs
are still commented on. Filtering on `headRepository` would be wrong.
- Same-repository PRs targeting non-default branches (e.g. backport PRs)
are kept, as before.
- Releasing from a fork (the #1032 scenario): the upstream repository's
PRs are now dropped, as they should be.
- Renamed or transferred repositories: both sides of the comparison come
from GitHub's canonical name.
- Issues referenced in commit or PR bodies are unaffected; that path
already filters on the `owner/repo` slug.

## Tests

- New test: a fork PR `#66` is returned next to PR `#1` of this
repository; only `#1` is looked up and commented on (no mock exists for
`#66`, so any request for it fails the test).
- "multipaged associatedPRs" test now exercises the second GraphQL query
and the four PRs returned across both pages.

Co-authored-by: Olabode Lawal-Shittabey <babblebey@gmail.com>
<!-- added by https://github.com/apps/hearts --><a
href='https://hearts.dev/projects/3/users/philsturgeon'><img width='50'
alt='' align='right'
src='https://hearts.dev/projects/3/users/philsturgeon/tally.svg'></a>

## Problem

If a commit message references an issue number that doesn't exist in the
repository (e.g. `closes #3068` copied from another repo, which is
common in forks and monorepo migrations), the `getRelatedIssues` GraphQL
query returns partial `data` plus a `NOT_FOUND` error.
`@octokit/graphql` throws on any `errors`, so the whole `success` step
fails:

```
Error: Could not resolve to an issue or pull request with the number of 3068.
  type: 'NOT_FOUND', path: [ 'repository', 'issue3068' ]
```

This is inconsistent with the existing handling of missing issues when
commenting (404 is logged and ignored, see "Ignore missing and forbidden
issues/PRs").

## Change

- Catch the error when resolving related issues. If every error is
`NOT_FOUND` and partial data is present, log the missing numbers and
continue with the issues that resolved (null entries are filtered out).
- Any other error is rethrown unchanged.
- Added a test; it fails without the fix. `npm run lint:prettier` and
`ava` (266 tests) pass.

Co-authored-by: Olabode Lawal-Shittabey <babblebey@gmail.com>
@babblebey
babblebey merged commit aefce20 into master Nov 12, 2026
7 checks passed
@babblebey
babblebey deleted the fix/success branch November 12, 2026 17:51
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 12.0.11 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

3 participants