This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-8624-68578712081006adeaa98dcfa038deff2232dff4 in repository https://gitbox.apache.org/repos/asf/texera.git
commit f9c7b613ef601e38bf8a2134463a623fa94def9a Author: Meng Wang <[email protected]> AuthorDate: Mon Sep 21 20:34:14 2026 +0000 revert: "ci: give GitHub Actions bypass on the release-branch ruleset" (#8624) ### What changes were proposed in this PR? Reverts #8379. GitHub will not create the `Merge Queue (release)` ruleset it adds — asfyaml has rejected it on every push to main since that PR merged, 38 mails to `commits@` so far, the first 49 seconds after the merge: ``` Validation failed while creating ruleset 'Merge Queue (release)': ['Actor GitHub Actions integration must be part of the ruleset source or owner organization'] ``` The fail-safe ordering #8379 built held: the apply aborts on that ruleset, so `Merge Queue` was never shrunk and the release branches were never left uncovered. But the abort takes the whole `github` feature with it, so nothing in `.asf.yaml`'s `github:` block has been applied to this repo since 2026-09-11 — the next label, notification or collaborator change would merge, do nothing, and say so only on a list its author does not read. Two side effects of #8379 go with it. The `push-backports` job's permissions were narrowed to `actions`, `contents`, `issues` and `statuses`; commenting on a pull request is scoped by `pull-requests`, not `issues`, so since 2026-09-11 the step that annotates the original PR when a backport fails has taken four 403s and given up with a warning, leaving the step green. The 2026-09-03 failures (#8347, #8343) did comment and were noticed; #8432, #8494 and #8562 did not. Dropping the block restores the workflow-level scope, which has `pull-requests: write`. The push also goes back to `AUTO_MERGE_TOKEN`, and the `workflow_dispatch` of `Required Checks` that only a `GITHUB_TOKEN` push needed goes with it. This does not revive the backport fast path — that push stays rejected, as it has been since 2026-07-24. Routing a clean backport through a pull request instead is #8378's job, and #8377 stays open until it lands. ### Any related issues, documentation, discussions? Relates to #8377 (closed by #8379, not actually fixed) and #8379. ### How was this PR tested? `git revert` applies cleanly to main, and the resulting `.asf.yaml` is byte-identical to the commit before #8379 — the file was not touched in between — so applying it asks asfyaml for exactly the configuration `GET /repos/apache/texera/rulesets` already returns. `.github/scripts/test_asf_rulesets.sh` is removed with the rest of #8379. Its duplicate-key-strict parse of `.asf.yaml` and every workflow is worth keeping and comes back on its own, without the ruleset assertions that no longer have a subject. ### Was this PR authored or co-authored using generative AI tooling? Yes. Generated-by: Claude Code (claude-opus-5) --- .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(-) diff --git a/.asf.yaml b/.asf.yaml index 7e4f86a375..42316db44a 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 66bd29c3dc..0000000000 --- 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 149c608556..b67fcc90fc 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 42b31d37fd..1db8a52668 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 593c70d130..848104e776 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
