Fix force-push detection in Check PR Modifications workflow#16086
Conversation
PR Summary by QodoSupport HTTP import into any open library + fix force-push detection in CI workflow Description
Diagram
High-Level Assessment
Files changed (24)
|
Code Review by Qodo
1. Javadoc tags in ///
|
The `no-force-push` job used `git cat-file -e <before>` to decide whether a push was a force-push, assuming the pre-push commit becomes unfetchable after a force-push. With `actions/checkout` fetching `fetch-depth: 0` against GitHub (which retains unreachable objects and serves arbitrary SHAs), the `before` commit is frequently still present locally, so the check reported "Regular push detected" for genuine force-pushes. The job then passed and ghprcomment never posted the force-push notice. Switch to an ancestry check: after a regular push `before` is an ancestor of the new head; after a rebase/amend force-push it is not. This holds regardless of whether the orphaned `before` object was fetched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9659485 to
c5a836e
Compare
* main: Fix force-push detection in Check PR Modifications (#16086) Chore(deps): Bump lucene from 10.4.0 to 10.5.0 in /versions (#16089) Chore(deps): Bump org.apache.httpcomponents.core5:httpcore5 in /versions (#16090) Add file notification to OCRed files (#16082) Refine CHECKLIST.md and surface it as a final gate (#16083) Gate postgres initialization behind preference & decouple search highlighting (#16084) limit aissignments globally (#16085) Parameterize toolchain JDK vendor and Java version via gradle properties (#16073) Chore(deps): Bump jablib/src/main/abbrv.jabref.org (#16078) Chore(deps): Bump actions/cache from 5 to 6 (#16079) Chore(deps): Bump actions/cache in /.github/actions/setup-gradle (#16081) Chore(deps): Bump jablib/src/main/resources/csl-styles (#16077) Document `@NullMarked` requirement for new classes (#16071) Downgrade gradle to 9.5.1 (#16072) Fix medline fetcher test (#16070)
The `no-force-push` job used `git cat-file -e <before>` to decide whether a push was a force-push, assuming the pre-push commit becomes unfetchable after a force-push. With `actions/checkout` fetching `fetch-depth: 0` against GitHub (which retains unreachable objects and serves arbitrary SHAs), the `before` commit is frequently still present locally, so the check reported "Regular push detected" for genuine force-pushes. The job then passed and ghprcomment never posted the force-push notice. Switch to an ancestry check: after a regular push `before` is an ancestor of the new head; after a rebase/amend force-push it is not. This holds regardless of whether the orphaned `before` object was fetched. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Related issues and pull requests
Context: #16074 (comment)
PR Description
The
no-force-pushjob in theCheck PR Modificationsworkflow decided force-push vs. regular push withgit cat-file -e <before>, assuming the pre-push commit is unfetchable after a force-push. Becauseactions/checkoutruns withfetch-depth: 0against GitHub (which retains unreachable objects and serves arbitrary SHAs), thebeforecommit is frequently still present locally, so the check reported "Regular push detected" for genuine force-pushes — the job passed andghprcommentnever posted the force-push notice. This switches detection to an ancestry check (git merge-base --is-ancestor <before> HEAD), which is reliable regardless of whether the orphanedbeforeobject was fetched.Steps to test
This is a CI workflow change. To verify: on a PR, push normally (job stays green, "Regular push detected") and then force-push (job fails with "Force push detected", and
ghprcommentposts the force-push notice). Empirically, PR #16074 had 15+head_ref_force_pushedevents on 2026-06-24 where every run wrongly reported "Regular push detected"; the new ancestry check fails in that scenario.Analogies
Like honey, this fix is a small, sticky one-liner that sweetens an otherwise sour contributor experience. Like chocolate, it melts away a subtle bitterness — the silent passing of force-pushes — that was easy to miss until you tasted it. And like the moon, the orphaned
beforecommit was still up there, visible togit cat-filelong after it should have set; checking ancestry instead simply stops mistaking moonlight for daylight.jabref-contrib-policy:4.2:reviewed:okAI usage
Claude Code (model claude-opus-4-8). Investigation and the one-line workflow fix were AI-assisted; reviewed and owned by the contributor.
AI CHECKLIST.md walkthrough
This change touches only
.github/workflows/pr-modifications.yml(a CI workflow). No Java, FXML, Markdown, or build inputs changed, so the Java/build/docs items below are not applicable.Code rules
== nullchecks.@NullMarked(org.jspecify.annotations.NullMarked).org.jabref.logic.util.strings.StringUtil.isBlank(java.lang.String)used instead of== null || ...isBlank().catch (Exception e)— only specific exceptions caught.Localization.langin Java,%prefix in FXML).BibEntryobjects created with withers (withField, notsetField).///) uses Markdown syntax, not JavaDoc inline tags:`code`instead of{@code},[ClassName]instead of{@link}.text/htmlresponse — including exception/error messages, not just the success body (XSS).org.jabref.model/org.jabref.logic.Verification commands
./gradlew :jablib:check(or./gradlew checkfor all modules) passes../gradlew checkstyleMain checkstyleTest checkstyleJmhpasses../gradlew modernizerpasses../gradlew --no-configuration-cache :rewriteDryRunreports no changes (run./gradlew rewriteRunto fix)../gradlew javadocpasses.npx markdownlint-cli2 "docs/**/*.md" "*.md"passes.docker run -v $(pwd):/github/workspace ghcr.io/leventebajczi/intellij-format:master "*.java" "" ".idea/codeStyles/Project.xml"executed to ensure proper formatting.Documentation
CHANGELOG.mdentry added if the change is visible to the user (end-user wording, no extra blank lines). UseTODOas the issue/PR reference placeholder when no issue is known and the PR is not yet created — never a fake number.TODO(nocloses/fixesfor merely-similar issues).docs/requirements/<area>.mdif the change is a new feature or significant bug fix (skip for refactors, minor fixes, and internal changes).docs/updated if behavior or architecture changed.Pull request
.github/PULL_REQUEST_TEMPLATE.md, every section filled.[x],[ ], or[/].gh pr create --body-file <file>(not--body).TODOplaceholder, it was replaced with the real PR-number link after PR creation, then committed and pushed.Checklist
CHANGELOG.mdin a way that can be understood by the average user (if change is visible to the user) — not user-visible