Skip to content

Commit d7a130d

Browse files
authored
cfl: remove resource-read -o json (BREAKING) [#392] (#396)
* feat!: remove resource-read -o json from cfl JSON is reserved for round-trip payloads and control-plane envelopes per cli-common docs/output-and-rendering.md §2. Today's surviving JSON surface is cfl set-credential --json (control-plane envelope, §1.5.2); no resource command emits JSON. The global -o/--output flag now accepts only {table, plain}; -o json, -o yaml, or any other value errors uniformly at the root prerun ("invalid output format: \"json\" (valid formats: table, plain)"), before config or keyring work runs. 23 JSON branches across page/, space/, attachment/, search/ (including create/edit/delete/upload mutation-success renderers) are deleted along with their tests and docs/examples. me/ had no production JSON branch; only its fixture is removed. BREAKING CHANGE: cfl <resource> -o json now errors. Scripts that piped "cfl page create -o json | jq -r '.id'" can extract the ID from the default text output via "awk -F': ' '/^ID:/ {print $2}'"; the bundled roundtrip-test.sh is updated in this PR to use that pattern. Closes #392 * test+docs: add local-flag smoke test; inline-mark obsolete JSON rows - TestRoot_LocalJSONFlag_NotRejectedByOutputGuard pins the invariant that the root's closed-set output guard does not interfere with child-command local boolean --json flags (set-credential's §1.5.2 control-plane envelope). - Inline-mark obsolete JSON rows in integration-tests.md and test-plan-writes.md with ~~strikethrough~~ + #392 so the matrix itself signals which rows now error rather than relying on the top-of-file banner alone. - Replace the page-create ID-capture row's command with the awk-based text-output parser (matches the updated roundtrip-test.sh). * test: assert attachment empty-result banners now always print #392 removed the `opts.Output != "json"` skip from attachment/list.go so the 'No attachments found.' / 'No unused attachments found.' stderr banners now print unconditionally. Pin that with assertions on TestRunList_Empty and TestRunList_UnusedFlag_NoUnused. * test+docs+script: real-root set-credential test; harden awk; fix obsolete row expecteds Daemon feedback (PR #396): - Add TestSetCredential_ThroughRealRoot_LocalJSONFlagPreserved which dispatches set-credential --json through root.NewCmd() with the production PersistentPreRunE chain wired. Prior probe-stub test in root_test.go covers the general invariant; this version exercises the exact production path so a future regression in PersistentPreRunE + set-credential interaction is caught. - Harden roundtrip-test.sh ID extraction: capture create_output first (no more '|| true' masking non-zero exit codes), then run awk with gsub-based whitespace trim so 'ID: 12345' / 'ID:\t12345' still yield '12345'. Failure paths now include the raw cfl output. - Update the 'Expected Result' cells of the inline-marked obsolete rows in integration-tests.md to say 'Errors: invalid output format' instead of stale 'Valid JSON array' / 'Valid JSON object' text.
1 parent cab8938 commit d7a130d

35 files changed

Lines changed: 223 additions & 620 deletions

docs/ARTIFACT_CONTRACT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Some commands expose a `--raw` mode for source-faithful content where transforma
6060
6161
## Output Format
6262

63-
JTK uses text-first output. The `-o json/plain/table` flag has been removed from JTK (CFL retains it). JTK commands render through presenters; `automation export` is the only command that emits JSON directly.
63+
JTK and CFL both use text-first output. The `-o json` resource surface has been removed from both tools (JTK earlier, then CFL via #392); CFL retains `-o table` and `-o plain` only. Both tools render through presenters; JSON is reserved for control-plane envelopes (`cfl set-credential --json`, `jtk set-credential --json`) and round-trip payloads (`jtk automation export`).
6464

6565
**Text output modes:**
6666
- Default = focused output for human and agent consumption (defined per-command)

tools/cfl/README.md

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,6 @@ cfl me
231231
# Show only the account ID (for scripting)
232232
cfl me --id
233233
# → 60e09bae7fcd820073089249
234-
235-
# -o json falls through to the one-liner — there is no JSON representation of `cfl me`.
236-
cfl me -o json
237-
# → 60e09bae7fcd820073089249 | Rian Stockbower | rian@example.com
238234
```
239235

240236
| Flag | Short | Default | Description |
@@ -253,7 +249,7 @@ List Confluence spaces.
253249
cfl space list
254250
cfl space list --type global
255251
cfl space list --type personal
256-
cfl space list -l 50 -o json
252+
cfl space list -l 50
257253
```
258254

259255
| Flag | Short | Default | Description |
@@ -273,7 +269,6 @@ List pages in a space.
273269
cfl page list --space DEV
274270
cfl page list -s DEV -l 50
275271
cfl page list -s DEV --status archived
276-
cfl page list -s DEV -o json
277272
```
278273

279274
| Flag | Short | Default | Description |
@@ -292,7 +287,6 @@ View a Confluence page. **Content is displayed as markdown by default.**
292287
cfl page view 12345
293288
cfl page view 12345 --raw
294289
cfl page view 12345 --web
295-
cfl page view 12345 -o json
296290
cfl page view 12345 --content-only # Output only content (no headers)
297291
cfl page view 12345 --show-macros --content-only | cfl page edit 12345 --legacy # Roundtrip with macros
298292
```
@@ -402,7 +396,7 @@ cfl page edit 12345 --file content.md --legacy
402396
echo "<p>Updated</p>" | cfl page edit 12345 --storage
403397

404398
# Extract, transform, and re-upload storage-format content
405-
cfl page view 12345 --output json | jq -r '.body.storage.value' | \
399+
cfl page view 12345 --raw --content-only | \
406400
sed 's/old/new/g' | cfl page edit 12345 --storage
407401
```
408402

@@ -497,9 +491,6 @@ cfl search "kubernetes" --space DEV --type page --label infrastructure
497491

498492
# Raw CQL for power users (find pages modified in last 7 days)
499493
cfl search --cql "type=page AND space=DEV AND lastModified > now('-7d')"
500-
501-
# Output as JSON for scripting
502-
cfl search "config" -o json
503494
```
504495

505496
| Flag | Short | Default | Description |
@@ -581,7 +572,6 @@ List attachments on a page.
581572
```bash
582573
cfl attachment list --page 12345
583574
cfl attachment list -p 12345 -l 50
584-
cfl attachment list -p 12345 -o json
585575

586576
# List unused (orphaned) attachments not referenced in page content
587577
cfl attachment list --page 12345 --unused
@@ -881,10 +871,15 @@ Use `--output` or `-o` to change output format:
881871

882872
```bash
883873
cfl space list -o table # Default: human-readable table
884-
cfl space list -o json # JSON for scripting/automation
885874
cfl space list -o plain # Tab-separated for piping to other tools
886875
```
887876

877+
**Breaking change (#392):** resource `-o json` has been removed. JSON is
878+
reserved for control-plane envelopes per cli-common
879+
`docs/output-and-rendering.md` §2. The surviving JSON surface is
880+
[`cfl set-credential --json`](#cfl-set-credential), which emits a §1.5.2
881+
write-confirmation envelope for scripted credential rotation.
882+
888883
---
889884

890885
## Shell Completion

tools/cfl/chaos-testing.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
**Started:** 2026-01-03
44
**Focus:** Read-only operations (list, view, download)
55

6+
> **Historical note (#392):** The `-o json` rows below describe behavior from
7+
> a session that pre-dates the removal of resource-read JSON. As of #392 the
8+
> closed set is `{table, plain}`; the `-o json` and `-o yaml` rows below are
9+
> no longer reproducible — both now error at the root with the same
10+
> "invalid output format" message.
11+
612
---
713

814
## Bugs Found

tools/cfl/integration-tests.md

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
This document catalogs the manual integration test suite for `cfl`. These tests verify real-world behavior against a live Confluence instance and catch edge cases that are difficult to cover with unit tests.
44

5+
> **#392 update:** Rows that exercise `-o json` / `--output json` on resource commands are obsolete — the resource JSON surface has been removed. They now error at the root with `invalid output format: "json" (valid formats: table, plain)`. Skip those rows. The surviving JSON surface is `cfl set-credential --json` (control-plane envelope per cli-common §1.5.2); test that one normally.
6+
57
## Auth Methods
68

79
cfl supports two authentication methods. The full integration test suite should be run with both:
@@ -61,7 +63,7 @@ All cfl commands should work with both auth methods (no scope limitations for Co
6163
|-----------|---------|-----------------|
6264
| List pages in space | `cfl page list --space confluence` | Shows table of pages with ID, title, status, version |
6365
| List with limit | `cfl page list --space confluence --limit 5` | Shows only 5 pages with "showing first N results" message |
64-
| JSON output | `cfl page list --space confluence --output json` | Valid JSON array |
66+
| ~~JSON output~~ (#392 removed) | `cfl page list --space confluence --output json` | Errors: invalid output format |
6567
| Plain output | `cfl page list --space confluence --output plain` | Tab-separated values |
6668
| List trashed pages | `cfl page list --space confluence --status trashed` | Shows deleted pages |
6769
| List archived pages | `cfl page list --space confluence --status archived` | Shows archived pages |
@@ -73,13 +75,13 @@ All cfl commands should work with both auth methods (no scope limitations for Co
7375
|-----------|---------|-----------------|
7476
| View page content | `cfl page view <page-id>` | Shows title, ID, version, and markdown content |
7577
| View raw HTML | `cfl page view <page-id> --raw` | Shows Confluence storage format (XHTML) |
76-
| JSON output | `cfl page view <page-id> --output json` | Full page object as JSON |
78+
| ~~JSON output~~ (#392 removed) | `cfl page view <page-id> --output json` | Errors: invalid output format |
7779
| Non-existent page | `cfl page view 99999999999` | Error: 404 not found |
7880
| View content only | `cfl page view <id> --content-only` | Markdown only, no Title/ID/Version headers |
7981
| Content only with raw | `cfl page view <id> --content-only --raw` | XHTML only, no headers |
8082
| Content only with macros | `cfl page view <id> --content-only --show-macros` | Markdown with [TOC] etc., no headers |
8183
| Roundtrip macros (content-only) | `cfl page view <id> --show-macros --content-only \| cfl page edit <id> --legacy` | Macros preserved |
82-
| Content only JSON error | `cfl page view <id> --content-only -o json` | Error: incompatible flags |
84+
| ~~Content only JSON error~~ (#392 removed; -o json itself errors before --content-only checks) | `cfl page view <id> --content-only -o json` | Errors: invalid output format |
8385
| Content only web error | `cfl page view <id> --content-only --web` | Error: incompatible flags |
8486

8587
### page create
@@ -152,7 +154,7 @@ All cfl commands should work with both auth methods (no scope limitations for Co
152154
|-----------|---------|-----------------|
153155
| List attachments | `cfl attachment list --page <id>` | Table of attachments with ID, title, type, size |
154156
| No attachments | List on page with none | "No attachments found" |
155-
| JSON output | `cfl attachment list --page <id> --output json` | Valid JSON array with full attachment metadata |
157+
| ~~JSON output~~ (#392 removed) | `cfl attachment list --page <id> --output json` | Errors: invalid output format |
156158
| List unused attachments | `cfl attachment list --page <id> --unused` | Only attachments not referenced in page content |
157159
| No unused attachments | `--unused` on page using all attachments | "No unused attachments found" |
158160

@@ -196,15 +198,15 @@ All cfl commands should work with both auth methods (no scope limitations for Co
196198
| Test Case | Command | Expected Result |
197199
|-----------|---------|-----------------|
198200
| List all spaces | `cfl space list` | Table of spaces with key, name, type |
199-
| JSON output | `cfl space list --output json` | Valid JSON array |
201+
| ~~JSON output~~ (#392 removed) | `cfl space list --output json` | Errors: invalid output format |
200202
| Limit results | `cfl space list --limit 5` | Shows first 5 spaces |
201203

202204
### space view
203205

204206
| Test Case | Command | Expected Result |
205207
|-----------|---------|-----------------|
206208
| View space by key | `cfl space view confluence` | Key-value pairs: KEY, NAME, ID, TYPE, STATUS, DESCRIPTION |
207-
| JSON output | `cfl space view confluence -o json` | Valid JSON object with id, key, name, type, status, description |
209+
| ~~JSON output~~ (#392 removed) | `cfl space view confluence -o json` | Errors: invalid output format |
208210
| Non-existent space | `cfl space view NONEXISTENT` | Error: Space with key 'NONEXISTENT' not found |
209211
| View personal space | `cfl space view ~accountid` | Shows personal space details (if accessible) |
210212
| Alias: get | `cfl space get confluence` | Same output as `space view` |
@@ -214,7 +216,7 @@ All cfl commands should work with both auth methods (no scope limitations for Co
214216
| Test Case | Command | Expected Result |
215217
|-----------|---------|-----------------|
216218
| Create global space | `cfl space create --key INTTEST --name "[Test] Integration" --description "Test space"` | Space created, shows KEY, NAME, URL |
217-
| Create with JSON output | `cfl space create --key INTTEST2 --name "[Test] Int2" -o json` | Valid JSON with id, key, name, type |
219+
| ~~Create with JSON output~~ (#392 removed) | `cfl space create --key INTTEST2 --name "[Test] Int2" -o json` | Errors: invalid output format |
218220
| Missing key flag | `cfl space create --name "Test"` | Error: required flag(s) "key" not set |
219221
| Missing name flag | `cfl space create --key TST` | Error: required flag(s) "name" not set |
220222
| Duplicate key | `cfl space create --key INTTEST --name "Duplicate"` (after creating INTTEST) | Error: API rejects duplicate key |
@@ -226,7 +228,7 @@ All cfl commands should work with both auth methods (no scope limitations for Co
226228
| Update name | `cfl space update INTTEST --name "[Test] Updated Name"` | Shows updated key and name |
227229
| Update description | `cfl space update INTTEST --description "Updated description"` | Shows updated key and name |
228230
| Update both | `cfl space update INTTEST --name "[Test] Both" --description "Both updated"` | Both name and description changed |
229-
| JSON output | `cfl space update INTTEST --name "[Test] JSON" -o json` | Valid JSON with updated fields |
231+
| ~~JSON output~~ (#392 removed) | `cfl space update INTTEST --name "[Test] JSON" -o json` | Errors: invalid output format |
230232
| No flags provided | `cfl space update INTTEST` | Error: at least one of --name or --description required |
231233
| Non-existent space | `cfl space update NONEXISTENT --name "X"` | Error: not found |
232234
| Verify update | `cfl space view INTTEST` | Shows new name and description |
@@ -238,7 +240,7 @@ All cfl commands should work with both auth methods (no scope limitations for Co
238240
| Delete with confirmation | `cfl space delete INTTEST` (type "y") | Space deleted after confirmation prompt |
239241
| Delete cancelled | `cfl space delete INTTEST` (type "n") | "Deletion cancelled" message |
240242
| Delete with --force | `cfl space delete INTTEST --force` | Space deleted without confirmation |
241-
| JSON output | `cfl space delete INTTEST --force -o json` | `{"status": "deleted", "space_key": "INTTEST", "name": "..."}` |
243+
| ~~JSON output~~ (#392 removed) | `cfl space delete INTTEST --force -o json` | Errors: invalid output format |
242244
| Non-existent space | `cfl space delete NONEXISTENT --force` | Error: not found |
243245

244246
### Space CRUD End-to-End (sequential)
@@ -250,7 +252,7 @@ All cfl commands should work with both auth methods (no scope limitations for Co
250252
| 3. Update name | `cfl space update INTTEST --name "[Test] Updated"` | Name updated |
251253
| 4. Verify update | `cfl space view INTTEST` | Shows new name |
252254
| 5. Update desc | `cfl space update INTTEST --description "New description"` | Description updated |
253-
| 6. List includes it | `cfl space list -o json \| jq '.[] \| select(.key == "INTTEST")'` | Space appears in list |
255+
| 6. List includes it | `cfl space list \| grep INTTEST` | Space appears in list (was `-o json \| jq` pre-#392) |
254256
| 7. Delete | `cfl space delete INTTEST --force` | "Deleted space INTTEST" |
255257
| 8. Verify gone | `cfl space view INTTEST` | Error: not found |
256258

@@ -269,7 +271,7 @@ All cfl commands should work with both auth methods (no scope limitations for Co
269271
| Search by label | `cfl search --label test-label` | Content with specified label |
270272
| Combined filters | `cfl search "deploy" --space DEV --type page` | Filtered results |
271273
| Raw CQL | `cfl search --cql "type=page AND space=DEV"` | CQL executed directly |
272-
| JSON output | `cfl search "test" -o json` | Valid JSON with results and _meta |
274+
| ~~JSON output~~ (#392 removed) | `cfl search "test" -o json` | Errors: invalid output format |
273275
| Plain output | `cfl search "test" -o plain` | Tab-separated values |
274276
| Limit results | `cfl search "test" --limit 5` | Max 5 results |
275277
| No results | `cfl search "xyznonexistent123"` | "No results found" message |
@@ -531,7 +533,7 @@ Copies in the TEST space (originals from INT, CUS, PROD, PLAYBOOK):
531533
|-----------|---------|-----------------|
532534
| View ADF page (default) | `cfl page view <adf-id>` | Shows markdown content (not "(No content)") |
533535
| View ADF page (raw) | `cfl page view <adf-id> --raw` | Shows raw XHTML (or ADF JSON if storage was empty) |
534-
| View ADF page (JSON) | `cfl page view <adf-id> -o json` | `body.storage` populated (or `body.atlas_doc_format` if storage was empty) |
536+
| ~~View ADF page (JSON)~~ (#392 removed) | `cfl page view <adf-id> -o json` | Errors: invalid output format |
535537
| View ADF page (content-only) | `cfl page view <adf-id> --content-only` | Shows content without headers |
536538
| View legacy page (no regression) | `cfl page view <legacy-id>` | Shows markdown content via storage path |
537539

@@ -578,7 +580,7 @@ Copies in the TEST space (originals from INT, CUS, PROD, PLAYBOOK):
578580
| Format | Flag | Verified With |
579581
|--------|------|---------------|
580582
| Table (default) | (none) | Visual inspection |
581-
| JSON | `--output json` | `jq .` parsing |
583+
| ~~JSON~~ (#392 removed) | `--output json` | errors at root |
582584
| Plain | `--output plain` | Tab-separated, scriptable |
583585

584586
---
@@ -620,7 +622,7 @@ All cfl commands work with both auth methods (no scope restrictions for Confluen
620622
#### ADF Body Fallback (#150)
621623
- [ ] View ADF page with empty storage → content displayed via ADF fallback
622624
- [ ] View ADF page (raw) → shows ADF JSON
623-
- [ ] View ADF page (JSON output) → body.atlas_doc_format populated
625+
- [ ] ~~View ADF page (JSON output)~~ (#392 removed)
624626
- [ ] Edit ADF page (title only) → ADF body preserved
625627
- [ ] Edit ADF page (new content) → submitted as ADF
626628
- [ ] View/edit legacy page → no regression (storage path used)
@@ -646,15 +648,15 @@ All cfl commands work with both auth methods (no scope restrictions for Confluen
646648
- [ ] Full-text search returns results
647649
- [ ] Space filter works
648650
- [ ] Type filter works
649-
- [ ] JSON output is valid
651+
- [ ] ~~JSON output is valid~~ (#392 removed; -o json errors at root)
650652
- [ ] Raw CQL works
651653

652654
#### Space CRUD
653655
- [ ] View space (table output)
654-
- [ ] View space (JSON output)
656+
- [ ] ~~View space (JSON output)~~ (#392 removed)
655657
- [ ] View non-existent space (expect error)
656658
- [ ] Create space with key, name, description
657-
- [ ] Create space (JSON output)
659+
- [ ] ~~Create space (JSON output)~~ (#392 removed)
658660
- [ ] Create duplicate key (expect error)
659661
- [ ] Update space name
660662
- [ ] Update space description
@@ -713,7 +715,7 @@ All cfl commands work with both auth methods (no scope restrictions for Confluen
713715
#### ADF Body Fallback (#150)
714716
- [ ] View ADF page with empty storage → content displayed via ADF fallback
715717
- [ ] View ADF page (raw) → shows ADF JSON
716-
- [ ] View ADF page (JSON output) → body.atlas_doc_format populated
718+
- [ ] ~~View ADF page (JSON output)~~ (#392 removed)
717719
- [ ] Edit ADF page (title only) → ADF body preserved
718720
- [ ] Edit ADF page (new content) → submitted as ADF
719721
- [ ] View/edit legacy page → no regression (storage path used)
@@ -739,15 +741,15 @@ All cfl commands work with both auth methods (no scope restrictions for Confluen
739741
- [ ] Full-text search returns results
740742
- [ ] Space filter works
741743
- [ ] Type filter works
742-
- [ ] JSON output is valid
744+
- [ ] ~~JSON output is valid~~ (#392 removed; -o json errors at root)
743745
- [ ] Raw CQL works
744746

745747
#### Space CRUD
746748
- [ ] View space (table output)
747-
- [ ] View space (JSON output)
749+
- [ ] ~~View space (JSON output)~~ (#392 removed)
748750
- [ ] View non-existent space (expect error)
749751
- [ ] Create space with key, name, description
750-
- [ ] Create space (JSON output)
752+
- [ ] ~~Create space (JSON output)~~ (#392 removed)
751753
- [ ] Create duplicate key (expect error)
752754
- [ ] Update space name
753755
- [ ] Update space description

tools/cfl/internal/cmd/attachment/delete.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ func runDeleteAttachment(ctx context.Context, attachmentID string, opts *deleteO
7676
return fmt.Errorf("deleting attachment: %w", err)
7777
}
7878

79-
if opts.Output == "json" {
80-
return v.JSON(map[string]string{
81-
"status": "deleted",
82-
"attachment_id": attachmentID,
83-
"title": attachment.Title,
84-
})
85-
}
86-
8779
v.Success("Deleted attachment: %s (ID: %s)", attachment.Title, attachmentID)
8880

8981
return nil

tools/cfl/internal/cmd/attachment/list.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func runList(ctx context.Context, opts *listOptions) error {
9797
rows = append(rows, []string{att.ID, att.Title, att.MediaType, size})
9898
}
9999

100-
if len(attachments) == 0 && opts.Output != "json" {
100+
if len(attachments) == 0 {
101101
if opts.unused {
102102
_, _ = fmt.Fprintln(opts.Stderr, "No unused attachments found.")
103103
} else {
@@ -108,7 +108,7 @@ func runList(ctx context.Context, opts *listOptions) error {
108108

109109
_ = v.RenderList(headers, rows, result.HasMore())
110110

111-
if result.HasMore() && opts.Output != "json" {
111+
if result.HasMore() {
112112
fmt.Fprintf(os.Stderr, "\n(showing first %d results, use --limit to see more)\n", len(attachments))
113113
}
114114

tools/cfl/internal/cmd/attachment/list_test.go

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ func TestRunList_Empty(t *testing.T) {
6969

7070
err := runList(context.Background(), opts)
7171
testutil.RequireNoError(t, err)
72+
// The empty-results banner used to be suppressed under -o json; #392
73+
// removed that skip, so the banner now always prints to stderr.
74+
testutil.Contains(t, rootOpts.Stderr.(*bytes.Buffer).String(), "No attachments found.")
7275
}
7376

7477
func TestRunList_APIError(t *testing.T) {
@@ -94,33 +97,6 @@ func TestRunList_APIError(t *testing.T) {
9497
testutil.Contains(t, err.Error(), "listing attachments")
9598
}
9699

97-
func TestRunList_JSONOutput(t *testing.T) {
98-
t.Parallel()
99-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
100-
w.WriteHeader(http.StatusOK)
101-
_, _ = w.Write([]byte(`{
102-
"results": [
103-
{"id": "att1", "title": "doc.pdf", "mediaType": "application/pdf", "fileSize": 1024}
104-
]
105-
}`))
106-
}))
107-
defer server.Close()
108-
109-
rootOpts := newListTestRootOptions()
110-
rootOpts.Output = "json"
111-
client := api.NewClient(server.URL, "test@example.com", "token")
112-
rootOpts.SetAPIClient(client)
113-
114-
opts := &listOptions{
115-
Options: rootOpts,
116-
pageID: "12345",
117-
limit: 25,
118-
}
119-
120-
err := runList(context.Background(), opts)
121-
testutil.RequireNoError(t, err)
122-
}
123-
124100
func TestRunList_InvalidOutputFormat(t *testing.T) {
125101
t.Parallel()
126102
// Don't need a server - should fail before API call
@@ -352,4 +328,5 @@ func TestRunList_UnusedFlag_NoUnused(t *testing.T) {
352328

353329
err := runList(context.Background(), opts)
354330
testutil.RequireNoError(t, err)
331+
testutil.Contains(t, rootOpts.Stderr.(*bytes.Buffer).String(), "No unused attachments found.")
355332
}

tools/cfl/internal/cmd/attachment/upload.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ func runUpload(ctx context.Context, opts *uploadOptions) error {
6666

6767
v := opts.View()
6868

69-
if opts.Output == "json" {
70-
return v.JSON(attachment)
71-
}
72-
7369
v.Success("Uploaded: %s", filename)
7470
v.RenderKeyValue("ID", attachment.ID)
7571
v.RenderKeyValue("Title", attachment.Title)

0 commit comments

Comments
 (0)