From 1b2c4ab02068207ab0348f5d68bbcdbfb64ca41d Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Thu, 21 May 2026 21:07:43 -0600 Subject: [PATCH 1/2] fix: Restore release PR auto-merge --- .github/actions/check-release-pr/action.yml | 15 ++++++++------- .github/workflows/test-js-packages.yml | 8 ++++---- .github/workflows/turborepo-test.yml | 12 ++++++------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/.github/actions/check-release-pr/action.yml b/.github/actions/check-release-pr/action.yml index 5e787410f3703..8220f8105e9fb 100644 --- a/.github/actions/check-release-pr/action.yml +++ b/.github/actions/check-release-pr/action.yml @@ -1,11 +1,12 @@ name: Check Release PR description: | Detects automated release PRs created by github-actions[bot] with title - matching "release(turborepo):*". These PRs only contain version bumps and - can skip full test suites. + matching "release(turborepo):*". These PRs only contain generated release + updates and can skip full test suites. This action also validates that release PRs only modify expected files - (version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG). + (version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, + pnpm-lock.yaml, and Turborepo skill Markdown files). outputs: is-release-pr: @@ -58,7 +59,7 @@ runs: echo "$CHANGED_FILES" # Validate each file matches expected release patterns - ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml)$" + ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/.*\.md)$" INVALID_FILES="" while IFS= read -r file; do @@ -68,10 +69,10 @@ runs: done <<< "$CHANGED_FILES" if [[ -n "$INVALID_FILES" ]]; then - echo "::error::Release PR contains unexpected files that are not version-related:" + echo "::error::Release PR contains unexpected files that are not generated release updates:" echo "$INVALID_FILES" - echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, or pnpm-lock.yaml" + echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or Turborepo skill Markdown files" exit 1 fi - echo "Release PR content validation passed - only version-related files changed" + echo "Release PR content validation passed - only generated release files changed" diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index f5bf8ecddd8ad..20aea455c06a5 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -54,7 +54,7 @@ jobs: echo "Changed files in release PR:" printf '%s\n' "$CHANGED_FILES" - ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml)$" + ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/.*\.md)$" INVALID_FILES="" while IFS= read -r file; do if [[ -n "$file" && ! "$file" =~ $ALLOWED_PATTERN ]]; then @@ -63,14 +63,14 @@ jobs: done <<< "$CHANGED_FILES" if [[ -n "$INVALID_FILES" ]]; then - echo "::error::Release PR contains unexpected files that are not version-related:" + echo "::error::Release PR contains unexpected files that are not generated release updates:" printf '%s\n' "$INVALID_FILES" - echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, or pnpm-lock.yaml" + echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or Turborepo skill Markdown files" exit 1 fi echo "is-release-pr=true" >> "$GITHUB_OUTPUT" - echo "Release PR content validation passed - only version-related files changed" + echo "Release PR content validation passed - only generated release files changed" - name: Checkout if: steps.check.outputs.is-release-pr != 'true' diff --git a/.github/workflows/turborepo-test.yml b/.github/workflows/turborepo-test.yml index 7e37c041e33d8..9f5e671c8da2a 100644 --- a/.github/workflows/turborepo-test.yml +++ b/.github/workflows/turborepo-test.yml @@ -26,9 +26,9 @@ jobs: rust: ${{ steps.filter.outputs.rust }} native-lib: ${{ steps.filter.outputs.native-lib }} steps: - # Detect automated release PRs which only contain version bumps. + # Detect automated release PRs which only contain generated release updates. # These PRs are created by the release workflow after code has already - # been tested on main. Skipping tests on version-only changes saves CI time. + # been tested on main. Skipping tests on generated release lets us auto-merge release PRs. - name: Check if automated release PR id: check-release shell: bash @@ -63,7 +63,7 @@ jobs: echo "Changed files in release PR:" printf '%s\n' "$CHANGED_FILES" - ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml)$" + ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/.*\.md)$" INVALID_FILES="" while IFS= read -r file; do if [[ -n "$file" && ! "$file" =~ $ALLOWED_PATTERN ]]; then @@ -72,14 +72,14 @@ jobs: done <<< "$CHANGED_FILES" if [[ -n "$INVALID_FILES" ]]; then - echo "::error::Release PR contains unexpected files that are not version-related:" + echo "::error::Release PR contains unexpected files that are not generated release updates:" printf '%s\n' "$INVALID_FILES" - echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, or pnpm-lock.yaml" + echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or Turborepo skill Markdown files" exit 1 fi echo "is-release-pr=true" >> "$GITHUB_OUTPUT" - echo "Release PR content validation passed - only version-related files changed" + echo "Release PR content validation passed - only generated release files changed" - name: Checkout if: steps.check-release.outputs.is-release-pr != 'true' From c1672b17c09d278f03fc9ab64c672ff7cb82ce7e Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Thu, 21 May 2026 21:17:07 -0600 Subject: [PATCH 2/2] fix: Harden release PR detection --- .github/actions/check-release-pr/action.yml | 15 ++++++++++++--- .github/workflows/test-js-packages.yml | 12 ++++++++++-- .github/workflows/turborepo-test.yml | 12 ++++++++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/.github/actions/check-release-pr/action.yml b/.github/actions/check-release-pr/action.yml index 8220f8105e9fb..a5e7b0eae88e5 100644 --- a/.github/actions/check-release-pr/action.yml +++ b/.github/actions/check-release-pr/action.yml @@ -6,7 +6,7 @@ description: | This action also validates that release PRs only modify expected files (version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, - pnpm-lock.yaml, and Turborepo skill Markdown files). + pnpm-lock.yaml, and generated Turborepo skill files). outputs: is-release-pr: @@ -23,6 +23,9 @@ runs: EVENT_NAME: ${{ github.event_name }} PR_AUTHOR: ${{ github.event.pull_request.user.login }} PR_TITLE: ${{ github.event.pull_request.title }} + PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} + PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} + REPOSITORY: ${{ github.repository }} PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | @@ -35,6 +38,12 @@ runs: # Check if PR is from github-actions[bot] with release title if [[ "$PR_AUTHOR" == "github-actions[bot]" && "$PR_TITLE" =~ ^release\(turborepo\): ]]; then + if [[ "$PR_HEAD_REPO" != "$REPOSITORY" || ! "$PR_HEAD_REF" =~ ^staging-[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then + echo "is-release-pr=false" >> $GITHUB_OUTPUT + echo "Not a release PR branch (head: $PR_HEAD_REPO:$PR_HEAD_REF)" + exit 0 + fi + echo "Detected automated release PR from $PR_AUTHOR" echo "Title: $PR_TITLE" echo "is-release-pr=true" >> $GITHUB_OUTPUT @@ -59,7 +68,7 @@ runs: echo "$CHANGED_FILES" # Validate each file matches expected release patterns - ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/.*\.md)$" + ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/SKILL\.md|skills/turborepo/references/best-practices/structure\.md|skills/turborepo/references/configuration/RULE\.md|skills/turborepo/references/environment/RULE\.md|skills/turborepo/references/environment/gotchas\.md)$" INVALID_FILES="" while IFS= read -r file; do @@ -71,7 +80,7 @@ runs: if [[ -n "$INVALID_FILES" ]]; then echo "::error::Release PR contains unexpected files that are not generated release updates:" echo "$INVALID_FILES" - echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or Turborepo skill Markdown files" + echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or generated Turborepo skill files" exit 1 fi diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index 20aea455c06a5..f7a0d169651b9 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -28,6 +28,8 @@ jobs: PR_AUTHOR: ${{ github.event.pull_request.user.login }} PR_TITLE: ${{ github.event.pull_request.title }} PR_NUMBER: ${{ github.event.pull_request.number }} + PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} + PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} REPOSITORY: ${{ github.repository }} GH_TOKEN: ${{ github.token }} run: | @@ -45,6 +47,12 @@ jobs: exit 0 fi + if [[ "$PR_HEAD_REPO" != "$REPOSITORY" || ! "$PR_HEAD_REF" =~ ^staging-[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then + echo "is-release-pr=false" >> "$GITHUB_OUTPUT" + echo "Not a release PR branch (head: $PR_HEAD_REPO:$PR_HEAD_REF)" + exit 0 + fi + CHANGED_FILES=$(gh api --paginate "repos/${REPOSITORY}/pulls/${PR_NUMBER}/files" --jq '.[].filename') if [[ -z "$CHANGED_FILES" ]]; then echo "::error::Unable to determine changed files for release PR" @@ -54,7 +62,7 @@ jobs: echo "Changed files in release PR:" printf '%s\n' "$CHANGED_FILES" - ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/.*\.md)$" + ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/SKILL\.md|skills/turborepo/references/best-practices/structure\.md|skills/turborepo/references/configuration/RULE\.md|skills/turborepo/references/environment/RULE\.md|skills/turborepo/references/environment/gotchas\.md)$" INVALID_FILES="" while IFS= read -r file; do if [[ -n "$file" && ! "$file" =~ $ALLOWED_PATTERN ]]; then @@ -65,7 +73,7 @@ jobs: if [[ -n "$INVALID_FILES" ]]; then echo "::error::Release PR contains unexpected files that are not generated release updates:" printf '%s\n' "$INVALID_FILES" - echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or Turborepo skill Markdown files" + echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or generated Turborepo skill files" exit 1 fi diff --git a/.github/workflows/turborepo-test.yml b/.github/workflows/turborepo-test.yml index 9f5e671c8da2a..13520a49e421d 100644 --- a/.github/workflows/turborepo-test.yml +++ b/.github/workflows/turborepo-test.yml @@ -37,6 +37,8 @@ jobs: PR_AUTHOR: ${{ github.event.pull_request.user.login }} PR_TITLE: ${{ github.event.pull_request.title }} PR_NUMBER: ${{ github.event.pull_request.number }} + PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} + PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} REPOSITORY: ${{ github.repository }} GH_TOKEN: ${{ github.token }} run: | @@ -54,6 +56,12 @@ jobs: exit 0 fi + if [[ "$PR_HEAD_REPO" != "$REPOSITORY" || ! "$PR_HEAD_REF" =~ ^staging-[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then + echo "is-release-pr=false" >> "$GITHUB_OUTPUT" + echo "Not a release PR branch (head: $PR_HEAD_REPO:$PR_HEAD_REF)" + exit 0 + fi + CHANGED_FILES=$(gh api --paginate "repos/${REPOSITORY}/pulls/${PR_NUMBER}/files" --jq '.[].filename') if [[ -z "$CHANGED_FILES" ]]; then echo "::error::Unable to determine changed files for release PR" @@ -63,7 +71,7 @@ jobs: echo "Changed files in release PR:" printf '%s\n' "$CHANGED_FILES" - ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/.*\.md)$" + ALLOWED_PATTERN="^(version\.txt|.*/package\.json|package\.json|Cargo\.toml|Cargo\.lock|.*/Cargo\.toml|CHANGELOG.*|pnpm-lock\.yaml|skills/turborepo/SKILL\.md|skills/turborepo/references/best-practices/structure\.md|skills/turborepo/references/configuration/RULE\.md|skills/turborepo/references/environment/RULE\.md|skills/turborepo/references/environment/gotchas\.md)$" INVALID_FILES="" while IFS= read -r file; do if [[ -n "$file" && ! "$file" =~ $ALLOWED_PATTERN ]]; then @@ -74,7 +82,7 @@ jobs: if [[ -n "$INVALID_FILES" ]]; then echo "::error::Release PR contains unexpected files that are not generated release updates:" printf '%s\n' "$INVALID_FILES" - echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or Turborepo skill Markdown files" + echo "::error::Release PRs should only modify version.txt, package.json, Cargo.toml, Cargo.lock, CHANGELOG, pnpm-lock.yaml, or generated Turborepo skill files" exit 1 fi