Skip to content

feat(ledger): add schemas commands (insert/get/list)#165

Open
BrieucCaillot wants to merge 2 commits into
mainfrom
feat/ledger-schemas
Open

feat(ledger): add schemas commands (insert/get/list)#165
BrieucCaillot wants to merge 2 commits into
mainfrom
feat/ledger-schemas

Conversation

@BrieucCaillot

@BrieucCaillot BrieucCaillot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Wrap the ledger v2 schema endpoints (InsertSchema, GetSchema, ListSchemas) in fctl under a new fctl ledger schemas command group.
  • insert <version> <source>source is a local file path or an http(s):// URL, and the content can be JSON or YAML (auto-detected, no flag). YAML is normalized to JSON before decoding into the SDK struct so its json tags are honored.
  • get <version> [--format json|yaml] — defaults to colorized JSON; --format yaml emits YAML for easy round-tripping (get --format yaml → edit → insert).
  • list [--page-size N] — table of Version, Created at, and chart/queries/transactions counts.
  • Ledger is taken from the persistent --ledger flag (consistent with transactions/accounts). No new dependencies (yaml.v3 was already required).

Test plan

  • go build, go vet ./..., gofmt -l, golangci-lint run --fix (0 issues), go mod tidy (no diff)
  • Verified live against staging (org kpuqzlfmhzqx, stack drru, ledger my-ledger):
    • insert from local JSON, local YAML, and a URL returning YAML
    • list shows all inserted versions
    • get renders both JSON (default) and --format yaml, round-tripping the stored schema
image

Wrap the ledger v2 schema endpoints in fctl. insert accepts a local
file or URL containing JSON or YAML; get renders json or yaml.
@BrieucCaillot BrieucCaillot requested a review from a team as a code owner June 11, 2026 12:38
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 38cfd12e-9e34-4f9c-915c-5a1e0e6cdbc4

📥 Commits

Reviewing files that changed from the base of the PR and between e976a6a and faa6293.

📒 Files selected for processing (2)
  • cmd/ledger/schemas/insert.go
  • cmd/ledger/schemas/list.go

Walkthrough

Adds a new ledger schemas CLI command with subcommands: get <version> (fetch and render a schema), list (paginate and table-list schemas), and insert <version> <source> (load schema from file or URL and upload via Ledger V2 API). All commands follow the fctl Store/Controller/Command pattern.

Changes

Ledger schemas CLI commands

Layer / File(s) Summary
Root command registration and schemas root setup
cmd/ledger/root.go, cmd/ledger/schemas/root.go
Registers the schemas root command in the ledger hierarchy with aliases and wires the three subcommands (get, insert, list).
Get command (schema retrieval)
cmd/ledger/schemas/get.go
Implements get <version> to authenticate the profile, build a stack client, call Ledger V2 GetSchema, store the result, and render as JSON (optionally colorized) or YAML.
List command (schema enumeration)
cmd/ledger/schemas/list.go
Implements list (aliases ls, l) to authenticate, call Ledger V2 ListSchemas with cursor or page-size, store results, and render a pterm table of version, RFC3339 created time, and component counts plus cursor output.
Insert command (schema upload)
cmd/ledger/schemas/insert.go
Implements insert <version> <source> to load schema bytes from a local path or HTTP(S) URL, normalize YAML→JSON→ledger.V2SchemaDataInput, require stack approval, call Ledger V2 InsertSchema, and render a success message on expected status.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Poem

🐰 I hopped through code and flags tonight,
three commands stitched neat and bright.
Get, list, insert — schemas sing,
files and URLs take wing.
nibbles a carrot, queues the write

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(ledger): add schemas commands (insert/get/list)' directly and clearly describes the main change: adding three new schema commands to the ledger CLI.
Description check ✅ Passed The description provides comprehensive details about the new schema commands (insert/get/list), their parameters, behavior, dependencies, and includes a thorough test plan with live verification results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ledger-schemas

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/ledger/schemas/insert.go`:
- Around line 90-96: The Render method for InsertController always prints
"Schema inserted!" regardless of the API result; check the stored result
(c.store.Success set from response.StatusCode == 201) inside
InsertController.Render and only print the success message when c.store.Success
is true, otherwise print a failure/error message (e.g., "Failed to insert
schema") and return a non-nil error or appropriate non-zero exit indication;
update Render to reference c.store.Success rather than unconditionally calling
pterm.Success.WithWriter(...).Printfln.
- Around line 124-130: The HTTP request in readSource uses cmd.Context() and
http.DefaultClient.Do(req) with no deadline, which can hang; wrap the existing
ctx with a timeout (e.g., ctx, cancel := context.WithTimeout(ctx,
10*time.Second); defer cancel()) and use that timed context when creating the
request (http.NewRequestWithContext) or instantiate a local http.Client with a
Timeout and use client.Do(req); update references in readSource and add the time
import.

In `@cmd/ledger/schemas/list.go`:
- Around line 46-47: Validate the page-size flag value locally before making the
API call: after reading the int flag (c.pageSizeFlag) in the command handler
(the function that builds/runs the list schema command where fctl.WithIntFlag is
used), check that the parsed page size is > 0 and return a clear error (e.g.
"invalid --page-size: must be > 0") if not; apply the same check in the other
handler code path referenced around the second occurrence (lines 68-71) so both
places reject non-positive values before issuing any API request.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1fe94cdd-cb7d-433a-a7df-13a89bb0a0b9

📥 Commits

Reviewing files that changed from the base of the PR and between bfe70b0 and e976a6a.

📒 Files selected for processing (5)
  • cmd/ledger/root.go
  • cmd/ledger/schemas/get.go
  • cmd/ledger/schemas/insert.go
  • cmd/ledger/schemas/list.go
  • cmd/ledger/schemas/root.go

Comment thread cmd/ledger/schemas/insert.go Outdated
Comment thread cmd/ledger/schemas/insert.go
Comment thread cmd/ledger/schemas/list.go Outdated

@flemzord flemzord left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J'ai laissé quelques commentaires inline. Le point principal est la pagination de schemas list: l'endpoint est cursor-paginé mais la commande ne permet pas de récupérer les pages suivantes.

Comment thread cmd/ledger/schemas/list.go Outdated
return nil, err
}

response, err := stackClient.Ledger.V2.ListSchemas(cmd.Context(), operations.V2ListSchemasRequest{

@flemzord flemzord Jun 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint is cursor-paginated (V2ListSchemasRequest.Cursor, then V2SchemasCursor.HasMore/Next/Previous in the response), but the command only exposes --page-size and only stores Data. Once a ledger has more than 15 schema versions, or more than the requested page size, the remaining pages are unreachable from fctl. Please add a --cursor flag, pass it into the request, and render the cursor metadata like the other list commands do.

Comment thread cmd/ledger/schemas/list.go Outdated

response, err := stackClient.Ledger.V2.ListSchemas(cmd.Context(), operations.V2ListSchemasRequest{
Ledger: fctl.GetString(cmd, internal.LedgerFlag),
PageSize: pointer.For(int64(fctl.GetInt(cmd, c.pageSizeFlag))),

@flemzord flemzord Jun 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--page-size is read with GetInt without validation, so --page-size 0 or a negative value is forwarded to the API. Recent paginated commands use fctl.WithPageSizeFlag() plus fctl.GetPageSize() to reject these values in the CLI; doing the same here would avoid an invalid API call.

Comment thread cmd/ledger/schemas/insert.go Outdated
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)

@flemzord flemzord Jun 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This request bypasses the HTTP client configured by fctl, so global transport flags such as --insecure-tls do not apply to https:// schema sources. Since URLs are an official input for this command, please use a client built from the command flags, or inject it from Run, instead of using http.DefaultClient.

- insert: error out unless the API returns 204 (correct success code;
  was 201 and masked by an unconditional success message)
- insert: fetch URL sources via fctl's configured HTTP client (honors
  --insecure-tls) with a request timeout
- list: use WithCursorFlag/WithPageSizeFlag, follow cursor pagination,
  validate page size, and render cursor metadata
@BrieucCaillot

Copy link
Copy Markdown
Contributor Author

Review feedback addressed (commit faa6293)

All five points from @flemzord and CodeRabbit are fixed and verified live against staging.

insert

  • Now errors unless the API returns the documented success code, so the success message is no longer printed unconditionally. This surfaced a latent bug: the success status is 204, not 201 (per the ledger OpenAPI spec) — the old unconditional Render had been masking it.
  • URL sources are now fetched via fctl's configured HTTP client (fctl.GetHttpClient), so --insecure-tls and other transport flags apply, plus a 30s request timeout.

list

  • Switched to the canonical cursor-paginated pattern (matching payments/orders/list.go): WithCursorFlag() + WithPageSizeFlag(), cursor sent XOR page-size, and cursor metadata rendered via fctl.RenderCursor.
  • --page-size <= 0 is now rejected locally via fctl.GetPageSize.

Pagination — full test

Created a dedicated ledger with 12 schemas (v01v12) and walked the full set:

  • page-size 5 → page 1 returns 5 (HasMore=true), then the rest; all 12 seen, 0 duplicates.
  • page-size 3 → same shape; all 12 unique.
  • Previous cursor from page 2 returns exactly the page-1 set.
  • --page-size 0 → local error "page size must be greater than 0".

Server-side observation (not an fctl issue): the first page honors page-size, but pages fetched via the cursor return all remaining rows rather than pageSize (5→7, 3→9). I decoded the Next token and it correctly carries pageSize: 5, so the ledger backend appears to ignore page-size after the first page. fctl faithfully passes the cursor and renders what the server returns. Flagging for the ledger team; out of scope here.

gofmt clean, golangci-lint 0 issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants