Skip to content

backport: automate backport PR creation from checklist and fix changelog links #19214

Description

@mrodm

Summary

Add auto-backport.yml to create backport PRs automatically for each checked branch when a PR merges into main, and post-backport-branch.yml to replace the placeholder changelog.yml link with the actual backport PR URL once the PR exists. Together these deliver the full automated backport loop: check a box, merge, get a PR.

Background

With the checklist in place, authors can indicate which branches need a backport. auto-backport.yml closes the loop by reading those checked boxes on merge and calling backport_apply.sh for each. It also supports adding missed branches after merge via issue_comment edits.

post-backport-branch.yml handles a timing issue: the changelog.yml entry is written by backport_apply.sh before the PR URL is known, so the link is initially a placeholder (the original PR link). This workflow fires after the backport PR is opened and replaces it with the correct URL. It mirrors the post-dependabot.yml pattern already used in elastic/elastic-agent.

Deliverables

auto-backport.yml

  • Permissions: contents: write, pull-requests: write

Triggers:

  • push to main — fires after every merged PR
  • issue_comment edited — job-level condition if: ${{ github.event.issue.pull_request }} ensures this only runs for PR comments, not plain issue comments; further guards: PR must be merged, comment must contain the <!-- backport-checklist --> marker, and baseRefName must be main, and the editing actor must have write or admin permission on the repository

Behaviour:

  • (issue_comment) Verifies the editing actor has write or admin permission via repos/{owner}/{repo}/collaborators/{actor}/permission; exits silently if not
  • Recovers the merged PR via gh pr list --search <sha>
  • Skips PRs with the backport:sync-changelog label (prevents re-triggering on changelog-sync PRs)
  • Finds and parses the <!-- backport-checklist --> comment; exits silently if not found
  • Deduplication: gh pr list --head auto-backport/<pkg>-<major.minor>-<sha> --state all — skips branches already processed (handles re-runs, issue_comment re-triggers, and deliberately closed backport attempts)
  • For each checked branch: calls backport_apply.sh --sha <merge-sha> --package <pkg> --target <branch> --open-pr --json
  • On success: updates checklist line → - [x] \backport-aws-6.14` — ✅ #XXXX`
  • On conflict: updates checklist line → - [x] \backport-aws-6.14` — ⚠️ conflict: @ please run manually: ...`

post-backport-branch.yml

  • Permissions: contents: write

Trigger: pull_request opened → backport-*, condition startsWith(head_ref, 'auto-backport/')

Flow:

  1. Checks out the PR branch
  2. Identifies the package from the branch name (auto-backport/<package>-<major.minor>-<sha>)
  3. Replaces the placeholder link in changelog.yml with github.event.pull_request.html_url via yq
  4. Commits and pushes

Only triggers on opened (not synchronize) so the follow-on commit does not re-trigger the workflow.

Considerations

  • Nested package directories: post-backport-branch.yml identifies the package from the branch name (auto-backport/<package>-<major.minor>-<sha>) and then locates changelog.yml to update the link. The path resolution must support both packages/<package> and packages/<technology>/<package>. Investigate whether mage listPackages or an equivalent helper provides a name → path mapping.

  • No pull_request_target: auto-backport.yml uses push to main (not pull_request_target closed) intentionally, to avoid the security risks associated with pull_request_target. Do not change this trigger.

  • issue_comment actor permission: the issue_comment edited trigger runs with contents: write + pull-requests: write on a public repository. Without a permission check, any GitHub user can post a comment containing <!-- backport-checklist --> with fabricated checked entries, edit it, and trigger backport_apply.sh with arbitrary --package / --target values. The actor permission check (first step of the job) closes this. A job-level if on github.event.comment.user.login is not sufficient here because GitHub records checkbox toggles as edits by the toggler, not the original comment author.

  • Upstream repository only: this workflow assumes the backport branch (auto-backport/<package>-<major.minor>-<sha>) is created and pushed directly to the elastic/integrations upstream repository, not to a fork. auto-backport.yml runs on push to main (base repository context) with contents: write permissions, so it can push branches to the upstream repo. Contributors working from forks will need to trigger backports manually via backport_apply.sh on their own fork or request a team member to run the automation.

Acceptance criteria

EDITED:

  • Updated the label to skip Pull Requests to be backport:sync-changelog instead of automation.

Activity

  1. infra-vault-gh-plugin-prod commented on May 26, 2026

    @infra-vault-gh-plugin-prod

    Pinging @elastic/ecosystem (Team:Ecosystem)

  2. github-actions commented on May 26, 2026

    @github-actions
    Contributor

    tl;dr: #19214 is the right next orchestration issue, but it should be implemented on top of the foundation issues (#19210, #19212, #19213) and by reusing existing idempotency/guard patterns already present in repo workflows.

    Recommendation

    Implement auto-backport.yml + post-backport-branch.yml as proposed in this issue, sequenced after the inventory/apply/checklist foundations.

    Concretely:

    1. Use push to main + issue_comment edited triggers for auto-backport.yml (as specified here, and avoiding pull_request_target).
    2. Gate execution on: merged PR targeting main, presence of <!-- backport-checklist -->, and not labeled automation.
    3. Reuse existing repo patterns for dedupe and safe PR targeting before writing comments/updates.
    4. Keep post-backport-branch.yml as a narrow pull_request: opened handler for backport-* + startsWith(head_ref, 'auto-backport/') to patch the placeholder changelog link once the PR URL exists.
    Findings
    • Backport branch creation is currently still Buildkite/UI driven:
      • .buildkite/pipeline.backport.yml:13-19 (if: build.source != 'ui' guard)
      • .buildkite/pipeline.backport.yml:20-50 (manual input fields)
      • docs/ci_pipelines.md:225-227 (explicitly documented as UI-triggered only)
    • The requested GH workflows do not exist yet in repo (.github/workflows has no backport/changelog automation workflow names).
    • Existing workflow patterns to reuse for backport: automate backport PR creation from checklist and fix changelog links #19214 already exist:
      • PR-comment trigger guard: .github/workflows/trigger-mention-in-pr.yml:3-4,20-21
      • Post-close trigger pattern: .github/workflows/docs-preview-cleanup.yml:3-4
      • Safe PR targeting + duplicate suppression: .github/workflows/notify-package-docs-failure.yml:40-50
      • Label-based skip gates: .github/workflows/trigger-pr-actions-detective.yml:40
      • Existing automation/backport conventions: .mergify.yml:9-14
    • Checklist marker is not yet present in repo source (backport-checklist search returned no hits), which aligns with this being staged work tied to #19213.
    • Placeholder changelog links are a real existing pattern in current packages:
      • packages/cisco_meraki/changelog.yml:11 → link: TBD
      • packages/tenable_io/changelog.yml:124 → /pull/999999
    • Dependency chain is explicit in the issue set:
      • #19210 defines .backports.yml + active-branch check as foundation
      • #19212 defines backport_apply.sh (the per-branch execution primitive)
      • #19213 defines checklist posting/update mechanism
      • #19214 then consumes that checklist to drive PR creation + link fix
    Verification

    I ran repository commands to verify current state and concrete gaps:

    $ find .github/workflows -maxdepth 1 -type f | grep -E 'backport|changelog' || true
    # (no results)
    
    $ grep -RIn "issue_comment" .github/workflows/*.yml
    .github/workflows/trigger-mention-in-issue.yml:3:  issue_comment:
    .github/workflows/trigger-mention-in-pr.yml:3:  issue_comment:
    
    $ grep -RIn "backport-checklist" . || true
    # (no results)
    
    $ grep -RIn "link: TBD" packages | head -n 5
    packages/cisco_meraki/changelog.yml:11:      link: TBD
    
    $ grep -RIn "pull/999999" packages | head -n 5
    packages/tenable_io/changelog.yml:124:      link: https://github.com/elastic/integrations/pull/999999
    ```
    
    I also ran the existing dev-script test suite to check baseline behavior around backport helper scripts:
    
    ```
    $ .buildkite/scripts/run_dev_scripts_tests.sh
    --- Running get_release_commit.sh tests
    FAIL: finds commit for package at packages/<p>/ (unquoted version) — expected '43bb655db0', got '9004e054'
    FAIL: finds commit for package at packages/<p>/ (quoted version) — expected '8b024204a8', got '9004e054'
    Error: no commit found that released version '9.3.8' of package 'security_detection_engine'.
    
    Detailed Action Plan
    1. Add .github/workflows/auto-backport.yml:

      • Trigger on push to main and issue_comment edited.
      • For push: recover merged PR by SHA and hard-gate to base main.
      • For issue_comment: require github.event.issue.pull_request != null, merged PR, base main, and comment containing <!-- backport-checklist -->.
      • Add skip gate for automation label (same intent as existing label-gate workflows).
      • Parse checked checklist rows and dedupe per target branch by searching existing auto-backport/<pkg>-<target>-<sha> PRs/heads.
      • Call dev/scripts/backport_apply.sh --json once per checked branch; on each result update the checklist line with either ✅ PR or ⚠️ conflict details.
    2. Add .github/workflows/post-backport-branch.yml:

      • Trigger pull_request opened for base backport-*, plus startsWith(github.head_ref, 'auto-backport/').
      • Resolve package name from auto-backport/<package>-<series>-<sha>.
      • Resolve package filesystem path (must support nested package dirs) and patch only that package changelog.yml link to ${{ github.event.pull_request.html_url }}.
      • Commit/push once; do not run on synchronize to avoid loops.
    3. Reuse existing safety/idempotency patterns directly from current workflows:

      • PR-target verification and duplicate suppression style from notify-package-docs-failure.yml:40-50.
      • Label-skip gate style from trigger-pr-actions-detective.yml:40.
    4. Wire ordering with foundation issues:

    5. Update docs once workflows merge:

      • Amend docs/extend/developer-workflow-support-old-package.md:117-121 to describe automated changelog-link/PR flow and manual fallback path.
    Related Items
    Type Link Relevance
    Issue #19210 Inventory + active-branch foundation
    Issue #19212 backport_apply.sh execution primitive
    Issue #19213 Checklist production/update mechanism
    Issue #19215 Downstream changelog sync automation
    Issue #19016 Parent initiative for routine backport tooling
    PR #19104 Merged helper script/docs for release-commit lookup
    PR #19171 Mentioned by issue thread for changelog-link validation (could not inspect details due MCP integrity policy constraints in this run)
    File .buildkite/pipeline.backport.yml:13-19,20-50 Current UI-only backport branch creation
    File docs/ci_pipelines.md:225-227 Documentation confirms UI-only backport pipeline
    File .github/workflows/notify-package-docs-failure.yml:40-50 Safe PR verification and dedupe pattern to reuse

    Note

    🔒 Integrity filter blocked 8 items

    The following items were blocked because they don't meet the GitHub integrity level.

    • #18828 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
    • #18141 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
    • #15287 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
    • #11158 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
    • #13662 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
    • #19171 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
    • [CI] Add Buildkite step to validate changelog PR links #19171 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
    • #19186 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

    To allow these resources, lower min-integrity in your GitHub frontmatter:

    tools:
      github:
        min-integrity: approved  # merged | approved | unapproved | none

    What is this? | From workflow: Issue Triage

    Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

  3. mrodm commented on Jun 1, 2026

    @mrodm
    CollaboratorAuthor

    Updated the description to capture a security requirement for the issue_comment trigger: the editing actor must be verified as a repo collaborator with write or admin permission before the job proceeds. Without this, any GitHub user on a public repo can craft a comment that passes all the existing guards and trigger backport_apply.sh with arbitrary inputs. Added the guard to the Triggers spec, Behaviour steps, and Considerations.

  4. mrodm commented on Jul 2, 2026

    @mrodm
    CollaboratorAuthor

    In the description of this issue, it is mentioned to use the automation label.
    In this PR #19930 , it is being proposed to change the automation label to backport:sync-changelog. Thereby, this process uses a specific label that is not used by other automation processes.

  5. mrodm commented on Jul 6, 2026

    @mrodm
    CollaboratorAuthor

    It would be needed to update the message posted in the checklist comment to mention that with these changes are going to be created Pull Requests targeting the backport branches selected.

    Maybe something like this could feat:

    PRs will be created automatically on merge, or when you update this checklist after merge.
    

    Related https://github.com/elastic/integrations/pull/19997/changes#r3530418845

  6. mrodm commented on Jul 8, 2026

    @mrodm
    CollaboratorAuthor

    It will be needed to recover the checkboxes in the checklist comment.
    For context #19997 (comment)

  7. self-assigned this
    on Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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