bitflicker64 commented on code in PR #3271:
URL: https://github.com/apache/hugegraph/pull/3271#discussion_r4187729414


##########
.github/scripts/ci-policy.py:
##########
@@ -0,0 +1,443 @@
+#!/usr/bin/env python3
+# 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.
+
+"""Conservative CI selection and GitHub-verified test receipt reuse."""
+
+import argparse
+import hashlib
+import io
+import json
+import os
+from pathlib import Path
+import subprocess
+import zipfile
+from urllib.parse import urlencode
+
+MODULES = {
+    "server": ["server", "commons", "struct", "pd", "store", "hstore", 
"cluster", "docker", "helm", "dependency_license"],
+    "toolchain": ["client", "loader", "tools", "spark", "hubble", "go"],
+}
+PREFIXES = {
+    "server": {"hugegraph-server/": "server", "hugegraph-commons/": "commons",
+               "hugegraph-struct/": "struct", "hugegraph-pd/": "pd", 
"hugegraph-store/": "store",
+               "hugegraph-cluster-test/": "cluster", "docker/": "docker", 
"helm/": "helm"},
+    "toolchain": {"hugegraph-client/": "client", "hugegraph-client-go/": "go",
+                  "hugegraph-loader/": "loader", "hugegraph-tools/": "tools",
+                  "hugegraph-spark-connector/": "spark", "hugegraph-hubble/": 
"hubble"},
+}
+WORKFLOWS = {
+    "server": {"server-ci.yml": ["server"], "commons-ci.yml": ["commons"],
+               "pd-store-ci.yml": ["pd", "store", "hstore"], 
"cluster-test-ci.yml": ["cluster"],
+               "docker-build-ci.yml": ["docker"], "helm-chart-ci.yml": 
["helm"],
+               "codeql-analysis.yml": [], "riscv64-ci.yml": ["server"], 
"check-dependencies.yml": ["dependency_license"]},
+    "toolchain": {"client-ci.yml": ["client"], "client-go-ci.yml": ["go"],
+                  "loader-ci.yml": ["loader"], "tools-ci.yml": ["tools"],
+                  "spark-connector-ci.yml": ["spark"], "hubble-ci.yml": 
["hubble"],
+                  "codeql-analysis.yml": []},
+}
+DEPENDENTS = {
+    "server": {"commons": ["server", "pd", "store", "hstore", "cluster"],
+               "struct": ["server", "pd", "store", "hstore", "cluster"],
+               "server": ["cluster"], "pd": ["store", "hstore", "cluster"],
+               "store": ["hstore", "cluster"], "hstore": ["cluster"]},
+    "toolchain": {"client": ["loader", "tools", "spark", "hubble"], "loader": 
["hubble"]},
+}
+
+
+def git(*args):
+    return subprocess.check_output(["git", *args], text=True).strip()
+
+
+def api(path, binary=False):
+    result = subprocess.run(["gh", "api", "--method", "GET", path], 
check=True, capture_output=True, timeout=30)
+    return result.stdout if binary else json.loads(result.stdout)
+
+
+def documentation(path, mode="100644"):
+    """Only prose and static documentation assets; never source or config."""
+    if mode != "100644":
+        return False
+    p = Path(path)
+    prose_names = {"README.md", "README_CN.md", "README_ZH.md", "AGENTS.md"}
+    module_roots = {prefix.rstrip("/") for mapping in PREFIXES.values() for 
prefix in mapping}
+    module_roots.update("hugegraph-server/" + module for module in [
+        "hugegraph-api", "hugegraph-core", "hugegraph-dist", 
"hugegraph-example",
+        "hugegraph-hbase", "hugegraph-hstore", "hugegraph-rocksdb", 
"hugegraph-test"])
+    if p.name in prose_names and (str(p.parent) == "." or str(p.parent) in 
module_roots):
+        return True
+    return path.startswith("docs/") and p.suffix.lower() in {".md", ".rst", 
".txt", ".png", ".jpg", ".jpeg", ".svg"}
+
+
+def unsafe_documentation(ref, paths):
+    entries = subprocess.check_output(["git", "ls-tree", "-rz", "--full-tree", 
ref]).split(b"\0")
+    for entry in entries:
+        if not entry:
+            continue
+        metadata, name = entry.split(b"\t", 1)
+        path = name.decode("utf-8", "surrogateescape")
+        if path in paths and documentation(path) and metadata.split(b" ", 
1)[0] != b"100644":
+            return True
+    return False
+
+
+def select(project, paths):
+    selected = set()
+    for path in paths:
+        if documentation(path):
+            continue
+        if project == "server" and (Path(path).name == "pom.xml" or 
path.startswith("install-dist/")):
+            selected.add("dependency_license")
+        if path.startswith(".github/workflows/") and Path(path).name in 
WORKFLOWS[project]:
+            selected.update(WORKFLOWS[project][Path(path).name])
+            continue
+        if path.endswith(".proto"):
+            return set(MODULES[project])
+        if project == "server":
+            if path.startswith("hugegraph-server/hugegraph-hstore/"):
+                selected.add("hstore")
+                continue
+            if path.startswith("hugegraph-server/hugegraph-dist/"):
+                selected.update(["server", "pd", "store", "hstore", "docker", 
"cluster"])
+                continue
+            if path.startswith(("hugegraph-server/hugegraph-core/", 
"hugegraph-server/hugegraph-api/",

Review Comment:
   Important: Server paths outside core/api/test/dist do not select the 
PD/Store/HStore suite, so two checks that read those files never run.
   
   `select("server", ["hugegraph-server/pom.xml"])` and `select("server", 
["hugegraph-server/hugegraph-rocksdb/pom.xml"])` both return {server, cluster, 
dependency_license}, so `pd_store` is skipped. But 
`hugegraph-server/hugegraph-hstore/pom.xml` uses `hugegraph-server/pom.xml` as 
its parent, and `pd_store / rocksdb-compatibility` 
(rocksdb-compatibility/run.sh line 49) compares the effective rocksdbjni 
version of `hugegraph-server/hugegraph-rocksdb`. A server-side RocksDB override 
or a parent-pom dependency change passes the gate without either check. On 
master, pd-store-ci ran for `hugegraph-server/**`.
   
   Please add `hstore` for `hugegraph-server/pom.xml` and 
`hugegraph-server/hugegraph-rocksdb/`, or move the compatibility job into the 
server suite.



##########
.github/workflows/server-ci.yml:
##########
@@ -223,51 +270,133 @@ jobs:
           disable_search: true
           fail_ci_if_error: false
 
+  server-rocksdb:
+    name: server_rocksdb (Java ${{ matrix.JAVA_VERSION }})
+    needs: [plan, java-runtime]
+    if: needs.plan.outputs.server == 'true'
+    runs-on: ubuntu-24.04
+    env: *linux-server-env
+    strategy:
+      fail-fast: false
+      matrix:
+        BACKEND: [ rocksdb ]
+        JAVA_VERSION: ${{ fromJSON(needs.java-runtime.outputs.versions || 
'["unavailable"]') }}
+    steps: *linux-server-steps
+
+  commons:
+    name: commons
+    needs: plan
+    if: needs.plan.outputs.commons == 'true'
+    uses: ./.github/workflows/commons-ci.yml
+    secrets: inherit
+
+  pd_store:
+    name: pd_store
+    needs: plan
+    if: needs.plan.outputs.pd_store == 'true'
+    uses: ./.github/workflows/pd-store-ci.yml
+    secrets: inherit
+
+  cluster:
+    name: cluster
+    needs: plan
+    if: needs.plan.outputs.cluster == 'true'
+    uses: ./.github/workflows/cluster-test-ci.yml
+    secrets: inherit
+
+  docker:
+    name: docker
+    needs: plan
+    if: needs.plan.outputs.docker == 'true'
+    uses: ./.github/workflows/docker-build-ci.yml
+    secrets: inherit
+
+  helm:
+    name: helm
+    needs: plan
+    if: needs.plan.outputs.helm == 'true'
+    uses: ./.github/workflows/helm-chart-ci.yml
+
+  dependency_license:

Review Comment:
   Important: `dependency_license` is part of the required 
`affected-module-tests` gate, so the "3rd-party" check becomes a merge blocker, 
while docs/ci.md says license checks run independently.
   
   Any change to a pom.xml, `install-dist/` or an unknown path selects 
`dependency_license`, and `gate()` fails when `dependency-review` fails. On 
master this workflow is not required. The four latest failed "3rd-party" runs 
on other PRs (for example run 37348245036) stop on "Dependency review detected 
vulnerable packages", and in this PR's run `dependency_license / 
dependency-review` failed with "fetch failed", so `affected-module-tests` here 
will fail as well.
   
   Please keep `dependency_license` out of the gate (run it next to 
`check-license`), or state in docs/ci.md and the PR body that it is now 
blocking.



##########
.github/scripts/ci-policy.py:
##########
@@ -0,0 +1,443 @@
+#!/usr/bin/env python3
+# 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.
+
+"""Conservative CI selection and GitHub-verified test receipt reuse."""
+
+import argparse
+import hashlib
+import io
+import json
+import os
+from pathlib import Path
+import subprocess
+import zipfile
+from urllib.parse import urlencode
+
+MODULES = {
+    "server": ["server", "commons", "struct", "pd", "store", "hstore", 
"cluster", "docker", "helm", "dependency_license"],
+    "toolchain": ["client", "loader", "tools", "spark", "hubble", "go"],
+}
+PREFIXES = {
+    "server": {"hugegraph-server/": "server", "hugegraph-commons/": "commons",
+               "hugegraph-struct/": "struct", "hugegraph-pd/": "pd", 
"hugegraph-store/": "store",
+               "hugegraph-cluster-test/": "cluster", "docker/": "docker", 
"helm/": "helm"},
+    "toolchain": {"hugegraph-client/": "client", "hugegraph-client-go/": "go",
+                  "hugegraph-loader/": "loader", "hugegraph-tools/": "tools",
+                  "hugegraph-spark-connector/": "spark", "hugegraph-hubble/": 
"hubble"},
+}
+WORKFLOWS = {
+    "server": {"server-ci.yml": ["server"], "commons-ci.yml": ["commons"],
+               "pd-store-ci.yml": ["pd", "store", "hstore"], 
"cluster-test-ci.yml": ["cluster"],
+               "docker-build-ci.yml": ["docker"], "helm-chart-ci.yml": 
["helm"],
+               "codeql-analysis.yml": [], "riscv64-ci.yml": ["server"], 
"check-dependencies.yml": ["dependency_license"]},
+    "toolchain": {"client-ci.yml": ["client"], "client-go-ci.yml": ["go"],
+                  "loader-ci.yml": ["loader"], "tools-ci.yml": ["tools"],
+                  "spark-connector-ci.yml": ["spark"], "hubble-ci.yml": 
["hubble"],
+                  "codeql-analysis.yml": []},
+}
+DEPENDENTS = {
+    "server": {"commons": ["server", "pd", "store", "hstore", "cluster"],
+               "struct": ["server", "pd", "store", "hstore", "cluster"],
+               "server": ["cluster"], "pd": ["store", "hstore", "cluster"],
+               "store": ["hstore", "cluster"], "hstore": ["cluster"]},
+    "toolchain": {"client": ["loader", "tools", "spark", "hubble"], "loader": 
["hubble"]},
+}
+
+
+def git(*args):
+    return subprocess.check_output(["git", *args], text=True).strip()
+
+
+def api(path, binary=False):
+    result = subprocess.run(["gh", "api", "--method", "GET", path], 
check=True, capture_output=True, timeout=30)
+    return result.stdout if binary else json.loads(result.stdout)
+
+
+def documentation(path, mode="100644"):
+    """Only prose and static documentation assets; never source or config."""
+    if mode != "100644":
+        return False
+    p = Path(path)
+    prose_names = {"README.md", "README_CN.md", "README_ZH.md", "AGENTS.md"}
+    module_roots = {prefix.rstrip("/") for mapping in PREFIXES.values() for 
prefix in mapping}
+    module_roots.update("hugegraph-server/" + module for module in [
+        "hugegraph-api", "hugegraph-core", "hugegraph-dist", 
"hugegraph-example",
+        "hugegraph-hbase", "hugegraph-hstore", "hugegraph-rocksdb", 
"hugegraph-test"])
+    if p.name in prose_names and (str(p.parent) == "." or str(p.parent) in 
module_roots):
+        return True
+    return path.startswith("docs/") and p.suffix.lower() in {".md", ".rst", 
".txt", ".png", ".jpg", ".jpeg", ".svg"}
+
+
+def unsafe_documentation(ref, paths):
+    entries = subprocess.check_output(["git", "ls-tree", "-rz", "--full-tree", 
ref]).split(b"\0")
+    for entry in entries:
+        if not entry:
+            continue
+        metadata, name = entry.split(b"\t", 1)
+        path = name.decode("utf-8", "surrogateescape")
+        if path in paths and documentation(path) and metadata.split(b" ", 
1)[0] != b"100644":
+            return True
+    return False
+
+
+def select(project, paths):
+    selected = set()
+    for path in paths:
+        if documentation(path):
+            continue
+        if project == "server" and (Path(path).name == "pom.xml" or 
path.startswith("install-dist/")):
+            selected.add("dependency_license")
+        if path.startswith(".github/workflows/") and Path(path).name in 
WORKFLOWS[project]:
+            selected.update(WORKFLOWS[project][Path(path).name])
+            continue
+        if path.endswith(".proto"):
+            return set(MODULES[project])
+        if project == "server":
+            if path.startswith("hugegraph-server/hugegraph-hstore/"):
+                selected.add("hstore")
+                continue
+            if path.startswith("hugegraph-server/hugegraph-dist/"):
+                selected.update(["server", "pd", "store", "hstore", "docker", 
"cluster"])
+                continue
+            if path.startswith(("hugegraph-server/hugegraph-core/", 
"hugegraph-server/hugegraph-api/",
+                                "hugegraph-server/hugegraph-test/")):
+                selected.update(["server", "hstore"])
+                continue
+        module = next((value for prefix, value in PREFIXES[project].items() if 
path.startswith(prefix)), None)
+        if module is None or path.endswith(".proto"):
+            return set(MODULES[project])
+        selected.add(module)
+        if project == "server" and ("Dockerfile" in Path(path).name or 
"docker-entrypoint" in path):
+            selected.add("docker")
+    changed = True
+    while changed:
+        before = set(selected)
+        for module in before:
+            selected.update(DEPENDENTS[project].get(module, []))
+        changed = before != selected
+    return selected
+
+
+def fingerprint(ref, policy=False):
+    """Hash blob identities, including paths; exclude only the strict prose 
whitelist."""
+    entries = subprocess.check_output(["git", "ls-tree", "-rz", "--full-tree", 
ref]).split(b"\0")
+    digest = hashlib.sha256()
+    for entry in sorted(entries, key=lambda e: e.split(b"\t", 1)[-1]):
+        if not entry:
+            continue
+        metadata, name = entry.split(b"\t", 1)
+        path = name.decode("utf-8", "surrogateescape")
+        if policy:
+            if not (path.startswith(".github/") or path == ".asf.yaml"):
+                continue
+        elif documentation(path, metadata.split(b" ", 1)[0].decode()):
+            continue
+        digest.update(metadata + b"\t" + name + b"\0")
+    return digest.hexdigest()
+
+
+def remote_fingerprint(repository, sha, policy_only=False, fetch=api):
+    tree = fetch(f"repos/{repository}/git/trees/{sha}?recursive=1")
+    if tree.get("truncated"):
+        raise ValueError("truncated proof tree")
+    digest = hashlib.sha256()
+    for entry in sorted(tree["tree"], key=lambda item: item["path"].encode()):
+        path = entry["path"]
+        if entry["type"] == "tree":
+            continue
+        if policy_only:
+            if not (path.startswith(".github/") or path == ".asf.yaml"):
+                continue
+        elif documentation(path, entry["mode"]):
+            continue
+        digest.update((entry["mode"] + " " + entry["type"] + " " + entry["sha"]
+                       + "\t" + path + "\0").encode())
+    return digest.hexdigest()
+
+
+def proof_pr(plan, run, fetch):
+    associations = run.get("pull_requests", [])
+    if any(pr.get("number") == plan["pr"] for pr in associations):
+        return True
+    owner = run.get("head_repository", {}).get("owner", {}).get("login")
+    branch = run.get("head_branch")
+    if not owner or not branch:
+        return False
+    candidates = pages(f"repos/{plan['repository']}/pulls?" + urlencode({
+        "state": "open", "head": f"{owner}:{branch}"}), fetch)
+    return any(pr.get("number") == plan["pr"]
+               and pr.get("base", {}).get("repo", {}).get("full_name") == 
plan["repository"]
+               and pr.get("head", {}).get("ref") == branch
+               and pr.get("head", {}).get("repo", {}).get("full_name") == 
plan["source"]
+               for pr in candidates)
+
+
+def suites(project, selected):
+    if project == "toolchain":
+        return sorted(selected)
+    result = []
+    if "server" in selected:
+        result.extend(["server_memory", "server_rocksdb"])
+    for module in ["commons", "cluster", "docker", "helm", 
"dependency_license"]:
+        if module in selected:
+            result.append(module)
+    if selected.intersection({"pd", "store", "hstore", "struct"}):
+        result.append("pd_store")
+    return sorted(result)
+
+
+def pages(path, fetch=api):
+    result = []
+    for page in range(1, 11):
+        value = fetch(path + ("&" if "?" in path else "?") + 
urlencode({"per_page": 100, "page": page}))
+        batch = value["jobs"] if isinstance(value, dict) else value
+        result.extend(batch)
+        if len(batch) < 100:
+            return result
+    raise ValueError("API pagination exceeded verification bound")
+
+
+def successful_jobs(repository, run_id, suite, fetch=api):
+    jobs = pages(f"repos/{repository}/actions/runs/{run_id}/jobs", fetch)
+    matching = [job for job in jobs if job.get("name") == suite or 
job.get("name", "").startswith((suite + " / ", suite + " ("))]
+    if not matching or any(job.get("conclusion") != "success" for job in 
matching):
+        raise ValueError("missing or unsuccessful suite jobs")
+    return sorted(job["id"] for job in matching)
+
+
+def validate_receipt(plan, receipt, fetch=api):
+    for key in ["schema", "repository", "project", "pr", "source", "branch", 
"base", "inputFingerprint", "policyFingerprint"]:
+        if receipt.get(key) != plan.get(key):
+            raise ValueError("receipt provenance differs: " + key)
+    proof = receipt.get("proofs", {})
+    required = plan["expected"]
+    if not required or not set(required).issubset(proof):
+        raise ValueError("receipt lacks selected suites")
+    verified = {}
+    for suite in required:
+        item = proof[suite]
+        run = 
fetch(f"repos/{plan['repository']}/actions/runs/{int(item['runID'])}")
+        if (run.get("status") != "completed"
+                or run.get("event") != "pull_request" or run.get("head_sha") 
!= item.get("head")
+                or run.get("workflow_id") != plan["workflowID"]
+                or run.get("head_repository", {}).get("full_name") != 
plan["source"]
+                or run.get("head_branch") != plan["branch"]):
+            raise ValueError("proof run is not a successful trusted workflow")
+        successful_jobs(plan["repository"], item["runID"], 
"affected-module-tests", fetch)
+        if not proof_pr(plan, run, fetch):
+            raise ValueError("proof run lacks matching PR association")
+        merge = 
fetch(f"repos/{plan['repository']}/git/commits/{item['testedMergeSHA']}")
+        if [parent["sha"] for parent in merge.get("parents", [])] != 
[plan["base"], item["head"]]:
+            raise ValueError("tested merge parents differ")
+        actual_input = remote_fingerprint(plan["repository"], 
item["testedMergeSHA"], fetch=fetch)
+        if plan["project"] == "toolchain":
+            context = json.dumps(plan.get("externalInputs", {}), 
sort_keys=True, separators=(",", ":"))
+            actual_input = hashlib.sha256((actual_input + 
context).encode()).hexdigest()
+        if (actual_input != plan["inputFingerprint"] or remote_fingerprint(
+                plan["repository"], item["testedMergeSHA"], policy_only=True, 
fetch=fetch)
+                != plan["policyFingerprint"]):
+            raise ValueError("actual tested inputs differ from claimed 
receipt")
+        ids = successful_jobs(plan["repository"], item["runID"], suite, fetch)
+        if ids != item.get("jobIDs"):
+            raise ValueError("actual job evidence differs")
+        verified[suite] = item
+    return verified
+
+
+def find_reuse(plan, fetch=api):
+    """Receipts are uploaded by this workflow, not read from the PR tree."""
+    repository = plan["repository"]
+    current = 
fetch(f"repos/{repository}/actions/runs/{os.environ['GITHUB_RUN_ID']}")
+    plan["workflowID"] = current["workflow_id"]
+    runs = 
fetch(f"repos/{repository}/actions/workflows/{plan['workflowID']}/runs?" + 
urlencode({

Review Comment:
   Important: Receipt lookup reads only the 30 newest completed pull_request 
runs of this workflow across the whole repository, so a docs follow-up misses 
its own receipt once the tested run leaves that window.
   
   The query has no `branch` filter and no pagination. Right now the 30 newest 
completed PR runs of this workflow (id 92515655) span 2026-10-04 18:36 to 
2026-10-05 17:24 UTC across 10 branches, 14 of them cancelled. A docs commit 
pushed about a day after the tested code push finds no receipt and reruns every 
selected suite, which is the case reuse is meant to save.
   
   Please add `branch=plan["branch"]` to the query (the loop already checks the 
head repository) and page further back with a fixed bound, as `pages()` does 
for jobs.



##########
.github/scripts/ci-policy.py:
##########
@@ -0,0 +1,443 @@
+#!/usr/bin/env python3
+# 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.
+
+"""Conservative CI selection and GitHub-verified test receipt reuse."""
+
+import argparse
+import hashlib
+import io
+import json
+import os
+from pathlib import Path
+import subprocess
+import zipfile
+from urllib.parse import urlencode
+
+MODULES = {
+    "server": ["server", "commons", "struct", "pd", "store", "hstore", 
"cluster", "docker", "helm", "dependency_license"],
+    "toolchain": ["client", "loader", "tools", "spark", "hubble", "go"],
+}
+PREFIXES = {
+    "server": {"hugegraph-server/": "server", "hugegraph-commons/": "commons",
+               "hugegraph-struct/": "struct", "hugegraph-pd/": "pd", 
"hugegraph-store/": "store",
+               "hugegraph-cluster-test/": "cluster", "docker/": "docker", 
"helm/": "helm"},

Review Comment:
   Important: Changes under `docker/` select only the `docker` suite, but the 
Compose tests for those files run only in `server_rocksdb`.
   
   `select("server", ["docker/test-compose.sh"])` and 
`docker/docker-compose.yml` both return {docker}. `docker/test-compose.sh 
render` and `smoke` are called only from the RocksDB lane in server-ci.yml 
("Validate Docker integration", "Run Compose auth-on smoke tests"); 
docker-build-ci.yml never calls them. A Compose change now merges with its own 
tests skipped, while master ran them on every PR. The same applies to 
`hugegraph-store/hg-store-dist/src/assembly/static/bin/util.sh`, which inside 
the gate only the RocksDB lane's check_port test covers.
   
   Please also select `server` for `docker/` (at least the compose files, 
`conf/` and `test-compose.sh`) and for that store `util.sh`, or move these 
steps into the docker suite.



##########
.github/scripts/ci-policy.py:
##########
@@ -0,0 +1,443 @@
+#!/usr/bin/env python3
+# 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.
+
+"""Conservative CI selection and GitHub-verified test receipt reuse."""
+
+import argparse
+import hashlib
+import io
+import json
+import os
+from pathlib import Path
+import subprocess
+import zipfile
+from urllib.parse import urlencode
+
+MODULES = {
+    "server": ["server", "commons", "struct", "pd", "store", "hstore", 
"cluster", "docker", "helm", "dependency_license"],
+    "toolchain": ["client", "loader", "tools", "spark", "hubble", "go"],
+}
+PREFIXES = {
+    "server": {"hugegraph-server/": "server", "hugegraph-commons/": "commons",
+               "hugegraph-struct/": "struct", "hugegraph-pd/": "pd", 
"hugegraph-store/": "store",
+               "hugegraph-cluster-test/": "cluster", "docker/": "docker", 
"helm/": "helm"},
+    "toolchain": {"hugegraph-client/": "client", "hugegraph-client-go/": "go",
+                  "hugegraph-loader/": "loader", "hugegraph-tools/": "tools",
+                  "hugegraph-spark-connector/": "spark", "hugegraph-hubble/": 
"hubble"},
+}
+WORKFLOWS = {
+    "server": {"server-ci.yml": ["server"], "commons-ci.yml": ["commons"],

Review Comment:
   Minor: `server-ci.yml` maps only to `server`, but this file now holds the 
plan, the gate and the calls for every suite.
   
   A PR that edits only the `pd_store`, `commons` or `docker` job in 
server-ci.yml selects server and cluster and skips the edited call. A wrong 
`if:`, `with:` or `secrets:` change then merges green and fails the next 
unrelated PR that selects that suite.
   
   Please map `server-ci.yml` to all server modules.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to