For a Ruby gem's CI, how would you use yard stats --list-undoc and yard doc --fail-on-warning to stop the public API documentation from rotting?
answer
- percent documented per object type
- undocumented means blank docstring
- warnings: unknown @param, unknown tag
- --fail-on-warning aborts the run
- .yardopts shared by dev and CI
basics
~20 syard stats --list-undoc prints a % documented figure and lists each undocumented public object with its file and line; it does not fail on gaps by itself. yard doc --fail-on-warning exits non-zero on warnings such as an unknown @param name.
solid answer
~50 s`yard stats` counts files, modules, classes, constants, attributes and methods, prints `NN.NN% documented`, and with `--list-undoc` lists every object whose docstring is blank, with `file:line`. It counts **public** objects unless you add `--protected` or `--private`, and `--no-private` drops `@private` ones. Undocumented objects are not warnings, so the stats run passes regardless; you gate coverage by parsing the percentage in a CI step, often as a ratchet that may not drop. Correctness is gated with `yard doc --fail-on-warning`, which aborts when YARD warns: an `@param` naming a parameter the method no longer has, an unknown tag such as `@returns`, a link it cannot resolve. Put the shared options in `.yardopts` so developers and CI run the same thing. With plain RDoc, `rdoc -C lib` gives the coverage report, and `RDoc::Task`'s `rdoc:coverage` raises when it is incomplete.
code
bash · 4 linesyard doc --fail-on-warning
yard stats --list-undoc | tee yard-stats.txt
pct=$(grep -o '[0-9.]*% documented' yard-stats.txt | cut -d% -f1)
awk -v p="$pct" 'BEGIN { exit (p < 90) }'go deeper
Recall that yard stats reports a percent-documented figure and that --list-undoc shows which objects lack comments.
Explain what counts as undocumented, a blank docstring on a public object, and which YARD warnings reveal stale tags.
Design the job: --fail-on-warning for drift, a scripted or ratcheted threshold for coverage, a shared .yardopts, and @api private excluded from the metric.
Decide how much documentation to enforce: coverage metrics invite empty comments, so pair a modest ratchet with review of public API changes and tested examples.
## What rots, and how you can detect it Documentation for a gem drifts in two different ways, and each needs its own check: - **Gaps**: someone adds `GeoLookup::Client#batch_geocode` and never writes a comment. A tool can count these. - **Lies**: someone renames `country:` to `region:` and the comment still says `@param country`. A tool can catch these only if the documentation is structured, which is what YARD tags give you. ## `yard stats`: measuring gaps `yard stats` parses the code (or, with `--use-cache`, loads the `.yardoc` database) and prints one line per object type, in the order files, modules, classes, constants, attributes and methods, followed by a total such as `87.50% documented`. - An object counts as **undocumented** when its docstring is **blank**: no prose and no visible tags. - `--list-undoc` appends an "Undocumented Objects" list sorted by file, each entry with its path and `file:line`; `--compact` shortens it. - By default only **public** objects are counted; `--protected` and `--private` add those, and `--no-private` drops objects tagged `@private`. - `--query` narrows the count, for example to objects that are not `@api private`. The important detail: an undocumented object is **not a warning**. `yard stats` exits successfully at 40% just as it does at 100%, so a coverage gate is a script around its output. ## `--fail-on-warning`: catching lies YARD logs warnings while parsing and rendering. The ones that matter for API docs: | Warning | Typical cause | |---|---| | `@param tag has unknown parameter name: country` | the argument was renamed or removed | | `@param tag has duplicate parameter name` | a copy-paste left two tags for one argument | | `Unknown tag @returns` | a misspelt tag that renders as nothing useful | | `Cannot resolve link to GeoLookup::Result` | a `{...}` reference to a class that no longer exists | `yard doc --fail-on-warning` makes the command **exit with an error status** whenever any warning was logged, which turns every row of that table into a red build. Link-resolution warnings appear while HTML is rendered, so the gate should run the real generation rather than `--no-output`. ## A CI job for the geocoding gem 1. Commit a `.yardopts` with the options everyone uses, such as `--markup markdown`, `--hide-api private` and `lib/**/*.rb - README.md CHANGELOG.md`. 2. Run `yard doc --fail-on-warning` to catch stale tags and broken links. 3. Run `yard stats --list-undoc`, extract the percentage, and fail below a threshold, or below the value on the main branch so coverage can only rise. 4. Keep the undocumented list in the job log so the author sees exactly which method to document. ## The RDoc equivalents If the gem uses plain RDoc: - `rdoc -C lib` (`--coverage-report`) prints the items that are not documented instead of generating HTML; `-C1` also reports undocumented parameter names. - In the RDoc 8.1 source, coverage mode exits unsuccessfully unless everything is documented, and the `rdoc:coverage` task that `RDoc::Task` defines raises `RDoc coverage is incomplete`. Ruby 4.0.7 bundles RDoc 7.0.4, so confirm the behaviour on the version your Gemfile resolves. ## Judgement calls - **Gate the API, not everything.** Excluding `@api private` objects keeps the metric about what users rely on. - **Ratchet rather than demand 100% on day one** for an existing gem; demanding it at once usually produces empty one-line comments that pass the counter and help nobody. - **A blank docstring is not the only failure.** A tagged but wrong comment passes `yard stats`; only the warning gate and review catch it.
- A method has a docstring made only of `@api private`. Does `yard stats` count it as documented?`yard stats` treats a docstring as blank when it has no text and no **visible** tags. `@api` is not shown in output, so a docstring holding only `@api private` still counts as undocumented unless you exclude those objects with a query. Tags like `@param` or `@return` do count.
- Why can a 100% documented gem still ship wrong documentation?Coverage only asks whether a docstring exists. A comment that describes an old return type or a behaviour the code no longer has passes `yard stats`. `--fail-on-warning` catches the structural drift, parameter names and links, but wrong prose needs review and `@example` code that is actually exercised by tests.
saying these in an interview costs you the question
- yard stats exits non-zero whenever an object is undocumented.
- --fail-on-warning fails the build on low documentation coverage.
- yard stats counts private methods by default.
- 100% documented means the documentation is correct.
- A comment with any text at all hides a wrong @param from YARD.