|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +This file provides guidance to coding agents when working with code in this repository. |
| 4 | + |
| 5 | +## What this is |
| 6 | + |
| 7 | +Please is a cross-language build system written in Go. This repo builds itself: `plz` is used to |
| 8 | +build `plz`. That bootstrap relationship shapes nearly everything below — most workflows involve |
| 9 | +building a new `please` binary and then running it against this same repo. |
| 10 | + |
| 11 | +## Commands |
| 12 | + |
| 13 | +Building requires an existing Please. `./pleasew` downloads/uses one if you don't have `plz` on |
| 14 | +your `$PATH`; substitute it for `plz` in any command below. |
| 15 | + |
| 16 | +```bash |
| 17 | +./bootstrap.sh # Build please from scratch with `go run`, then run all tests |
| 18 | +./bootstrap.sh --skip_tests # Just the build (alias: plz bootonly) |
| 19 | +plz build //src:please # Incremental rebuild -> plz-out/bin/src/please |
| 20 | +plz test //src/... # Run tests |
| 21 | +./test.sh # What bootstrap.sh runs: unit tests, then e2e separately |
| 22 | +``` |
| 23 | + |
| 24 | +Test selection: |
| 25 | + |
| 26 | +```bash |
| 27 | +plz test //src/core:core_test # One target |
| 28 | +plz test //src/core:core_test TestFoo # One test within a target (positional arg = selector) |
| 29 | +plz test //src/... --exclude=e2e # Skip end-to-end tests |
| 30 | +plz test //test/... --include=e2e # Only end-to-end tests |
| 31 | +plz test //src/core:core_test --rerun # Force rerun even if the hash is unchanged |
| 32 | +plz cover //src/... # Tests with coverage |
| 33 | +``` |
| 34 | + |
| 35 | +Results land in `plz-out/log/test_results.xml`; logs in `plz-out/log/`. |
| 36 | + |
| 37 | +Lint and format: |
| 38 | + |
| 39 | +```bash |
| 40 | +plz lint # golangci-lint over src/... and tools/..., plus a `plz fmt` check |
| 41 | +plz autofix # plz fmt -w, gofmt -s -w src tools test, and regenerate codegen |
| 42 | +plz fmt -w # Format BUILD files only |
| 43 | +plz puku sync # Reconcile third_party/go BUILD files with go.mod |
| 44 | +``` |
| 45 | + |
| 46 | +Testing a change to Please against the repo itself: |
| 47 | + |
| 48 | +```bash |
| 49 | +plz plz build //src/... # `plz plz` runs the freshly-built in-repo please (alias in .plzconfig) |
| 50 | +plz install # Install the built version into ~/.please |
| 51 | +``` |
| 52 | + |
| 53 | +All tests should be run via plz. Do not use `go test` or `go build` directly unless you have |
| 54 | +a specific reason to; there are differences between how plz and go act which means that some |
| 55 | +tests may not work as expected if run directly with `go`. |
| 56 | + |
| 57 | +## Architecture |
| 58 | + |
| 59 | +`src/please.go` is the CLI entry point — a big `go-flags` struct defining every subcommand. Each |
| 60 | +subcommand assembles a `core.BuildState` and hands it to `plz.Run` (`src/plz/plz.go`), which is the |
| 61 | +orchestrator: it spins up worker pools bounded by local and remote limiters and pulls from the task |
| 62 | +queues that `BuildState` exposes. |
| 63 | + |
| 64 | +The three pipeline stages each have their own package and their own README worth reading before |
| 65 | +changing them: |
| 66 | + |
| 67 | +- **`src/core`** — `BuildTarget`, `BuildLabel`, `BuildGraph`, `Configuration`, `Subrepo`, and |
| 68 | + `BuildState`. Everything hangs off this. The target queuing/activation logic here is the most |
| 69 | + subtle code in the repo: targets are added to the graph inactive, activated when needed, and |
| 70 | + progress through an ordered `BuildTargetState` enum that also acts as the synchronisation |
| 71 | + primitive. All queuing funnels through `QueueTarget()`. |
| 72 | +- **`src/parse`** — parses BUILD files into graph targets. `src/parse/asp` is a hand-written |
| 73 | + interpreter for the BUILD language: a Python subset (no `import`/`try`/`class`/`while`, no floats |
| 74 | + or sets, string-keyed dicts only, immutable-ish lists). Its README lists the exact divergences. |
| 75 | + Parsing synchronises on `state.SyncParsePackage(label)` — a nil return means you own the parse. |
| 76 | +- **`src/build`** — builds a target. Three-way check: already built in `plz-out`, restorable from |
| 77 | + cache, or needs a real build. Complicated by post-build functions and output dirs, which can |
| 78 | + change the output hash after the fact, so metadata files are fetched and replayed before the |
| 79 | + outputs are. |
| 80 | +- **`src/test`** — runs tests and collates results into `core.TestSuite`s in a Surefire-like XML |
| 81 | + format. Handles flaky reruns and `--num_runs` by keeping multiple `TestExecution`s per `TestCase`. |
| 82 | + |
| 83 | +Supporting packages: `src/remote` implements the Bazel remote execution API client; `src/cache` has the |
| 84 | +dir/http/cmd cache backends; `src/output` and `src/cli` handle the interactive display; `src/fs`, |
| 85 | +`src/process`, `src/sandbox` are the OS-level layers. `rules/*.build_defs` are the built-in build |
| 86 | +rules, written in the BUILD language itself and embedded into the binary. |
| 87 | + |
| 88 | +Caching is hash-based, not timestamp-based: hashes cover rule definition, config, sources, and |
| 89 | +secrets. Anything that changes what a target produces must be folded into its hash, or you will |
| 90 | +create stale-cache bugs that only show up on other people's machines. |
| 91 | + |
| 92 | +## Conventions |
| 93 | + |
| 94 | +- Language plugins (go, cc, python, shell) are external repos pinned in `plugins/BUILD` and |
| 95 | + preloaded via `.plzconfig`. Bumping a plugin version is a `plugins/BUILD` edit. |
| 96 | +- Third-party Go deps are BUILD targets under `third_party/go`, managed by `puku` from `go.mod`. |
| 97 | + Don't hand-edit them; run `plz puku sync`. |
| 98 | +- The end-to-end tests in `test/` invoke `plz` recursively against this repo. They are deliberately |
| 99 | + run in a separate pass (see `test.sh`) with the lock disabled and sandboxing off, and they assert |
| 100 | + on exact output text, so they're brittle — expect to update `.txt` golden files. `plz_e2e_test` |
| 101 | + in `test/build_defs/test.build_defs` is the macro they all use. |
| 102 | +- Some tests need toolchains that may be absent (python3, xz); `test.sh` detects this and passes |
| 103 | + `--exclude` flags. If a test fails locally but not in CI, check whether it's one of these. |
| 104 | +- Releases: bump `VERSION` and add a `ChangeLog` entry in the existing format (version heading, |
| 105 | + then bullets with PR numbers). |
| 106 | +- `tree/` is a generated perf-test repo, blacklisted from parsing; `plz-out/` is all build output. |
0 commit comments