Skip to content

Conversation

@knqyf263
Copy link
Collaborator

@knqyf263 knqyf263 commented Oct 8, 2025

Description

This PR fixes false positive breaking change detection in the apidiff workflow when PRs are created from an old base branch.

Problem

When a PR is created from an old base and the main branch has new commits with API additions, the current workflow compares:

  • base.sha (latest main with new features)
  • head.sha (PR branch without those features)

This causes features added to main after PR creation to appear as "removed" in the PR, resulting in false breaking change detection.

Solution

  1. Use merge commit: Changed from head.sha to refs/pull/{number}/merge to compare the actual post-merge state
  2. Detect conflicts: Added check for merge conflicts, as merge commits become frozen when conflicts exist

Reference

Checklist

  • I've read the guidelines for contributing to this repository.
  • I've followed the conventions in the PR title.
  • I've added tests that prove my fix is effective or that my feature works.
  • I've updated the documentation with the relevant information (if needed).
  • I've added usage information (if the PR introduces new options)
  • I've included a "before" and "after" example to the description (if the PR is a user interface change).

@knqyf263 knqyf263 self-assigned this Oct 8, 2025
@knqyf263 knqyf263 requested a review from Copilot October 8, 2025 16:06
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes false positive breaking change detection in the apidiff workflow by using merge commits instead of head commits for comparison. The issue occurs when PRs are created from outdated base branches, causing newly added features in main to appear as "removed" in the PR.

Key changes:

  • Changed checkout reference from head.sha to merge commit (refs/pull/{number}/merge)
  • Added merge conflict detection to prevent frozen merge commit issues
  • Updated comments to explain the new approach and rationale

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@knqyf263 knqyf263 marked this pull request as ready for review October 13, 2025 11:00
@knqyf263 knqyf263 requested a review from DmitriyLewen October 13, 2025 11:00
Comment on lines 26 to 30
- name: Check for merge conflicts
if: ${{ github.event.pull_request.mergeable != true }}
run: |
echo "::error::This PR has merge conflicts. Please resolve conflicts before running apidiff."
exit 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm... It looks like we need to update this.
Take a look this PR:
DmitriyLewen#191

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this change in trivy-test, but I added this validation at the end and probably forgot to retest it.
aquasecurity#52

I'll recheck it. Thanks.

Copy link
Contributor

@DmitriyLewen DmitriyLewen Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, the value of github.event.pull_request.mergeable is determined at the time the trigger runs (for example, when the PR is created) and isn’t updated afterward.
To get the current state, we can call the GH API.
Updated in 8067ef5

Test PRs:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it possible that the conflict calculation hasn’t finished yet, causing it to return null? In other words, do we need to wait in a while loop until it returns a non-null value? I’m not sure about mergeable_state, but isn’t there a similar risk?

The value of the mergeable attribute can be true, false, or null. If the value is null, then GitHub has started a background job to compute the mergeability. After giving the job time to complete, resubmit the request. When the job finishes, you will see a non-null value for the mergeable attribute in the response. If mergeable is true, then merge_commit_sha will be the SHA of the test merge commit.

https://docs.github.com/en/rest/pulls/pulls?utm_source=chatgpt.com&apiVersion=2022-11-28

Copy link
Contributor

@DmitriyLewen DmitriyLewen Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was looking into this as well and had the same concern.
My thought was that when using the pull_request trigger, if there’s a conflict, the pipelines won’t even start.
Although this might not be the case for pull_request_target (where the pipelines still run), I believe conflicts are checked first, before the pipelines start.
So we should still get the correct mergeable_state.

As far as I understand, when a PR is created or updated, a background process starts to update the mergeable value.
By the time the pipelines start, this value should already be calculated.
However, when using github.event.pull_request.mergeable, the value is fixed (null) and doesn’t get updated afterward.

But if you’d like, we can add a loop with a delay to wait until the value is no longer null.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're sure that conflicts are checked first, I'm okay.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're sure that conflicts are checked first, I'm okay.

Unfortunately, I couldn’t find any confirmation of this for pull_request_target.

I haven't had any problems with the current approach.
I think we can always add a verification loop if we run into any issues.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked again.
pull_request_target and mergeability are processed asynchronously.
So for large PRs, it’s possible that we start apidiff too early.
I added 5 retries with a 2-second delay - fc6559b
Could you take a look when you have time?

Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
@knqyf263
Copy link
Collaborator Author

LGTM

# frozen at an old state and apidiff cannot run correctly.
- name: Check for merge conflicts
env:
GH_TOKEN: ${{ github.token }}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While github.token should be equivalent to secrets.GITHUB_TOKEN, is there any reason to use github.token here? I was curious because GITHUB_TOKEN is used elsewhere in Trivy and also generally used in the documentation.
https://docs.github.com/en/actions/tutorials/authenticate-with-github_token

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't notice the AI ​​changed that...
Thanks for noticing.

Updated in b387659

@knqyf263 knqyf263 enabled auto-merge October 22, 2025 05:32
@knqyf263 knqyf263 added this pull request to the merge queue Oct 22, 2025
Merged via the queue into aquasecurity:main with commit 7ca1b8f Oct 22, 2025
13 checks passed
@knqyf263 knqyf263 deleted the fix-apidiff-merge-commit branch October 22, 2025 06:02
knqyf263 added a commit to knqyf263/trivy that referenced this pull request Oct 27, 2025
…ty#9622)

Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io>
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
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.

2 participants