From 26f78c9950f4bcd2932ae6ff57b38a2bd1c0601f Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 26 May 2026 12:03:28 +0200 Subject: [PATCH 1/3] ci: add pull-requests permissions to auto locking workflow (#10454) --- .github/workflows/lock-closed-issues.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lock-closed-issues.yml b/.github/workflows/lock-closed-issues.yml index 117a63df9f03..45aa4a1817e8 100644 --- a/.github/workflows/lock-closed-issues.yml +++ b/.github/workflows/lock-closed-issues.yml @@ -13,6 +13,7 @@ jobs: name: Lock Closed Issues permissions: issues: write # to lock issue + pull-requests: write # to lock prs steps: - uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6.0.0 with: From 52a91af2ec54e4066b3c904c1658eb764f34e538 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 26 May 2026 19:16:04 +0900 Subject: [PATCH 2/3] chore: document release branch and backporting branch convention (#10451) --- CONTRIBUTING.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a96cb2490ac..512c2dfb4fa3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -118,6 +118,49 @@ These measures help reduce maintenance burden and keep the team's work efficient > The following section is mostly for maintainers who have commit access, but it's helpful to go through if you intend to make non-trivial contributions to the codebase. +### Release Branches + +Public support ranges are documented in [Releases](./docs/releases.md). This section describes how maintainers map those ranges to Git branches for releases and backports. These names refer to branches, not release tags; release tags always include the full version, for example `v4.1.8`. + +- `main` is the active development branch for the next release line. +- `vN` is the latest maintained minor line for non-main major version `N`. +- `vN.M` is an older minor line for major version `N`, kept when that exact minor still needs releases or backports. + +As a hypothetical example, if `v5.1.2` is the latest Vitest release, and the latest releases for older majors are `v4.1.7` and `v3.2.4`, the branch shape can be: + +- `main` is the active development branch for `5.1.x`. +- `v5.0` is an older minor line for Vitest 5. +- `v4` is the latest maintained minor line for Vitest 4, so it is the `4.1.x` line. +- `v4.0` is an older minor line for Vitest 4. +- `v3` is the latest maintained minor line for Vitest 3, so it is the `3.2.x` line. +- `v3.1` and `v3.0` are older minor lines for Vitest 3. + +The `v5` branch does not exist yet. It will be created from the latest v5 minor only after `main` moves on to a newer release line, such as `6.0.0` or often `6.0.0-beta.x`. + +For backports, first use the public support policy to decide which version ranges are supported, then map them to branches: + +- Changes can land as usual on the `main` branch first. +- If the fix targets the latest maintained minor of major version `N`, target `vN`. This is the default backport target for a supported non-main major. +- If the fix also needs an older maintained minor `N.M`, target `vN.M`. + +For example, using the hypothetical `v5.1.2` release above, the public support policy covers regular fixes for `5.1.x` and important fixes or security patches for `5.0.x` and `4.1.x`: + +- fixes for `5.1.x` target `main` +- backports to `5.0.x` target `v5.0` +- backports to `4.1.x` target `v4` + +No backport is made to `v3` unless the support policy changes or maintainers decide on an explicit exception. + +Backport PR titles should include the target branch in a `[backport to x]` marker, for example `fix: [backport to v5.0] ...` or `fix: [backport to v4] ...`. Branch names never include patch versions. + +#### Documentation Branches + +The release branches are also linked with the documentation site releases: + +- `main` is the source for unreleased documentation at . +- `release` points to the latest stable release line used for . Release managers update it manually for non-beta releases from `main`; it is not moved for older-line backports. +- `vN` branches are used for old major documentation sites. For example, uses `v3`. + ### Issue Triaging Workflow ```mermaid From 6718dda2665e0c185f6e88616b1e674011c0846c Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 26 May 2026 12:19:28 +0200 Subject: [PATCH 3/3] ci: fix "needs reproduction" closing behaviour (#10455) --- .github/actions/issues-helper/action.yml | 27 +++++++++----- .github/workflows/issue-close-require.yml | 44 ++--------------------- 2 files changed, 22 insertions(+), 49 deletions(-) diff --git a/.github/actions/issues-helper/action.yml b/.github/actions/issues-helper/action.yml index 6faeceb23d06..604a42416f18 100644 --- a/.github/actions/issues-helper/action.yml +++ b/.github/actions/issues-helper/action.yml @@ -18,7 +18,7 @@ inputs: description: Comment body. Required for `create-comment`. inactive-day: required: false - description: Close issues with no activity for at least this many days. Required for `close-issues`. + description: Close issues whose matching label was added at least this many days ago. Required for `close-issues`. runs: using: composite @@ -68,6 +68,7 @@ runs: const labels = process.env.INPUT_LABELS const inactiveDay = Number(process.env.INPUT_INACTIVE_DAY) const cutoff = new Date(Date.now() - inactiveDay * 24 * 60 * 60 * 1000) + const labelSet = new Set(labels.split(',').map(l => l.trim())) const issues = await github.paginate(github.rest.issues.listForRepo, { owner: context.repo.owner, @@ -77,20 +78,30 @@ runs: per_page: 100, }) - const stale = issues.filter(issue => - !issue.pull_request && new Date(issue.updated_at) <= cutoff - ) + let closed = 0 + for (const issue of issues) { + const events = await github.paginate(github.rest.issues.listEvents, { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + per_page: 100, + }) + const labeledAt = events + .filter(e => e.event === 'labeled' && labelSet.has(e.label?.name)) + .at(-1)?.created_at + + if (!labeledAt || new Date(labeledAt) > cutoff) continue - for (const issue of stale) { - console.log(`Closing issue #${issue.number}, last updated at ${issue.updated_at}`) + console.log(`Closing #${issue.number}, labeled at ${labeledAt}`) await github.rest.issues.update({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issue.number, state: 'closed', }) + closed++ } - if (stale.length === 0) { - console.log(`No inactive issues with label "${labels}" found`) + if (closed === 0) { + console.log(`No stale items with label "${labels}" found`) } diff --git a/.github/workflows/issue-close-require.yml b/.github/workflows/issue-close-require.yml index acf65cbac4ea..3f88deccb2c9 100644 --- a/.github/workflows/issue-close-require.yml +++ b/.github/workflows/issue-close-require.yml @@ -8,12 +8,13 @@ on: permissions: {} jobs: - close-issues: + close-stale: runs-on: ubuntu-slim - name: Close Marked Issues + name: Close Marked Issues and PRs permissions: contents: read # to check out the repo for local actions issues: write # to close issues + pull-requests: write # to close pull requests steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -32,42 +33,3 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} labels: maybe automated inactive-day: 3 - - close-prs: - runs-on: ubuntu-slim - name: Close Marked PRs - permissions: - issues: read # to query PRs by label via the issues API - pull-requests: write # to close pull requests - steps: - - name: maybe automated PRs - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const cutoff = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000) - - const issues = await github.paginate(github.rest.issues.listForRepo, { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - labels: 'maybe automated', - per_page: 100, - }) - - const prs = issues.filter(issue => - issue.pull_request && new Date(issue.updated_at) <= cutoff - ) - - for (const pr of prs) { - console.log(`Closing PR #${pr.number}, last updated at ${pr.updated_at}`) - await github.rest.pulls.update({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: pr.number, - state: 'closed', - }) - } - - if (prs.length === 0) { - console.log('No inactive maybe automated PRs found') - }