Skip to content

Add specification format selection to apiops extract for feature parity with Azure/apiops #257

Open

Description

@GABRIELNGBTUC

Problem or use case

apiops extract currently lets users control the CLI stdout format via --format text|json, but it does not expose a user-facing option to control the exported API specification artifact format itself.

The current docs make this distinction visible:

  • docs/commands/extract.md documents --format <type> only as a global flag for command output (text or json).
  • The extract output section describes the artifact tree in general, but there is no documented flag to choose whether an extracted API specification is written as OpenAPI YAML vs JSON when APIM supports both.

This is a migration and usability gap for teams coming from the previous Azure/apiops repository, where specification output format selection was available. In apiops-cli, specification format selection is currently automatic/internal, which makes artifact output less predictable for users who:

  • want consistent JSON specs across repositories and environments,
  • need JSON for downstream tooling, validation, or transformations,
  • want explicit control instead of source-dialect-based auto-selection,
  • are migrating existing workflows from Azure/apiops and expect the same capability.

The current behavior can also be confusing because --format json sounds like it might affect extracted spec files, but according to the current command documentation it only affects machine-readable command output written to stdout.

Proposed solution

Add a user-facing option to explicitly select the exported API specification artifact format during extraction, while preserving the current automatic behavior as the default.

Suggested behavior:

  • Add a dedicated extract flag for specification artifact format selection, for example:
    • apiops extract --specification-format json
    • apiops extract --specification-format yaml
  • Scope this flag to API specification artifacts only, not general command output.
  • Keep --format text|json unchanged so it continues to mean stdout/log output format only.
  • When the new specification-format flag is omitted, preserve today's automatic behavior.
  • Validate unsupported combinations clearly. For example:
    • API types with no specification export should ignore or reject the option with a clear message.
    • Formats unsupported by the underlying APIM export path should fail fast with actionable guidance.
  • Document the mapping between the new CLI flag and the APIM export formats used internally.

Recommended documentation updates:

  • Update docs/commands/extract.md to distinguish:
    • --format = stdout format
    • --specification-format = extracted API spec artifact format
  • Add examples showing the new flag with apiops extract
  • Update migration guidance for users moving from Azure/apiops
  • Update artifact format/reference docs so the expected file extension/content is explicit

Suggested acceptance criteria:

  • Users can explicitly choose the extracted specification artifact format for supported API types.
  • For REST APIs where APIM supports multiple export forms, users can choose JSON vs YAML.
  • The selected format controls the written spec artifact consistently.
  • Existing extract behavior remains unchanged when the new flag is omitted.
  • The docs clearly distinguish stdout formatting from specification artifact formatting.
  • Migration documentation calls out this feature as parity with Azure/apiops.

Relevant current documentation context:

  • docs/commands/extract.md shows:
    • --format <type> with values text or json
    • “Machine-readable JSON output” as stdout behavior
  • README.md also documents --format <type> globally as text or json
  • Integration docs already show that the project cares about spec dialect/format fidelity across API types, including:
    • REST OpenAPI 3.0 YAML
    • REST Swagger 2.0 JSON
    • SOAP WSDL
    • GraphQL SDL

That existing format awareness makes explicit user selection feel like a natural extension of the current extract model.

Affected command

apiops extract

Activity

  1. kierenh commented on Sep 30, 2026

    @kierenh

    +1 from us, mainly because we need a backwards-compatible migration path.

    We're moving from Azure/apiops v5 to apiops-cli. Our v5 extractor runs with API_SPECIFICATION_FORMAT: OpenAPIV3Json, so every API in our repo has a specification.json. Publishing those files with apiops-cli works, which is great. The problem is extraction: apiops extract always writes OpenAPI 3.0 specs as specification.yaml, and there's no way to ask for JSON.

    We may well standardise on specification.yaml eventually, but we want that to be a deliberate, one-off change we schedule ourselves. We don't want it to happen as a side effect of switching extractors. Until then, we need to keep extracting specification.json:

    • Reviewing an extract depends on the spec diff. If the format changes on the first CLI extract, every API's spec appears as a brand-new file, and the real changes get lost in the noise.
    • We always have work in progress on feature branches. Changing format mid-flight means those branches conflict with, or silently diverge from, the new layout.
    • Downstream tooling (Spectral linting, some pipeline scripts) reads specification.json today. We'd like to move that on our own schedule.

    It also looks like a small change. ApimClient.getExportFormat() (src/clients/apim-client.ts) only returns swagger-link or openapi-link for REST APIs, even though its doc comment already lists openapi+json-link as an APIM export format. detectSpecificationFormat() and writeContent() already handle JSON output. A --specification-format json option (as proposed above) could map OpenAPI 3.0 APIs to openapi+json-link and leave Swagger 2.0 APIs on swagger-link.

    One related hazard while this option doesn't exist: running extract over an existing v5 repo writes specification.yaml next to the existing specification.json. In 1.0.4, publish (ArtifactStore.readContent) tries yaml before json, so the JSON file is silently ignored from then on while still looking authoritative in the repo. A warning when both files exist, or removing the other-format file on extract, would make this much easier to catch.

  2. added
    staleNo activity for 30+ days — will be closed if no further activity
    on Oct 31, 2026
  3. github-actions commented on Oct 31, 2026

    @github-actions

    ⚠️ Stale issue notice — This issue has had no activity for 30 day(s).

    It will be automatically closed after 60 days of inactivity.

    To keep this issue open:

    • Leave a comment describing the current status, or
    • Remove the stale label.

    This notice was posted automatically by the stale issue workflow.

  4. kierenh commented on Nov 1, 2026

    @kierenh
  5. GABRIELNGBTUC commented on Nov 2, 2026

    @GABRIELNGBTUC
    Author

    Peter Hauge (@petehauge) Alexander Zaslonov (@azaslonov) Could we have some feedback on this? At the very least something like "upvotes needed" if it's not a priority.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleNo activity for 30+ days — will be closed if no further activitytype:featureNew capability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions