Skip to content

Commit 9e7de37

Browse files
author
bootc-dev Bot
committed
Sync common files from infra repository
Synchronized from bootc-dev/infra@fd33b19. Signed-off-by: bootc-dev Bot <bot@bootc.dev>
1 parent 2db2824 commit 9e7de37

7 files changed

Lines changed: 282 additions & 13 deletions

File tree

.bootc-dev-infra-commit.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
b23aa64010d014befa5adc5bc54363b6fb60a3e4
1+
fd33b19a2003b20f68550980b7e03bc959f9f444

.github/actions/bootc-ubuntu-setup/action.yml

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,15 @@ runs:
6161
id: set_arch
6262
shell: bash
6363
run: echo "ARCH=$(arch)" >> $GITHUB_ENV
64-
# We often use Rust, so set up opinionated default caching
65-
- name: Setup Rust cache
66-
uses: Swatinem/rust-cache@v2
67-
with:
68-
cache-all-crates: true
69-
# Only generate caches on push to git main
70-
save-if: ${{ github.ref == 'refs/heads/main' }}
71-
# Suppress actually using the cache for builds running from
72-
# git main so that we avoid incremental compilation bugs
73-
lookup-only: ${{ github.ref == 'refs/heads/main' }}
7464
# Install libvirt stack if requested
7565
- name: Install libvirt and virtualization stack
7666
if: ${{ inputs.libvirt == 'true' }}
7767
shell: bash
7868
run: |
7969
set -xeuo pipefail
80-
export BCVK_VERSION=0.6.0
81-
/bin/time -f '%E %C' sudo apt install -y libkrb5-dev pkg-config libvirt-dev genisoimage qemu-utils qemu-kvm virtiofsd libvirt-daemon-system
70+
export BCVK_VERSION=0.9.0
71+
# see https://github.com/bootc-dev/bcvk/issues/176
72+
/bin/time -f '%E %C' sudo apt install -y libkrb5-dev pkg-config libvirt-dev genisoimage qemu-utils qemu-kvm virtiofsd libvirt-daemon-system python3-virt-firmware
8273
# Something in the stack is overriding this, but we want session right now for bcvk
8374
echo LIBVIRT_DEFAULT_URI=qemu:///session >> $GITHUB_ENV
8475
td=$(mktemp -d)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: 'Setup Rust'
2+
description: 'Install Rust toolchain with caching and nextest'
3+
runs:
4+
using: 'composite'
5+
steps:
6+
- name: Install Rust toolchain
7+
uses: dtolnay/rust-toolchain@stable
8+
- name: Install nextest
9+
uses: taiki-e/install-action@v2
10+
with:
11+
tool: nextest
12+
- name: Setup Rust cache
13+
uses: Swatinem/rust-cache@v2
14+
with:
15+
cache-all-crates: true
16+
# Only generate caches on push to git main
17+
save-if: ${{ github.ref == 'refs/heads/main' }}
18+
# Suppress actually using the cache for builds running from
19+
# git main so that we avoid incremental compilation bugs
20+
lookup-only: ${{ github.ref == 'refs/heads/main' }}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Gate PRs on OpenSSF Scorecard regressions.
2+
#
3+
# See also: https://github.com/ossf/scorecard/issues/1270
4+
name: OpenSSF Scorecard
5+
6+
on:
7+
pull_request:
8+
branches:
9+
- main
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
scorecard:
16+
name: Scorecard
17+
runs-on: ubuntu-24.04
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0
23+
24+
- name: Check for regressions
25+
uses: bootc-dev/actions/openssf-scorecard@main
26+
with:
27+
base-sha: ${{ github.event.pull_request.base.sha }}
28+
head-sha: ${{ github.event.pull_request.head.sha }}

.github/workflows/rebase.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Automatic Rebase
2+
on:
3+
pull_request:
4+
types: [labeled]
5+
6+
permissions:
7+
contents: read
8+
9+
jobs:
10+
rebase:
11+
name: Rebase
12+
if: github.event.label.name == 'needs-rebase'
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Generate Actions Token
16+
id: token
17+
uses: actions/create-github-app-token@v2
18+
with:
19+
app-id: ${{ secrets.APP_ID }}
20+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
21+
owner: ${{ github.repository_owner }}
22+
23+
- name: Checkout
24+
uses: actions/checkout@v6
25+
with:
26+
token: ${{ steps.token.outputs.token }}
27+
fetch-depth: 0
28+
29+
- name: Automatic Rebase
30+
uses: peter-evans/rebase@v4
31+
with:
32+
token: ${{ steps.token.outputs.token }}
33+
34+
- name: Remove needs-rebase label
35+
if: always()
36+
uses: actions/github-script@v8
37+
with:
38+
github-token: ${{ steps.token.outputs.token }}
39+
script: |
40+
await github.rest.issues.removeLabel({
41+
owner: context.repo.owner,
42+
repo: context.repo.repo,
43+
issue_number: context.issue.number,
44+
name: 'needs-rebase'
45+
});

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)