potiuk commented on code in PR #73182: URL: https://github.com/apache/airflow/pull/73182#discussion_r4072929022
########## scripts/ci/prek_cache_markers.py: ########## @@ -0,0 +1,56 @@ +# 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. + +"""Snapshot prek installation metadata used to detect cache repairs.""" + +from __future__ import annotations + +import base64 +import json +import sys +from pathlib import Path + +MARKERS = (("hooks", ".prek-hook.json"), ("repos", ".prek-repo.json")) + + +def snapshot_markers(cache_dir: Path) -> dict[str, str]: + """Return shallow marker paths and their byte-for-byte contents.""" + snapshot = {} + for directory, marker_name in MARKERS: + parent = cache_dir / directory + try: + entries = sorted(parent.iterdir()) + except FileNotFoundError: + continue + for entry in entries: + marker = entry / marker_name + try: + contents = marker.read_bytes() + except FileNotFoundError: + continue + relative_path = marker.relative_to(cache_dir).as_posix() + snapshot[relative_path] = base64.b64encode(contents).decode() + return snapshot Review Comment: **Repair detection fails open when the markers aren't there.** `snapshot_markers()` returns `{}` for a cache with no `hooks/`/`repos/` marker files — the `except FileNotFoundError: continue` on both the directory walk and the marker read. The before and after snapshots then compare equal, so `install-hooks` reports `cache-changed=false` with `change-detection-uncertain=false`, and on a pull-request run with a stash hit `cache-policy` picks `save=false, reason=unchanged`. Correct for a healthy cache today; wrong for a cache whose markers moved. `.prek-hook.json` and `.prek-repo.json` are prek internals, and this PR now puts `prek${PREK_VERSION}` in the cache key precisely because prek gets upgraded. A rename in a future prek makes both snapshots empty, repair detection silently turns off, and the discard-the-repair loop this PR exists to fix comes back — with the step summary reporting `Installation metadata changed: false`, which reads as healthy. Nothing in CI would catch it: `test_real_prek_repair_and_reuse` is the only check that these markers exist at all, and it is gated behind `RUN_PREK_INTEGRATION=1`, which nothing in the repo sets. `test_restored_hooks_are_always_validated` currently pins the fail-open — it asserts `cache-changed == "false"` and `change-detection-uncertain == "false"` for a cache containing no markers whatsoever. The uncertain path already exists and already routes to a save, so failing safe is a couple of lines — when the cache directory has content but the snapshot came back empty, report uncertainty rather than "unchanged". Something like: ```suggestion return snapshot def is_inconclusive(cache_dir: Path, snapshot: dict[str, str]) -> bool: """Whether an empty snapshot means an empty cache or markers we no longer recognise.""" if snapshot or not cache_dir.is_dir(): return False return any(cache_dir.iterdir()) ``` …with `main()` exiting non-zero when it is inconclusive, which the step already treats as `change-detection-uncertain`. -- 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]
