This is an automated email from the ASF dual-hosted git repository.
Yicong-Huang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git
The following commit(s) were added to refs/heads/main by this push:
new 382ebc21b7 feat(ci): gate stacks on a label-to-stacks map (#4640)
382ebc21b7 is described below
commit 382ebc21b7eaf1c5cb97e24a63a881b836adbcbb
Author: Yicong Huang <[email protected]>
AuthorDate: Fri May 1 20:35:49 2026 -0700
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]>
---
.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");