From eb3d0681c76ceb308bf4d4795a88b6e893f805eb Mon Sep 17 00:00:00 2001 From: mengw15 <125719918+mengw15@users.noreply.github.com> Date: Mon, 21 Sep 2026 00:21:41 -0700 Subject: [PATCH] revert: "ci: give GitHub Actions bypass on the release-branch ruleset" This reverts commit 069cd208c68d3f3a8e50d583a0a0ff7e00a4e536 (#8379). GitHub will not create the "Merge Queue (release)" ruleset it adds: Validation failed while creating ruleset 'Merge Queue (release)': ['Actor GitHub Actions integration must be part of the ruleset source or owner organization'] asfyaml has raised it on every push to main since #8379 merged, 38 mails to commits@ so far. The apply fails closed, so the rulesets on GitHub are still the ones from before #8379 -- but the abort takes the whole github feature in .asf.yaml with it, which has therefore been unapplied since 2026-09-11. Reverting also drops the push-backports job's narrowed permissions, which omitted pull-requests and so silenced the failure comment that tells the original PR its backport did not arrive. --- .asf.yaml | 60 +--------- .github/scripts/test_asf_rulesets.sh | 122 --------------------- .github/workflows/direct-backport-push.yml | 36 +----- .github/workflows/required-checks.yml | 2 - amber/dev-requirements.txt | 1 - 5 files changed, 7 insertions(+), 214 deletions(-) delete mode 100755 .github/scripts/test_asf_rulesets.sh diff --git a/.asf.yaml b/.asf.yaml index 7e4f86a3757..42316db44a0 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -69,76 +69,20 @@ github: rebase: false rulesets: - # Rule-for-rule identical to "Merge Queue" below; split out so the bypass - # here stays off main. The bypass exempts actions performed as the GitHub - # Actions app — i.e. any workflow's GITHUB_TOKEN, which is what - # direct-backport-push.yml's fast path pushes with (#8377). It cannot be - # scoped to a single workflow. People and PATs still face every rule. - # - # Listed BEFORE "Merge Queue" deliberately: asfyaml applies rulesets in - # file order, so this one is created before that one stops covering the - # release branches. If GitHub rejects this ruleset, the apply aborts with - # the old protections fully intact; the failure order never leaves the - # release branches uncovered. - - name: "Merge Queue (release)" + - name: Merge Queue target: branch enforcement: active conditions: ref_name: exclude: [] include: + - "~DEFAULT_BRANCH" # Merge queue rules do NOT support wildcard ref patterns, so # release branches must be listed explicitly (not release/*). # Add each release line here as it is cut. - "refs/heads/release/v1.1" - "refs/heads/release/v1.2" - "refs/heads/release/v1.3" - bypass_actors: - # The GitHub Actions app. - - actor_id: 15368 - actor_type: Integration - bypass_mode: always - rules: - - type: deletion - - type: non_fast_forward - - type: merge_queue - parameters: - merge_method: SQUASH - max_entries_to_build: 2 - min_entries_to_merge: 2 - max_entries_to_merge: 5 - min_entries_to_merge_wait_minutes: 3 - grouping_strategy: HEADGREEN - check_response_timeout_minutes: 45 - - type: pull_request - parameters: - allowed_merge_methods: - - squash - dismiss_stale_reviews_on_push: false - require_code_owner_review: false - require_last_push_approval: false - required_approving_review_count: 1 - required_review_thread_resolution: true - - type: required_linear_history - - type: required_status_checks - parameters: - strict_required_status_checks_policy: false - required_status_checks: - - context: Required Checks - - context: Check License Headers - - context: Validate PR title - - - name: Merge Queue - target: branch - enforcement: active - conditions: - ref_name: - exclude: [] - include: - # Release branches carry these same rules in "Merge Queue - # (release)" above — a separate ruleset because its Actions - # bypass must not extend to main. - - "~DEFAULT_BRANCH" rules: - type: deletion - type: non_fast_forward diff --git a/.github/scripts/test_asf_rulesets.sh b/.github/scripts/test_asf_rulesets.sh deleted file mode 100755 index 66bd29c3dc6..00000000000 --- a/.github/scripts/test_asf_rulesets.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# Invariants over the CI configuration that a plain YAML parse cannot see. -# -# 1. "Merge Queue" and "Merge Queue (release)" in .asf.yaml must carry -# identical rules: they are one policy split across two rulesets only so -# the release half can hold an Actions bypass that must not reach main. -# Nothing else keeps the copies from drifting apart. -# 2. .asf.yaml and every workflow must parse with a duplicate-key-strict -# loader. PyYAML silently keeps the last duplicate, but GitHub's loader -# rejects the file, so a duplicated trigger key passes local checks and -# then stops the workflow from ever starting. - -set -uo pipefail - -command -v python3 >/dev/null || { echo "python3 is required to run these tests" >&2; exit 1; } -# Runners ship python3 but not necessarily PyYAML (see release_branches.py); -# CI installs it via amber/dev-requirements.txt. -python3 -c 'import yaml' 2>/dev/null || { echo "PyYAML is required (pip install pyyaml)" >&2; exit 1; } - -cd "$(git rev-parse --show-toplevel)" - -python3 - <<'EOF' -import glob -import sys - -import yaml - - -class StrictLoader(yaml.SafeLoader): - pass - - -def no_duplicates(loader, node, deep=False): - seen = set() - for key_node, _ in node.value: - key = loader.construct_object(key_node, deep=deep) - if key in seen: - raise yaml.YAMLError( - f"duplicate key {key!r} at line {key_node.start_mark.line + 1}" - ) - seen.add(key) - return yaml.SafeLoader.construct_mapping(loader, node, deep) - - -StrictLoader.add_constructor( - yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, no_duplicates -) - -failures = [] - -files = sorted(glob.glob(".github/workflows/*.yml")) + [".asf.yaml"] -for path in files: - with open(path) as fh: - try: - yaml.load(fh, StrictLoader) - except yaml.YAMLError as exc: - failures.append(f"{path}: {exc}") - -with open(".asf.yaml") as fh: - ruleset_list = [ - r for r in yaml.safe_load(fh)["github"]["rulesets"] if isinstance(r, dict) - ] -rulesets = {r.get("name"): r for r in ruleset_list} -main_rs = rulesets.get("Merge Queue") -release_rs = rulesets.get("Merge Queue (release)") -if main_rs is None or release_rs is None: - failures.append( - ".asf.yaml: expected rulesets named 'Merge Queue' and 'Merge Queue (release)'" - ) -elif main_rs["rules"] != release_rs["rules"]: - failures.append( - ".asf.yaml: 'Merge Queue' and 'Merge Queue (release)' rules differ -- " - "these are one policy in two rulesets; change both or neither" - ) -if main_rs is not None and "bypass_actors" in main_rs: - failures.append( - ".asf.yaml: 'Merge Queue' must not carry bypass_actors -- " - "keeping the bypass off main is what the split exists for" - ) -ACTIONS_APP = [{"actor_id": 15368, "actor_type": "Integration", "bypass_mode": "always"}] -if release_rs is not None and release_rs.get("bypass_actors") != ACTIONS_APP: - failures.append( - ".asf.yaml: 'Merge Queue (release)' bypass_actors must be exactly the " - "GitHub Actions app -- widen this list and the test together, deliberately" - ) -names = [r.get("name") for r in ruleset_list] -if main_rs is not None and release_rs is not None and names.index( - "Merge Queue (release)" -) > names.index("Merge Queue"): - failures.append( - ".asf.yaml: 'Merge Queue (release)' must be listed before 'Merge Queue' -- " - "asfyaml applies rulesets in file order, and creating the release ruleset " - "before shrinking the main one is what keeps a rejected run fail-safe" - ) - -for failure in failures: - print(f"FAIL: {failure}") -if failures: - sys.exit(1) -print( - f"OK: {len(files)} files duplicate-key clean; " - "Merge Queue rules identical; bypass only on the release ruleset; " - "release ruleset listed first" -) -EOF diff --git a/.github/workflows/direct-backport-push.yml b/.github/workflows/direct-backport-push.yml index 149c6085566..b67fcc90fc0 100644 --- a/.github/workflows/direct-backport-push.yml +++ b/.github/workflows/direct-backport-push.yml @@ -342,15 +342,6 @@ jobs: needs: discover if: ${{ needs.discover.outputs.has_push == 'true' }} runs-on: ubuntu-latest - permissions: - # Everything this job's steps call, and nothing more: push the - # cherry-pick and comment on the commit (contents), dispatch Required - # Checks (actions), set the per-target commit status (statuses), - # annotate the original PR (issues). - actions: write - contents: write - issues: write - statuses: write name: "backport #${{ matrix.pr_number }} to ${{ matrix.target }}" strategy: fail-fast: false @@ -365,12 +356,11 @@ jobs: uses: actions/checkout@v7 with: fetch-depth: 0 - # Push with the default GITHUB_TOKEN: the release rulesets admit the - # GitHub Actions app as a bypass actor, while a PAT-authored push is - # evaluated as that person and rejected. A GITHUB_TOKEN push starts - # no downstream workflows, so the step after the cherry-pick - # dispatches Required Checks itself — workflow_dispatch runs are the - # documented exception that GITHUB_TOKEN may create. + # Use AUTO_MERGE_TOKEN (fine-grained PAT) so the push to the release + # branch retriggers workflows on that branch. GITHUB_TOKEN-authored + # pushes are excluded from triggering downstream workflows, which + # silences post-merge CI on backport commits. + token: ${{ secrets.AUTO_MERGE_TOKEN || secrets.GITHUB_TOKEN }} - name: Cherry-pick merge commit onto target branch id: cherry_pick env: @@ -581,22 +571,6 @@ jobs: log "new_sha=${new_sha}" echo "new_sha=${new_sha}" >> "$GITHUB_OUTPUT" - - name: Run Required Checks on the pushed release branch - if: success() - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TARGET_BRANCH: ${{ matrix.target }} - run: | - # The GITHUB_TOKEN push above starts no push-triggered workflows; - # dispatch the run the release branch would otherwise have gotten. - # Best-effort: the backport itself has landed, so a dispatch - # failure must not demote this job to failed -- the failure - # reporter below would then claim a landed backport was lost. - if ! gh workflow run required-checks.yml \ - --repo "${GITHUB_REPOSITORY}" --ref "${TARGET_BRANCH}"; then - echo "::warning::Could not start Required Checks on ${TARGET_BRANCH}; start it manually from the Actions tab." - fi - - name: Annotate original PR and commit on success if: success() uses: actions/github-script@v9 diff --git a/.github/workflows/required-checks.yml b/.github/workflows/required-checks.yml index 42b31d37fd8..1db8a52668e 100644 --- a/.github/workflows/required-checks.yml +++ b/.github/workflows/required-checks.yml @@ -30,8 +30,6 @@ on: - labeled - unlabeled merge_group: - # Also dispatched by direct-backport-push.yml after its GITHUB_TOKEN push - # to a release branch, which starts no push-triggered runs. workflow_dispatch: permissions: diff --git a/amber/dev-requirements.txt b/amber/dev-requirements.txt index 593c70d1308..848104e776a 100644 --- a/amber/dev-requirements.txt +++ b/amber/dev-requirements.txt @@ -42,5 +42,4 @@ textual==8.2.8 # Reads bin/k8s/values.yaml in bin/k8s/tests/test_helm_values.sh. That check fails # rather than skipping when this is missing, so the suite cannot go green by accident. -# Also read by .github/scripts/test_asf_rulesets.sh (infra job shell tests). PyYAML==6.0.2