@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.
Files changed (199) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +135 -0
  3. package/dist/cli/extract-command.d.ts +12 -0
  4. package/dist/cli/extract-command.d.ts.map +1 -0
  5. package/dist/cli/extract-command.js +157 -0
  6. package/dist/cli/extract-command.js.map +1 -0
  7. package/dist/cli/index.d.ts +7 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +74 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/init-command.d.ts +11 -0
  12. package/dist/cli/init-command.d.ts.map +1 -0
  13. package/dist/cli/init-command.js +87 -0
  14. package/dist/cli/init-command.js.map +1 -0
  15. package/dist/cli/publish-command.d.ts +12 -0
  16. package/dist/cli/publish-command.d.ts.map +1 -0
  17. package/dist/cli/publish-command.js +159 -0
  18. package/dist/cli/publish-command.js.map +1 -0
  19. package/dist/clients/apim-client.d.ts +110 -0
  20. package/dist/clients/apim-client.d.ts.map +1 -0
  21. package/dist/clients/apim-client.js +586 -0
  22. package/dist/clients/apim-client.js.map +1 -0
  23. package/dist/clients/artifact-store.d.ts +23 -0
  24. package/dist/clients/artifact-store.d.ts.map +1 -0
  25. package/dist/clients/artifact-store.js +188 -0
  26. package/dist/clients/artifact-store.js.map +1 -0
  27. package/dist/clients/iapim-client.d.ts +52 -0
  28. package/dist/clients/iapim-client.d.ts.map +1 -0
  29. package/dist/clients/iapim-client.js +6 -0
  30. package/dist/clients/iapim-client.js.map +1 -0
  31. package/dist/clients/iartifact-store.d.ts +50 -0
  32. package/dist/clients/iartifact-store.d.ts.map +1 -0
  33. package/dist/clients/iartifact-store.js +6 -0
  34. package/dist/clients/iartifact-store.js.map +1 -0
  35. package/dist/lib/auto-generated.d.ts +27 -0
  36. package/dist/lib/auto-generated.d.ts.map +1 -0
  37. package/dist/lib/auto-generated.js +34 -0
  38. package/dist/lib/auto-generated.js.map +1 -0
  39. package/dist/lib/cloud-config.d.ts +29 -0
  40. package/dist/lib/cloud-config.d.ts.map +1 -0
  41. package/dist/lib/cloud-config.js +60 -0
  42. package/dist/lib/cloud-config.js.map +1 -0
  43. package/dist/lib/config-loader.d.ts +21 -0
  44. package/dist/lib/config-loader.d.ts.map +1 -0
  45. package/dist/lib/config-loader.js +131 -0
  46. package/dist/lib/config-loader.js.map +1 -0
  47. package/dist/lib/dependency-graph.d.ts +43 -0
  48. package/dist/lib/dependency-graph.d.ts.map +1 -0
  49. package/dist/lib/dependency-graph.js +163 -0
  50. package/dist/lib/dependency-graph.js.map +1 -0
  51. package/dist/lib/exit-codes.d.ts +27 -0
  52. package/dist/lib/exit-codes.d.ts.map +1 -0
  53. package/dist/lib/exit-codes.js +33 -0
  54. package/dist/lib/exit-codes.js.map +1 -0
  55. package/dist/lib/logger.d.ts +39 -0
  56. package/dist/lib/logger.d.ts.map +1 -0
  57. package/dist/lib/logger.js +128 -0
  58. package/dist/lib/logger.js.map +1 -0
  59. package/dist/lib/parallel-runner.d.ts +38 -0
  60. package/dist/lib/parallel-runner.d.ts.map +1 -0
  61. package/dist/lib/parallel-runner.js +70 -0
  62. package/dist/lib/parallel-runner.js.map +1 -0
  63. package/dist/lib/resource-path.d.ts +205 -0
  64. package/dist/lib/resource-path.d.ts.map +1 -0
  65. package/dist/lib/resource-path.js +401 -0
  66. package/dist/lib/resource-path.js.map +1 -0
  67. package/dist/lib/resource-uri.d.ts +40 -0
  68. package/dist/lib/resource-uri.d.ts.map +1 -0
  69. package/dist/lib/resource-uri.js +86 -0
  70. package/dist/lib/resource-uri.js.map +1 -0
  71. package/dist/lib/user-agent.d.ts +2 -0
  72. package/dist/lib/user-agent.d.ts.map +1 -0
  73. package/dist/lib/user-agent.js +5 -0
  74. package/dist/lib/user-agent.js.map +1 -0
  75. package/dist/models/config.d.ts +83 -0
  76. package/dist/models/config.d.ts.map +1 -0
  77. package/dist/models/config.js +6 -0
  78. package/dist/models/config.js.map +1 -0
  79. package/dist/models/resource-types.d.ts +66 -0
  80. package/dist/models/resource-types.d.ts.map +1 -0
  81. package/dist/models/resource-types.js +243 -0
  82. package/dist/models/resource-types.js.map +1 -0
  83. package/dist/models/types.d.ts +47 -0
  84. package/dist/models/types.d.ts.map +1 -0
  85. package/dist/models/types.js +6 -0
  86. package/dist/models/types.js.map +1 -0
  87. package/dist/services/api-extractor.d.ts +36 -0
  88. package/dist/services/api-extractor.d.ts.map +1 -0
  89. package/dist/services/api-extractor.js +319 -0
  90. package/dist/services/api-extractor.js.map +1 -0
  91. package/dist/services/api-publisher.d.ts +18 -0
  92. package/dist/services/api-publisher.d.ts.map +1 -0
  93. package/dist/services/api-publisher.js +290 -0
  94. package/dist/services/api-publisher.js.map +1 -0
  95. package/dist/services/delete-unmatched-service.d.ts +17 -0
  96. package/dist/services/delete-unmatched-service.d.ts.map +1 -0
  97. package/dist/services/delete-unmatched-service.js +143 -0
  98. package/dist/services/delete-unmatched-service.js.map +1 -0
  99. package/dist/services/dry-run-reporter.d.ts +30 -0
  100. package/dist/services/dry-run-reporter.d.ts.map +1 -0
  101. package/dist/services/dry-run-reporter.js +111 -0
  102. package/dist/services/dry-run-reporter.js.map +1 -0
  103. package/dist/services/extract-service.d.ts +47 -0
  104. package/dist/services/extract-service.d.ts.map +1 -0
  105. package/dist/services/extract-service.js +374 -0
  106. package/dist/services/extract-service.js.map +1 -0
  107. package/dist/services/filter-service.d.ts +29 -0
  108. package/dist/services/filter-service.d.ts.map +1 -0
  109. package/dist/services/filter-service.js +143 -0
  110. package/dist/services/filter-service.js.map +1 -0
  111. package/dist/services/git-diff-service.d.ts +23 -0
  112. package/dist/services/git-diff-service.d.ts.map +1 -0
  113. package/dist/services/git-diff-service.js +135 -0
  114. package/dist/services/git-diff-service.js.map +1 -0
  115. package/dist/services/identity-guide-service.d.ts +11 -0
  116. package/dist/services/identity-guide-service.d.ts.map +1 -0
  117. package/dist/services/identity-guide-service.js +227 -0
  118. package/dist/services/identity-guide-service.js.map +1 -0
  119. package/dist/services/init-service.d.ts +16 -0
  120. package/dist/services/init-service.d.ts.map +1 -0
  121. package/dist/services/init-service.js +304 -0
  122. package/dist/services/init-service.js.map +1 -0
  123. package/dist/services/keyvault-checker.d.ts +58 -0
  124. package/dist/services/keyvault-checker.d.ts.map +1 -0
  125. package/dist/services/keyvault-checker.js +390 -0
  126. package/dist/services/keyvault-checker.js.map +1 -0
  127. package/dist/services/override-merger.d.ts +20 -0
  128. package/dist/services/override-merger.d.ts.map +1 -0
  129. package/dist/services/override-merger.js +102 -0
  130. package/dist/services/override-merger.js.map +1 -0
  131. package/dist/services/product-extractor.d.ts +26 -0
  132. package/dist/services/product-extractor.d.ts.map +1 -0
  133. package/dist/services/product-extractor.js +141 -0
  134. package/dist/services/product-extractor.js.map +1 -0
  135. package/dist/services/product-publisher.d.ts +15 -0
  136. package/dist/services/product-publisher.d.ts.map +1 -0
  137. package/dist/services/product-publisher.js +113 -0
  138. package/dist/services/product-publisher.js.map +1 -0
  139. package/dist/services/prompt-service.d.ts +13 -0
  140. package/dist/services/prompt-service.d.ts.map +1 -0
  141. package/dist/services/prompt-service.js +69 -0
  142. package/dist/services/prompt-service.js.map +1 -0
  143. package/dist/services/publish-service.d.ts +31 -0
  144. package/dist/services/publish-service.d.ts.map +1 -0
  145. package/dist/services/publish-service.js +445 -0
  146. package/dist/services/publish-service.js.map +1 -0
  147. package/dist/services/resource-extractor.d.ts +52 -0
  148. package/dist/services/resource-extractor.d.ts.map +1 -0
  149. package/dist/services/resource-extractor.js +168 -0
  150. package/dist/services/resource-extractor.js.map +1 -0
  151. package/dist/services/resource-publisher.d.ts +23 -0
  152. package/dist/services/resource-publisher.d.ts.map +1 -0
  153. package/dist/services/resource-publisher.js +349 -0
  154. package/dist/services/resource-publisher.js.map +1 -0
  155. package/dist/services/secret-redactor.d.ts +20 -0
  156. package/dist/services/secret-redactor.d.ts.map +1 -0
  157. package/dist/services/secret-redactor.js +45 -0
  158. package/dist/services/secret-redactor.js.map +1 -0
  159. package/dist/services/transitive-resolver.d.ts +45 -0
  160. package/dist/services/transitive-resolver.d.ts.map +1 -0
  161. package/dist/services/transitive-resolver.js +177 -0
  162. package/dist/services/transitive-resolver.js.map +1 -0
  163. package/dist/services/workspace-extractor.d.ts +34 -0
  164. package/dist/services/workspace-extractor.d.ts.map +1 -0
  165. package/dist/services/workspace-extractor.js +120 -0
  166. package/dist/services/workspace-extractor.js.map +1 -0
  167. package/dist/templates/azure-devops/extract-pipeline.d.ts +9 -0
  168. package/dist/templates/azure-devops/extract-pipeline.d.ts.map +1 -0
  169. package/dist/templates/azure-devops/extract-pipeline.js +95 -0
  170. package/dist/templates/azure-devops/extract-pipeline.js.map +1 -0
  171. package/dist/templates/azure-devops/publish-pipeline.d.ts +10 -0
  172. package/dist/templates/azure-devops/publish-pipeline.d.ts.map +1 -0
  173. package/dist/templates/azure-devops/publish-pipeline.js +100 -0
  174. package/dist/templates/azure-devops/publish-pipeline.js.map +1 -0
  175. package/dist/templates/configs/filter-config.d.ts +6 -0
  176. package/dist/templates/configs/filter-config.d.ts.map +1 -0
  177. package/dist/templates/configs/filter-config.js +51 -0
  178. package/dist/templates/configs/filter-config.js.map +1 -0
  179. package/dist/templates/configs/override-config.d.ts +6 -0
  180. package/dist/templates/configs/override-config.d.ts.map +1 -0
  181. package/dist/templates/configs/override-config.js +45 -0
  182. package/dist/templates/configs/override-config.js.map +1 -0
  183. package/dist/templates/configs/package-json.d.ts +10 -0
  184. package/dist/templates/configs/package-json.d.ts.map +1 -0
  185. package/dist/templates/configs/package-json.js +19 -0
  186. package/dist/templates/configs/package-json.js.map +1 -0
  187. package/dist/templates/copilot/identity-setup-prompt.d.ts +13 -0
  188. package/dist/templates/copilot/identity-setup-prompt.d.ts.map +1 -0
  189. package/dist/templates/copilot/identity-setup-prompt.js +279 -0
  190. package/dist/templates/copilot/identity-setup-prompt.js.map +1 -0
  191. package/dist/templates/github-actions/extract-workflow.d.ts +9 -0
  192. package/dist/templates/github-actions/extract-workflow.d.ts.map +1 -0
  193. package/dist/templates/github-actions/extract-workflow.js +126 -0
  194. package/dist/templates/github-actions/extract-workflow.js.map +1 -0
  195. package/dist/templates/github-actions/publish-workflow.d.ts +10 -0
  196. package/dist/templates/github-actions/publish-workflow.d.ts.map +1 -0
  197. package/dist/templates/github-actions/publish-workflow.js +105 -0
  198. package/dist/templates/github-actions/publish-workflow.js.map +1 -0
  199. package/package.json +65 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * T036: Git diff service
