From 1832f099f296366276668b484653e926da9c8ad4 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Aug 2026 15:23:56 -0400 Subject: [PATCH] backport: add pre-merge label-on-comment support; add copilot-instructions and auto-labeler for changelog exemptions (#10211) * Initial plan * chore: commit backport.yml pre-merge labeling enhancement Co-authored-by: kaovilai <11228024+kaovilai@users.noreply.github.com> * chore: auto-label kind/changelog-not-required for non-shipping PRs; add copilot-instructions.md Co-authored-by: kaovilai <11228024+kaovilai@users.noreply.github.com> * chore: add changelog naming convention to copilot-instructions; tighten labeler exclusions Co-authored-by: kaovilai <11228024+kaovilai@users.noreply.github.com> * fix: use # as sed delimiter to avoid conflict with | in alternation group Co-authored-by: kaovilai <11228024+kaovilai@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kaovilai <11228024+kaovilai@users.noreply.github.com> --- .github/copilot-instructions.md | 70 +++++++++++++++++++++++++ .github/labeler.yml | 22 ++++++++ .github/workflows/backport.yml | 93 +++++++++++++++++++++++++++++++-- 3 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..c4e7d9923 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,70 @@ +# GitHub Copilot instructions for velero-io/velero + +## Changelog requirement + +Velero uses per-PR changelog fragments that are assembled into release notes. + +### File naming convention + +Every shipping PR must add exactly **one** file at: + +``` +changelogs/unreleased/- +``` + +- `` is the pull request number (e.g. `10200`). +- `` is the GitHub login of the PR author (e.g. `jdoe`). +- The file has **no extension**. +- The file content is a single line describing the change (the PR title is a + sensible default). + +**Example:** PR #10200 by `jdoe` → `changelogs/unreleased/10200-jdoe` + +The easiest way to create this file is: + +```bash +make new-changelog CHANGELOG_BODY="Brief description of the change" +``` + +`make new-changelog` reads the PR number and author from `gh pr view`; the file +is written automatically to the correct path with the correct name. + +The CI check (`hack/changelog-check.sh`) looks for +`changelogs/unreleased/-*` and fails if no file is found. + +### When a changelog is NOT required + +A changelog entry is **not** required when a PR exclusively changes non-shipping +content, i.e. the only files touched belong to one or more of these categories: + +| Category | Paths | +|---|---| +| GitHub Actions / CI workflows | `.github/**` | +| Documentation | `site/content/docs/**`, `site/**`, `docs/**`, `*.md` | +| Website (non-docs) | `site/**` (excluding `site/content/docs/**`) | + +When you open or review a PR that falls into one of the above categories (and does +**not** modify `pkg/`, `internal/`, `cmd/`, `vendor/`, `hack/`, `Makefile`, +`go.mod`, `go.sum`, or `changelogs/**`), apply the label +**`kind/changelog-not-required`** instead of requesting a changelog entry. The +`labeler.yml` auto-labeler handles this automatically for most cases; apply the +label manually if the auto-labeler did not. + +## Backport / cherry-pick workflow + +Velero uses `.github/workflows/backport.yml` to automate cherry-picks onto release +branches. + +- **Before merge:** comment `/backport release-1.17` (or `/cherrypick release-1.17`) + to add the label `backport release-1.17` to the PR. Multiple branches can be + space-delimited: `/backport release-1.17 release-1.18`. The label causes the + backport to run automatically when the PR merges. +- **After merge:** the same comment immediately creates the backport PR. +- Only repository **owners, members, and collaborators** may trigger these commands. + +## General coding guidelines + +- Follow the existing code style of the file being edited. +- Add unit tests for new exported functions in `pkg/`. +- Do not commit secrets, credentials, or API tokens. +- Keep PRs focused; prefer small, reviewable changes over large omnibus PRs. diff --git a/.github/labeler.yml b/.github/labeler.yml index 183f8365f..880977caf 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -31,3 +31,25 @@ has-e2e-2tests: has-unit-tests: - changed-files: - any-glob-to-any-file: pkg/**/*_test.go +# PRs that only touch non-shipping files (.github/ config, workflows, or docs) +# do not need a changelog entry; auto-apply the label so the changelog check passes. +kind/changelog-not-required: + - all: + - changed-files: + - any-glob-to-any-file: + - .github/**/* + - site/content/docs/**/* + - site/**/* + - '*.md' + - docs/**/* + - all-globs-to-all-files: + - '!pkg/**' + - '!internal/**' + - '!cmd/**' + - '!vendor/**' + - '!hack/**' + - '!Makefile' + - '!go.mod' + - '!go.sum' + - '!changelogs/**' + - '!**/*.go' diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index d0e13129e..670e16103 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -1,8 +1,21 @@ name: Backport merged pull request # Automates cherry-picking merged PRs onto release branches. -# - Label a merged PR with e.g. `backport release-1.17` to backport on merge. -# - Or comment `/backport release-1.17` or `/cherrypick release-1.17` on a merged PR. +# +# Pre-merge (open PR): +# An authorized /backport or /cherrypick comment adds one `backport ` +# label per requested branch. These labels are then picked up automatically +# when the PR is merged (see the pull_request_target: closed trigger below). +# +# Post-merge (merged PR): +# - Label a PR with e.g. `backport release-1.17` before merging; the label +# triggers the backport automatically when the PR closes as merged. +# - Comment `/backport release-1.17` or `/cherrypick release-1.17` on an +# already-merged PR to create the backport PR immediately. +# +# In both cases multiple target branches can be space-delimited in a comment: +# /backport release-1.17 release-1.18 +# # See: https://github.com/velero-io/velero/issues/9603 on: @@ -13,7 +26,78 @@ on: permissions: {} +# Shared condition for authorized /backport or /cherrypick comments. +# Used by both jobs below to avoid duplicating the gate logic. +env: + AUTHORIZED_COMMENT: >- + ${{ + github.event_name == 'issue_comment' && + github.event.issue.pull_request != '' && + github.event.comment.user.id != 97796249 && + contains( + fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), + github.event.comment.author_association + ) && + ( + startsWith(github.event.comment.body, '/backport') || + startsWith(github.event.comment.body, '/cherrypick') + ) + }} + jobs: + # ── Pre-merge: convert a /backport or /cherrypick comment into labels ─────── + # When the PR is still open the backport-action cannot run (it requires a + # merged commit). Instead, add one `backport ` label per requested + # branch so that the post-merge job picks them up automatically on close. + label-for-backport: + name: Label PR for deferred backport + # Run only when an authorized command is posted on an *open* (unmerged) PR. + if: > + github.repository == 'velero-io/velero' && + github.event_name == 'issue_comment' && + github.event.issue.pull_request != '' && + github.event.issue.state == 'open' && + github.event.comment.user.id != 97796249 && + contains( + fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), + github.event.comment.author_association + ) && + ( + startsWith(github.event.comment.body, '/backport') || + startsWith(github.event.comment.body, '/cherrypick') + ) + runs-on: ubuntu-latest + permissions: + issues: write # apply labels to the PR (PRs share the issues API) + steps: + - name: Parse branches and apply labels + env: + COMMENT_BODY: ${{ github.event.comment.body }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + PR_NUMBER: ${{ github.event.issue.number }} + run: | + # Extract branch names from the first line of the comment. + # Strip the /backport or /cherrypick prefix; what remains is a + # space-delimited list of target branch names. + line=$(printf '%s' "$COMMENT_BODY" | head -n1 | tr -d '\r') + branches=$(printf '%s' "$line" | sed -E 's#^/(backport|cherrypick)[[:space:]]*##') + + if [ -z "$branches" ]; then + echo "No target branches specified in comment; nothing to label." + exit 0 + fi + + for branch in $branches; do + label="backport ${branch}" + echo "Applying label: '${label}'" + # Create the label if it does not exist yet (idempotent). + gh label create "${label}" --repo "${REPO}" --color "0075ca" \ + --description "Backport to ${branch}" 2>/dev/null || true + gh issue edit "${PR_NUMBER}" --repo "${REPO}" --add-label "${label}" + done + + # ── Post-merge: create backport PRs ───────────────────────────────────────── backport: name: Backport pull request # Exclude comments from the backport-action bot (user id 97796249) to prevent @@ -28,7 +112,8 @@ jobs: contains(toJSON(github.event.pull_request.labels.*.name), '"backport ') ) || ( github.event_name == 'issue_comment' && - github.event.issue.pull_request && + github.event.issue.pull_request != '' && + github.event.issue.state == 'closed' && github.event.comment.user.id != 97796249 && contains( fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), @@ -55,7 +140,7 @@ jobs: # Remaining text is a space-delimited list of target branches # (may be empty, falls back to labels). line=$(printf '%s' "$COMMENT_BODY" | head -n1 | tr -d '\r') - branches=$(printf '%s' "$line" | sed -E 's|^/(backport|cherrypick)[[:space:]]*||') + branches=$(printf '%s' "$line" | sed -E 's#^/(backport|cherrypick)[[:space:]]*##') echo "branches=${branches}" >> "$GITHUB_OUTPUT" - uses: actions/checkout@v7