Repository navigation
fix: release-please repeatedly force-pushes duplicate commits to open release PRs when no changes occurred on main #2881
Description
Environment details
- OS: Linux
release-pleaseversion: v17.x / latest (andrelease-please-botinrepo-automation-bots)- Example Repository:
googleapis/google-cloud-python - Example PR: chore: release main google-cloud-python#18013
Problem Description
In large monorepos (such as googleapis/google-cloud-python), release-please repeatedly force-pushes new commits to open release pull requests every 15–30 minutes, even when no new commits have merged into `main`.
Every force-push updates the `HEAD` ref of the release PR branch (`release-please--branches--`), which fires `pull_request.synchronize` webhooks. In repositories configured with GitHub Actions concurrency cancellation (`cancel-in-progress: true`), this repeatedly cancels in-flight CI runs and restarts them from scratch. Because full CI runs in large monorepos take 30–45 minutes, the continuous re-pushing prevents CI from ever finishing.
Root Cause Analysis
-
Brittle PR Body String Comparison in `Manifest.maybeUpdateExistingPullRequest`:
In `src/manifest.ts`:private async maybeUpdateExistingPullRequest( existing: PullRequest, pullRequest: ReleasePullRequest ): Promise<PullRequest | undefined> { // If unchanged, no need to push updates if (existing.body === pullRequest.body.toString()) { this.logger.info( `PR https://github.com/${this.repository.owner}/${this.repository.repo}/pull/${existing.number} remained the same` ); return undefined; } return await this.updateExistingPullRequest(existing, pullRequest); }
`release-please` strictly compares raw string equality between `existing.body` (fetched from GitHub API) and `pullRequest.body.toString()`. GitHub API normalizes whitespace, line breaks (`\r\n` vs `\n`), and HTML comment formatting. This causes string equality to evaluate to `false` even when release notes and file contents are identical.
-
No Git Tree Idempotency in `code-suggester` (`commitAndPush`):
When `maybeUpdateExistingPullRequest` calls `updateExistingPullRequest`, `code-suggester` creates brand new commit objects on top of `main` without checking if the target branch (`release-please--branches--`) already points to the exact same git tree.
Because a new commit object is created with new timestamps, a new commit SHA is produced and `updateRef(..., force: true)` is executed, triggering GitHub push webhooks. -
Multi-Commit Chunking Amplification:
`src/util/code-suggester/github/commit-and-push.ts` sets `DEFAULT_FILES_PER_COMMIT = 100`. For large bulk release PRs touching >100 files (e.g., 218 files across ~100 packages in PR #18013), each run creates 3 separate sequential commits (`chore: release main`), which amplifies webhook events and CI churn.
Proposed Solution
- Normalize Line Endings & Whitespace:
In `Manifest.maybeUpdateExistingPullRequest`, normalize line endings (`\r\n` -> `\n`) and trim whitespace before comparing `existing.body` with `pullRequest.body`. - Decouple PR Metadata Updates from Git Ref Updates:
If the PR body or title has minor text formatting changes but the generated code tree is identical, update only the pull request description via `octokit.pulls.update(...)` without creating new git commits or updating git refs. - Tree Idempotency in `commitAndPush`:
In `src/util/code-suggester/github/commit-and-push.ts`, inspect the current `HEAD` commit tree of the remote branch. If the tree SHA matches the newly generated tree SHA, skip `updateRef`.
Activity
sofisl commentedon Aug 20, 2026
I'm also worried if this breaks someone's workflow - are there cases where people expect these updates? (worried specifically about #2). I think #1 and #3 seem safe though. @chingor13, WDYT?
suztomo commentedon Aug 20, 2026
This analysis lacks what triggers Release Please invocation every 15-30 minutes without any commit in the main branch.
IIRC, Release Please GitHub App (Cloud Run) is only triggered when a new commit is added to the main branch or its GitHub label on pull requests.
codyoss commentedon Aug 24, 2026
The root cause of the issue we were experiencing was a retry on a commit that wasn't able to be processed. This is being fixed right now, and here was the first PR towards its progress: googleapis/repo-automation-bots#6354
codyoss commentedon Aug 25, 2026
This is currently in the process of being deployed. Closing.