This is an automated email from the ASF dual-hosted git repository.

github-actions[bot] pushed a commit to branch release/v1.1.0-incubating
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/release/v1.1.0-incubating by 
this push:
     new 3f087cdf00 feat(ci): gate stacks on a label-to-stacks map (#4640)
3f087cdf00 is described below

commit 3f087cdf00d808f8cfda6068e1c095e8d7b71bd9
Author: Yicong Huang <[email protected]>
AuthorDate: Sat May 2 03:36:10 2026 +0000

    feat(ci): gate stacks on a label-to-stacks map (#4640)
    
    ### What changes were proposed in this PR?
    
    Replace the precheck's hand-written rule cascade in
    `required-checks.yml` (skip all on `docs`/`dev` only, skip frontend if
    no `frontend` label, …) with a static label → required-stacks map. The
    run set is the union of stacks across the PR's current labels.
    
    ```js
    const LABEL_STACKS = {
      frontend:    ["frontend"],
      python:      ["scala", "python"],         // pyamber drives scala 
integration tests too
      engine:      ["scala", "python"],         // amber/** spans both
      service:     ["scala", "agent-service"],
      common:      ["scala"],
      "ddl-change":["scala"],
      ci:          ["frontend", "scala", "python", "agent-service"],
    };
    ```
    
    Per-label contribution to the run set (final stacks = union across all
    PR labels):
    
    | label | frontend | scala | python | agent-service |
    |---|---|---|---|---|
    | `frontend` | ✓ |  |  |  |
    | `python` |  | ✓ | ✓ |  |
    | `engine` |  | ✓ | ✓ |  |
    | `service` |  | ✓ |  | ✓ |
    | `common` |  | ✓ |  |  |
    | `ddl-change` |  | ✓ |  |  |
    | `ci` | ✓ | ✓ | ✓ | ✓ |
    | `docs` / `dev` / `dependencies` / `release/*` / branch-name | | | | |
    
    Labels not in `LABEL_STACKS` (`docs`, `dev`, `dependencies`,
    `release/*`, branch-name labels) contribute no stacks. `dependencies` is
    intentionally a no-op: every dep manifest the labeler matches already
    sits under a component directory and is covered by that component's
    label (`frontend/package.json` → `frontend`, `*-service/build.sbt` →
    `service`, `amber/{,operator-}requirements.txt` → `engine`).
    
    Push and `workflow_dispatch` events keep the all-true default.
    
    ### Any related issues, documentation, discussions?
    
    Closes #4639.
    
    ### How was this PR tested?
    
    To be exercised by this PR's own run on CI: it touches
    `.github/workflows/**`, which gives it the `ci` label, so every stack
    should run. Removing `ci` (manually, for testing) and leaving only
    `docs` should skip everything; adding `frontend` only should run only
    the frontend stack.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Opus 4.7
    
    Co-authored-by: github-actions[bot] 
<github-actions[bot]@users.noreply.github.com>
    Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
    
    (backported from commit 382ebc21b7eaf1c5cb97e24a63a881b836adbcbb)
---
 .github/workflows/required-checks.yml | 68 +++++++++++++++++++++++------------
 1 file changed, 45 insertions(+), 23 deletions(-)

diff --git a/.github/workflows/required-checks.yml 
b/.github/workflows/required-checks.yml
index d9100fc06c..2ce4b809ad 100644
--- a/.github/workflows/required-checks.yml
+++ b/.github/workflows/required-checks.yml
@@ -47,10 +47,10 @@ jobs:
   #     the labels it applies (frontend, docs, dev, ...) are available, then
   #     gate run_* outputs on those labels.
   #   - run_frontend / run_scala / run_python / run_agent_service: gate the
-  #     main build stacks. PRs labelled exclusively with docs and/or dev skip
-  #     every stack; otherwise frontend skips when no `frontend` label is
-  #     present (the other stacks always run when at least one non-docs/dev
-  #     label exists). Push and dispatch events run every stack.
+  #     main build stacks. Each labeler-applied label maps to the stacks it
+  #     requires (LABEL_STACKS below); the run set is the union across all
+  #     PR labels. Empty union (e.g. docs-only / dev-only PRs) skips every
+  #     stack. Push and workflow_dispatch events run every stack.
   #   - backport_targets: JSON array of release/* labels currently on the PR.
   #     Drives the backport matrix; empty array means no backport runs.
   precheck:
@@ -106,31 +106,53 @@ jobs:
               core.info(`PR labels: ${labels.join(", ") || "(none)"}`);
             }
 
-            const SKIP_ONLY = new Set(["docs", "dev"]);
-            const FRONTEND_ONLY_ALLOWED = new Set(["frontend", "docs", "dev"]);
-            const onlySkippable =
-              eventName === "pull_request" &&
-              labels.length > 0 &&
-              labels.every((l) => SKIP_ONLY.has(l));
-            const frontendOnly =
-              eventName === "pull_request" &&
-              labels.includes("frontend") &&
-              labels.every((l) => FRONTEND_ONLY_ALLOWED.has(l));
+            // Map each labeler-applied label to the stacks it requires. The
+            // run set is the union across all PR labels. Labels not listed
+            // here (release/*, feature, fix, refactor) contribute no stacks.
+            // dependencies is intentionally a no-op: every dep manifest the
+            // labeler matches lives under a component dir and is already
+            // covered by that component's label.
+            //
+            //   label                | frontend | scala | python | 
agent-service
+            //   
---------------------|----------|-------|--------|--------------
+            //   frontend             |    x     |       |        |
+            //   python               |          |   x   |   x    |
+            //   engine               |          |   x   |   x    |
+            //   service              |          |   x   |        |     x
+            //   common               |          |   x   |        |
+            //   ddl-change           |          |   x   |        |
+            //   ci                   |    x     |   x   |   x    |     x
+            //   docs / dev / deps /  |          |       |        |
+            //   release/* / branch   |          |       |        |
+            const LABEL_STACKS = {
+              frontend: ["frontend"],
+              python: ["scala", "python"],   // pyamber drives scala 
integration tests too
+              engine: ["scala", "python"],   // amber/** spans both
+              service: ["scala", "agent-service"],
+              common: ["scala"],
+              "ddl-change": ["scala"],
+              ci: ["frontend", "scala", "python", "agent-service"],
+            };
 
             let runFrontend = true;
             let runScala = true;
             let runPython = true;
             let runAgentService = true;
 
-            if (onlySkippable) {
-              runFrontend = runScala = runPython = runAgentService = false;
-              core.info("Labels are docs/dev only; skipping all build 
stacks.");
-            } else if (frontendOnly) {
-              runScala = runPython = runAgentService = false;
-              core.info("Labels touch only frontend; skipping non-frontend 
stacks.");
-            } else if (eventName === "pull_request" && 
!labels.includes("frontend")) {
-              runFrontend = false;
-              core.info("No frontend label; skipping frontend stack.");
+            if (eventName === "pull_request") {
+              const stacks = new Set();
+              for (const label of labels) {
+                for (const stack of LABEL_STACKS[label] || []) {
+                  stacks.add(stack);
+                }
+              }
+              runFrontend = stacks.has("frontend");
+              runScala = stacks.has("scala");
+              runPython = stacks.has("python");
+              runAgentService = stacks.has("agent-service");
+              core.info(
+                `Stacks selected by label union: ${[...stacks].sort().join(", 
") || "(none)"}`
+              );
             }
 
             core.setOutput("run_frontend", runFrontend ? "true" : "false");

Reply via email to