Skip to content

fix: release-please repeatedly force-pushes duplicate commits to open release PRs when no changes occurred on main #2881

Closed

Description

@quirogas

Environment details

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

  1. 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.

  2. 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.

  3. 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

  1. Normalize Line Endings & Whitespace:
    In `Manifest.maybeUpdateExistingPullRequest`, normalize line endings (`\r\n` -> `\n`) and trim whitespace before comparing `existing.body` with `pullRequest.body`.
  2. 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.
  3. 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

  1. sofisl commented on Aug 20, 2026

    @sofisl
    Contributor

    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?

  2. suztomo commented on Aug 20, 2026

    @suztomo
    Member

    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

    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.

  3. added
    type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.
    priority: p1Important issue which blocks shipping the next release. Will be fixed prior to next release.
    on Aug 21, 2026
  4. codyoss commented on Aug 24, 2026

    @codyoss
    Member

    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

  5. codyoss commented on Aug 25, 2026

    @codyoss
    Member

    This is currently in the process of being deployed. Closing.

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

Metadata

Metadata

Assignees

Labels

priority: p1Important issue which blocks shipping the next release. Will be fixed prior to next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions