Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Support machine-friendly output (JSON) #135

Open
maxtruxa opened this issue Jun 29, 2022 · 1 comment
Open

[FEATURE] Support machine-friendly output (JSON) #135

maxtruxa opened this issue Jun 29, 2022 · 1 comment
Labels
enhancement New feature or request
Milestone

Comments

@maxtruxa
Copy link
Contributor

Describe the scenario and circumstances that should be addressed / Describe alternatives you've considered

Tooling built around bpt frequently needs to get information from bpt. Parsing the "normal", user-friendly output for that information kind of works but is error-prone and can easily break with every update of bpt. Especially accurately detecting error reasons is... not pretty.

Describe the solution you'd like

An alternative, machine-friendly output format - like JSON - would allow reliable parsing of bpt's output.

I imagine some global option to switch to JSON output:

  • --output-format=json: Probably confusing because bpt --output-format=json build --output=foo looks like --output-format= refers to --output=.
  • --output-json: Same issue as --output-format=json.
  • --log-style=json: Somewhat consistent with --log-level=.
  • --json

All flag-style options (--output-json, --json) suffer from the fact that if additional output formats are introduced in the future more (mutually exclusive) options have to be added.

Once that flag is turned on, one of these behaviors would be expected:

  1. All non-JSON output is suppressed. Relevant information is JSON-formatted and sent to stdout. Error messages might still appear on stderr.
  2. All non-JSON output (including error messages) is sent to stderr. Relevant information is JSON-formatted and sent to stdout.
  3. All non-JSON output is wrapped in a JSON object (like [info] foo bar becoming {"type": "msg", "data": {"level": "info", "msg": "foo bar"}}) and sent to stdout. Relevant information is JSON-formatted and sent to stdout as well.

Additional considerations:

  • It would be super helpful if errors like "repo doesn't exist", "package doesn't exist", "package already exists", etc. would get some kind of stable identifier (see Example 2).
  • There are various ways for separating JSON objects in the output. I'll reuse the aliases used by journalctl:
    • json: Output one JSON object per line, separated by newlines.
    • json-pretty: Like json but JSON objects are pretty-printed to make them easier to read for humans. This is not really relevant for the goal of machine-friendly output but is a developer-friendly addition that is trivially to implement if json works already.
    • json-seq: Output JSON objects prefixed by ASCII RS (0x1e) and suffixed by LF (0x0a). This is standardized by RFC 7464. This format even allows interleaving JSON objects and normal output lines.

Example 1

bpt repo import "$PATH_TO_REPO" .

Normal output:

[info ] [nbt-local]: Imported my-app@0.1.0~1 from [.]

JSON output:

{
  "type": "repo-import",
  "data": {
    "pkg":"my-app@0.1.0~1",
    "source": "."
  }
}
// or maybe
{
  "type": "repo-import",
  "data": {
    "pkg": {
      "id": "my-app@0.1.0~1",
      "name": "my-app",
      "version": "0.1.0",
      "revision": 1
    },
    "source": "."
  }
}

Example 2

bpt repo import "$PATH_TO_REPO" . # again

Normal output:

[error] Refusing to overwrite existing package my-app@0.1.0~1 (Importing from [.])

JSON output:

{
  "type":"error",
  "data": {
    "id": "package-already-exists",
    "msg": "Refusing to overwrite existing package my-app@0.1.0~1",
    "pkg":"my-app@0.1.0~1",
    "source": "."
  }
}
// or maybe
{
  "type":"error",
  "data": {
    "id": "package-already-exists",
    "msg": "Refusing to overwrite existing package my-app@0.1.0~1",
    "pkg": {
      "id": "my-app@0.1.0~1",
      "name": "my-app",
      "version": "0.1.0",
      "revision": 1
    },
    "source": "."
  }
}

Example 3

bpt repo ls "$PATH_TO_REPO"

Normal output:

my-lib@0.1.2~1
my-app@0.1.0~1

JSON output:

{
  "type": "repo-ls",
  "data": {
    "pkg":"my-app@0.1.0~1"
  }
}
{
  "type": "repo-ls",
  "data": {
    "pkg":"my-lib@0.1.2~1"
  }
}
// or maybe
{
  "type": "repo-ls",
  "data": {
    "pkg": {
      "id": "my-app@0.1.0~1",
      "name": "my-app",
      "version": "0.1.0",
      "revision": 1
    }
  }
}
{
  "type": "repo-ls",
  "data": {
    "pkg": {
      "id": "my-lib@0.1.2~1",
      "name": "my-lib",
      "version": "0.1.2",
      "revision": 1
    }
  }
}
@maxtruxa maxtruxa added the enhancement New feature or request label Jun 29, 2022
@vector-of-bool
Copy link
Owner

This is something that I have wanted to address from early on. I would very much like to provide a json-based subcommand API consisting of invoking functionality in a programmatic manner and returning data via stdout. This would be very helpful for tooling integration (e.g. editor extensions).

I'll use this ticket to track the feature. This is beyond the scope of the beta improvements, but I'll hope to get to it sooner than later.

@vector-of-bool vector-of-bool added this to the Backlog milestone Jun 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants