Compare commits

...

1 Commits

Author SHA1 Message Date
overtrue 0f77a65743 ci(arch): ratchet ecstore module-level lint blankets
backlog#1823 step 9. The step 2 burn-down cleared every module-level #![allow(dead_code)] from ecstore, but nothing stops the next PR from adding one back, and the other module-level blankets (unused_variables, unused_must_use, clippy::all) were never counted at all.

Two rules land in check_architecture_migration_rules.sh:

ecstore must carry zero module-level #![allow(dead_code)]. The count is asserted at zero rather than registered, since there is nothing left to grandfather; a genuinely unused item takes an item-level allow with a reason, which is what step 2 produced roughly 350 times.

Every other module-level blanket must match scripts/ecstore-module-lint-register.txt exactly — 94 entries across 33 files, nearly all of them in the MinIO-ported client module.

The exact match is the point. A "no new entries" rule lets the register rot into an amnesty list, which is the failure mode backlog#1834 found in the layer-dependency baseline: rebuilt at 29 entries, 2 more added by a later PR, zero retired. Here, removing a blanket costs one line in the register, so it can only shrink, and adding one shows up as a register line a reviewer has to accept.

Verified by injection, since a guard that cannot fail is worse than no guard: adding a dead_code blanket, adding an unregistered clippy::all blanket, and deleting a registered blanket without updating the register each produce the expected failure, and the tree passes once reverted.

make pre-commit exit 0.

Ref rustfs/backlog#1823 (step 9).
2026-08-17 00:02:48 +08:00
2 changed files with 164 additions and 0 deletions
@@ -5450,6 +5450,57 @@ if [[ -s "$LEAF_CRATE_DEP_HITS_FILE" ]]; then
report_failure "leaf crates (config/credentials/crypto/io-metrics/madmin) must not depend on internal rustfs-* crates (allowlist: io-metrics -> rustfs-s3-ops, backlog#1834): $(paste -sd '; ' "$LEAF_CRATE_DEP_HITS_FILE")"
fi
# --- ecstore module-level lint blankets (backlog#1823 step 9) ---
#
# Two rules:
# 1. ecstore carries zero `#![allow(dead_code)]` after the step 2 burn-down;
# the count may only stay at zero.
# 2. Every other module-level blanket (unused_variables / unused_must_use /
# clippy::all) must match scripts/ecstore-module-lint-register.txt exactly.
# Exact match, not "no additions": a one-way rule lets the register rot
# into an amnesty list, which is what backlog#1834 found in the
# layer-dependency baseline.
ECSTORE_LINT_REGISTER="${ROOT_DIR}/scripts/ecstore-module-lint-register.txt"
ECSTORE_DEAD_CODE_HITS="${TMP_DIR}/ecstore_dead_code_blankets.txt"
ECSTORE_LINT_ACTUAL="${TMP_DIR}/ecstore_lint_actual.txt"
ECSTORE_LINT_EXPECTED="${TMP_DIR}/ecstore_lint_expected.txt"
(
cd "$ROOT_DIR"
rg -n '^#!\[allow\(dead_code\)\]' crates/ecstore/src/ 2>/dev/null || true
) >"$ECSTORE_DEAD_CODE_HITS"
if [[ -s "$ECSTORE_DEAD_CODE_HITS" ]]; then
report_failure "ecstore must carry no module-level #![allow(dead_code)] (backlog#1823 step 2 cleared them; re-add an item-level allow with a reason instead): $(paste -sd '; ' "$ECSTORE_DEAD_CODE_HITS")"
fi
(
cd "$ROOT_DIR"
rg -n '^#!\[allow\((unused_variables|unused_must_use|clippy::all)\)\]' crates/ecstore/src/ 2>/dev/null |
sed -E 's#^([^:]+):[0-9]+:\#!\[allow\(([^)]+)\)\]#\1|\2#' | sort -u
) >"$ECSTORE_LINT_ACTUAL"
if [[ ! -f "$ECSTORE_LINT_REGISTER" ]]; then
report_failure "missing scripts/ecstore-module-lint-register.txt (backlog#1823 step 9)"
else
rg -v '^\s*(#|$)' "$ECSTORE_LINT_REGISTER" | sort -u >"$ECSTORE_LINT_EXPECTED"
while IFS= read -r entry; do
[[ -z "$entry" ]] && continue
if ! rg -qxF "$entry" "$ECSTORE_LINT_EXPECTED"; then
report_failure "new ecstore module-level lint blanket '${entry}' is not in scripts/ecstore-module-lint-register.txt; prefer an item-level allow with a reason, or add the line with a rationale in the PR description (backlog#1823 step 9)"
fi
done <"$ECSTORE_LINT_ACTUAL"
while IFS= read -r entry; do
[[ -z "$entry" ]] && continue
if ! rg -qxF "$entry" "$ECSTORE_LINT_ACTUAL"; then
report_failure "scripts/ecstore-module-lint-register.txt lists '${entry}' but the blanket is gone; delete the line in the same PR so the register can only shrink (backlog#1823 step 9)"
fi
done <"$ECSTORE_LINT_EXPECTED"
fi
if (( FAILURES > 0 )); then
exit 1
fi
+113
View File
@@ -0,0 +1,113 @@
# ecstore module-level lint blanket register (backlog#1823 step 9)
#
# Each line is `path|lint` for a `#![allow(<lint>)]` at the top of an ecstore
# source file. These blankets disable the lint for a whole module, so a real
# defect introduced anywhere in the file goes unreported.
#
# The guard in scripts/check_architecture_migration_rules.sh compares this file
# against the tree and fails on ANY difference, in either direction:
#
# * a blanket not listed here -> new suppression, justify it in the PR
# * a line here with no blanket -> delete the line in the same PR
#
# Exact match is deliberate. A "no new entries" rule would let the register rot
# into an amnesty list, which is the failure mode backlog#1834 found in the
# layer-dependency baseline. Removing a blanket must cost one line here, so the
# register can only shrink.
#
# `#![allow(dead_code)]` is NOT listed: ecstore carries zero of those after the
# step 2 burn-down, and the guard asserts that count stays at zero.
crates/ecstore/src/bucket/lifecycle/tier_last_day_stats.rs|clippy::all
crates/ecstore/src/bucket/lifecycle/tier_last_day_stats.rs|unused_must_use
crates/ecstore/src/bucket/lifecycle/tier_last_day_stats.rs|unused_variables
crates/ecstore/src/bucket/lifecycle/tier_sweeper.rs|clippy::all
crates/ecstore/src/bucket/lifecycle/tier_sweeper.rs|unused_must_use
crates/ecstore/src/bucket/lifecycle/tier_sweeper.rs|unused_variables
crates/ecstore/src/client/api_error_response.rs|clippy::all
crates/ecstore/src/client/api_error_response.rs|unused_must_use
crates/ecstore/src/client/api_error_response.rs|unused_variables
crates/ecstore/src/client/api_get_object.rs|clippy::all
crates/ecstore/src/client/api_get_object.rs|unused_must_use
crates/ecstore/src/client/api_get_object.rs|unused_variables
crates/ecstore/src/client/api_get_options.rs|clippy::all
crates/ecstore/src/client/api_get_options.rs|unused_must_use
crates/ecstore/src/client/api_get_options.rs|unused_variables
crates/ecstore/src/client/api_list.rs|clippy::all
crates/ecstore/src/client/api_list.rs|unused_must_use
crates/ecstore/src/client/api_list.rs|unused_variables
crates/ecstore/src/client/api_put_object.rs|clippy::all
crates/ecstore/src/client/api_put_object.rs|unused_must_use
crates/ecstore/src/client/api_put_object.rs|unused_variables
crates/ecstore/src/client/api_put_object_common.rs|clippy::all
crates/ecstore/src/client/api_put_object_common.rs|unused_must_use
crates/ecstore/src/client/api_put_object_common.rs|unused_variables
crates/ecstore/src/client/api_put_object_multipart.rs|clippy::all
crates/ecstore/src/client/api_put_object_multipart.rs|unused_must_use
crates/ecstore/src/client/api_put_object_multipart.rs|unused_variables
crates/ecstore/src/client/api_put_object_streaming.rs|clippy::all
crates/ecstore/src/client/api_put_object_streaming.rs|unused_must_use
crates/ecstore/src/client/api_put_object_streaming.rs|unused_variables
crates/ecstore/src/client/api_remove.rs|clippy::all
crates/ecstore/src/client/api_remove.rs|unused_must_use
crates/ecstore/src/client/api_remove.rs|unused_variables
crates/ecstore/src/client/api_s3_datatypes.rs|clippy::all
crates/ecstore/src/client/api_s3_datatypes.rs|unused_must_use
crates/ecstore/src/client/api_s3_datatypes.rs|unused_variables
crates/ecstore/src/client/api_stat.rs|clippy::all
crates/ecstore/src/client/api_stat.rs|unused_must_use
crates/ecstore/src/client/api_stat.rs|unused_variables
crates/ecstore/src/client/bucket_cache.rs|clippy::all
crates/ecstore/src/client/bucket_cache.rs|unused_must_use
crates/ecstore/src/client/bucket_cache.rs|unused_variables
crates/ecstore/src/client/checksum.rs|clippy::all
crates/ecstore/src/client/checksum.rs|unused_must_use
crates/ecstore/src/client/checksum.rs|unused_variables
crates/ecstore/src/client/constants.rs|unused_must_use
crates/ecstore/src/client/constants.rs|unused_variables
crates/ecstore/src/client/credentials.rs|clippy::all
crates/ecstore/src/client/credentials.rs|unused_must_use
crates/ecstore/src/client/credentials.rs|unused_variables
crates/ecstore/src/client/object_api_utils.rs|clippy::all
crates/ecstore/src/client/object_api_utils.rs|unused_must_use
crates/ecstore/src/client/object_api_utils.rs|unused_variables
crates/ecstore/src/client/transition_api.rs|clippy::all
crates/ecstore/src/client/transition_api.rs|unused_must_use
crates/ecstore/src/client/transition_api.rs|unused_variables
crates/ecstore/src/services/event_notification.rs|unused_variables
crates/ecstore/src/services/tier/tier.rs|clippy::all
crates/ecstore/src/services/tier/tier.rs|unused_must_use
crates/ecstore/src/services/tier/tier.rs|unused_variables
crates/ecstore/src/services/tier/tier_admin.rs|clippy::all
crates/ecstore/src/services/tier/tier_admin.rs|unused_must_use
crates/ecstore/src/services/tier/tier_admin.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_aliyun.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_aliyun.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_aliyun.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_azure.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_azure.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_azure.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_gcs.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_gcs.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_gcs.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_huaweicloud.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_huaweicloud.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_huaweicloud.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_minio.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_minio.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_minio.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_r2.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_r2.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_r2.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_rustfs.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_rustfs.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_rustfs.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_s3.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_s3.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_s3.rs|unused_variables
crates/ecstore/src/services/tier/warm_backend_tencent.rs|clippy::all
crates/ecstore/src/services/tier/warm_backend_tencent.rs|unused_must_use
crates/ecstore/src/services/tier/warm_backend_tencent.rs|unused_variables
crates/ecstore/src/set_disk/mod.rs|unused_variables