Skip to content

Commit d88f07c

Browse files
author
bootc-dev Bot
committed
Sync common files from infra repository
Synchronized from bootc-dev/infra@d5a5a62. Signed-off-by: bootc-dev Bot <bot@bootc.dev>
1 parent 37cf9e7 commit d88f07c

File tree

3 files changed

+186
-1
lines changed

3 files changed

+186
-1
lines changed

.bootc-dev-infra-commit.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2dd498656b9653c321e5d9a8600e6b506714acb3
1+
d5a5a62c9810a416e4cc98f377c05343393f7c14

AGENTS.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ When generating substantial amounts of code, you SHOULD
2222
include an `Assisted-by: TOOLNAME (MODELNAME)`. For example,
2323
`Assisted-by: Goose (Sonnet 4.5)`.
2424

25+
## Code guidelines
26+
27+
The [REVIEW.md](REVIEW.md) file describes expectations around
28+
testing, code quality, commit organization, etc. If you're
29+
creating a change, it is strongly encouraged after each
30+
commit and especially when you think a task is complete
31+
to spawn a subagent to perform a review using guidelines (alongside
32+
looking for any other issues).
33+
34+
If you are performing a review of other's code, the same
35+
principles apply.
36+
2537
## Follow other guidelines
2638

2739
Look at the project README.md and look for guidelines

