ci: fail format job when rustfmt rewrites any Rust file#44877
Closed
Copilot wants to merge 2 commits into
Closed
Conversation
Agent-Logs-Url: https://github.com/envoyproxy/envoy/sessions/9569953c-ae1b-41e9-9854-fa659fbd8a7e Co-authored-by: phlax <454682+phlax@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix ci/format_pre.sh to fail on unformatted Rust code
ci: fail format job when rustfmt rewrites any Rust file
May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ci/format_pre.shranbazel run @rules_rust//:rustfmt(apply-mode), which always exits 0 — so the format CI job never actually caught rustfmt violations. Unformatted Rust landed onmainat least three times as a result.Change
After the apply-mode rustfmt run, check the working tree for changes and fail if any were made:
falsetriggers the existingERRtrap →rustfmtis appended toFAILED→ script exits non-zero.git diff > "$DIFF_OUTPUT"block at the end captures the rewrite diff for CI artifact upload, identical tocheck_formatfailure behavior.git status --porcelainis empty, the block is skipped.Original prompt
Problem
ci/format_pre.shdoes not actually fail when Rust code is mis-formatted. The rustfmt step is currently:bazel run @rules_rust//:rustfmtisrules_rust's apply-mode runner — it rewrites files in place and exits 0 whether or not it had to change anything. The only place the script reports failure is via theERRtrap appending to theFAILEDarray, so a clean exit means the format job passes even when rustfmt has rewritten files.This has already caused at least three real incidents where unformatted Rust code landed on
main:hickory_dnsPR) — landed with formatting issues.source/extensions/dynamic_modules/builtin_extensions/hickory_dns.rsonly via therustfmt_testBazel target in a downstream test shard.#44276 ("Fix format") had to clean these up after the fact.
The validating target already exists in
source/extensions/dynamic_modules/builtin_extensions/BUILD:…and rules_rust ships
@rules_rust//:rustfmt_check(the same runner in--checkmode), but neither is invoked from theformatCI job. So formatting issues only surface from abazel testshard that happens to include therustfmt_testtarget — which the format-only PR check does not run.Goal
Ensure that
ci/format_pre.sh(theformatCI job that runs on every PR) fails when any Rust file under the repo is not rustfmt-clean, so we never again merge a PR that introduces a rustfmt diff.Proposed change
Update the
rustfmtstep inci/format_pre.shso that it both attempts a fix (preserving today's helpful diff-upload-on-failure behaviour) and fails when there is anything to fix. The simplest, least-invasive way to do this is to run the apply-mode rustfmt and then check the working tree:The trailing
falsetriggers the existingERRtrap, which appends toFAILEDand causes the script to exit non‑zero at the end. The existinggit diff > "$DIFF_OUTPUT"block at the bottom of the script will then upload the rustfmt diff as a CI artefact, exactly like it already does forcheck_formatfailures, so contributors get a copy-pasteable diff.Alternatively (and equivalently in effect), invoke the check-mode runner directly, which exits non‑zero on diff without modifying files:
The first option is preferred because it preserves the auto-fix-and-upload-diff UX that the other steps already use; please go with that unless
rustfmt_checkintegrates more cleanly.Acceptance criteria
ci/format_pre.shexits non‑zero when any Rust source in the tree is not rustfmt-clean against the repo'srustfmt.toml.rustfmtas the failing step (the existingCURRENT=rustfmt+FAILEDmechanism is sufficient).$DIFF_OUTPUTand uploaded as a CI artefact when rustfmt is the cause of failure (this should "just work" given the existing block at the bottom of the script — please verify).Verification
bazel run //ci:format(or runci/format_pre.shdirectly) on a clean checkout — should pass..rsfile undersource/extensions/dynamic_modules/and re-run — the script must exit non‑zero withrustfmtlisted in theTESTS FAILEDblock, andfix_format.diffmust contain the expected rewrite.Out of scope
rustfmt.tomlor anyrustfmt_testtargets.tools/code_format/check_formator the spelling/check_format steps.Files to touch
ci/format_pre.sh— the rustfmt step.That should be the entire change.
The following is the prior conversation context from the user's chat exploration (may be truncated):
User: ```
diff --git a/source/extensions/dynamic_modules/builtin_extensions/hickory_dns.rs b/source/extensions/dynamic_modules/builtin_exte...
This pull request was created from Copilot chat.