Skip to content

Commit aa605bf

Browse files
yonromaiclaude
andcommitted
fix: detect missing proto outputs in iris hatch build hook
The build hook only compared timestamps to decide if regeneration was needed, so adding a new .proto file (query.proto in #3649) without regenerating left query_pb2.py missing — breaking all local iris CLI usage. Add _has_missing_outputs() to check that every .proto has its _pb2.py counterpart, and use it in both the rebuild decision and the npx/script fallback paths so they raise instead of silently continuing with incomplete outputs. Also add the missing query_pb2 import to rpc/__init__.py (required by the descriptor pool load order since cluster.proto imports query.proto). Fixes #3709 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 73970cc commit aa605bf

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

lib/iris/hatch_build.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,29 @@ def _outputs_exist(root: Path, output_globs: list[str]) -> bool:
5757
return _oldest_mtime(root, output_globs) > 0.0
5858

5959

60+
def _has_missing_outputs(root: Path, source_globs: list[str]) -> bool:
61+
"""Return True if any .proto source is missing its corresponding _pb2.py."""
62+
for pattern in source_globs:
63+
for proto_path in root.glob(pattern):
64+
pb2_path = proto_path.with_name(proto_path.stem + "_pb2.py")
65+
if not pb2_path.exists():
66+
return True
67+
return False
68+
69+
6070
def _needs_rebuild(root: Path, source_globs: list[str], output_globs: list[str]) -> bool:
61-
"""Return True if any source file is strictly newer than the oldest output file.
71+
"""Return True if outputs are incomplete or stale.
72+
73+
Checks two conditions:
74+
1. Any .proto source is missing its _pb2.py output (new proto added).
75+
2. Any source file is strictly newer than the oldest output file.
6276
6377
Uses a 60-second tolerance because zip archives (used by task bundles)
6478
can extract files with slightly different timestamps, causing spurious
6579
rebuilds.
6680
"""
81+
if _has_missing_outputs(root, source_globs):
82+
return True
6783
source_newest = _newest_mtime(root, source_globs)
6884
output_oldest = _oldest_mtime(root, output_globs)
6985
return source_newest > output_oldest + 60.0
@@ -78,14 +94,15 @@ def initialize(self, version: str, build_data: dict) -> None:
7894

7995
def _maybe_generate_protos(self, root: Path) -> None:
8096
outputs_present = _outputs_exist(root, _PROTO_OUTPUT_GLOBS)
97+
outputs_complete = outputs_present and not _has_missing_outputs(root, _PROTO_SOURCE_GLOBS)
8198

82-
if outputs_present and not _needs_rebuild(root, _PROTO_SOURCE_GLOBS, _PROTO_OUTPUT_GLOBS):
99+
if outputs_complete and not _needs_rebuild(root, _PROTO_SOURCE_GLOBS, _PROTO_OUTPUT_GLOBS):
83100
logger.info("Protobuf outputs are up-to-date, skipping generation")
84101
return
85102

86103
generate_script = root / "scripts" / "generate_protos.py"
87104
if not generate_script.exists():
88-
if not outputs_present:
105+
if not outputs_complete:
89106
raise RuntimeError(
90107
"Protobuf outputs are missing and scripts/generate_protos.py not found. "
91108
"Cannot build iris without generated protobuf files."
@@ -94,7 +111,7 @@ def _maybe_generate_protos(self, root: Path) -> None:
94111
return
95112

96113
if shutil.which("npx") is None:
97-
if not outputs_present:
114+
if not outputs_complete:
98115
raise RuntimeError(
99116
"Protobuf outputs are missing and npx is not installed. "
100117
"Install Node.js (which provides npx) to generate protobuf files: "

lib/iris/src/iris/rpc/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
# Import order matters for proto descriptor pool: each module must be loaded
5-
# after its dependencies. Chain: time → config → vm → cluster.
5+
# after its dependencies. Chain: time → config → vm → query → cluster.
66
from iris.rpc import time_pb2 as time_pb2
77
from iris.rpc import config_pb2 as config_pb2
88
from iris.rpc import vm_pb2 as vm_pb2
9+
from iris.rpc import query_pb2 as query_pb2
910
from iris.rpc import cluster_pb2 as cluster_pb2

0 commit comments

Comments
 (0)