Skip to content

Commit db565a4

Browse files
docs: expand AGENTS.md with test marker guidance and CI audit notes
Document the four-way test marker decision (expectedFailure / expectedFailureIf vs skip / skipIf, with skip reserved for tests that crash the interpreter), add guidance on avoiding zizmor's impostor-commit audit when pinning third-party actions, link the wiki guide for syncing tests from upstream CPython, and note the grep recipe for finding WIP TODO: RUSTPYTHON entries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d3272e7 commit db565a4

1 file changed

Lines changed: 57 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,35 @@ The `Lib/` directory contains Python standard library files copied from the CPyt
8181
- `unittest.skip("TODO: RustPython <reason>")`
8282
- `unittest.expectedFailure` with `# TODO: RUSTPYTHON <reason>` comment
8383

84+
#### Choosing the right marker
85+
86+
When marking a test that fails on RustPython, prefer one of the following forms:
87+
88+
```python
89+
@unittest.expectedFailure # TODO: RUSTPYTHON; <reason>
90+
# or
91+
@unittest.expectedFailureIf(<condition>, "TODO: RUSTPYTHON; <reason>")
92+
```
93+
94+
If the test would crash the interpreter (segfault, Rust panic, abort, infinite loop), use `skip` instead so the rest of the suite can still run:
95+
96+
```python
97+
@unittest.skip("TODO: RUSTPYTHON; <reason>")
98+
# or
99+
@unittest.skipIf(<condition>, "TODO: RUSTPYTHON; <reason>")
100+
```
101+
102+
**When to use which:**
103+
104+
- **Prefer `expectedFailure` / `expectedFailureIf`** by default. The test body still runs, so if RustPython is later fixed, the unexpected pass surfaces immediately and the decorator can be removed. Use the conditional `*If` form when the failure is environment-specific (e.g., a platform or build flag).
105+
- **Use `skip` / `skipIf` only when running the test would take down the test process** — segfaults, Rust panics, aborts, or hangs that block subsequent tests. Skipping keeps the suite usable; `expectedFailure` cannot help here, because the test body still executes.
106+
107+
To find WIP entries that are partly modified and may need follow-up:
108+
109+
```bash
110+
grep -d recurse 'TODO: RUSTPYTHON' Lib/test/
111+
```
112+
84113
### Clean Build
85114

86115
When you modify bytecode instructions, a full clean is required:
@@ -258,9 +287,37 @@ See DEVELOPMENT.md "CPython Version Upgrade Checklist" section.
258287
- Document that it requires PEP 695 support
259288
- Focus on tests that can be fixed through Rust code changes only
260289

290+
## CI Workflows and Security Audits
291+
292+
PR CI runs [zizmor](https://docs.zizmor.sh/) to audit `.github/workflows/*.yaml` for security issues. The most common failure for contributors editing workflows is the `impostor-commit` audit, which can reject a PR even when the SHA pin "looks correct".
293+
294+
### Avoiding the `impostor-commit` audit
295+
296+
GitHub's fork network lets a commit that exists only on a fork be referenced via the parent repo's `owner/repo` slug. A malicious fork could publish a backdoored commit and reference it as if it lived on the canonical upstream — a hash-pinned `uses:` line that visually matches best practice but actually points into a fork. zizmor's [`impostor-commit` audit](https://docs.zizmor.sh/audits/#impostor-commit) detects this by querying whether the commit really exists in the claimed repo.
297+
298+
**Rule:** when adding or updating a `uses:` line, always pin to a SHA that exists in the **canonical** upstream repo for that action, never one that only exists on a fork.
299+
300+
Verify a pin before pushing:
301+
302+
```bash
303+
# For: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
304+
gh api repos/actions/checkout/commits/de0fac2e4500dabe0009e67214ff5f5447ce83dd --jq .sha
305+
```
306+
307+
If the response is the same SHA, the commit is canonical and the pin is safe. A `404` means the SHA does not exist in `actions/checkout` (it lives only on a fork) — zizmor will flag it as an impostor and CI will fail.
308+
309+
**Repo convention:** every third-party action is pinned to a full 40-char SHA with the human-readable tag in a trailing comment, e.g. `actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2`. Use the same style when adding new actions.
310+
311+
To find the canonical SHA for a tag, use the canonical repo's release/tag page on github.com (the SHA shown next to the tag) or:
312+
313+
```bash
314+
gh api repos/<owner>/<repo>/git/refs/tags/<tag> --jq .object.sha
315+
```
316+
261317
## Documentation
262318

263319
- Check the [architecture document](/architecture/architecture.md) for a high-level overview
264320
- Read the [development guide](/DEVELOPMENT.md) for detailed setup instructions
265321
- Generate documentation with `cargo doc --no-deps --all`
266322
- Online documentation is available at [docs.rs/rustpython](https://docs.rs/rustpython/)
323+
- [How to update test files](https://github.com/RustPython/RustPython/wiki/How-to-update-test-files#checkout-cpython-source-code-initial-setup) — guide for syncing test cases from upstream CPython into the `Lib/` directory

0 commit comments

Comments
 (0)