REVIEW.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Code Review Guidelines
2+
3+
These guidelines are derived from analysis of code reviews across the bootc-dev
4+
organization (October–December 2024). They represent the collective expectations
5+
and standards that have emerged from real review feedback.
6+
7+
## Testing
8+
9+
Tests are expected for all non-trivial changes - unit and integration by default.
10+
11+
If there's something that's difficult to write a test for at the current time,
12+
please do at least state if it was tested manually.
13+
14+
### Choosing the Right Test Type
15+
16+
Unit tests are appropriate for parsing logic, data transformations, and
17+
self-contained functions. Use integration tests for anything that involves
18+
running containers or VMs.
19+
20+
Default to table-driven tests instead of having a separate unit test per
21+
case. Especially LLMs like to generate the latter, but it can become
22+
too verbose. Context windows matter to both humans and LLMs reading the
23+
code later (this applies outside of unit tests too of course, but it's
24+
easy to generate a *lot* of code for unit tests unnecessarily).
25+
26+
### Separating Parsing from I/O
27+
28+
A recurring theme is structuring code for testability. Split parsers from data
29+
reading: have the parser accept a `&str`, then have a separate function that
30+
reads from disk and calls the parser. This makes unit testing straightforward
31+
without filesystem dependencies.
32+
33+
### Test Assertions
34+
35+
Make assertions strict and specific. Don't just verify that code "didn't crash"—
36+
check that outputs match expected values. When adding new commands or output
37+
formats, tests should verify the actual content, not just that something was
38+
produced.
39+
40+
## Code Quality
41+
42+
### Parsing Structured Data
43+
44+
Never parse structured data formats (JSON, YAML, XML) with text tools like `grep`
45+
or `sed`.
46+
47+
### Shell Scripts
48+
49+
Try to avoid having shell script longer than 50 lines. This commonly occurs
50+
in build system and tests. For the build system, usually there's higher
51+
level ways to structure things (Justfile e.g.) and several of our projects
52+
use the `cargo xtask` pattern to put arbitrary "glue" code in Rust using
53+
the `xshell` crate to keep it easy to run external commands.
54+
55+
### Constants and Magic Values
56+
57+
Extract magic numbers into named constants. Any literal number that isn't
58+
immediately obvious—buffer sizes, queue lengths, retry counts, timeouts—should
59+
be a constant with a descriptive name. The same applies to magic strings:
60+
deduplicate repeated paths, configuration keys, and other string literals.
61+
62+
When values aren't self-explanatory, add a comment explaining why that specific
63+
value was chosen.
64+
65+
### Don't ignore (swallow) errors
66+
67+
Avoid the `if let Ok(v) = ... { }` in Rust, or `foo 2>/dev/null || true`
68+
pattern in shell script by default. Most errors should be propagated by
69+
default. If not, it's usually appropriate to at least log error messages
70+
at a `tracing::debug!` or equivalent level.
71+
72+
Handle edge cases explicitly: missing data, malformed input, offline systems.
73+
Error messages should provide clear context for diagnosis.
74+
75+
### Code Organization
76+
77+
Separate concerns: I/O operations, parsing logic, and business logic belong in
78+
different functions. Structure code so core logic can be unit tested without
79+
external dependencies.
80+
81+
It can be OK to duplicate a bit of code in a slightly different form twice,
82+
but having it happen in 3 places asks for deduplication.
83+
84+
## Commits and Pull Requests
85+
86+
### Commit Organization
87+
88+
Break changes into logical, atomic commits. Reviewers appreciate being able to
89+
follow your reasoning: "Especially grateful for breaking it up into individual
90+
commits so I can more easily follow your train of thought."
91+
92+
Preparatory refactoring should be separate from behavioral changes. Each commit
93+
should tell a clear story and be reviewable independently. Commit messages should
94+
explain the "why" not just the "what," and use imperative mood ("Add feature"
95+
not "Added feature").
96+
97+
### PR Descriptions
98+
99+
PRs should link to the issues they address using `Closes:` or `Fixes:` with
100+
full URLs. One reviewer noted: "I edited this issue just now to have
101+
`Closes: <URL>` but let's try to be sure we're doing that kind of thing in
102+
general in the future."
103+
104+
Document known limitations and caveats explicitly. When approaches have tradeoffs
105+
or don't fully solve a problem, say so. For complex investigations, use collapsible
106+
`<details>` sections to include debugging notes without cluttering the main
107+
description.
108+
109+
Think about broader implications: "But we'll have this problem across all repos
110+
right?" Consider how your change affects the wider ecosystem.
111+
112+
### Keeping PRs Current
113+
114+
Keep PRs rebased on main. When CI failures are fixed in other PRs, rebase to
115+
pick up the fixes. Reference the fixing PR when noting that a rebase is needed.
116+
117+
### Before Merge
118+
119+
Self-review your diff before requesting review. Catch obvious issues yourself
120+
rather than burning reviewer cycles.
121+
122+
Do not add `Signed-off-by` lines automatically—these require explicit human
123+
action after review. If code was AI-assisted, include an `Assisted-by:` trailer
124+
indicating the tool and model used.
125+
126+
127+
## Architecture and Design
128+
129+
### Workarounds vs Proper Fixes
130+
131+
When implementing a workaround, document where the proper fix belongs and link
132+
to relevant upstream issues. Invest time investigating proper fixes before
133+
settling on workarounds.
134+
135+
### Cross-Project Considerations
136+
137+
Prefer pushing fixes upstream when the root cause is in a dependency. Reduce
138+
scope where possible; don't reimplement functionality that belongs elsewhere.
139+
140+
When multiple systems interact (like Renovate and custom sync tooling), be
141+
explicit about which system owns what and how they coordinate.
142+
143+
### Avoiding Regressions
144+
145+
Verify that new code paths handle all cases the old code handled. When rewriting
146+
functionality, ensure equivalent coverage exists.
147+
148+
### Review Requirements
149+
150+
When multiple contributors co-author a PR, bring in an independent reviewer.
151+
152+
## Rust-Specific Guidance
153+
154+
Prefer rustix over `libc`. All `unsafe` code must be very carefully
155+
justified.
156+
157+
### Dependencies
158+
159+
New dependencies should be justified. Glance at existing reverse dependencies
160+
on crates.io to see if a crate is widely used. Consider alternatives: "I'm
161+
curious if you did any comparative analysis at all with alternatives?"
162+
163+
Prefer well-maintained crates with active communities. Consider `cargo deny`
164+
policies when adding dependencies.
165+
166+
### API Design
167+
168+
When adding new commands or options, think about machine-readable output early.
169+
JSON is generally preferred for that.
170+
171+
Keep helper functions in appropriate modules. Move command output formatting
172+
close to the CLI layer, keeping core logic functions focused on their primary
173+
purpose.

0 commit comments

Comments
 (0)