Skip to content

[CI] Add /sync-changelog comment trigger to retry failed changelog sync PRs #19321

Description

@mrodm

Summary

When the Sync backport changelog to main workflow fails after pushing the working branch but before opening the PR (e.g. a transient gh pr create error), there is currently no way to retry without pushing a new commit to the backport branch. Add a /sync-changelog comment command on the originating backport PR to re-trigger the workflow and create the sync PR targeting main.

Background

The existing workflow (sync-backport-changelog.yml) triggers on push to backport-* branches. When gh pr create fails after the working branch (changelog/pr-<N>) has already been pushed, the failure comment includes a compare link but the user must push a dummy commit to re-trigger — there is no self-service retry path.

Deliverables

sync-backport-changelog.yml

Add issue_comment: types: [created] to the on: block and a new retry-sync job:

Trigger condition (job-level if):

  • Comment is on a PR (github.event.issue.pull_request != null)
  • Comment body contains /sync-changelog
  • Actor has write or admin permission on the repository (see Security below)

Behaviour:

  • Verify the commenting actor has write permission — abort if not (see Security below)
  • Fetch the PR's merge_commit_sha via the GitHub API; exit silently if the PR is not merged
  • Derive before as the first parent of the merge commit (parents[0].sha)
  • Check out the repository at full depth (fetch-depth: 0)
  • Run the same collect → setup-go → mage → create → comment steps as the existing sync-changelog job, passing github.event.issue.number directly as the backport PR number

backport_create_sync_pr.py

Change the git push call to use --force-with-lease so that a pre-existing working branch (left over from the previous failed attempt) is overwritten cleanly:

# before
_git("push", "origin", working_branch)

# after
_git("push", "--force-with-lease", "origin", working_branch)

backport_collect_entries.py

No changes required. The existing _sync_pr_exists check (which uses --state all) correctly returns False when the working branch was pushed but no PR was created, allowing the retry to proceed.

Security

The issue_comment event runs in the default-branch context with contents: write and pull-requests: write. On a public repository, any GitHub user can post a comment, so the existing guards (PR comment / PR merged / base is main) are not sufficient — an attacker could craft a comment that passes all of them and trigger the workflow with arbitrary inputs.

The retry-sync job must check the commenting actor's permission as its first step, before any other work:

- name: Check actor write permission
  uses: actions/github-script@v7
  with:
    script: |
      const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
        owner: context.repo.owner,
        repo: context.repo.repo,
        username: context.actor,
      });
      if (!['write', 'admin'].includes(data.permission)) {
        core.setFailed(`@${context.actor} does not have write access`);
      }

context.actor is the person who posted the comment, which is the correct principal to check. A job-level if on github.event.comment.user.login == 'github-actions[bot]' is not a substitute: it would match the bot's own comments, not the collaborator performing the retry.

Note: this same pattern is required for any issue_comment-triggered workflow that carries write permissions. See also the discussion in #19214.

Acceptance criteria

  • Commenting /sync-changelog on a merged backport PR triggers the retry workflow
  • The retry creates the sync PR targeting main and posts a success comment with the PR URL
  • Commenting on an unmerged PR exits silently without error
  • A retry when the sync PR already exists posts a skipped comment
  • A commenter without write access causes the job to fail immediately with no side effects
  • git push --force-with-lease is used so a pre-existing working branch does not block the retry

Related

Metadata

Metadata

Assignees

Labels

Team:EcosystemPackages Ecosystem team [elastic/ecosystem]

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions