@peterhauge/apiops-cli 0.1.3-alpha.0
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.md +21 -0
- package/README.md +135 -0
- package/dist/cli/extract-command.d.ts +12 -0
- package/dist/cli/extract-command.d.ts.map +1 -0
- package/dist/cli/extract-command.js +157 -0
- package/dist/cli/extract-command.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +74 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-command.d.ts +11 -0
- package/dist/cli/init-command.d.ts.map +1 -0
- package/dist/cli/init-command.js +87 -0
- package/dist/cli/init-command.js.map +1 -0
- package/dist/cli/publish-command.d.ts +12 -0
- package/dist/cli/publish-command.d.ts.map +1 -0
- package/dist/cli/publish-command.js +159 -0
- package/dist/cli/publish-command.js.map +1 -0
- package/dist/clients/apim-client.d.ts +110 -0
- package/dist/clients/apim-client.d.ts.map +1 -0
- package/dist/clients/apim-client.js +586 -0
- package/dist/clients/apim-client.js.map +1 -0
- package/dist/clients/artifact-store.d.ts +23 -0
- package/dist/clients/artifact-store.d.ts.map +1 -0
- package/dist/clients/artifact-store.js +188 -0
- package/dist/clients/artifact-store.js.map +1 -0
- package/dist/clients/iapim-client.d.ts +52 -0
- package/dist/clients/iapim-client.d.ts.map +1 -0
- package/dist/clients/iapim-client.js +6 -0
- package/dist/clients/iapim-client.js.map +1 -0
- package/dist/clients/iartifact-store.d.ts +50 -0
- package/dist/clients/iartifact-store.d.ts.map +1 -0
- package/dist/clients/iartifact-store.js +6 -0
- package/dist/clients/iartifact-store.js.map +1 -0
- package/dist/lib/auto-generated.d.ts +27 -0
- package/dist/lib/auto-generated.d.ts.map +1 -0
- package/dist/lib/auto-generated.js +34 -0
- package/dist/lib/auto-generated.js.map +1 -0
- package/dist/lib/cloud-config.d.ts +29 -0
- package/dist/lib/cloud-config.d.ts.map +1 -0
- package/dist/lib/cloud-config.js +60 -0
- package/dist/lib/cloud-config.js.map +1 -0
- package/dist/lib/config-loader.d.ts +21 -0
- package/dist/lib/config-loader.d.ts.map +1 -0
- package/dist/lib/config-loader.js +131 -0
- package/dist/lib/config-loader.js.map +1 -0
- package/dist/lib/dependency-graph.d.ts +43 -0
- package/dist/lib/dependency-graph.d.ts.map +1 -0
- package/dist/lib/dependency-graph.js +163 -0
- package/dist/lib/dependency-graph.js.map +1 -0
- package/dist/lib/exit-codes.d.ts +27 -0
- package/dist/lib/exit-codes.d.ts.map +1 -0
- package/dist/lib/exit-codes.js +33 -0
- package/dist/lib/exit-codes.js.map +1 -0
- package/dist/lib/logger.d.ts +39 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +128 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/parallel-runner.d.ts +38 -0
- package/dist/lib/parallel-runner.d.ts.map +1 -0
- package/dist/lib/parallel-runner.js +70 -0
- package/dist/lib/parallel-runner.js.map +1 -0
- package/dist/lib/resource-path.d.ts +205 -0
- package/dist/lib/resource-path.d.ts.map +1 -0
- package/dist/lib/resource-path.js +401 -0
- package/dist/lib/resource-path.js.map +1 -0
- package/dist/lib/resource-uri.d.ts +40 -0
- package/dist/lib/resource-uri.d.ts.map +1 -0
- package/dist/lib/resource-uri.js +86 -0
- package/dist/lib/resource-uri.js.map +1 -0
- package/dist/lib/user-agent.d.ts +2 -0
- package/dist/lib/user-agent.d.ts.map +1 -0
- package/dist/lib/user-agent.js +5 -0
- package/dist/lib/user-agent.js.map +1 -0
- package/dist/models/config.d.ts +83 -0
- package/dist/models/config.d.ts.map +1 -0
- package/dist/models/config.js +6 -0
- package/dist/models/config.js.map +1 -0
- package/dist/models/resource-types.d.ts +66 -0
- package/dist/models/resource-types.d.ts.map +1 -0
- package/dist/models/resource-types.js +243 -0
- package/dist/models/resource-types.js.map +1 -0
- package/dist/models/types.d.ts +47 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +6 -0
- package/dist/models/types.js.map +1 -0
- package/dist/services/api-extractor.d.ts +36 -0
- package/dist/services/api-extractor.d.ts.map +1 -0
- package/dist/services/api-extractor.js +319 -0
- package/dist/services/api-extractor.js.map +1 -0
- package/dist/services/api-publisher.d.ts +18 -0
- package/dist/services/api-publisher.d.ts.map +1 -0
- package/dist/services/api-publisher.js +290 -0
- package/dist/services/api-publisher.js.map +1 -0
- package/dist/services/delete-unmatched-service.d.ts +17 -0
- package/dist/services/delete-unmatched-service.d.ts.map +1 -0
- package/dist/services/delete-unmatched-service.js +143 -0
- package/dist/services/delete-unmatched-service.js.map +1 -0
- package/dist/services/dry-run-reporter.d.ts +30 -0
- package/dist/services/dry-run-reporter.d.ts.map +1 -0
- package/dist/services/dry-run-reporter.js +111 -0
- package/dist/services/dry-run-reporter.js.map +1 -0
- package/dist/services/extract-service.d.ts +47 -0
- package/dist/services/extract-service.d.ts.map +1 -0
- package/dist/services/extract-service.js +374 -0
- package/dist/services/extract-service.js.map +1 -0
- package/dist/services/filter-service.d.ts +29 -0
- package/dist/services/filter-service.d.ts.map +1 -0
- package/dist/services/filter-service.js +143 -0
- package/dist/services/filter-service.js.map +1 -0
- package/dist/services/git-diff-service.d.ts +23 -0
- package/dist/services/git-diff-service.d.ts.map +1 -0
- package/dist/services/git-diff-service.js +135 -0
- package/dist/services/git-diff-service.js.map +1 -0
- package/dist/services/identity-guide-service.d.ts +11 -0
- package/dist/services/identity-guide-service.d.ts.map +1 -0
- package/dist/services/identity-guide-service.js +227 -0
- package/dist/services/identity-guide-service.js.map +1 -0
- package/dist/services/init-service.d.ts +16 -0
- package/dist/services/init-service.d.ts.map +1 -0
- package/dist/services/init-service.js +304 -0
- package/dist/services/init-service.js.map +1 -0
- package/dist/services/keyvault-checker.d.ts +58 -0
- package/dist/services/keyvault-checker.d.ts.map +1 -0
- package/dist/services/keyvault-checker.js +390 -0
- package/dist/services/keyvault-checker.js.map +1 -0
- package/dist/services/override-merger.d.ts +20 -0
- package/dist/services/override-merger.d.ts.map +1 -0
- package/dist/services/override-merger.js +102 -0
- package/dist/services/override-merger.js.map +1 -0
- package/dist/services/product-extractor.d.ts +26 -0
- package/dist/services/product-extractor.d.ts.map +1 -0
- package/dist/services/product-extractor.js +141 -0
- package/dist/services/product-extractor.js.map +1 -0
- package/dist/services/product-publisher.d.ts +15 -0
- package/dist/services/product-publisher.d.ts.map +1 -0
- package/dist/services/product-publisher.js +113 -0
- package/dist/services/product-publisher.js.map +1 -0
- package/dist/services/prompt-service.d.ts +13 -0
- package/dist/services/prompt-service.d.ts.map +1 -0
- package/dist/services/prompt-service.js +69 -0
- package/dist/services/prompt-service.js.map +1 -0
- package/dist/services/publish-service.d.ts +31 -0
- package/dist/services/publish-service.d.ts.map +1 -0
- package/dist/services/publish-service.js +445 -0
- package/dist/services/publish-service.js.map +1 -0
- package/dist/services/resource-extractor.d.ts +52 -0
- package/dist/services/resource-extractor.d.ts.map +1 -0
- package/dist/services/resource-extractor.js +168 -0
- package/dist/services/resource-extractor.js.map +1 -0
- package/dist/services/resource-publisher.d.ts +23 -0
- package/dist/services/resource-publisher.d.ts.map +1 -0
- package/dist/services/resource-publisher.js +349 -0
- package/dist/services/resource-publisher.js.map +1 -0
- package/dist/services/secret-redactor.d.ts +20 -0
- package/dist/services/secret-redactor.d.ts.map +1 -0
- package/dist/services/secret-redactor.js +45 -0
- package/dist/services/secret-redactor.js.map +1 -0
- package/dist/services/transitive-resolver.d.ts +45 -0
- package/dist/services/transitive-resolver.d.ts.map +1 -0
- package/dist/services/transitive-resolver.js +177 -0
- package/dist/services/transitive-resolver.js.map +1 -0
- package/dist/services/workspace-extractor.d.ts +34 -0
- package/dist/services/workspace-extractor.d.ts.map +1 -0
- package/dist/services/workspace-extractor.js +120 -0
- package/dist/services/workspace-extractor.js.map +1 -0
- package/dist/templates/azure-devops/extract-pipeline.d.ts +9 -0
- package/dist/templates/azure-devops/extract-pipeline.d.ts.map +1 -0
- package/dist/templates/azure-devops/extract-pipeline.js +95 -0
- package/dist/templates/azure-devops/extract-pipeline.js.map +1 -0
- package/dist/templates/azure-devops/publish-pipeline.d.ts +10 -0
- package/dist/templates/azure-devops/publish-pipeline.d.ts.map +1 -0
- package/dist/templates/azure-devops/publish-pipeline.js +100 -0
- package/dist/templates/azure-devops/publish-pipeline.js.map +1 -0
- package/dist/templates/configs/filter-config.d.ts +6 -0
- package/dist/templates/configs/filter-config.d.ts.map +1 -0
- package/dist/templates/configs/filter-config.js +51 -0
- package/dist/templates/configs/filter-config.js.map +1 -0
- package/dist/templates/configs/override-config.d.ts +6 -0
- package/dist/templates/configs/override-config.d.ts.map +1 -0
- package/dist/templates/configs/override-config.js +45 -0
- package/dist/templates/configs/override-config.js.map +1 -0
- package/dist/templates/configs/package-json.d.ts +10 -0
- package/dist/templates/configs/package-json.d.ts.map +1 -0
- package/dist/templates/configs/package-json.js +19 -0
- package/dist/templates/configs/package-json.js.map +1 -0
- package/dist/templates/copilot/identity-setup-prompt.d.ts +13 -0
- package/dist/templates/copilot/identity-setup-prompt.d.ts.map +1 -0
- package/dist/templates/copilot/identity-setup-prompt.js +279 -0
- package/dist/templates/copilot/identity-setup-prompt.js.map +1 -0
- package/dist/templates/github-actions/extract-workflow.d.ts +9 -0
- package/dist/templates/github-actions/extract-workflow.d.ts.map +1 -0
- package/dist/templates/github-actions/extract-workflow.js +126 -0
- package/dist/templates/github-actions/extract-workflow.js.map +1 -0
- package/dist/templates/github-actions/publish-workflow.d.ts +10 -0
- package/dist/templates/github-actions/publish-workflow.d.ts.map +1 -0
- package/dist/templates/github-actions/publish-workflow.js +105 -0
- package/dist/templates/github-actions/publish-workflow.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* T030: Publish orchestration service
|
|
3
|
+
* Coordinates PUT/DELETE across dependency tiers in topological order
|
|
4
|
+
* PUTs in dependency order (tier 1-4), DELETEs in reverse order (tier 4-1)
|
|
5
|
+
*/
|
|
6
|
+
import { ResourceType } from '../models/resource-types.js';
|
|
7
|
+
import { getResourceTier } from '../lib/dependency-graph.js';
|
|
8
|
+
import { runParallel } from '../lib/parallel-runner.js';
|
|
9
|
+
import { logger } from '../lib/logger.js';
|
|
10
|
+
import { isAutoGeneratedId } from '../lib/auto-generated.js';
|
|
11
|
+
import { EXIT_SUCCESS, EXIT_PARTIAL, EXIT_FATAL } from '../lib/exit-codes.js';
|
|
12
|
+
import { buildResourceLabel } from '../lib/resource-uri.js';
|
|
13
|
+
import { getNamePart, isChildType } from '../lib/resource-path.js';
|
|
14
|
+
// Import from other agents' files (will be created in parallel)
|
|
15
|
+
import { publishResource } from './resource-publisher.js';
|
|
16
|
+
import { publishApi } from './api-publisher.js';
|
|
17
|
+
import { publishProduct } from './product-publisher.js';
|
|
18
|
+
import { generateDryRunReport } from './dry-run-reporter.js';
|
|
19
|
+
import { computeDeleteActions } from './delete-unmatched-service.js';
|
|
20
|
+
import { computeGitDiff } from './git-diff-service.js';
|
|
21
|
+
/**
|
|
22
|
+
* The APIM Backend properties.type value that identifies a pool backend.
|
|
23
|
+
* Pool backends reference other Backend resources and must be published
|
|
24
|
+
* after the individual backends they aggregate.
|
|
25
|
+
*/
|
|
26
|
+
const POOL_BACKEND_TYPE = 'pool';
|
|
27
|
+
/**
|
|
28
|
+
* Main publish orchestration function.
|
|
29
|
+
* Coordinates PUT/DELETE operations across dependency tiers.
|
|
30
|
+
*/
|
|
31
|
+
export async function runPublish(client, store, config) {
|
|
32
|
+
try {
|
|
33
|
+
// Step 0: Pre-flight validation — ensure the resource group and APIM service exist
|
|
34
|
+
await client.validatePreFlight(config.service);
|
|
35
|
+
// Step 1: Determine target descriptors based on incremental mode
|
|
36
|
+
const targetDescriptors = await determineTargetDescriptors(store, config);
|
|
37
|
+
logger.debug(`Publishing ${targetDescriptors.length} resources (dry-run: ${config.dryRun})`);
|
|
38
|
+
// Step 2: Handle dry-run mode
|
|
39
|
+
if (config.dryRun) {
|
|
40
|
+
const dryRunReport = await generateDryRunReport(store, client, config.service, config, targetDescriptors);
|
|
41
|
+
return {
|
|
42
|
+
totalPuts: dryRunReport.summary.creates,
|
|
43
|
+
totalDeletes: dryRunReport.summary.deletes,
|
|
44
|
+
totalErrors: 0,
|
|
45
|
+
totalSkipped: dryRunReport.summary.skips,
|
|
46
|
+
exitCode: EXIT_SUCCESS,
|
|
47
|
+
actions: [],
|
|
48
|
+
dryRunReport,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Step 3: Execute PUTs in dependency order (tier 1 → tier 4)
|
|
52
|
+
const putResults = await executePuts(client, store, config.service, config, targetDescriptors);
|
|
53
|
+
// Step 4: Execute DELETEs in reverse dependency order (tier 4 → tier 1) if requested
|
|
54
|
+
let deleteResults = [];
|
|
55
|
+
if (config.deleteUnmatched) {
|
|
56
|
+
deleteResults = await executeDeletes(client, store, config.service, config);
|
|
57
|
+
}
|
|
58
|
+
// Step 5: Combine results and determine exit code
|
|
59
|
+
const allResults = [...putResults, ...deleteResults];
|
|
60
|
+
const totalPuts = putResults.length;
|
|
61
|
+
const totalDeletes = deleteResults.length;
|
|
62
|
+
const totalErrors = allResults.filter((r) => r.status === 'failed').length;
|
|
63
|
+
const totalSkipped = allResults.filter((r) => r.status === 'skipped').length;
|
|
64
|
+
const exitCode = determineExitCode(allResults);
|
|
65
|
+
return {
|
|
66
|
+
totalPuts,
|
|
67
|
+
totalDeletes,
|
|
68
|
+
totalErrors,
|
|
69
|
+
totalSkipped,
|
|
70
|
+
exitCode,
|
|
71
|
+
actions: allResults,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
logger.error('Fatal error during publish:', error);
|
|
76
|
+
return {
|
|
77
|
+
totalPuts: 0,
|
|
78
|
+
totalDeletes: 0,
|
|
79
|
+
totalErrors: 1,
|
|
80
|
+
totalSkipped: 0,
|
|
81
|
+
exitCode: EXIT_FATAL,
|
|
82
|
+
actions: [],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Determine which resources to publish based on incremental mode.
|
|
88
|
+
*/
|
|
89
|
+
async function determineTargetDescriptors(store, config) {
|
|
90
|
+
if (config.commitId) {
|
|
91
|
+
// Incremental mode: use git diff
|
|
92
|
+
logger.debug(`Using incremental publish mode with commit ID: ${config.commitId}`);
|
|
93
|
+
const diffResult = await computeGitDiff(config.sourceDir, config.commitId);
|
|
94
|
+
return diffResult.changedDescriptors;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Full mode: publish all artifacts
|
|
98
|
+
logger.debug('Using full publish mode (all artifacts)');
|
|
99
|
+
return await store.listResources(config.sourceDir);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Execute PUT operations in dependency order (tier 1 → tier 4).
|
|
104
|
+
*/
|
|
105
|
+
async function executePuts(client, store, context, config, targetDescriptors) {
|
|
106
|
+
const results = [];
|
|
107
|
+
// Group descriptors by tier
|
|
108
|
+
const tierGroups = new Map();
|
|
109
|
+
for (const descriptor of targetDescriptors) {
|
|
110
|
+
const tier = getResourceTier(descriptor.type);
|
|
111
|
+
if (!tierGroups.has(tier)) {
|
|
112
|
+
tierGroups.set(tier, []);
|
|
113
|
+
}
|
|
114
|
+
tierGroups.get(tier).push(descriptor);
|
|
115
|
+
}
|
|
116
|
+
// Build a map of parent type → Set of parent names being published in tier 2.
|
|
117
|
+
// Top-level types (not child types) handle their children internally,
|
|
118
|
+
// so we exclude those children from tiers 3/4 to avoid double-publishing.
|
|
119
|
+
const parentNamesByType = new Map();
|
|
120
|
+
for (const d of tierGroups.get(2) || []) {
|
|
121
|
+
// Top-level types are those that are NOT child types
|
|
122
|
+
if (!isChildType(d.type)) {
|
|
123
|
+
if (!parentNamesByType.has(d.type)) {
|
|
124
|
+
parentNamesByType.set(d.type, new Set());
|
|
125
|
+
}
|
|
126
|
+
parentNamesByType.get(d.type).add(getNamePart(d.nameParts, 0));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Execute each tier in order (1, 2, 3, 4)
|
|
130
|
+
for (const tier of [1, 2, 3, 4]) {
|
|
131
|
+
const descriptors = tierGroups.get(tier) || [];
|
|
132
|
+
if (descriptors.length === 0)
|
|
133
|
+
continue;
|
|
134
|
+
logger.debug(`Publishing tier ${tier}: ${descriptors.length} resources`);
|
|
135
|
+
if (tier === 1) {
|
|
136
|
+
// Within Tier 1 we publish in three ordered waves to satisfy implicit
|
|
137
|
+
// runtime dependencies:
|
|
138
|
+
//
|
|
139
|
+
// Wave 1 — NamedValues only.
|
|
140
|
+
// Loggers and backends may reference named values by name in their
|
|
141
|
+
// configuration (e.g. AppInsights instrumentation key stored as a
|
|
142
|
+
// named value). Publishing named values first ensures they exist
|
|
143
|
+
// before any resource that references them.
|
|
144
|
+
//
|
|
145
|
+
// Wave 2 — All remaining Tier 1 resources except pool backends.
|
|
146
|
+
// Loggers, tags, gateways, etc. can now reference named values safely.
|
|
147
|
+
//
|
|
148
|
+
// Wave 3 — Pool backends.
|
|
149
|
+
// Pool backends reference individual Backend resources and must be
|
|
150
|
+
// published after the backends they aggregate (see pool backend
|
|
151
|
+
// ordering comments in splitPoolBackends).
|
|
152
|
+
const { namedValues, otherTier1 } = splitNamedValues(descriptors);
|
|
153
|
+
if (namedValues.length > 0) {
|
|
154
|
+
logger.debug(`Publishing ${namedValues.length} named value(s) first (wave 1 of tier 1)`);
|
|
155
|
+
await publishAndOutput(client, store, context, config, namedValues, results);
|
|
156
|
+
}
|
|
157
|
+
const { poolBackends, regularTier1 } = await splitPoolBackends(store, config.sourceDir, otherTier1);
|
|
158
|
+
await publishAndOutput(client, store, context, config, regularTier1, results);
|
|
159
|
+
if (poolBackends.length > 0) {
|
|
160
|
+
logger.debug(`Publishing ${poolBackends.length} pool backend(s) after regular backends`);
|
|
161
|
+
await publishAndOutput(client, store, context, config, poolBackends, results);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// For tiers 3/4, exclude child resources whose parent is being published
|
|
166
|
+
// in tier 2 (publishApi/publishProduct handle their children internally).
|
|
167
|
+
// Use getParentType() to dynamically determine parent-child relationships.
|
|
168
|
+
let tierDescriptors = descriptors;
|
|
169
|
+
if (parentNamesByType.size > 0) {
|
|
170
|
+
const countBefore = tierDescriptors.length;
|
|
171
|
+
tierDescriptors = tierDescriptors.filter((d) => {
|
|
172
|
+
// Top-level types have no parent to check
|
|
173
|
+
if (!isChildType(d.type))
|
|
174
|
+
return true;
|
|
175
|
+
// Child resources have the parent name as nameParts[0]
|
|
176
|
+
const owningParent = getNamePart(d.nameParts, 0);
|
|
177
|
+
// Skip if this parent name is being published in tier 2
|
|
178
|
+
for (const parentNames of parentNamesByType.values()) {
|
|
179
|
+
if (parentNames.has(owningParent))
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
return true;
|
|
183
|
+
});
|
|
184
|
+
const skipped = countBefore - tierDescriptors.length;
|
|
185
|
+
if (skipped > 0) {
|
|
186
|
+
logger.debug(`Skipping ${skipped} child resource(s) in tier ${tier} (handled by parent publisher)`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
await publishAndOutput(client, store, context, config, tierDescriptors, results);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return results;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Publish a batch of descriptors and write their status lines to stdout/stderr.
|
|
196
|
+
*/
|
|
197
|
+
async function publishAndOutput(client, store, context, config, descriptors, results) {
|
|
198
|
+
if (descriptors.length === 0)
|
|
199
|
+
return;
|
|
200
|
+
const tierResults = await publishTier(client, store, context, config, descriptors);
|
|
201
|
+
results.push(...tierResults);
|
|
202
|
+
for (const result of tierResults) {
|
|
203
|
+
outputActionStatus(result);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Separates NamedValue descriptors from all other descriptors in the supplied list.
|
|
208
|
+
*
|
|
209
|
+
* NamedValues must be published before loggers, backends, and other Tier 1
|
|
210
|
+
* resources that may reference them by name in their configuration (e.g. a
|
|
211
|
+
* Logger that stores its instrumentation key as a named value).
|
|
212
|
+
*
|
|
213
|
+
* Auto-generated NamedValues (24-char hex IDs like Logger credentials) are
|
|
214
|
+
* filtered out because APIM recreates them when the referencing Logger is
|
|
215
|
+
* published. Publishing them would create orphan duplicates.
|
|
216
|
+
*/
|
|
217
|
+
function splitNamedValues(descriptors) {
|
|
218
|
+
const namedValues = [];
|
|
219
|
+
const otherTier1 = [];
|
|
220
|
+
for (const descriptor of descriptors) {
|
|
221
|
+
if (descriptor.type === ResourceType.NamedValue) {
|
|
222
|
+
// Skip auto-generated named values (24-char hex IDs) - APIM recreates
|
|
223
|
+
// these when publishing loggers with credential references
|
|
224
|
+
const name = getNamePart(descriptor.nameParts, 0);
|
|
225
|
+
if (isAutoGeneratedId(name)) {
|
|
226
|
+
logger.debug(`Skipping auto-generated named value: ${name}`);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
namedValues.push(descriptor);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
otherTier1.push(descriptor);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { namedValues, otherTier1 };
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Separates Backend descriptors that are pool backends (properties.type === "Pool")
|
|
239
|
+
* from all other descriptors in the supplied list.
|
|
240
|
+
*
|
|
241
|
+
* Pool backends reference individual Backend resources and must therefore be
|
|
242
|
+
* published *after* those backends are created. Reading the artifact JSON is
|
|
243
|
+
* the only reliable way to detect pool backends at publish time because the
|
|
244
|
+
* ResourceType enum treats all backends as the same type.
|
|
245
|
+
*/
|
|
246
|
+
async function splitPoolBackends(store, sourceDir, descriptors) {
|
|
247
|
+
const poolBackends = [];
|
|
248
|
+
const regularTier1 = [];
|
|
249
|
+
for (const descriptor of descriptors) {
|
|
250
|
+
if (descriptor.type === ResourceType.Backend) {
|
|
251
|
+
const json = await store.readResource(sourceDir, descriptor);
|
|
252
|
+
const props = json?.properties;
|
|
253
|
+
const backendType = props?.type;
|
|
254
|
+
if (typeof backendType === 'string' && backendType.toLowerCase() === POOL_BACKEND_TYPE) {
|
|
255
|
+
poolBackends.push(descriptor);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
regularTier1.push(descriptor);
|
|
260
|
+
}
|
|
261
|
+
return { poolBackends, regularTier1 };
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Publish a single tier of resources in parallel.
|
|
265
|
+
*/
|
|
266
|
+
async function publishTier(client, store, context, config, descriptors) {
|
|
267
|
+
const tasks = descriptors.map((descriptor) => async () => {
|
|
268
|
+
try {
|
|
269
|
+
let publishResult;
|
|
270
|
+
// Use specialized publishers for Api and Product types
|
|
271
|
+
if (descriptor.type === ResourceType.Api) {
|
|
272
|
+
publishResult = await publishApi(client, store, context, descriptor, config);
|
|
273
|
+
}
|
|
274
|
+
else if (descriptor.type === ResourceType.Product) {
|
|
275
|
+
publishResult = await publishProduct(client, store, context, descriptor, config);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
publishResult = await publishResource(client, store, context, descriptor, config);
|
|
279
|
+
}
|
|
280
|
+
return convertToActionResult(publishResult);
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
logger.error(`Failed to publish ${buildResourceLabel(descriptor)}:`, error);
|
|
284
|
+
return {
|
|
285
|
+
descriptor,
|
|
286
|
+
action: 'put',
|
|
287
|
+
status: 'failed',
|
|
288
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
const taskResults = await runParallel(tasks, 5);
|
|
293
|
+
return taskResults.map((tr, index) => {
|
|
294
|
+
if (tr.status === 'fulfilled' && tr.value) {
|
|
295
|
+
return tr.value;
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
// Should not happen given error handling above, but be defensive
|
|
299
|
+
const descriptor = descriptors[index];
|
|
300
|
+
if (!descriptor) {
|
|
301
|
+
throw new Error('No descriptor found for failed task');
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
descriptor,
|
|
305
|
+
action: 'put',
|
|
306
|
+
status: 'failed',
|
|
307
|
+
error: tr.reason || new Error('Unknown error'),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Execute DELETE operations in reverse dependency order (tier 4 → tier 1).
|
|
314
|
+
*/
|
|
315
|
+
async function executeDeletes(client, store, context, config) {
|
|
316
|
+
const deleteDescriptors = await computeDeleteActions(client, store, context, config);
|
|
317
|
+
if (deleteDescriptors.length === 0) {
|
|
318
|
+
logger.debug('No resources to delete');
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
logger.debug(`Deleting ${deleteDescriptors.length} unmatched resources`);
|
|
322
|
+
const results = [];
|
|
323
|
+
// Group by tier
|
|
324
|
+
const tierGroups = new Map();
|
|
325
|
+
for (const descriptor of deleteDescriptors) {
|
|
326
|
+
const tier = getResourceTier(descriptor.type);
|
|
327
|
+
if (!tierGroups.has(tier)) {
|
|
328
|
+
tierGroups.set(tier, []);
|
|
329
|
+
}
|
|
330
|
+
tierGroups.get(tier).push(descriptor);
|
|
331
|
+
}
|
|
332
|
+
// Execute in REVERSE tier order (4, 3, 2, 1)
|
|
333
|
+
for (const tier of [4, 3, 2, 1]) {
|
|
334
|
+
const descriptors = tierGroups.get(tier) || [];
|
|
335
|
+
if (descriptors.length === 0)
|
|
336
|
+
continue;
|
|
337
|
+
logger.debug(`Deleting tier ${tier}: ${descriptors.length} resources`);
|
|
338
|
+
const tierResults = await deleteTier(client, context, descriptors);
|
|
339
|
+
results.push(...tierResults);
|
|
340
|
+
// Output per-resource status lines
|
|
341
|
+
for (const result of tierResults) {
|
|
342
|
+
outputActionStatus(result);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return results;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Delete a single tier of resources in parallel.
|
|
349
|
+
*/
|
|
350
|
+
async function deleteTier(client, context, descriptors) {
|
|
351
|
+
const tasks = descriptors.map((descriptor) => async () => {
|
|
352
|
+
try {
|
|
353
|
+
const deleted = await client.deleteResource(context, descriptor);
|
|
354
|
+
return {
|
|
355
|
+
descriptor,
|
|
356
|
+
action: 'delete',
|
|
357
|
+
status: deleted ? 'success' : 'skipped',
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
logger.error(`Failed to delete ${buildResourceLabel(descriptor)}:`, error);
|
|
362
|
+
return {
|
|
363
|
+
descriptor,
|
|
364
|
+
action: 'delete',
|
|
365
|
+
status: 'failed',
|
|
366
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
const taskResults = await runParallel(tasks, 5);
|
|
371
|
+
return taskResults.map((tr, index) => {
|
|
372
|
+
if (tr.status === 'fulfilled' && tr.value) {
|
|
373
|
+
return tr.value;
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
const descriptor = descriptors[index];
|
|
377
|
+
if (!descriptor) {
|
|
378
|
+
throw new Error('No descriptor found for failed task');
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
descriptor,
|
|
382
|
+
action: 'delete',
|
|
383
|
+
status: 'failed',
|
|
384
|
+
error: tr.reason || new Error('Unknown error'),
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Convert ResourcePublishResult to PublishActionResult.
|
|
391
|
+
*/
|
|
392
|
+
function convertToActionResult(result) {
|
|
393
|
+
return {
|
|
394
|
+
descriptor: result.descriptor,
|
|
395
|
+
action: result.action,
|
|
396
|
+
status: result.status,
|
|
397
|
+
error: result.error,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Output per-resource status line to stdout.
|
|
402
|
+
*/
|
|
403
|
+
function outputActionStatus(result) {
|
|
404
|
+
const verb = result.action.toUpperCase();
|
|
405
|
+
const path = buildResourcePath(result.descriptor);
|
|
406
|
+
if (result.status === 'success') {
|
|
407
|
+
process.stdout.write(`${verb} ${path}\n`);
|
|
408
|
+
}
|
|
409
|
+
else if (result.status === 'skipped') {
|
|
410
|
+
process.stdout.write(`SKIP ${path}\n`);
|
|
411
|
+
}
|
|
412
|
+
else if (result.status === 'failed') {
|
|
413
|
+
process.stderr.write(`ERROR ${verb} ${path}: ${result.error?.message}\n`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Build a human-readable path for a resource descriptor.
|
|
418
|
+
*/
|
|
419
|
+
function buildResourcePath(descriptor) {
|
|
420
|
+
const parts = [descriptor.type.toLowerCase()];
|
|
421
|
+
if (descriptor.workspace) {
|
|
422
|
+
parts.push(`workspace:${descriptor.workspace}`);
|
|
423
|
+
}
|
|
424
|
+
parts.push(...descriptor.nameParts);
|
|
425
|
+
return parts.join('/');
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Determine exit code based on results.
|
|
429
|
+
* Uses standardised constants from exit-codes module.
|
|
430
|
+
*/
|
|
431
|
+
function determineExitCode(results) {
|
|
432
|
+
if (results.length === 0) {
|
|
433
|
+
return EXIT_SUCCESS;
|
|
434
|
+
}
|
|
435
|
+
const successCount = results.filter((r) => r.status === 'success').length;
|
|
436
|
+
const failedCount = results.filter((r) => r.status === 'failed').length;
|
|
437
|
+
if (failedCount === 0) {
|
|
438
|
+
return EXIT_SUCCESS;
|
|
439
|
+
}
|
|
440
|
+
if (successCount > 0) {
|
|
441
|
+
return EXIT_PARTIAL;
|
|
442
|
+
}
|
|
443
|
+
return EXIT_FATAL;
|
|
444
|
+
}
|
|
445
|
+
//# sourceMappingURL=publish-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-service.js","sourceRoot":"","sources":["../../src/services/publish-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* T021: Resource type extractor
|
|
3
|
+
* Generic extract logic: list resources via IApimClient, write each to IArtifactStore.
|
|
4
|
+
* Handles all 33 types using ResourceType metadata. Preserves opaque JSON per FR-009.
|
|
5
|
+
*/
|
|
6
|
+
import { IApimClient } from '../clients/iapim-client.js';
|
|
7
|
+
import { IArtifactStore } from '../clients/iartifact-store.js';
|
|
8
|
+
import { ApimServiceContext, ResourceDescriptor } from '../models/types.js';
|
|
9
|
+
import { ResourceType } from '../models/resource-types.js';
|
|
10
|
+
import { FilterConfig } from '../models/config.js';
|
|
11
|
+
/**
|
|
12
|
+
* Result of extracting a single resource.
|
|
13
|
+
*/
|
|
14
|
+
export interface ExtractedResource {
|
|
15
|
+
descriptor: ResourceDescriptor;
|
|
16
|
+
json: Record<string, unknown>;
|
|
17
|
+
status: 'success' | 'error';
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of extracting all resources of a given type.
|
|
22
|
+
*/
|
|
23
|
+
export interface TypeExtractionResult {
|
|
24
|
+
type: ResourceType;
|
|
25
|
+
extracted: ExtractedResource[];
|
|
26
|
+
totalCount: number;
|
|
27
|
+
errorCount: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Extract the ARM resource name from a raw JSON object.
|
|
31
|
+
* ARM resources have a 'name' field at the top level.
|
|
32
|
+
*/
|
|
33
|
+
export declare function extractResourceName(json: Record<string, unknown>): string;
|
|
34
|
+
/**
|
|
35
|
+
* Extract all resources of a given type from APIM and write to artifact store.
|
|
36
|
+
*
|
|
37
|
+
* @param client - APIM REST client
|
|
38
|
+
* @param store - Artifact file store
|
|
39
|
+
* @param context - APIM service context
|
|
40
|
+
* @param type - Resource type to extract
|
|
41
|
+
* @param outputDir - Output directory
|
|
42
|
+
* @param filter - Optional filter config
|
|
43
|
+
* @param parent - Parent descriptor for child resources
|
|
44
|
+
* @param workspace - Optional workspace name
|
|
45
|
+
* @returns Extraction result
|
|
46
|
+
*/
|
|
47
|
+
export declare function extractResourceType(client: IApimClient, store: IArtifactStore, context: ApimServiceContext, type: ResourceType, outputDir: string, filter?: FilterConfig, parent?: ResourceDescriptor, workspace?: string): Promise<TypeExtractionResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Extract a single resource by descriptor and write to artifact store.
|
|
50
|
+
*/
|
|
51
|
+
export declare function extractSingleResource(client: IApimClient, store: IArtifactStore, context: ApimServiceContext, descriptor: ResourceDescriptor, outputDir: string): Promise<ExtractedResource>;
|
|
52
|
+
//# sourceMappingURL=resource-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-extractor.d.ts","sourceRoot":"","sources":["../../src/services/resource-extractor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAA0B,MAAM,6BAA6B,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAanD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAMzE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,EACrB,MAAM,CAAC,EAAE,kBAAkB,EAC3B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,CAAC,CA4E/B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,kBAAkB,EAC3B,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,CAAC,CA2B5B"}
|