close
Skip to content

V7#844

Merged
guythetechie merged 89 commits into
mainfrom
v7
Apr 28, 2026
Merged

V7#844
guythetechie merged 89 commits into
mainfrom
v7

Conversation

@guythetechie
Copy link
Copy Markdown
Contributor

@guythetechie guythetechie commented Apr 27, 2026

Breaking changes

  • Extractor configuration section names now match the publisher's.

    Before

    apiNames:
    - api1
    - api2
    productNames:
    - product1
    - product2

    After

    apis:
    - api1
    - api2
    products:
    - product1
    - product2

    See configuration.extractor.yaml in the repo root for a correct sample.

  • SOAP API specifications are no longer extracted. The WSDL exported by APIM cannot be reimported by APIM (#387).

  • Tag relationships are now stored under the tag instead of the linked API or product.

    Before

     apis/{apiName}/tags/{tagName}/apiTagInformation.json
     products/{productName}/tags/{tagName}/productTagInformation.json
    

    After

     tags/{tagName}/apis/{apiName}/tagApiInformation.json
     tags/{tagName}/products/{productName}/tagProductInformation.json
    

Note on configuration key casing: during the v7 alpha cycle we briefly experimented with space-separated (named values) and snake_case (named_values) keys. Based on community feedback (#813, #814, #817, #819, #823), we reverted to camelCase (e.g. namedValues).

Added

  • Workspace support

    The extractor and publisher now support the following workspace-scoped resources: APIs, operations, policies, diagnostics, schemas, releases, backends, groups, loggers, named values, policy fragments, products, subscriptions, tags, and version sets. Note that creating workspaces through the tool is NOT supported. You can only manage pre-existing workspaces.

  • Nested configuration for child resources

    We now support nested levels of configuration for the extractor and publisher. This allows the configuration of child resources (e.g. api operations, workspace api diagnostics, etc).

    Sample extractor configuration
    Only operation1 and operation2 will be extracted in api1. All operations in api2 will be extracted.

    apis:
    - api1:
        operations:
        - operation1
        - operation2
    - api2
    ...

    Sample publisher configuration
    The display name of diagnostic3 in api2 in workspace1 will be overriden with my display name.

    workspaces:
    - workspace1:
        apis:
        - api2:
            diagnostics:
            - diagnostic3:
                properties:
                  displayName: my display name
    ...
  • Empty configuration in extractor

    Previously, if we wanted to skip extracting all resources of a type, we had to put a random placeholder value (e.g. ignore). We now support the more intuitive [].

    Before

    apis: ignore # Workaround to skip extracting all APIs.

    After

    apis: [] # All APIs will be skipped.
  • Better ID references across APIM instances

    Many APIM resources reference others through IDs. For example, here is a diagnostic that references a logger through the loggerId property:

     {
      "properties": {
        ...
        "loggerId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.ApiManagement/service/apimService1/loggers/azuremonitor"
        ...
      }
    }

    If we publish this diagnostic as-is to another APIM instance, the publisher will fail. The logger reference is specific to APIM instance apimService1 in resource group rg1 and subscription 00000000-0000-0000-0000-000000000000. To work around this, we have to edit the JSON or override the publisher configuration to reference the new APIM instance.

    Going forward, the extractor will use relative references where possible. In the above scenario, it will write loggerId: "/loggers/azuremonitor". This relative reference will work when publishing across instances.

  • Dry-run mode for the publisher (#754)

    The publisher can now run in dry-run mode. It logs what it would do without making changes to APIM. Dry-run is disabled by default, but you can control this by:

    • Setting the DRY_RUN configuration value to true (or false to disable).
    • Passing --dry-run to the publisher executable (the bare flag enables dry run).
    • Passing --dry-run true|false to the publisher executable explicitly.
  • Pre-publish validation

    Before making any changes to APIM, the publisher now validates the resource set to catch these problems earlier:

    • Cyclical relationships (e.g. subscriptionA depending on groupB which depends on apiC with depends on subscriptionA). These are always flagged as errors and will throw an exception.
    • Missing predecessors (e.g. a policy that uses a named value that isn't in source). Behavior is controlled by the STRICT_VALIDATION configuration variable:
      • STRICT_VALIDATION=true: the publisher throws an exception.
      • Otherwise: the publisher logs a warning and continues. This supports scenarios where different teams own different resource types.
  • Configuration logging at startup

    The extractor and publisher now log configuration values. This should make it a lot easier to troubleshoot configuration issues. Sensitive values are redacted, with only the first 3 characters shown.

    Extractor version is 7.0.0.
    Configuration summary
      apimServiceName ........................... (not set)
      apiSpecificationFormat .................... (not set)
      API_MANAGEMENT_SERVICE_NAME ............... api****
      API_MANAGEMENT_SERVICE_OUTPUT_FOLDER_PATH . C:\Users\me\AppData\Local\Temp\apiops
      API_SPECIFICATION_FORMAT .................. (not set)
      APPLICATION_INSIGHTS_CONNECTION_STRING .... (set to whitespace)
      ARM_API_VERSION ........................... (not set)
      AZURE_BEARER_TOKEN ........................ eyJ****
      AZURE_CLOUD_ENVIRONMENT ................... (not set)
      AZURE_RESOURCE_GROUP_NAME ................. wor****
      AZURE_SUBSCRIPTION_ID ..................... 105****
      COMMIT_ID ................................. (not set)
      CONFIGURATION_YAML_PATH ................... C:\Users\me\Local\Temp\apiops\configuration.extractor.yaml
      DRY-RUN ................................... (not set)
      DRY_RUN ................................... true
      OTEL_EXPORTER_OTLP_ENDPOINT ............... https://ote****
      STRICT_VALIDATION ......................... (not set)
    
  • Extractor and publisher executable versions now match the GitHub release version automatically, so it's clear which build you're running (#811).

Fixed

  • Improved publishing of API specifications across several scenarios (#818).
  • Worked around an APIM issue where importing certain API specifications wiped the display name and description.
  • Publisher now puts named values one at a time to avoid race conditions with policies.
  • Fixed issue with backend pools that depend on individual backends (#797).
  • Fixed empty serviceUrl values causing deployment failures (#760).
  • Made tag APIs, tag products, and product APIs more reliable on both extract and publish.
  • Made HTTP retry logic more robust against transient APIM errors.

Guy Fankam and others added 30 commits September 10, 2025 14:36
- Added unit tests for extractor and publisher
- Version bumps
- Fixed bug in workspace API revision
Guy Fankam and others added 29 commits February 24, 2026 00:43
- Relax parser validation
- Remove silent failures
…n commit mode (#841)

When running with COMMIT_ID set and FeatureManagement__Workspaces=true, the
publisher would hang silently after 'Running publisher...' with no APIM calls
and no error output.

Root cause: processDelete cascaded to successors for every resource where
isInFileSystem=false, not just resources actually being deleted. WorkspaceResource
has no artifact file and is never part of the resource set, so it always entered
processDelete. Its cascade logic then awaited the workspace child tasks (e.g.
WorkspaceApiResource), which were themselves waiting for the workspace task via
the predecessor relationship — a circular wait.

Fix: add a guard at the top of processDelete that returns immediately when the
resource is not in the resource set. The existing conditional around deleteResource
is removed as it is now unreachable when false.

Fixes #838

Co-authored-by: Michel Versluijs <michel.versluijs@ns.nl>
@guythetechie guythetechie merged commit 27de477 into main Apr 28, 2026
1 check passed
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