3
+ * Compute changed resource artifacts between commits using simple-git.
4
+ * Maps file paths to ResourceDescriptors for incremental publish.
5
+ */
6
+ import { simpleGit } from 'simple-git';
7
+ import * as path from 'node:path';
8
+ import { parseArtifactPath } from '../lib/resource-path.js';
9
+ import { logger } from '../lib/logger.js';
10
+ /**
11
+ * Compute which resource artifacts changed between commitId~1 and commitId.
12
+ * Uses simple-git. Maps file paths to ResourceDescriptors.
13
+ * Returns empty arrays if git is unavailable or path not in a repo.
14
+ *
15
+ * @param sourceDir - Root artifact directory
16
+ * @param commitId - Commit SHA to diff against its parent
17
+ * @returns Changed and deleted resource descriptors
18
+ */
19
+ export async function computeGitDiff(sourceDir, commitId) {
20
+ const git = simpleGit(sourceDir);
21
+ try {
22
+ // Check if we're in a git repository
23
+ const isRepo = await git.checkIsRepo();
24
+ if (!isRepo) {
25
+ logger.warn('Not in a git repository; skipping incremental diff');
26
+ return { changedDescriptors: [], deletedDescriptors: [] };
27
+ }
28
+ // Verify the commit exists
29
+ try {
30
+ await git.revparse([commitId]);
31
+ }
32
+ catch {
33
+ logger.warn(`Commit ${commitId} not found; skipping incremental diff`);
34
+ return { changedDescriptors: [], deletedDescriptors: [] };
35
+ }
36
+ // Check if parent commit exists (handle first commit case)
37
+ const parentCommit = `${commitId}~1`;
38
+ let hasParent = true;
39
+ try {
40
+ await git.revparse([parentCommit]);
41
+ }
42
+ catch {
43
+ logger.debug(`Commit ${commitId} has no parent (first commit); treating all files as added`);
44
+ hasParent = false;
45
+ }
46
+ // Get diff between parent and current commit
47
+ // If no parent, diff against empty tree (shows all files as added)
48
+ const diffTarget = hasParent ? parentCommit : '4b825dc642cb6eb9a060e54bf8d69288fbee4904'; // Git empty tree SHA
49
+ const diffOutput = await git.diff(['--name-status', diffTarget, commitId]);
50
+ return parseDiffOutput(diffOutput, sourceDir);
51
+ }
52
+ catch (error) {
53
+ logger.warn(`Git diff failed: ${error instanceof Error ? error.message : String(error)}`);
54
+ return { changedDescriptors: [], deletedDescriptors: [] };
55
+ }
56
+ }
57
+ /**
58
+ * Parse git diff --name-status output into changed and deleted descriptors.
59
+ *
60
+ * Format: Each line is "{status}\t{filepath}"
61
+ * - M = modified
62
+ * - A = added
63
+ * - D = deleted
64
+ * - R = renamed (includes old and new paths)
65
+ * - C = copied
66
+ *
67
+ * @param diffOutput - Raw output from git diff --name-status
68
+ * @param sourceDir - Base directory for artifact paths
69
+ * @returns Parsed descriptors
70
+ */
71
+ function parseDiffOutput(diffOutput, sourceDir) {
72
+ const changedDescriptors = [];
73
+ const deletedDescriptors = [];
74
+ const seenChanged = new Set();
75
+ const seenDeleted = new Set();
76
+ const lines = diffOutput.split('\n').filter((line) => line.trim());
77
+ for (const line of lines) {
78
+ const parts = line.split('\t');
79
+ if (parts.length < 2) {
80
+ continue;
81
+ }
82
+ const status = parts[0]?.charAt(0); // Get first character (M, A, D, R, C)
83
+ const filePath = parts[1];
84
+ if (!status || !filePath) {
85
+ continue;
86
+ }
87
+ // Convert relative path to absolute for parsing
88
+ const absolutePath = path.isAbsolute(filePath)
89
+ ? filePath
90
+ : path.join(sourceDir, filePath);
91
+ const descriptor = parseArtifactPath(sourceDir, absolutePath);
92
+ if (!descriptor) {
93
+ continue;
94
+ }
95
+ // Create unique key for deduplication
96
+ const key = descriptorKey(descriptor);
97
+ if (status === 'D') {
98
+ // Deleted file
99
+ if (!seenDeleted.has(key)) {
100
+ deletedDescriptors.push(descriptor);
101
+ seenDeleted.add(key);
102
+ }
103
+ }
104
+ else if (status === 'M' || status === 'A' || status === 'R' || status === 'C') {
105
+ // Modified, added, renamed, or copied file
106
+ if (!seenChanged.has(key)) {
107
+ changedDescriptors.push(descriptor);
108
+ seenChanged.add(key);
109
+ }
110
+ // For renames, also parse the new path (in parts[2])
111
+ if (status === 'R' && parts[2]) {
112
+ const newPath = path.isAbsolute(parts[2])
113
+ ? parts[2]
114
+ : path.join(sourceDir, parts[2]);
115
+ const newDescriptor = parseArtifactPath(sourceDir, newPath);
116
+ if (newDescriptor) {
117
+ const newKey = descriptorKey(newDescriptor);
118
+ if (!seenChanged.has(newKey)) {
119
+ changedDescriptors.push(newDescriptor);
120
+ seenChanged.add(newKey);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ logger.debug(`Git diff found ${changedDescriptors.length} changed, ${deletedDescriptors.length} deleted resources`);
127
+ return { changedDescriptors, deletedDescriptors };
128
+ }
129
+ /**
130
+ * Create a unique key for a resource descriptor to enable deduplication.
131
+ */
132
+ function descriptorKey(descriptor) {
133
+ return [descriptor.type, ...descriptor.nameParts, descriptor.workspace ?? ''].join('::');
134
+ }
135
+ //# sourceMappingURL=git-diff-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-diff-service.js","sourceRoot":"","sources":["../../src/services/git-diff-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * T048: Identity setup guide generator
3
+ * Step-by-step instructions for service principal, RBAC, federated credentials,
4
+ * pipeline secrets/service connections. Optional az CLI automation per FR-021.
5
+ */
6
+ export interface IdentityGuideService {
7
+ generateGitHubActionsGuide(subscriptionId: string, resourceGroup: string, environments: string[]): string;
8
+ generateAzureDevOpsGuide(subscriptionId: string, resourceGroup: string, environments: string[]): string;
9
+ }
10
+ export declare const identityGuideService: IdentityGuideService;
11
+ //# sourceMappingURL=identity-guide-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-guide-service.d.ts","sourceRoot":"","sources":["../../src/services/identity-guide-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,oBAAoB;IACnC,0BAA0B,CACxB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EAAE,GACrB,MAAM,CAAC;IAEV,wBAAwB,CACtB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EAAE,GACrB,MAAM,CAAC;CACX;AAwOD,eAAO,MAAM,oBAAoB,EAAE,oBAAqD,CAAC"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * T048: Identity setup guide generator
3
+ * Step-by-step instructions for service principal, RBAC, federated credentials,
4
+ * pipeline secrets/service connections. Optional az CLI automation per FR-021.
5
+ */
6
+ class IdentityGuideServiceImpl {
7
+ generateGitHubActionsGuide(subscriptionId, resourceGroup, environments) {
8
+ return `# GitHub Actions Identity Setup Guide
9
+
10
+ ## Prerequisites
11
+ - Azure subscription: ${subscriptionId}
12
+ - Resource group: ${resourceGroup}
13
+ - GitHub repository with OIDC enabled
14
+
15
+ ## Step 1: Create Service Principal
16
+
17
+ Run the following Azure CLI commands to create a service principal with federated credentials:
18
+
19
+ \`\`\`bash
20
+ # Set variables
21
+ SUBSCRIPTION_ID="${subscriptionId}"
22
+ RESOURCE_GROUP="${resourceGroup}"
23
+ APP_NAME="apiops-github-sp"
24
+ GITHUB_ORG="<your-github-org>"
25
+ GITHUB_REPO="<your-github-repo>"
26
+
27
+ # Create Azure AD Application
28
+ APP_ID=$(az ad app create \\
29
+ --display-name "$APP_NAME" \\
30
+ --query appId -o tsv)
31
+
32
+ # Create Service Principal
33
+ az ad sp create --id "$APP_ID"
34
+
35
+ # Get Service Principal Object ID
36
+ SP_OBJECT_ID=$(az ad sp show --id "$APP_ID" --query id -o tsv)
37
+
38
+ echo "Application (client) ID: $APP_ID"
39
+ echo "Service Principal Object ID: $SP_OBJECT_ID"
40
+ \`\`\`
41
+
42
+ ## Step 2: Assign RBAC Roles
43
+
44
+ Grant the service principal "API Management Service Contributor" role on your APIM instance:
45
+
46
+ \`\`\`bash
47
+ # Get APIM resource ID
48
+ APIM_RESOURCE_ID=$(az apim show \\
49
+ --resource-group "$RESOURCE_GROUP" \\
50
+ --name "<your-apim-service-name>" \\
51
+ --query id -o tsv)
52
+
53
+ # Assign role
54
+ az role assignment create \\
55
+ --assignee "$APP_ID" \\
56
+ --role "API Management Service Contributor" \\
57
+ --scope "$APIM_RESOURCE_ID"
58
+ \`\`\`
59
+
60
+ ## Step 3: Configure Federated Credentials
61
+
62
+ Set up OIDC federation for GitHub Actions:
63
+
64
+ \`\`\`bash
65
+ # For main branch deployments
66
+ az ad app federated-credential create \\
67
+ --id "$APP_ID" \\
68
+ --parameters '{
69
+ "name": "github-main-branch",
70
+ "issuer": "https://token.actions.githubusercontent.com",
71
+ "subject": "repo:'"$GITHUB_ORG"'/'"$GITHUB_REPO"':ref:refs/heads/main",
72
+ "audiences": ["api://AzureADTokenExchange"]
73
+ }'
74
+
75
+ # For environment deployments (repeat for each environment)
76
+ ${environments.map((env) => `az ad app federated-credential create \\
77
+ --id "$APP_ID" \\
78
+ --parameters '{
79
+ "name": "github-env-${env}",
80
+ "issuer": "https://token.actions.githubusercontent.com",
81
+ "subject": "repo:'"$GITHUB_ORG"'/'"$GITHUB_REPO"':environment:${env}",
82
+ "audiences": ["api://AzureADTokenExchange"]
83
+ }'`).join('\n\n')}
84
+ \`\`\`
85
+
86
+ ## Step 4: Configure GitHub Secrets
87
+
88
+ Add the following secrets to your GitHub repository (Settings → Secrets and variables → Actions):
89
+
90
+ ### Repository Secrets:
91
+ - \`AZURE_CLIENT_ID\`: $APP_ID (from Step 1)
92
+ - \`AZURE_TENANT_ID\`: Run \`az account show --query tenantId -o tsv\`
93
+ - \`AZURE_SUBSCRIPTION_ID\`: ${subscriptionId}
94
+
95
+ ### Environment-Specific Secrets:
96
+ ${environments.map((env) => `
97
+ **For ${env} environment:**
98
+ - \`APIM_RESOURCE_GROUP_${env.toUpperCase()}\`: Resource group for ${env}
99
+ - \`APIM_SERVICE_NAME_${env.toUpperCase()}\`: APIM service name for ${env}
100
+ `).join('\n')}
101
+
102
+ ### Extract Workflow Secrets:
103
+ - \`APIM_RESOURCE_GROUP\`: Default resource group for extract
104
+ - \`APIM_SERVICE_NAME\`: Default APIM service name for extract
105
+
106
+ ## Step 5: Verify Setup
107
+
108
+ Test the authentication by running a workflow manually or pushing to main branch.
109
+
110
+ ## Security Notes
111
+ - Use GitHub Environments for production deployments with required reviewers
112
+ - Rotate service principal credentials periodically
113
+ - Review federated credential subjects regularly
114
+ - Use least-privilege RBAC assignments
115
+ `;
116
+ }
117
+ generateAzureDevOpsGuide(subscriptionId, resourceGroup, environments) {
118
+ return `# Azure DevOps Identity Setup Guide
119
+
120
+ ## Prerequisites
121
+ - Azure subscription: ${subscriptionId}
122
+ - Resource group: ${resourceGroup}
123
+ - Azure DevOps organization and project
124
+
125
+ ## Step 1: Create Service Principal
126
+
127
+ Create a service principal for each environment or use a single shared one:
128
+
129
+ \`\`\`bash
130
+ # Set variables
131
+ SUBSCRIPTION_ID="${subscriptionId}"
132
+ RESOURCE_GROUP="${resourceGroup}"
133
+ APP_NAME="apiops-azdo-sp"
134
+
135
+ # Create Service Principal with Contributor role
136
+ SP_OUTPUT=$(az ad sp create-for-rbac \\
137
+ --name "$APP_NAME" \\
138
+ --role "API Management Service Contributor" \\
139
+ --scopes "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP" \\
140
+ --sdk-auth)
141
+
142
+ echo "$SP_OUTPUT"
143
+
144
+ # Save the output - you'll need these values:
145
+ # - appId (client ID)
146
+ # - password (client secret)
147
+ # - tenant
148
+ \`\`\`
149
+
150
+ ## Step 2: Create Azure Service Connections
151
+
152
+ In Azure DevOps, create service connections for Azure Resource Manager:
153
+
154
+ 1. Go to Project Settings → Service connections
155
+ 2. Click "New service connection" → "Azure Resource Manager" → "Service principal (manual)"
156
+ 3. Fill in the details from Step 1:
157
+ - **Subscription ID**: ${subscriptionId}
158
+ - **Subscription Name**: (your subscription name)
159
+ - **Service Principal ID**: appId from Step 1
160
+ - **Service Principal Key**: password from Step 1
161
+ - **Tenant ID**: tenant from Step 1
162
+
163
+ ${environments.map((env) => `
164
+ **For ${env} environment:**
165
+ - Connection name: \`AZURE_SERVICE_CONNECTION_${env.toUpperCase()}\`
166
+ - Verify: Test the connection
167
+ `).join('\n')}
168
+
169
+ **For extract pipeline:**
170
+ - Connection name: \`AZURE_SERVICE_CONNECTION\`
171
+ - Verify: Test the connection
172
+
173
+ ## Step 3: Create Variable Groups
174
+
175
+ Create variable groups in Azure DevOps Library:
176
+
177
+ ### Common Variable Group (\`apim-common\`):
178
+ - \`AZURE_SUBSCRIPTION_ID\`: ${subscriptionId}
179
+ - \`APIM_RESOURCE_GROUP\`: ${resourceGroup}
180
+ - \`APIM_SERVICE_NAME\`: <your-apim-service-name>
181
+ - \`AZURE_SERVICE_CONNECTION\`: Name from Step 2
182
+
183
+ ${environments.map((env) => `
184
+ ### ${env} Environment Variable Group (\`apim-${env}\`):
185
+ - \`APIM_RESOURCE_GROUP_${env.toUpperCase()}\`: Resource group for ${env}
186
+ - \`APIM_SERVICE_NAME_${env.toUpperCase()}\`: APIM service name for ${env}
187
+ - \`AZURE_SERVICE_CONNECTION_${env.toUpperCase()}\`: Service connection name for ${env}
188
+ `).join('\n')}
189
+
190
+ ## Step 4: Configure Pipeline Permissions
191
+
192
+ 1. Go to Pipelines → Library → Variable Groups
193
+ 2. For each variable group, click "Pipeline permissions"
194
+ 3. Allow the extract and publish pipelines to use these variable groups
195
+
196
+ ## Step 5: Create Environments
197
+
198
+ Create deployment environments in Azure DevOps:
199
+
200
+ 1. Go to Pipelines → Environments
201
+ 2. Create new environment for each:
202
+ ${environments.map((env) => ` - \`${env}\``).join('\n')}
203
+ 3. Configure approvals and checks as needed for production environments
204
+
205
+ ## Step 6: Enable Pipeline Contributions
206
+
207
+ For the extract pipeline to commit changes:
208
+
209
+ 1. Go to Project Settings → Repositories → Security
210
+ 2. Find "Build Service" account
211
+ 3. Grant "Contribute" and "Contribute to pull requests" permissions
212
+
213
+ ## Step 7: Verify Setup
214
+
215
+ Run the extract pipeline manually to verify authentication and permissions.
216
+
217
+ ## Security Notes
218
+ - Use separate service principals for production environments
219
+ - Enable environment approvals for production deployments
220
+ - Rotate service principal secrets periodically (recommended: 90 days)
221
+ - Use managed identities when possible for Azure-hosted agents
222
+ - Review RBAC assignments regularly
223
+ `;
224
+ }
225
+ }
226
+ export const identityGuideService = new IdentityGuideServiceImpl();
227
+ //# sourceMappingURL=identity-guide-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-guide-service.js","sourceRoot":"","sources":["../../src/services/identity-guide-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,MAAM,wBAAwB;IAC5B,0BAA0B,CACxB,cAAsB,EACtB,aAAqB,EACrB,YAAsB;QAEtB,OAAO;;;wBAGa,cAAc;oBAClB,aAAa;;;;;;;;;mBASd,cAAc;kBACf,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsD7B,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;;;0BAGF,GAAG;;oEAEuC,GAAG;;KAElE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;+BAUY,cAAc;;;EAG3C,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QACpB,GAAG;0BACe,GAAG,CAAC,WAAW,EAAE,0BAA0B,GAAG;wBAChD,GAAG,CAAC,WAAW,EAAE,6BAA6B,GAAG;CACxE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;CAeZ,CAAC;IACA,CAAC;IAED,wBAAwB,CACtB,cAAsB,EACtB,aAAqB,EACrB,YAAsB;QAEtB,OAAO;;;wBAGa,cAAc;oBAClB,aAAa;;;;;;;;;mBASd,cAAc;kBACf,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;4BAyBH,cAAc;;;;;;EAMxC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QACpB,GAAG;gDACqC,GAAG,CAAC,WAAW,EAAE;;CAEhE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;+BAWkB,cAAc;6BAChB,aAAa;;;;EAIxC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;MACtB,GAAG,uCAAuC,GAAG;0BACzB,GAAG,CAAC,WAAW,EAAE,0BAA0B,GAAG;wBAChD,GAAG,CAAC,WAAW,EAAE,6BAA6B,GAAG;+BAC1C,GAAG,CAAC,WAAW,EAAE,mCAAmC,GAAG;CACrF,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;EAcX,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;CAqBxD,CAAC;IACA,CAAC;CACF;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAyB,IAAI,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * T042 & T051: Init orchestrator service
3
+ * Coordinates interactive prompts or flag-based config, generates scaffold files,
4
+ * and detects existing file conflicts
5
+ */
6
+ import { InitConfig } from '../models/config.js';
7
+ export interface GeneratedFiles {
8
+ pipelines: string[];
9
+ configs: string[];
10
+ directories: string[];
11
+ }
12
+ export interface InitService {
13
+ run(config: InitConfig): Promise<GeneratedFiles>;
14
+ }
15
+ export declare const initService: InitService;
16
+ //# sourceMappingURL=init-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-service.d.ts","sourceRoot":"","sources":["../../src/services/init-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AA6BjD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAClD;AAqXD,eAAO,MAAM,WAAW,EAAE,WAAmC,CAAC"}