sunchao commented on code in PR #5976:
URL: https://github.com/apache/datafusion-comet/pull/5976#discussion_r4127435969


##########
.github/actions/build-native-ci/action.yaml:
##########
@@ -0,0 +1,81 @@
+# 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.
+
+name: Build or restore the Linux CI native library
+description: 'Reuse an exact-input native library, otherwise build it with the 
CI profile'
+runs:
+  using: composite
+  steps:
+    - name: Pin native build flags
+      shell: bash
+      run: echo 'RUSTFLAGS=-Ctarget-cpu=x86-64-v3 -Clink-arg=-fuse-ld=bfd' >> 
"$GITHUB_ENV"

Review Comment:
   Fixed in de25d50f. RUSTFLAGS is now step-scoped: the fingerprint step 
defines it once and exports a step output that the Cargo step consumes. Nothing 
writes these flags to GITHUB_ENV, so later caller steps retain their original 
environment. A regression test executes both action scripts and checks the 
flags seen by the helper/Cargo plus the untouched environment file.



##########
dev/ci/native-cache-key.py:
##########
@@ -0,0 +1,145 @@
+#!/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.
+
+"""Fingerprint the clean Linux checkout and toolchain used by Comet CI.
+
+Run after setup-builder and before Cargo generates source files. This helper
+supports the official Rust container, setup-builder's JDK/packages, and the
+build commands in our workflows; it is not a general local-build cache.
+"""
+
+import argparse
+import hashlib
+import importlib.util
+import json
+import os
+from pathlib import Path
+import subprocess
+
+
+# Share both the input patterns and their glob semantics with main's warmer.
+SPEC = importlib.util.spec_from_file_location("compute_changes", 
Path(__file__).with_name("compute-changes.py"))
+CHANGES = importlib.util.module_from_spec(SPEC)
+SPEC.loader.exec_module(CHANGES)
+
+
+def digest(value):
+    return hashlib.sha256(json.dumps(value, 
sort_keys=True).encode()).hexdigest()
+
+
+def command(args, cwd):
+    return subprocess.check_output(args, cwd=cwd, text=True).strip()
+
+
+def source_inputs(root, profile="ci"):
+    """Return dependency and source maps for the selected native build profile.
+
+    Each map contains relative names, Git modes and content digests. Untracked
+    generated Rust, target files and documentation are excluded. CI library
+    builds omit benchmarks; debug checks compile them. Trust only this checkout
+    for the Git read: container steps can run as a different owner than 
checkout.
+    """
+    patterns = CHANGES.NATIVE_LIBRARY_INPUTS if profile == "ci" else 
CHANGES.NATIVE_BUILD_INPUTS
+    inventory = command(["git", "-c", f"safe.directory={root}",
+                         "ls-files", "--stage", "-z"], root)
+    sources = {}
+    for record in inventory.split("\0"):
+        if not record:
+            continue
+        metadata, name = record.split("\t", 1)
+        if CHANGES.matches(patterns, [name]):
+            sources[name] = [metadata.split()[0],

Review Comment:
   Implemented the single-traversal and reusable-matcher parts in de25d50f. 
source_inputs now compiles the shared matcher once and builds both maps in one 
inventory loop; compute-changes uses the same predicate. I retained 
working-tree byte hashing so the key describes the bytes Cargo reads, including 
any tracked file changed by setup. The measured cost is small, and switching to 
index OIDs would weaken that property. Leaving the remaining OID suggestion 
open for your assessment.



##########
dev/ci/native-cache-key.py:
##########
@@ -0,0 +1,145 @@
+#!/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.
+
+"""Fingerprint the clean Linux checkout and toolchain used by Comet CI.
+
+Run after setup-builder and before Cargo generates source files. This helper
+supports the official Rust container, setup-builder's JDK/packages, and the
+build commands in our workflows; it is not a general local-build cache.
+"""
+
+import argparse
+import hashlib
+import importlib.util
+import json
+import os
+from pathlib import Path
+import subprocess
+
+
+# Share both the input patterns and their glob semantics with main's warmer.
+SPEC = importlib.util.spec_from_file_location("compute_changes", 
Path(__file__).with_name("compute-changes.py"))
+CHANGES = importlib.util.module_from_spec(SPEC)
+SPEC.loader.exec_module(CHANGES)
+
+
+def digest(value):
+    return hashlib.sha256(json.dumps(value, 
sort_keys=True).encode()).hexdigest()
+
+
+def command(args, cwd):
+    return subprocess.check_output(args, cwd=cwd, text=True).strip()
+
+
+def source_inputs(root, profile="ci"):
+    """Return dependency and source maps for the selected native build profile.
+
+    Each map contains relative names, Git modes and content digests. Untracked
+    generated Rust, target files and documentation are excluded. CI library
+    builds omit benchmarks; debug checks compile them. Trust only this checkout
+    for the Git read: container steps can run as a different owner than 
checkout.
+    """
+    patterns = CHANGES.NATIVE_LIBRARY_INPUTS if profile == "ci" else 
CHANGES.NATIVE_BUILD_INPUTS
+    inventory = command(["git", "-c", f"safe.directory={root}",
+                         "ls-files", "--stage", "-z"], root)
+    sources = {}
+    for record in inventory.split("\0"):
+        if not record:
+            continue
+        metadata, name = record.split("\t", 1)
+        if CHANGES.matches(patterns, [name]):
+            sources[name] = [metadata.split()[0],
+                             hashlib.sha256((root / 
name).read_bytes()).hexdigest()]
+    dependencies = {name: value for name, value in sources.items()
+                    if Path(name).name in {"Cargo.toml", "Cargo.lock"}}
+    return dependencies, sources
+
+
+def environment_inputs(root, env):
+    """Identify the official tools installed by setup-builder without 
modifying them.
+
+    Rust's versions include the compiler commit; dpkg identifies the installed
+    C/C++/protobuf tools and system libraries. The JDK release file identifies
+    the vendor/build supplying JNI headers and libjvm. Record build overrides,
+    including target-qualified cc variables and HDFS linking options, without
+    including unrelated per-run GitHub variables. The shared setup/build 
actions
+    are hashed separately; caller test configuration does not affect the 
library.
+    """
+    java_home = Path(env["JAVA_HOME"])
+    return {
+        "workspace": str(root),
+        "architecture": command(["uname", "-m"], root),
+        "rust": {tool: command([tool, flag], root / "native")
+                 for tool, flag in (("rustc", "-vV"), ("cargo", "--version"),
+                                    ("rustfmt", "--version"))},
+        "packages": sorted(command(["dpkg-query", "-W",

Review Comment:
   I retained the conservative package/JDK boundary for the reasons in my 
earlier reply. The updated README and PR description explicitly document 
conservative misses and matching producer environments; preflight now rejects 
producer JDK/image/environment drift. The rollout still requires measuring 
actual hits and package/JDK changes behind misses. I have not claimed that the 
narrower dependency set is implemented, and am leaving that design choice open 
for review.



##########
dev/ci/native-cache-key.py:
##########
@@ -0,0 +1,145 @@
+#!/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.
+
+"""Fingerprint the clean Linux checkout and toolchain used by Comet CI.
+
+Run after setup-builder and before Cargo generates source files. This helper
+supports the official Rust container, setup-builder's JDK/packages, and the
+build commands in our workflows; it is not a general local-build cache.
+"""
+
+import argparse
+import hashlib
+import importlib.util
+import json
+import os
+from pathlib import Path
+import subprocess
+
+
+# Share both the input patterns and their glob semantics with main's warmer.
+SPEC = importlib.util.spec_from_file_location("compute_changes", 
Path(__file__).with_name("compute-changes.py"))
+CHANGES = importlib.util.module_from_spec(SPEC)
+SPEC.loader.exec_module(CHANGES)
+
+
+def digest(value):
+    return hashlib.sha256(json.dumps(value, 
sort_keys=True).encode()).hexdigest()
+
+
+def command(args, cwd):
+    return subprocess.check_output(args, cwd=cwd, text=True).strip()
+
+
+def source_inputs(root, profile="ci"):
+    """Return dependency and source maps for the selected native build profile.
+
+    Each map contains relative names, Git modes and content digests. Untracked
+    generated Rust, target files and documentation are excluded. CI library
+    builds omit benchmarks; debug checks compile them. Trust only this checkout
+    for the Git read: container steps can run as a different owner than 
checkout.
+    """
+    patterns = CHANGES.NATIVE_LIBRARY_INPUTS if profile == "ci" else 
CHANGES.NATIVE_BUILD_INPUTS
+    inventory = command(["git", "-c", f"safe.directory={root}",
+                         "ls-files", "--stage", "-z"], root)
+    sources = {}
+    for record in inventory.split("\0"):
+        if not record:
+            continue
+        metadata, name = record.split("\t", 1)
+        if CHANGES.matches(patterns, [name]):
+            sources[name] = [metadata.split()[0],
+                             hashlib.sha256((root / 
name).read_bytes()).hexdigest()]
+    dependencies = {name: value for name, value in sources.items()
+                    if Path(name).name in {"Cargo.toml", "Cargo.lock"}}
+    return dependencies, sources
+
+
+def environment_inputs(root, env):
+    """Identify the official tools installed by setup-builder without 
modifying them.
+
+    Rust's versions include the compiler commit; dpkg identifies the installed
+    C/C++/protobuf tools and system libraries. The JDK release file identifies
+    the vendor/build supplying JNI headers and libjvm. Record build overrides,
+    including target-qualified cc variables and HDFS linking options, without
+    including unrelated per-run GitHub variables. The shared setup/build 
actions
+    are hashed separately; caller test configuration does not affect the 
library.
+    """
+    java_home = Path(env["JAVA_HOME"])
+    return {
+        "workspace": str(root),
+        "architecture": command(["uname", "-m"], root),
+        "rust": {tool: command([tool, flag], root / "native")
+                 for tool, flag in (("rustc", "-vV"), ("cargo", "--version"),
+                                    ("rustfmt", "--version"))},
+        "packages": sorted(command(["dpkg-query", "-W",
+                                    
"-f=${binary:Package}\t${Version}\t${Architecture}\n"], root).splitlines()),
+        "java_home": str(java_home),
+        "java_release": (java_home / "release").read_text(),
+        "cargo_home": env.get("CARGO_HOME", str(Path.home() / ".cargo")),
+        "env": {name: value for name, value in env.items()
+                if name.startswith(("CARGO_", "RUST", "HOST_", "TARGET_", 
"HDFS_"))
+                or name.split("_", 1)[0] in {"CC", "CXX", "CFLAGS", 
"CXXFLAGS", "CXXSTDLIB",
+                                           "LDFLAGS", "AR", "ARFLAGS", 
"RANLIB", "RANLIBFLAGS", "PROTOC"}
+                or name in {"JAVA_HOME", "PATH", "HADOOP_HOME", "DOCS_RS",
+                            "CRATE_CC_NO_DEFAULTS", "CROSS_COMPILE"}},
+    }
+
+
+def cache_keys(profile, dependencies, sources, environment):
+    """Return output keys for one pre-build snapshot.
+
+    Only the incremental Cargo cache has a source-independent restore prefix.
+    The library key includes all tracked build inputs and never uses fallback.
+    Both retain the environment: native build scripts can reuse C objects
+    without detecting changes to external compiler binaries or JNI headers.
+    """
+    prefix = f"Linux-cargo-{profile}-v3-{digest([environment, dependencies])}-"
+    return {
+        "cargo-home": environment["cargo_home"],
+        "source-key": prefix + digest(sources),
+        "restore-prefix": prefix,
+        "binary-key": f"Linux-native-ci-v2-{digest([environment, sources])}" 
if profile == "ci" else "",

Review Comment:
   Applied the cleanup in de25d50f: the debug profile now omits the unused 
library-key output (renamed from binary-key), and the profile test checks this. 
As noted earlier, omission does not itself change GitHub's missing-property 
behavior; the action still explicitly requests the CI profile.



-- 
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