Repository navigation
fix(cli): help text for validate, examples, and materialize; rust-api features - #2016
Conversation
… features - Move validate's doc comment back onto Validate; it was attached to Graphql, leaving validate with no description and graphql showing SHACL text. - Add verbatim_doc_comment where doc comments carry Examples blocks, so clap stops reflowing them onto one line. - Remove internal design references from materialize help, its s3 error, and docs/cli/materialize.md. - Drop the duplicated --timeout default and tighten the sync summary. - rust-api.md: document sql, delta, graphql; correct the full bundle. - Add tests/help_text.rs: every command has an about, Examples blocks keep their line breaks and start with the command's own invocation.
aaj3f
left a comment
There was a problem hiding this comment.
✅ Approve with nits.
Thanks for chasing these down. The validate/graphql swap was a good catch, since fluree --help showed nothing for validate, and the reflowed Examples: blocks were hurting every command that had one. I confirmed all four defects on main. The feature lines in rust-api.md match fluree-db-api/Cargo.toml, fluree-db-server/Cargo.toml and fluree-db-cli/Cargo.toml exactly, including what each new feature implies and the contents of full. Grepping fluree-db-cli/src and docs/ for DEC-, § and O1–O6, what's left is code comments that clap never renders and the docs/audit* trees that SUMMARY.md doesn't include, so the user-facing sweep is complete.
The new gate is a nice addition. It walks the real clap tree, it runs in CI (all three tests appear by name in the test job), and each check goes red on its own bug. I moved the validate block back above Graphql and dropped verbatim_doc_comment from insert: every_command_has_an_about reported ["validate"], examples_invoke_their_own_command reported graphql: fluree validate mydb, and example_blocks_keep_their_line_breaks reported ["insert"]. The two inline notes on help_text.rs are about what it can't see yet: blocks headed something other than Examples:, and the graph/graphql and doc/docs prefix pairs. There's also a one-word nit on the full line.
Adherence to repo commitments:
- Patterns/abstractions: ✔ Uses clap's own
verbatim_doc_commentand moves the misplaced block; the gate readsCli::command()rather than parsing source. - Performance (speed first, memory second): ✔ No runtime path changes, only help text, one usage-error string, docs and a test.
- Deployment targets: ✔ n/a. Only the CLI binary's help text changes; the
fluree-db-api/Cargo.tomlchange is a comment. - Testing: ✔
help_text.rsis auto-discovered, runs in CI, and each check fails when its bug is reintroduced;⚠️ its reach stops at the literalExamples:header and at a prefix match (inline). - Conventions: ✔ Self-describing title, bulleted commit body, docs updated alongside the help text.
Verified locally at branch HEAD: cargo test -p fluree-db-cli --test help_text --test docs_coverage (3 + 5 passed by name), the three-way mutation above (restored), and both suggested help_text.rs changes run at the head.
Approving so you can merge when ready, but maybe worth considering the two help_text.rs notes first.
| if texts | ||
| .iter() | ||
| .flat_map(|t| t.lines()) | ||
| .any(|l| l.trim_start().starts_with("Examples:") && l.trim() != "Examples:") |
There was a problem hiding this comment.
🟡 Optional: this check only sees blocks headed Examples:, so several blocks this PR made verbatim can reflow again without anything going red.
The PR adds verbatim_doc_comment to blocks with other headers too: delta generate's Example:, publish and clone's Usage:, bm25 create's JSON example, and the With 0 args / 1 arg / 2 args lists on the insert/update/upsert/query args. starts_with("Examples:") can't match any of those. I checked by removing verbatim_doc_comment from insert, delta generate and bm25 create together: this test reported only ["insert"].
When clap reflows one of these blocks, the header and the first invocation always end up on one line, so ": fluree " appearing anywhere in a rendered line is a header-agnostic signature for it. Something like this (illustrative, rustfmt'd):
if texts.iter().flat_map(|t| t.lines()).any(|l| {
l.contains(": fluree ")
|| (l.trim_start().starts_with("Examples:") && l.trim() != "Examples:")
}) {I ran that variant: it passes at the head, and with verbatim_doc_comment removed from publish and delta generate it reports ["publish", "delta generate"]. It still can't see bm25 create's JSON block or the args lists, but it covers every block that shows a command. The same reasoning applies to examples_invoke_their_own_command, which only enters a block on line == "Examples:"; accepting Example: and Usage: there would check those blocks for misplacement too. This is minor and non-blocking, but if you agree it's right, I'd rather see it folded in now than lost in the backlog.
| in_examples = true; | ||
| } else if in_examples && line.starts_with("fluree ") { | ||
| in_examples = false; | ||
| if !line.starts_with(&own) { |
There was a problem hiding this comment.
🟡 Optional: starts_with(&own) has no word boundary, and the CLI has two real prefix pairs: graph/graphql and doc/docs.
"fluree graphql mydb …".starts_with("fluree graph") is true, so a graphql example block that drifts onto graph, which is the same kind of misplacement this PR fixes for validate, would pass. Requiring the next character to be a space or the end of the line closes it:
| if !line.starts_with(&own) { | |
| if line != own && !line.starts_with(&format!("{own} ")) { |
I ran the suite with this line at the head and it passes. Then I gave graph an Examples: block that runs fluree graphql mydb …, and it reported graph: fluree graphql mydb '{ persons { id } }', which the current check accepts. Minor and non-blocking, same fold-it-in-now ask as above.
| - `search-remote-client` - Remote search service client (HTTP client for remote BM25 and vector search services) | ||
| - `aws-testcontainers` - Opt-in LocalStack-backed S3/DynamoDB tests (auto-start via testcontainers) | ||
| - `full` - Convenience bundle: `native`, `credential`, `iceberg`, `shacl`, `ipfs` | ||
| - `full` - Convenience bundle: `native`, `credential`, `iceberg`, `sql`, `shacl`, `ipfs`, `graphql` (excludes `delta`, `aws`, `vector`) |
There was a problem hiding this comment.
🟡 Nit: the exclusions list leaves out search-remote-client, which is documented two lines up.
Since this line now spells out what full excludes, a reader could take search-remote-client as included. fluree-db-api/Cargo.toml:57 doesn't include it.
| - `full` - Convenience bundle: `native`, `credential`, `iceberg`, `sql`, `shacl`, `ipfs`, `graphql` (excludes `delta`, `aws`, `vector`) | |
| - `full` - Convenience bundle: `native`, `credential`, `iceberg`, `sql`, `shacl`, `ipfs`, `graphql` (excludes `delta`, `aws`, `vector`, `search-remote-client`) |
…aring commands - Reflow check flags any rendered line containing ": fluree ", so blocks headed Example: or Usage: (publish, clone, delta generate) are covered. - Example-placement check enters blocks on Example: and Usage: too, and requires a word boundary after the command path (graph/graphql, doc/docs). - rust-api.md: list search-remote-client among the features full excludes.
Summary
validate's doc comment was attached toGraphql:fluree --helpshowed no description forvalidate, andgraphql --helpled with SHACL validation text. Moved it back.Examples:block onto a single line (28 commands/args, e.g.insert,query,sync,bm25,* map). Addedverbatim_doc_commentto those items.DEC-003,O1–O6) frommaterializehelp, its--output s3error, anddocs/cli/materialize.md.--timeoutno longer states its default twice;syncsummary tightened.rust-api.md: documents thesql,delta, andgraphqlfeatures and corrects thefullbundle (addssql,graphql).Tests
New
fluree-db-cli/tests/help_text.rswalks every visible command and checks that:Examples:blocks keep their line breaksExamples:block starts with the command's own invocationEach check fails when its bug is reintroduced.