@postman-cse/onboarding-azure-spec-discovery 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/RELEASE_POLICY.md +43 -0
- package/SECURITY.md +32 -0
- package/SUPPORT.md +30 -0
- package/action.yml +83 -0
- package/dist/cli.cjs +178405 -0
- package/dist/index.cjs +180605 -0
- package/docs/LIVE_TESTING_RUNBOOK.md +51 -0
- package/docs/providers.md +26 -0
- package/package.json +75 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Live Azure validation runbook
|
|
2
|
+
|
|
3
|
+
Live validation provisions disposable real Azure resources, exercises the compiled `dist/cli.cjs` against them, captures sanitized evidence, and tears the resources down. Provisioning is operator-triggered and runs in the shared Azure DevOps deployment context; it is never wired into pull-request CI.
|
|
4
|
+
|
|
5
|
+
## Deployment context
|
|
6
|
+
|
|
7
|
+
- Azure DevOps organization: `https://dev.azure.com/PostmanDevOps`
|
|
8
|
+
- Project: `CSE Pilots`
|
|
9
|
+
- Azure Resource Manager service connection: `azure-cse-pilot-builders`
|
|
10
|
+
- Scope: the service connection's `Active Azure Subscription`
|
|
11
|
+
- Resource group: `CSE-Azure-Team` (the connection's Contributor scope)
|
|
12
|
+
|
|
13
|
+
Do not provision live-validation resources from a personal Azure subscription. The Azure DevOps `AzureCLI@2` task authenticates with the workload-identity service connection and derives `AZURE_SUBSCRIPTION_ID` from `az account show`; no personal login, tenant, or subscription ID belongs in the pipeline or committed evidence.
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
- Permission to queue the `PostmanDevOps` live-validation pipeline in `CSE Pilots`.
|
|
18
|
+
- The `azure-cse-pilot-builders` service connection remains ready and authorized for the pipeline.
|
|
19
|
+
- A fresh build: `npm run build`.
|
|
20
|
+
|
|
21
|
+
## Run
|
|
22
|
+
|
|
23
|
+
Queue the `postman-azure-spec-discovery-live-validation` pipeline in `PostmanDevOps/CSE Pilots`. Its `AzureCLI@2` task checks out the requested GitHub ref, builds it, derives the service-connection subscription, and runs:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
node validation/scripts/validate-live-azure-surfaces.mjs --provision --teardown
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Download the sanitized `azure-spec-discovery-live-evidence` pipeline artifact and commit only `live-azure-surfaces.json` after reviewing it against `validation/evidence/README.md`.
|
|
30
|
+
|
|
31
|
+
The runner:
|
|
32
|
+
|
|
33
|
+
1. Derives and pins the subscription supplied by `azure-cse-pilot-builders` (`az account show` then `az account set`).
|
|
34
|
+
2. Deploys collision-resistant, run-tagged resources into `CSE-Azure-Team` using `validation/fixtures/azure/live-stack.bicep` (APIM Consumption + current HTTP API + App Service plan/site).
|
|
35
|
+
3. Deploys the local App Service stub zip and points `siteConfig.apiDefinition.url` at the stub's `/openapi.json`.
|
|
36
|
+
4. Polls APIM until export is available (5-minute ceiling, 10-second interval).
|
|
37
|
+
5. Runs six CLI cases: explicit APIM `api-id`; APIM discovery; App Service API definition; `discover-many`; local IaC single resolve; ambiguity fixture.
|
|
38
|
+
6. Writes sanitized evidence to `validation/evidence/live-azure-surfaces.json` (schema 1: totals plus per-case `{name,status,sourceType,providerType,specFormat}` — no IDs, hosts, URLs, or spec bodies).
|
|
39
|
+
7. In `finally`, deletes only the exact App Service site, plan, and APIM service whose identity and run-marker tag match the manifest, removes the deployment record, and polls for up to five minutes before failing if any resource with that run marker remains. It never deletes the shared resource group. Outside ADO, the fallback dedicated-group mode retains its guarded group deletion.
|
|
40
|
+
|
|
41
|
+
## Flags
|
|
42
|
+
|
|
43
|
+
- `--provision` — required to create any Azure resource.
|
|
44
|
+
- `--teardown` — required to delete the run-created resources.
|
|
45
|
+
- Omit both to re-validate an existing stack from a `.local.json` manifest within the same service-connection subscription.
|
|
46
|
+
|
|
47
|
+
## Safety rules
|
|
48
|
+
|
|
49
|
+
- Shared-group mode deletes only exact run-created resources verified by name, type, subscription, group, and run marker. Dedicated-group mode deletes only the group it created, verified by run marker and subscription.
|
|
50
|
+
- Raw manifests, deployment outputs, and zips are gitignored (`validation/.gitignore`); only sanitized evidence is committed.
|
|
51
|
+
- Never substitute a personal service connection, personal `az login`, or production subscription.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Provider contracts
|
|
2
|
+
|
|
3
|
+
Azure spec discovery ships three providers in v1. Each implements the same `SpecProvider` seam (`probe`, `listCandidates`, `exportSpec`) and is probed fail-soft: authorization failures map to `skipped:iam`, other failures to `skipped:error`, and discovery continues with the remaining providers.
|
|
4
|
+
|
|
5
|
+
## `apim` — Azure API Management
|
|
6
|
+
|
|
7
|
+
- Enumerates every visible APIM service (subscription-wide or scoped by `resource-group`) plus each service workspace and lists both service- and workspace-scoped APIs.
|
|
8
|
+
- Only **current revisions** are candidates; non-current revisions are dropped at enumeration.
|
|
9
|
+
- Only **HTTP** APIs are exportable. SOAP, GraphQL, WebSocket, gRPC, and OData APIs stay visible as unsupported candidates so ambiguity output can name them, but selecting one resolves to manual review and never writes a file.
|
|
10
|
+
- Export uses the ARM export protocol: the management call returns a short-lived Storage SAS link, and the document is fetched from that link immediately. A 403 discards the expired link and repeats the whole export/fetch cycle within `max-attempts`; links are never logged. The exported document is validated (`Swagger 2.0`/`OpenAPI 3.x`, non-empty `paths`) before it is written.
|
|
11
|
+
- The full APIM API ARM resource ID appears only in the `api-id` output and `resolution-json.apiId`. Logs, evidence, and Step Summaries redact it.
|
|
12
|
+
|
|
13
|
+
## `app-service` — App Service API definition
|
|
14
|
+
|
|
15
|
+
- Lists App Service sites and reads `siteConfig.apiDefinition.url`.
|
|
16
|
+
- A site is a candidate when its API definition URL is set. Export fetches the URL over HTTPS with a bounded, redirect-limited, content-validated fetch (private-address and non-HTTPS URLs are refused).
|
|
17
|
+
- The fetched document is validated the same way as APIM exports before it is written.
|
|
18
|
+
|
|
19
|
+
## `iac-local` — repository Azure IaC
|
|
20
|
+
|
|
21
|
+
- Always `available` (no network probe). Scans a bounded set of repository files: ARM templates (`*.json` with `Microsoft.ApiManagement` resources carrying inline OpenAPI), Bicep-compiled JSON, and `azure.yaml` service hints.
|
|
22
|
+
- A single embedded spec resolves directly; multiple hits become ranked candidates like any other provider.
|
|
23
|
+
|
|
24
|
+
## Ordering and narrowing
|
|
25
|
+
|
|
26
|
+
Probe order is `apim`, `app-service`, `iac-local`. Candidates from all available providers enter the same four-tier narrowing pipeline (`iac-fingerprint`, `rg-correlation`, `tag-prefilter`, `naming-heuristic`); the chosen tier is reported in the `narrowing-strategy` output. Tags in the `postman:*` namespace (`postman:repo`, `postman:project-name`) are the strongest ownership signals.
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@postman-cse/onboarding-azure-spec-discovery",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Discover Azure-hosted API specs and hand the result to Postman API onboarding.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"postman-azure-spec-discovery": "dist/cli.cjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"action.yml",
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md",
|
|
14
|
+
"docs",
|
|
15
|
+
"SECURITY.md",
|
|
16
|
+
"SUPPORT.md",
|
|
17
|
+
"RELEASE_POLICY.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"prepare": "git config core.hooksPath .githooks",
|
|
21
|
+
"bundle": "rm -rf dist && esbuild src/index.ts --bundle --platform=node --target=node24 --format=cjs --outfile=dist/index.cjs && esbuild src/cli.ts --bundle --platform=node --target=node24 --format=cjs --banner:js='#!/usr/bin/env node' --outfile=dist/cli.cjs && chmod 755 dist/cli.cjs",
|
|
22
|
+
"build": "npm run typecheck && npm run bundle",
|
|
23
|
+
"verify:dist:assert": "git diff --ignore-space-at-eol --text --exit-code -- dist && node scripts/verify-dist-artifact.mjs",
|
|
24
|
+
"verify:dist": "npm run build && npm run verify:dist:assert",
|
|
25
|
+
"docs:tables": "node scripts/render-action-tables.mjs",
|
|
26
|
+
"lint": "eslint .",
|
|
27
|
+
"lint:fix": "eslint . --fix",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"github-action",
|
|
33
|
+
"postman",
|
|
34
|
+
"azure",
|
|
35
|
+
"azure-api-management",
|
|
36
|
+
"apim",
|
|
37
|
+
"app-service",
|
|
38
|
+
"openapi",
|
|
39
|
+
"api-onboarding"
|
|
40
|
+
],
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/postman-cs/postman-azure-spec-discovery-action"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@actions/core": "^3.0.1",
|
|
51
|
+
"@azure/arm-apimanagement": "10.0.0",
|
|
52
|
+
"@azure/arm-appservice": "19.0.0",
|
|
53
|
+
"@azure/arm-resourcegraph": "4.2.1",
|
|
54
|
+
"@azure/arm-resources": "8.0.0",
|
|
55
|
+
"@azure/arm-subscriptions": "6.0.0",
|
|
56
|
+
"@azure/identity": "4.13.1",
|
|
57
|
+
"@postman-cse/automation-telemetry-core": "^0.2.0",
|
|
58
|
+
"yaml": "^2.6.1"
|
|
59
|
+
},
|
|
60
|
+
"overrides": {
|
|
61
|
+
"uuid": "11.1.1"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@eslint/js": "^9.17.0",
|
|
65
|
+
"@types/node": "^24.0.0",
|
|
66
|
+
"esbuild": "0.28.1",
|
|
67
|
+
"eslint": "^9.17.0",
|
|
68
|
+
"typescript": "^5.7.0",
|
|
69
|
+
"typescript-eslint": "^8.18.0",
|
|
70
|
+
"vitest": "^4.0.0"
|
|
71
|
+
},
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=24"
|
|
74
|
+
}
|
|
75
|
+
}
|