Skip to main content
← Back to list
01Issue
FeatureOpenExtensions

Add Azure provider pipeline to codegen

Opened by stack72 · 4/7/2026· GitHub #25

Context

We have codegen pipelines for AWS, GCP, Hetzner Cloud, and DigitalOcean that generate swamp extension models from provider API schemas. Azure is the remaining major cloud provider.

Azure is the most complex provider due to:

  • Schema source is a Git repo of OpenAPI 2.0 (Swagger) specs (~4,000+ files)
  • Specs use allOf extensively for inheritance, requiring a complex normalizer
  • Discriminator-based polymorphism needs expansion into concrete property sets
  • Long-Running Operations (LRO) with two polling patterns (Azure-AsyncOperation and Location headers)
  • Per-resource API versioning (each resource type has its own API version)
  • OAuth2 client credentials auth (unlike AWS SDK chain or GCP gcloud)

What Needs to Be Built

Codegen files (codegen/azure/)

  • pipeline.ts — schema fetching (git clone/update of azure-rest-api-specs), spec discovery with version deduplication, OpenAPI parsing, generation orchestration
  • extensionModelGenerator.ts — generates per-resource TypeScript model files
  • libGenerator.ts — generates _lib/azure.ts (OAuth2 auth, URL template substitution, ARM REST CRUD, LRO polling)
  • normalizer.ts — AzureNormalizer (allOf/oneOf/anyOf flattening, discriminator expansion, type inference, format normalization). This is the hardest part.
  • pathParser.tsparseEndpointPath() for ARM resource paths
  • overrides.ts — schema-specific fixes (case sensitivity, validation relaxation)

Generated output (model/azure/{service}/)

Per-service packages following the same pattern as model/aws/{service}/ and model/gcp/{service}/. Each service directory contains manifest.yaml, deno.json, deno.lock, README.md, LICENSE.txt, and extensions/models/*.ts + _lib/azure.ts.

Wiring

  • Add case "azure" to codegen/commands/generate.ts and codegen/commands/fetchSchema.ts
  • Add --provider azure to codegen/main.ts
  • Add tasks to codegen/deno.json: fetch-schema:azure, generate:azure, update-lockfiles:azure, bump-versions:azure
  • Add generateAzureReadme() to codegen/shared/readmeGenerator.ts
  • Add generateAzureDenoConfig() to codegen/shared/denoConfigGenerator.ts (just zod — no SDK deps in generated output)
  • Add @apidevtools/swagger-parser to codegen/deno.json imports (for OpenAPI dereferencing)

CI

  • Add azure-check batch job to .github/workflows/ci.yml (same pattern as aws-check and gcp-check)
  • Add azure-lockfile job
  • Add to review needs: lists

Design Document

Read codegen/designs/azure.md — it covers the full architecture: schema source, normalization, property classification, _lib helper design, model structure, naming conventions, overrides, and implementation order.

Old Code Reference

The original Azure implementation (for the old SI architecture, not swamp) lives at: /Users/stack72/code/systeminit/si/bin/clover/src/pipelines/azure/

Key files:

  • spec.ts (1074 lines) — AzureNormalizer, parseEndpointPath(), parseAzureSpec(). This is the core complexity. The normalization logic (allOf flattening, discriminator expansion, intersect/union) ports directly.
  • schema.tsinitAzureRestApiSpecsRepo(), findLatestAzureOpenApiSpecFiles(), readAzureSwaggerSpec(), EXCLUDE_SPECS list, IGNORE_RESOURCE_TYPES list
  • overrides.ts — case sensitivity fixes, validation relaxation
  • pipeline-steps/addDefaultProps.ts — injected properties (resourceGroupName, subscriptionId, resourceId template, apiVersion, PropUsageMap)
  • funcs/actions/create.ts — LRO polling implementation (Azure-AsyncOperation and Location header patterns)

Important: The old code generates SI-specific output (base classes, action functions). The schema parsing and normalization logic ports directly; the output generation is completely different (swamp extension models with Zod schemas).

Existing Patterns to Follow

Look at these for the established patterns:

  • codegen/aws/pipeline.ts — per-service generation with CalVer versioning, file writing, deno fmt
  • codegen/gcp/pipeline.ts — similar but with Discovery Documents instead of CloudFormation
  • codegen/shared/zodGenerator.ts — converts CfProperty → Zod schema code (reuse for Azure)
  • codegen/shared/schema/types.ts — CfProperty type definitions (Azure normalizer output should produce these)
  • codegen/commands/generate.tsgenerateAwsProvider() shows the file-writing loop pattern

Acceptance Criteria

  • deno task fetch-schema:azure clones/updates the azure-rest-api-specs repo
  • deno task generate:azure produces per-service extension packages under model/azure/
  • Generated models have correct Zod schemas (GlobalArgs from PUT, Resource from GET)
  • _lib/azure.ts handles OAuth2 auth, URL template substitution, ARM CRUD, and LRO polling
  • Generation is idempotent (second run produces 0 changes)
  • deno check, deno lint, deno fmt --check all pass on generated output
  • Codegen itself passes deno check main.ts, deno lint, deno fmt --check
  • AzureNormalizer handles allOf, oneOf/anyOf, and discriminator expansion correctly
  • Known problematic specs/resources are excluded (see old code's exclude lists)
  • CI jobs added (azure-check, azure-lockfile)

Implementation Order (suggested)

  1. _lib/azure.ts generator — self-contained, testable
  2. Path parser — parseEndpointPath() with tests
  3. AzureNormalizer — start basic (allOf/type inference), then add discriminators
  4. Pipeline — schema fetching, spec parsing, resource discovery
  5. Model generator — should be straightforward once pipeline produces right data
  6. Wire up CLI/commands/CI — mechanical, same pattern as AWS/GCP

Automoved by swampadmin from GitHub issue #25

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED

Open

4/7/2026, 11:28:52 PM

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.