Skip to content

feat: add --json to list/modes/env-info/version and remove the workflow project type#205

Open
wyli wants to merge 3 commits into
mainfrom
feat/json-read-verbs
Open

feat: add --json to list/modes/env-info/version and remove the workflow project type#205
wyli wants to merge 3 commits into
mainfrom
feat/json-read-verbs

Conversation

@wyli

@wyli wyli commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Two related changes to the read/discovery surface.

1. --json on every read verb

Extends the opt-in --json flag — already on status and env-check — to the four remaining read commands, so agents and scripts can parse output instead of scraping prose.

Command Payload
list --json {projects: [{name, project_type, source_folder, language[], modes[]}]} — includes source_folder, the one field callers previously had to guess
modes <project> --json the resolved metadata.modes object plus project / language
env-info --json full structured host report (cli, system, python, source_project, git, docker, cuda_gpu, sccache, environment_variables)
version --json {package, version, executable, module}

How

  • New utils/json_output.dumps() injects an additive schema_version (1) as the first key of every --json payload. Retrofitted onto the existing status / env-check JSON — additive only, no field moves/renames.
  • env_info.py gains a parallel gather_* data layer beside the collect_* prose printers (the same collect/format split status.py uses). Only one rendering path runs per invocation.
  • Env-var name lists and the Python-environment classification are extracted to single-source helpers shared by the prose and JSON renderers.
  • Payloads are lean: no redundant command/status wrapper — the exit code already carries status.

2. Remove the workflow project-type concept

Mirrors nvidia-holoscan/holohub#1646 ("Remove Holohub Workflow Concept Entirely"), which folded the AI Surgical Video workflow into applications/ and dropped the type — it has no meaningful difference from an application.

  • Delete metadata/workflow.schema.json (packaged via the *.schema.json glob).
  • Drop the workflows dir + workflow schema from METADATA_DIRECTORY_CONFIG, gather_metadata SCHEMA_TYPES, and metadata_validator KNOWN_ENVELOPES.
  • Drop workflows from holohub root-detection and search-path dir lists, and workflow from PROJECT_PREFIXES.
  • Drop workflow from the benchmark-eligible project types in build (help text and fatal message now say "applications and benchmarks").
  • Drop workflow from external_resolver's dependency-envelope keys and from list's LIST_TYPES.

Generic-English/product-name uses ("source-project workflows", "I4H Workflows") are intentionally left.

Tests

  • One lean test per new --json surface — list, modes, and env-info (parseable output, with env-info also covering null sections on a tool-less host); schema_version == 1 added to the existing status/env-check JSON tests.
  • Resolver envelope test retargeted to application/benchmark; workflow.schema.json dropped from the required-package-data set.
  • Full unit suite: 411 passed. ruff check + ruff format clean.

🤖 Generated with Claude Code

Completes the F3 "--json on every read verb" surface from the agentic-CLI
design. `status` and `env-check` already emitted JSON; this adds the same
opt-in `--json` flag to the four remaining read commands so agents can parse
discovery and diagnostic output instead of scraping prose:

* `list --json`     — {projects: [{name, project_type, source_folder,
                      language[], modes[]}]}. Includes source_folder, the one
                      field agents previously had to guess.
* `modes --json`    — the resolved metadata.modes object plus project/language.
* `env-info --json` — full structured host report. env_info.py grows a
                      parallel `gather_*` data layer beside the `collect_*`
                      prose printers (the status.py collect/format split);
                      only one path runs per invocation.
* `version --json`  — package/version/executable/module.

All payloads flow through a new utils/json_output.dumps that injects an
additive `schema_version` (1) as the first key; the same wrapper is
retrofitted onto the existing status/env-check JSON (additive, no field moves).
Env-var name lists and the Python-environment classification are extracted to
single-source helpers shared by the prose and JSON renderers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@wyli
wyli requested a review from Copilot July 24, 2026 08:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The CLI adds schema-versioned JSON output for version, project information, environment information, status, and system checks. Workflow metadata discovery, validation, dependency extraction, packaging, and benchmark handling are removed or restricted.

Changes

CLI JSON output

Layer / File(s) Summary
Shared JSON serialization contract
src/holoscan_cli/utils/json_output.py, src/holoscan_cli/status.py, src/holoscan_cli/system_check.py, tests/unit/test_status.py, tests/unit/test_env_info.py
A shared serializer adds schema_version: 1 to JSON output, and existing status and system-check formatters use it.
Version and project information JSON modes
src/holoscan_cli/__main__.py, src/holoscan_cli/version/version.py, src/holoscan_cli/commands/info.py, tests/unit/test_command_registry.py
version, list, and modes accept --json and emit structured payloads with normalized project metadata.
Environment information JSON reporting
src/holoscan_cli/utils/env_info.py, src/holoscan_cli/commands/info.py, tests/unit/test_env_info.py
Environment classification, variable collection, host-tool discovery, GPU parsing, and JSON assembly are added for env-info --json.

Workflow metadata removal

Layer / File(s) Summary
Workflow metadata and packaging removal
src/holoscan_cli/metadata/*, tests/unit/test_package_data.py
Workflow metadata is removed from schema recognition, directory configuration, documentation examples, and required packaged schemas.
Workflow discovery and dependency removal
src/holoscan_cli/utils/holohub.py, src/holoscan_cli/utils/external_resolver.py, tests/unit/test_external_resolver.py
Repository discovery, component search paths, project prefixes, and external dependency extraction no longer include workflows.
Workflow benchmark handling removal
src/holoscan_cli/commands/build.py
Benchmark patching and restoration are restricted to application and benchmark projects, with updated help and error text.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: tbirdso

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main changes: new --json support and removal of the workflow project type.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/holoscan_cli/commands/info.py (1)

148-158: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Normalize language for parity with list --json.

list --json runs language through _project_languages() to always emit a list[str], but the modes --json payload returns metadata.get("language") raw — which can be a string, a list, or None. Consumers of the new machine-readable contract then have to handle two shapes for the same field name.

♻️ Reuse the existing normalizer
     if getattr(args, "json", False):
         print(
             json_dumps(
                 {
                     "project": args.project,
-                    "language": metadata.get("language"),
+                    "language": _project_languages(metadata),
                     "modes": modes,
                 }
             )
         )
         return
🤖 Prompt for 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.

In `@src/holoscan_cli/commands/info.py` around lines 148 - 158, Update the JSON
payload in the info command’s json branch to pass metadata.get("language")
through the existing _project_languages() normalizer, matching the list --json
contract and always emitting a list[str]. Keep the project and modes fields
unchanged.
🤖 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.

Nitpick comments:
In `@src/holoscan_cli/commands/info.py`:
- Around line 148-158: Update the JSON payload in the info command’s json branch
to pass metadata.get("language") through the existing _project_languages()
normalizer, matching the list --json contract and always emitting a list[str].
Keep the project and modes fields unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4c58a10f-02a3-45cf-8d98-0a12858e7340

📥 Commits

Reviewing files that changed from the base of the PR and between 6c8cf98 and 6acb967.

📒 Files selected for processing (11)
  • src/holoscan_cli/__main__.py
  • src/holoscan_cli/commands/info.py
  • src/holoscan_cli/status.py
  • src/holoscan_cli/system_check.py
  • src/holoscan_cli/utils/env_info.py
  • src/holoscan_cli/utils/json_output.py
  • src/holoscan_cli/version/version.py
  • tests/unit/test_command_registry.py
  • tests/unit/test_env_info.py
  • tests/unit/test_status.py
  • tests/unit/version/test_version.py

Mirrors holohub#1646 ("Remove Holohub Workflow Concept Entirely"), which
folded the AI Surgical Video workflow into applications and dropped the
workflow type: it has no meaningful difference from an application.

Removes the workflow project type across the CLI:
* delete metadata/workflow.schema.json (packaged via the *.schema.json glob)
* drop the "workflows" dir + "workflow" schema from METADATA_DIRECTORY_CONFIG,
  gather_metadata SCHEMA_TYPES, and metadata_validator KNOWN_ENVELOPES
* drop "workflows" from the holohub root-detection and search-path dir lists,
  and "workflow" from PROJECT_PREFIXES
* drop "workflow" from the benchmark-eligible project types in build (help
  text, patch/restore guards, and the fatal message now say "applications")
* drop "workflow" from external_resolver's dependency-envelope keys and from
  the `list` LIST_TYPES

Tests: retarget the resolver envelope test to application/benchmark and drop
workflow.schema.json from the required-package-data set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wyli wyli changed the title feat: add --json to list, modes, env-info, and version feat: add --json to list/modes/env-info/version and remove the workflow project type Jul 24, 2026
@wyli
wyli requested a review from tbirdso July 24, 2026 09:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/unit/test_external_resolver.py (1)

134-135: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Keep regression coverage for ignored workflow metadata.

Add a case asserting that a metadata object containing only "workflow" dependencies returns no parsed dependencies. This protects the behavior introduced by removing workflow support.

🤖 Prompt for 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.

In `@tests/unit/test_external_resolver.py` around lines 134 - 135, Add a
parametrized regression case to test_parses_application_and_benchmark_shapes, or
the surrounding external-resolver tests, with metadata containing only
“workflow” dependencies; assert that parsing returns no dependencies, preserving
the behavior after workflow support removal.
🤖 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 `@src/holoscan_cli/commands/build.py`:
- Around line 120-122: Update the --benchmark help text in
src/holoscan_cli/commands/build.py lines 120-122 to state that it is valid for
applications and benchmarks, and update the corresponding fatal error message in
lines 252-260 to use the same accepted project types.

---

Nitpick comments:
In `@tests/unit/test_external_resolver.py`:
- Around line 134-135: Add a parametrized regression case to
test_parses_application_and_benchmark_shapes, or the surrounding
external-resolver tests, with metadata containing only “workflow” dependencies;
assert that parsing returns no dependencies, preserving the behavior after
workflow support removal.
🪄 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: 30ecbbb1-ef71-4816-8790-50675a3e7a9e

📥 Commits

Reviewing files that changed from the base of the PR and between 6acb967 and b527f29.

📒 Files selected for processing (10)
  • src/holoscan_cli/commands/build.py
  • src/holoscan_cli/commands/info.py
  • src/holoscan_cli/metadata/gather_metadata.py
  • src/holoscan_cli/metadata/metadata_validator.py
  • src/holoscan_cli/metadata/utils.py
  • src/holoscan_cli/metadata/workflow.schema.json
  • src/holoscan_cli/utils/external_resolver.py
  • src/holoscan_cli/utils/holohub.py
  • tests/unit/test_external_resolver.py
  • tests/unit/test_package_data.py
💤 Files with no reviewable changes (7)
  • src/holoscan_cli/metadata/workflow.schema.json
  • tests/unit/test_package_data.py
  • src/holoscan_cli/metadata/gather_metadata.py
  • src/holoscan_cli/metadata/metadata_validator.py
  • src/holoscan_cli/metadata/utils.py
  • src/holoscan_cli/utils/holohub.py
  • src/holoscan_cli/commands/info.py

Comment thread src/holoscan_cli/commands/build.py Outdated
Source fixes from review:
* modes --json: normalize `language` via _project_languages() so it is always
  a list[str], matching the list --json contract.
* build --benchmark: help text and fatal message now say "applications and
  benchmarks" (benchmark is an eligible type, application-only was inaccurate).

Tests: pare the --json additions to one lean test per new surface — list,
modes, and env-info (parseable + null handling). Drop the redundant version
JSON test and the extra edge-case cases; keep the one-line schema_version
assertions on the existing status/env-check JSON tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@tbirdso tbirdso left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🎉 looks good! Minor questions about schema, no blockers

Comment on lines +325 to +332
return {
"version": holoscan_cli.__version__,
"package": str(Path(holoscan_cli.__file__).parent),
"environment": env["kind"],
"environment_prefix": env["prefix"],
"uninstall": env["uninstall"],
"source_override": os.environ.get("HOLOSCAN_CLI_SOURCE"),
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I wonder if we have any schema or interface contract expectation for these JSON outputs, or should they be considered unstable and subject to change? Suggest documenting for developer expectations, up to you how far we should go at this point in time

Comment on lines +29 to +31
# Bump only for a breaking change (a removed or renamed field). Additive
# changes — new keys — keep the same version.
SCHEMA_VERSION = 1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there any actual schema to help validate or is this a placeholder for now?

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.

3 participants