@swovohq/fuel 0.2.2-alpha.9 → 0.2.2-alpha.91

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 (232) hide show
  1. package/README.md +173 -69
  2. package/dist/bin/fuel.js +77 -31
  3. package/dist/bin/fuel.js.map +1 -1
  4. package/dist/cleanup/finalize.d.ts.map +1 -1
  5. package/dist/cleanup/finalize.js +11 -3
  6. package/dist/cleanup/finalize.js.map +1 -1
  7. package/dist/commands/config-verify.d.ts.map +1 -1
  8. package/dist/commands/config-verify.js +14 -6
  9. package/dist/commands/config-verify.js.map +1 -1
  10. package/dist/commands/create-app.d.ts.map +1 -1
  11. package/dist/commands/create-app.js +41 -7
  12. package/dist/commands/create-app.js.map +1 -1
  13. package/dist/commands/infra-deploy.d.ts +15 -1
  14. package/dist/commands/infra-deploy.d.ts.map +1 -1
  15. package/dist/commands/infra-deploy.js +164 -18
  16. package/dist/commands/infra-deploy.js.map +1 -1
  17. package/dist/commands/infra-destroy.d.ts.map +1 -1
  18. package/dist/commands/infra-destroy.js +3 -3
  19. package/dist/commands/infra-destroy.js.map +1 -1
  20. package/dist/commands/infra-init.d.ts +91 -0
  21. package/dist/commands/infra-init.d.ts.map +1 -1
  22. package/dist/commands/infra-init.js +644 -113
  23. package/dist/commands/infra-init.js.map +1 -1
  24. package/dist/commands/infra-pull.d.ts +8 -0
  25. package/dist/commands/infra-pull.d.ts.map +1 -0
  26. package/dist/commands/infra-pull.js +81 -0
  27. package/dist/commands/infra-pull.js.map +1 -0
  28. package/dist/commands/list-modules.d.ts.map +1 -1
  29. package/dist/commands/list-modules.js +10 -3
  30. package/dist/commands/list-modules.js.map +1 -1
  31. package/dist/engines/convention.d.ts +2 -2
  32. package/dist/engines/convention.d.ts.map +1 -1
  33. package/dist/engines/convention.js +8 -6
  34. package/dist/engines/convention.js.map +1 -1
  35. package/dist/engines/dependencies.d.ts +2 -0
  36. package/dist/engines/dependencies.d.ts.map +1 -1
  37. package/dist/engines/dependencies.js.map +1 -1
  38. package/dist/engines/monorepo.d.ts.map +1 -1
  39. package/dist/engines/monorepo.js.map +1 -1
  40. package/dist/engines/template-source.d.ts.map +1 -1
  41. package/dist/engines/template-source.js +3 -1
  42. package/dist/engines/template-source.js.map +1 -1
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js.map +1 -1
  45. package/dist/infra/azure-defaults.d.ts +49 -0
  46. package/dist/infra/azure-defaults.d.ts.map +1 -0
  47. package/dist/infra/azure-defaults.js +52 -0
  48. package/dist/infra/azure-defaults.js.map +1 -0
  49. package/dist/infra/azure-keyvault-client.d.ts +4 -0
  50. package/dist/infra/azure-keyvault-client.d.ts.map +1 -0
  51. package/dist/infra/azure-keyvault-client.js +57 -0
  52. package/dist/infra/azure-keyvault-client.js.map +1 -0
  53. package/dist/infra/azure-rbac.d.ts +11 -0
  54. package/dist/infra/azure-rbac.d.ts.map +1 -0
  55. package/dist/infra/azure-rbac.js +49 -0
  56. package/dist/infra/azure-rbac.js.map +1 -0
  57. package/dist/infra/azure-state-storage.d.ts +20 -0
  58. package/dist/infra/azure-state-storage.d.ts.map +1 -0
  59. package/dist/infra/azure-state-storage.js +229 -0
  60. package/dist/infra/azure-state-storage.js.map +1 -0
  61. package/dist/infra/config-loader.d.ts.map +1 -1
  62. package/dist/infra/config-loader.js.map +1 -1
  63. package/dist/infra/config-writer.js +1 -1
  64. package/dist/infra/credentials.d.ts +2 -2
  65. package/dist/infra/credentials.d.ts.map +1 -1
  66. package/dist/infra/credentials.js +8 -4
  67. package/dist/infra/credentials.js.map +1 -1
  68. package/dist/infra/dependency-checker.d.ts.map +1 -1
  69. package/dist/infra/dependency-checker.js.map +1 -1
  70. package/dist/infra/deployment-detect.d.ts +9 -0
  71. package/dist/infra/deployment-detect.d.ts.map +1 -0
  72. package/dist/infra/deployment-detect.js +53 -0
  73. package/dist/infra/deployment-detect.js.map +1 -0
  74. package/dist/infra/git-client.d.ts.map +1 -1
  75. package/dist/infra/git-client.js +6 -10
  76. package/dist/infra/git-client.js.map +1 -1
  77. package/dist/infra/github-client.d.ts +7 -0
  78. package/dist/infra/github-client.d.ts.map +1 -1
  79. package/dist/infra/github-client.js +47 -7
  80. package/dist/infra/github-client.js.map +1 -1
  81. package/dist/infra/github-secrets-client.d.ts.map +1 -1
  82. package/dist/infra/github-secrets-client.js +2 -2
  83. package/dist/infra/github-secrets-client.js.map +1 -1
  84. package/dist/infra/github-token-link.d.ts +4 -0
  85. package/dist/infra/github-token-link.d.ts.map +1 -0
  86. package/dist/infra/github-token-link.js +32 -0
  87. package/dist/infra/github-token-link.js.map +1 -0
  88. package/dist/infra/orchestrator.d.ts +4 -1
  89. package/dist/infra/orchestrator.d.ts.map +1 -1
  90. package/dist/infra/orchestrator.js +218 -63
  91. package/dist/infra/orchestrator.js.map +1 -1
  92. package/dist/infra/port-utils.d.ts.map +1 -1
  93. package/dist/infra/port-utils.js.map +1 -1
  94. package/dist/infra/preflight.d.ts.map +1 -1
  95. package/dist/infra/preflight.js +25 -11
  96. package/dist/infra/preflight.js.map +1 -1
  97. package/dist/infra/remote-secret.d.ts +14 -0
  98. package/dist/infra/remote-secret.d.ts.map +1 -0
  99. package/dist/infra/remote-secret.js +42 -0
  100. package/dist/infra/remote-secret.js.map +1 -0
  101. package/dist/infra/s3-state-bucket.d.ts.map +1 -1
  102. package/dist/infra/s3-state-bucket.js +8 -4
  103. package/dist/infra/s3-state-bucket.js.map +1 -1
  104. package/dist/infra/secrets-manager-client.d.ts.map +1 -1
  105. package/dist/infra/secrets-manager-client.js +8 -5
  106. package/dist/infra/secrets-manager-client.js.map +1 -1
  107. package/dist/infra/subprocess.js +1 -1
  108. package/dist/infra/template-engine.d.ts +14 -5
  109. package/dist/infra/template-engine.d.ts.map +1 -1
  110. package/dist/infra/template-engine.js +157 -39
  111. package/dist/infra/template-engine.js.map +1 -1
  112. package/dist/infra/tofu-runner.d.ts +4 -3
  113. package/dist/infra/tofu-runner.d.ts.map +1 -1
  114. package/dist/infra/tofu-runner.js +40 -34
  115. package/dist/infra/tofu-runner.js.map +1 -1
  116. package/dist/infra/types.d.ts +241 -17
  117. package/dist/infra/types.d.ts.map +1 -1
  118. package/dist/infra/types.js +419 -22
  119. package/dist/infra/types.js.map +1 -1
  120. package/dist/infra-templates/TODO-azure-prod.md +127 -0
  121. package/dist/infra-templates/modules/azure-container-app/main.tf +124 -0
  122. package/dist/infra-templates/modules/azure-container-app/outputs.tf +24 -0
  123. package/dist/infra-templates/modules/azure-container-app/variables.tf +80 -0
  124. package/dist/infra-templates/modules/azure-container-apps-environment/main.tf +18 -0
  125. package/dist/infra-templates/modules/azure-container-apps-environment/outputs.tf +14 -0
  126. package/dist/infra-templates/modules/azure-container-apps-environment/variables.tf +24 -0
  127. package/dist/infra-templates/modules/azure-container-registry/main.tf +10 -0
  128. package/dist/infra-templates/modules/azure-container-registry/outputs.tf +14 -0
  129. package/dist/infra-templates/modules/azure-container-registry/variables.tf +20 -0
  130. package/dist/infra-templates/modules/azure-front-door/main.tf +80 -0
  131. package/dist/infra-templates/modules/azure-front-door/outputs.tf +20 -0
  132. package/dist/infra-templates/modules/azure-front-door/variables.tf +26 -0
  133. package/dist/infra-templates/modules/azure-github-oidc/main.tf +48 -0
  134. package/dist/infra-templates/modules/azure-github-oidc/outputs.tf +9 -0
  135. package/dist/infra-templates/modules/azure-github-oidc/variables.tf +69 -0
  136. package/dist/infra-templates/modules/azure-key-vault/main.tf +21 -0
  137. package/dist/infra-templates/modules/azure-key-vault/outputs.tf +11 -0
  138. package/dist/infra-templates/modules/azure-key-vault/variables.tf +43 -0
  139. package/dist/infra-templates/modules/azure-monitor/main.tf +29 -0
  140. package/dist/infra-templates/modules/azure-monitor/outputs.tf +17 -0
  141. package/dist/infra-templates/modules/azure-monitor/variables.tf +32 -0
  142. package/dist/infra-templates/modules/azure-network/main.tf +134 -0
  143. package/dist/infra-templates/modules/azure-network/outputs.tf +44 -0
  144. package/dist/infra-templates/modules/azure-network/variables.tf +56 -0
  145. package/dist/infra-templates/modules/azure-postgresql-flexible/main.tf +34 -0
  146. package/dist/infra-templates/modules/azure-postgresql-flexible/outputs.tf +20 -0
  147. package/dist/infra-templates/modules/azure-postgresql-flexible/variables.tf +54 -0
  148. package/dist/infra-templates/modules/azure-redis-cache/main.tf +32 -0
  149. package/dist/infra-templates/modules/azure-redis-cache/outputs.tf +15 -0
  150. package/dist/infra-templates/modules/azure-redis-cache/variables.tf +30 -0
  151. package/dist/infra-templates/modules/azure-resource-group/main.tf +5 -0
  152. package/dist/infra-templates/modules/azure-resource-group/outputs.tf +11 -0
  153. package/dist/infra-templates/modules/azure-resource-group/variables.tf +16 -0
  154. package/dist/infra-templates/modules/azure-sql-database/main.tf +63 -0
  155. package/dist/infra-templates/modules/azure-sql-database/outputs.tf +20 -0
  156. package/dist/infra-templates/modules/azure-sql-database/variables.tf +78 -0
  157. package/dist/infra-templates/modules/azure-storage-account/main.tf +13 -0
  158. package/dist/infra-templates/modules/azure-storage-account/outputs.tf +16 -0
  159. package/dist/infra-templates/modules/azure-storage-account/variables.tf +38 -0
  160. package/dist/infra-templates/modules/cloud-watch/event-bridge.tf +15 -0
  161. package/dist/infra-templates/modules/cloud-watch/lambda.tf +84 -0
  162. package/dist/infra-templates/modules/cloud-watch/lambda_function.zip +0 -0
  163. package/dist/infra-templates/modules/cloud-watch/lambda_function_deploy.zip +0 -0
  164. package/dist/infra-templates/modules/cloud-watch/main.tf +156 -0
  165. package/dist/infra-templates/modules/cloud-watch/sns.tf +3 -0
  166. package/dist/infra-templates/modules/cloud-watch/variables.tf +38 -0
  167. package/dist/infra-templates/modules/ecs-core/alb.tf +126 -0
  168. package/dist/infra-templates/modules/ecs-core/cloudwatch.tf +48 -0
  169. package/dist/infra-templates/modules/ecs-core/iam.tf +95 -0
  170. package/dist/infra-templates/modules/ecs-core/main.tf +12 -0
  171. package/dist/infra-templates/modules/ecs-core/outputs.tf +44 -0
  172. package/dist/infra-templates/modules/ecs-core/secrets.tf +9 -0
  173. package/dist/infra-templates/modules/ecs-core/security_groups.tf +73 -0
  174. package/dist/infra-templates/modules/ecs-core/variables.tf +96 -0
  175. package/dist/infra-templates/modules/ecs-service/ecs_autoscaling.tf +51 -0
  176. package/dist/infra-templates/modules/ecs-service/ecs_service.tf +39 -0
  177. package/dist/infra-templates/modules/ecs-service/ecs_task_definition.tf +56 -0
  178. package/dist/infra-templates/modules/ecs-service/variables.tf +170 -0
  179. package/dist/infra-templates/modules/elastic-container-registry/main.tf +32 -0
  180. package/dist/infra-templates/modules/elastic-container-registry/outputs.tf +9 -0
  181. package/dist/infra-templates/modules/elastic-container-registry/variables.tf +25 -0
  182. package/dist/infra-templates/modules/github-oidc-role/main.tf +46 -0
  183. package/dist/infra-templates/modules/github-oidc-role/outputs.tf +4 -0
  184. package/dist/infra-templates/modules/github-oidc-role/variables.tf +11 -0
  185. package/dist/infra-templates/modules/guardduty/main.tf +8 -0
  186. package/dist/infra-templates/modules/iam/main.tf +205 -0
  187. package/dist/infra-templates/modules/iam/outputs.tf +3 -0
  188. package/dist/infra-templates/modules/iam/variables.tf +4 -0
  189. package/dist/infra-templates/modules/random-key/main.tf +11 -0
  190. package/dist/infra-templates/modules/random-key/outputs.tf +4 -0
  191. package/dist/infra-templates/modules/random-key/variables.tf +10 -0
  192. package/dist/infra-templates/modules/redis/main.tf +47 -0
  193. package/dist/infra-templates/modules/redis/outputs.tf +8 -0
  194. package/dist/infra-templates/modules/redis/variables.tf +20 -0
  195. package/dist/infra-templates/modules/relational-database-service/main.tf +44 -0
  196. package/dist/infra-templates/modules/relational-database-service/outputs.tf +13 -0
  197. package/dist/infra-templates/modules/relational-database-service/security-group.tf +15 -0
  198. package/dist/infra-templates/modules/relational-database-service/variables.tf +50 -0
  199. package/dist/infra-templates/modules/secret/main.tf +14 -0
  200. package/dist/infra-templates/modules/secret/outputs.tf +3 -0
  201. package/dist/infra-templates/modules/secret/variables.tf +8 -0
  202. package/dist/infra-templates/modules/simple-storage-service/main.tf +28 -0
  203. package/dist/infra-templates/modules/simple-storage-service/variables.tf +4 -0
  204. package/dist/infra-templates/modules/vpc/data.tf +2 -0
  205. package/dist/infra-templates/modules/vpc/main.tf +76 -0
  206. package/dist/infra-templates/modules/vpc/outputs.tf +23 -0
  207. package/dist/infra-templates/modules/vpc/variables.tf +5 -0
  208. package/dist/infra-templates/package.json +6 -0
  209. package/dist/infra-templates/templates/azure/MANUAL_DEPLOY.md +168 -0
  210. package/dist/infra-templates/templates/azure/backend.tf +8 -0
  211. package/dist/infra-templates/templates/azure/data.tf +21 -0
  212. package/dist/infra-templates/templates/azure/default.tfvars +0 -0
  213. package/dist/infra-templates/templates/azure/locals.tf +116 -0
  214. package/dist/infra-templates/templates/azure/main.tf +421 -0
  215. package/dist/infra-templates/templates/azure/outputs.tf +40 -0
  216. package/dist/infra-templates/templates/azure/providers.tf +65 -0
  217. package/dist/infra-templates/templates/azure/variables.tf +69 -0
  218. package/dist/infra-templates/templates/azure/workflows/build_and_deploy.yml +155 -0
  219. package/dist/infra-templates/templates/azure/workflows/tests.yml +63 -0
  220. package/dist/infra-templates/templates/ecs/README.md +235 -0
  221. package/dist/infra-templates/templates/ecs/backend.tf +7 -0
  222. package/dist/infra-templates/templates/ecs/data.tf +6 -0
  223. package/dist/infra-templates/templates/ecs/default.tfvars +1 -0
  224. package/dist/infra-templates/templates/ecs/locals.tf +97 -0
  225. package/dist/infra-templates/templates/ecs/main.tf +185 -0
  226. package/dist/infra-templates/templates/ecs/outputs.tf +42 -0
  227. package/dist/infra-templates/templates/ecs/providers.tf +21 -0
  228. package/dist/infra-templates/templates/ecs/variables.tf +105 -0
  229. package/dist/infra-templates/templates/ecs/workflows/build_and_deploy.yml +188 -0
  230. package/dist/infra-templates/templates/ecs/workflows/tests.yml +65 -0
  231. package/package.json +10 -2
  232. package/schema/fuel.schema.json +570 -91
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getSecret = getSecret;
37
+ exports.putSecret = putSecret;
38
+ const identity_1 = require("@azure/identity");
39
+ const keyvault_secrets_1 = require("@azure/keyvault-secrets");
40
+ const YAML = __importStar(require("yaml"));
41
+ function buildClient(credentials, vaultName) {
42
+ const credential = new identity_1.ClientSecretCredential(credentials.AZURE_TENANT_ID, credentials.AZURE_CLIENT_ID, credentials.AZURE_CLIENT_SECRET);
43
+ return new keyvault_secrets_1.SecretClient(`https://${vaultName}.vault.azure.net`, credential);
44
+ }
45
+ async function getSecret(credentials, vaultName, secretName) {
46
+ const client = buildClient(credentials, vaultName);
47
+ const response = await client.getSecret(secretName);
48
+ if (!response.value) {
49
+ throw new Error(`Secret "${secretName}" exists in vault "${vaultName}" but has no value.`);
50
+ }
51
+ return YAML.parse(response.value);
52
+ }
53
+ async function putSecret(credentials, vaultName, secretName, value) {
54
+ const client = buildClient(credentials, vaultName);
55
+ await client.setSecret(secretName, YAML.stringify(value));
56
+ }
57
+ //# sourceMappingURL=azure-keyvault-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-keyvault-client.js","sourceRoot":"","sources":["../../src/infra/azure-keyvault-client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,8BAaC;AAED,8BAQC;AAxCD,8CAAwD;AACxD,8DAAsD;AACtD,2CAA4B;AAG5B,SAAS,WAAW,CAClB,WAAwB,EACxB,SAAiB;IAEjB,MAAM,UAAU,GAAG,IAAI,iCAAsB,CAC3C,WAAW,CAAC,eAAe,EAC3B,WAAW,CAAC,eAAe,EAC3B,WAAW,CAAC,mBAAmB,CAChC,CAAA;IACD,OAAO,IAAI,+BAAY,CAAC,WAAW,SAAS,kBAAkB,EAAE,UAAU,CAAC,CAAA;AAC7E,CAAC;AAEM,KAAK,UAAU,SAAS,CAC7B,WAAwB,EACxB,SAAiB,EACjB,UAAkB;IAElB,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IAClD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;IACnD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,WAAW,UAAU,sBAAsB,SAAS,qBAAqB,CAC1E,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACnC,CAAC;AAEM,KAAK,UAAU,SAAS,CAC7B,WAAwB,EACxB,SAAiB,EACjB,UAAkB,EAClB,KAA8B;IAE9B,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IAClD,MAAM,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;AAC3D,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Credentials } from './types';
2
+ export declare function actionMatches(pattern: string, action: string): boolean;
3
+ /**
4
+ * The deploy creates role assignments (GitHub OIDC -> ACR push, GitHub OIDC -> RG contributor),
5
+ * which need `Microsoft.Authorization/roleAssignments/write`. Azure's built-in Contributor role
6
+ * explicitly excludes that action (it's in Contributor's `notActions`), so a SP with only
7
+ * Contributor always fails here — regardless of scope. Checked against the resource group
8
+ * (not the subscription) so it reflects the SP's actual effective permissions at apply time.
9
+ */
10
+ export declare function ensureRoleAssignmentPermission(credentials: Credentials, resourceGroupName: string): Promise<void>;
11
+ //# sourceMappingURL=azure-rbac.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-rbac.d.ts","sourceRoot":"","sources":["../../src/infra/azure-rbac.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAarC,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAMtE;AAaD;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CAClD,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.actionMatches = actionMatches;
7
+ exports.ensureRoleAssignmentPermission = ensureRoleAssignmentPermission;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const identity_1 = require("@azure/identity");
10
+ const arm_authorization_1 = require("@azure/arm-authorization");
11
+ const ROLE_ASSIGNMENT_WRITE_ACTION = 'Microsoft.Authorization/roleAssignments/write';
12
+ function credential(credentials) {
13
+ return new identity_1.ClientSecretCredential(credentials.AZURE_TENANT_ID, credentials.AZURE_CLIENT_ID, credentials.AZURE_CLIENT_SECRET);
14
+ }
15
+ function actionMatches(pattern, action) {
16
+ const escaped = pattern
17
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
18
+ .replace(/\\\*/g, '.*');
19
+ const regex = new RegExp(`^${escaped}$`, 'i');
20
+ return regex.test(action);
21
+ }
22
+ function isActionAllowed(permissions, action) {
23
+ return permissions.some((p) => (p.actions ?? []).some((a) => actionMatches(a, action)) &&
24
+ !(p.notActions ?? []).some((a) => actionMatches(a, action)));
25
+ }
26
+ /**
27
+ * The deploy creates role assignments (GitHub OIDC -> ACR push, GitHub OIDC -> RG contributor),
28
+ * which need `Microsoft.Authorization/roleAssignments/write`. Azure's built-in Contributor role
29
+ * explicitly excludes that action (it's in Contributor's `notActions`), so a SP with only
30
+ * Contributor always fails here — regardless of scope. Checked against the resource group
31
+ * (not the subscription) so it reflects the SP's actual effective permissions at apply time.
32
+ */
33
+ async function ensureRoleAssignmentPermission(credentials, resourceGroupName) {
34
+ const client = new arm_authorization_1.AuthorizationManagementClient(credential(credentials), credentials.AZURE_SUBSCRIPTION_ID);
35
+ const permissions = [];
36
+ for await (const permission of client.permissions.listForResourceGroup(resourceGroupName)) {
37
+ permissions.push(permission);
38
+ }
39
+ if (isActionAllowed(permissions, ROLE_ASSIGNMENT_WRITE_ACTION)) {
40
+ console.log(chalk_1.default.green(' ✓ Service principal can create role assignments'));
41
+ return;
42
+ }
43
+ throw new Error(`Service principal ${credentials.AZURE_CLIENT_ID} cannot create role assignments in resource group ` +
44
+ `"${resourceGroupName}" (missing "${ROLE_ASSIGNMENT_WRITE_ACTION}"). Contributor alone never grants this — ` +
45
+ `grant "User Access Administrator" too:\n\n` +
46
+ ` az role assignment create --assignee ${credentials.AZURE_CLIENT_ID} --role "User Access Administrator" ` +
47
+ `--scope /subscriptions/${credentials.AZURE_SUBSCRIPTION_ID}/resourceGroups/${resourceGroupName}\n`);
48
+ }
49
+ //# sourceMappingURL=azure-rbac.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-rbac.js","sourceRoot":"","sources":["../../src/infra/azure-rbac.ts"],"names":[],"mappings":";;;;;AAgBA,sCAMC;AAoBD,wEA8BC;AAxED,kDAAyB;AACzB,8CAAwD;AACxD,gEAAwE;AAGxE,MAAM,4BAA4B,GAChC,+CAA+C,CAAA;AAEjD,SAAS,UAAU,CAAC,WAAwB;IAC1C,OAAO,IAAI,iCAAsB,CAC/B,WAAW,CAAC,eAAe,EAC3B,WAAW,CAAC,eAAe,EAC3B,WAAW,CAAC,mBAAmB,CAChC,CAAA;AACH,CAAC;AAED,SAAgB,aAAa,CAAC,OAAe,EAAE,MAAc;IAC3D,MAAM,OAAO,GAAG,OAAO;SACpB,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC;SACtC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACzB,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,EAAE,GAAG,CAAC,CAAA;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAC3B,CAAC;AAED,SAAS,eAAe,CACtB,WAAiE,EACjE,MAAc;IAEd,OAAO,WAAW,CAAC,IAAI,CACrB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAC9D,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,8BAA8B,CAClD,WAAwB,EACxB,iBAAyB;IAEzB,MAAM,MAAM,GAAG,IAAI,iDAA6B,CAC9C,UAAU,CAAC,WAAW,CAAC,EACvB,WAAW,CAAC,qBAAqB,CAClC,CAAA;IAED,MAAM,WAAW,GAAyD,EAAE,CAAA;IAC5E,IAAI,KAAK,EAAE,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,CAAC,oBAAoB,CACpE,iBAAiB,CAClB,EAAE,CAAC;QACF,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC9B,CAAC;IAED,IAAI,eAAe,CAAC,WAAW,EAAE,4BAA4B,CAAC,EAAE,CAAC;QAC/D,OAAO,CAAC,GAAG,CACT,eAAK,CAAC,KAAK,CAAC,mDAAmD,CAAC,CACjE,CAAA;QACD,OAAM;IACR,CAAC;IAED,MAAM,IAAI,KAAK,CACb,qBAAqB,WAAW,CAAC,eAAe,oDAAoD;QAClG,IAAI,iBAAiB,eAAe,4BAA4B,4CAA4C;QAC5G,4CAA4C;QAC5C,0CAA0C,WAAW,CAAC,eAAe,sCAAsC;QAC3G,0BAA0B,WAAW,CAAC,qBAAqB,mBAAmB,iBAAiB,IAAI,CACtG,CAAA;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { Credentials } from './types';
2
+ import { deriveSuffix } from './s3-state-bucket';
3
+ export { deriveSuffix };
4
+ export declare function buildResourceGroupName(projectName: string): string;
5
+ export declare function buildStateStorageAccountName(projectName: string, suffix: string): string;
6
+ export declare function buildKeyVaultName(projectName: string, suffix: string): string;
7
+ export declare const STATE_CONTAINER_NAME = "tfstate";
8
+ /**
9
+ * Polls DNS until `hostname` resolves. A freshly-created Azure PaaS resource (Key Vault,
10
+ * Storage Account, ...) is reported "Succeeded" by the ARM control plane before its public
11
+ * DNS record has actually propagated — an immediate follow-up call can fail with ENOTFOUND
12
+ * even though the resource exists. Only needed right after creating a new resource.
13
+ */
14
+ export declare function waitForDns(hostname: string, timeoutMs?: number, intervalMs?: number): Promise<void>;
15
+ export declare function ensureResourceGroup(credentials: Credentials, resourceGroupName: string, location: string): Promise<void>;
16
+ /** Ensures the storage account + blob container backing the `azurerm` Tofu state backend exist. */
17
+ export declare function ensureStateStorage(credentials: Credentials, resourceGroupName: string, storageAccountName: string, location: string, containerName?: string): Promise<void>;
18
+ /** Ensures the Key Vault that stores the fuel.yml infrastructure secret exists and grants the CLI's SP access to it. */
19
+ export declare function ensureBootstrapKeyVault(credentials: Credentials, resourceGroupName: string, keyVaultName: string, location: string): Promise<void>;
20
+ //# sourceMappingURL=azure-state-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-state-storage.d.ts","sourceRoot":"","sources":["../../src/infra/azure-state-storage.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,CAAA;AAMvB,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,MAAM,CAKR;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK7E;AAED,eAAO,MAAM,oBAAoB,YAAY,CAAA;AAc7C;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAS,EAClB,UAAU,SAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CAWf;AAiCD,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED,mGAAmG;AACnG,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,MAAM,EACzB,kBAAkB,EAAE,MAAM,EAC1B,QAAQ,EAAE,MAAM,EAChB,aAAa,GAAE,MAA6B,GAC3C,OAAO,CAAC,IAAI,CAAC,CAyEf;AAED,wHAAwH;AACxH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAuEf"}
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.STATE_CONTAINER_NAME = exports.deriveSuffix = void 0;
40
+ exports.buildResourceGroupName = buildResourceGroupName;
41
+ exports.buildStateStorageAccountName = buildStateStorageAccountName;
42
+ exports.buildKeyVaultName = buildKeyVaultName;
43
+ exports.waitForDns = waitForDns;
44
+ exports.ensureResourceGroup = ensureResourceGroup;
45
+ exports.ensureStateStorage = ensureStateStorage;
46
+ exports.ensureBootstrapKeyVault = ensureBootstrapKeyVault;
47
+ const https = __importStar(require("https"));
48
+ const dns = __importStar(require("dns"));
49
+ const chalk_1 = __importDefault(require("chalk"));
50
+ const identity_1 = require("@azure/identity");
51
+ const arm_resources_1 = require("@azure/arm-resources");
52
+ const arm_storage_1 = require("@azure/arm-storage");
53
+ const arm_keyvault_1 = require("@azure/arm-keyvault");
54
+ const storage_blob_1 = require("@azure/storage-blob");
55
+ const s3_state_bucket_1 = require("./s3-state-bucket");
56
+ Object.defineProperty(exports, "deriveSuffix", { enumerable: true, get: function () { return s3_state_bucket_1.deriveSuffix; } });
57
+ function slugify(name) {
58
+ return name.replace(/[^a-z0-9]/gi, '').toLowerCase();
59
+ }
60
+ function buildResourceGroupName(projectName) {
61
+ return `${projectName}-rg`.replace(/[^a-zA-Z0-9-_.()]/g, '-');
62
+ }
63
+ function buildStateStorageAccountName(projectName, suffix) {
64
+ const safeSuffix = slugify(suffix).slice(-8);
65
+ const base = slugify(projectName).slice(0, 24 - 2 - safeSuffix.length) || 'app';
66
+ return `st${base}${safeSuffix}`;
67
+ }
68
+ function buildKeyVaultName(projectName, suffix) {
69
+ const safeSuffix = slugify(suffix).slice(-8);
70
+ const base = slugify(projectName).slice(0, 24 - 3 - 1 - safeSuffix.length) || 'app';
71
+ return `kv-${base}-${safeSuffix}`;
72
+ }
73
+ exports.STATE_CONTAINER_NAME = 'tfstate';
74
+ function credential(credentials) {
75
+ return new identity_1.ClientSecretCredential(credentials.AZURE_TENANT_ID, credentials.AZURE_CLIENT_ID, credentials.AZURE_CLIENT_SECRET);
76
+ }
77
+ function isNotFound(err) {
78
+ return err?.statusCode === 404 || err?.code === 'ResourceNotFound';
79
+ }
80
+ /**
81
+ * Polls DNS until `hostname` resolves. A freshly-created Azure PaaS resource (Key Vault,
82
+ * Storage Account, ...) is reported "Succeeded" by the ARM control plane before its public
83
+ * DNS record has actually propagated — an immediate follow-up call can fail with ENOTFOUND
84
+ * even though the resource exists. Only needed right after creating a new resource.
85
+ */
86
+ async function waitForDns(hostname, timeoutMs = 60_000, intervalMs = 3_000) {
87
+ const deadline = Date.now() + timeoutMs;
88
+ for (;;) {
89
+ try {
90
+ await dns.promises.lookup(hostname);
91
+ return;
92
+ }
93
+ catch {
94
+ if (Date.now() >= deadline)
95
+ return; // give up silently — the caller's own request will surface the real error
96
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
97
+ }
98
+ }
99
+ }
100
+ /** Looks up the AAD object ID for the service principal identified by AZURE_CLIENT_ID, via Microsoft Graph. */
101
+ async function getServicePrincipalObjectId(cred, clientId) {
102
+ const token = await cred.getToken('https://graph.microsoft.com/.default');
103
+ const url = `https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '${clientId}'`;
104
+ const body = await new Promise((resolve, reject) => {
105
+ const req = https.get(url, { headers: { Authorization: `Bearer ${token.token}` } }, (res) => {
106
+ let data = '';
107
+ res.on('data', (chunk) => (data += chunk));
108
+ res.on('end', () => resolve(data));
109
+ });
110
+ req.on('error', reject);
111
+ });
112
+ const parsed = JSON.parse(body);
113
+ if (!parsed.value || parsed.value.length === 0) {
114
+ throw new Error(`Could not resolve service principal object ID for AZURE_CLIENT_ID=${clientId}: ${parsed.error?.message ?? 'not found'}`);
115
+ }
116
+ return parsed.value[0].id;
117
+ }
118
+ async function ensureResourceGroup(credentials, resourceGroupName, location) {
119
+ const client = new arm_resources_1.ResourceManagementClient(credential(credentials), credentials.AZURE_SUBSCRIPTION_ID);
120
+ // checkExistence resolves to { body: boolean }, not a plain boolean — the object itself is always truthy.
121
+ const { body: exists } = await client.resourceGroups.checkExistence(resourceGroupName);
122
+ if (exists) {
123
+ console.log(chalk_1.default.green(` ✓ Resource group already exists: ${resourceGroupName}`));
124
+ return;
125
+ }
126
+ console.log(chalk_1.default.cyan(` Creating resource group: ${resourceGroupName}`));
127
+ await client.resourceGroups.createOrUpdate(resourceGroupName, { location });
128
+ console.log(chalk_1.default.green(' ✓ Resource group created'));
129
+ }
130
+ /** Ensures the storage account + blob container backing the `azurerm` Tofu state backend exist. */
131
+ async function ensureStateStorage(credentials, resourceGroupName, storageAccountName, location, containerName = exports.STATE_CONTAINER_NAME) {
132
+ const cred = credential(credentials);
133
+ const storageClient = new arm_storage_1.StorageManagementClient(cred, credentials.AZURE_SUBSCRIPTION_ID);
134
+ let exists = true;
135
+ try {
136
+ await storageClient.storageAccounts.getProperties(resourceGroupName, storageAccountName);
137
+ }
138
+ catch (err) {
139
+ if (!isNotFound(err)) {
140
+ throw new Error(`Failed to check state storage account "${storageAccountName}": ${err.message || err}`);
141
+ }
142
+ exists = false;
143
+ }
144
+ if (!exists) {
145
+ console.log(chalk_1.default.cyan(` Creating state storage account: ${storageAccountName}`));
146
+ const poller = await storageClient.storageAccounts.beginCreate(resourceGroupName, storageAccountName, {
147
+ location,
148
+ sku: { name: 'Standard_LRS' },
149
+ kind: 'StorageV2',
150
+ allowBlobPublicAccess: false,
151
+ minimumTlsVersion: 'TLS1_2'
152
+ });
153
+ await poller.pollUntilDone();
154
+ await waitForDns(`${storageAccountName}.blob.core.windows.net`);
155
+ console.log(chalk_1.default.green(' ✓ State storage account created'));
156
+ }
157
+ else {
158
+ console.log(chalk_1.default.green(` ✓ State storage account already exists: ${storageAccountName}`));
159
+ }
160
+ const keys = await storageClient.storageAccounts.listKeys(resourceGroupName, storageAccountName);
161
+ const key = keys.keys?.[0]?.value;
162
+ if (!key) {
163
+ throw new Error(`Could not retrieve an access key for storage account "${storageAccountName}"`);
164
+ }
165
+ const blobServiceClient = new storage_blob_1.BlobServiceClient(`https://${storageAccountName}.blob.core.windows.net`, new storage_blob_1.StorageSharedKeyCredential(storageAccountName, key));
166
+ const containerClient = blobServiceClient.getContainerClient(containerName);
167
+ if (await containerClient.exists()) {
168
+ console.log(chalk_1.default.green(` ✓ State container already exists: ${containerName}`));
169
+ }
170
+ else {
171
+ console.log(chalk_1.default.cyan(` Creating state container: ${containerName}`));
172
+ await containerClient.create();
173
+ console.log(chalk_1.default.green(' ✓ State container created'));
174
+ }
175
+ }
176
+ /** Ensures the Key Vault that stores the fuel.yml infrastructure secret exists and grants the CLI's SP access to it. */
177
+ async function ensureBootstrapKeyVault(credentials, resourceGroupName, keyVaultName, location) {
178
+ const cred = credential(credentials);
179
+ const client = new arm_keyvault_1.KeyVaultManagementClient(cred, credentials.AZURE_SUBSCRIPTION_ID);
180
+ let exists = true;
181
+ try {
182
+ await client.vaults.get(resourceGroupName, keyVaultName);
183
+ }
184
+ catch (err) {
185
+ if (!isNotFound(err)) {
186
+ throw new Error(`Failed to check Key Vault "${keyVaultName}": ${err.message || err}`);
187
+ }
188
+ exists = false;
189
+ }
190
+ const objectId = await getServicePrincipalObjectId(cred, credentials.AZURE_CLIENT_ID);
191
+ if (exists) {
192
+ // A vault created outside this flow (or before this SP existed) may not grant it
193
+ // secret access yet. "add" merges/replaces just this principal's policy, leaving
194
+ // every other access policy on the vault untouched.
195
+ await client.vaults.updateAccessPolicy(resourceGroupName, keyVaultName, 'add', {
196
+ properties: {
197
+ accessPolicies: [
198
+ {
199
+ tenantId: credentials.AZURE_TENANT_ID,
200
+ objectId,
201
+ permissions: { secrets: ['Get', 'List', 'Set', 'Delete'] }
202
+ }
203
+ ]
204
+ }
205
+ });
206
+ console.log(chalk_1.default.green(` ✓ Key Vault already exists: ${keyVaultName}`));
207
+ return;
208
+ }
209
+ console.log(chalk_1.default.cyan(` Creating Key Vault: ${keyVaultName}`));
210
+ const poller = await client.vaults.beginCreateOrUpdate(resourceGroupName, keyVaultName, {
211
+ location,
212
+ properties: {
213
+ tenantId: credentials.AZURE_TENANT_ID,
214
+ sku: { family: 'A', name: 'standard' },
215
+ enableRbacAuthorization: false,
216
+ accessPolicies: [
217
+ {
218
+ tenantId: credentials.AZURE_TENANT_ID,
219
+ objectId,
220
+ permissions: { secrets: ['Get', 'List', 'Set', 'Delete'] }
221
+ }
222
+ ]
223
+ }
224
+ });
225
+ await poller.pollUntilDone();
226
+ await waitForDns(`${keyVaultName}.vault.azure.net`);
227
+ console.log(chalk_1.default.green(' ✓ Key Vault created'));
228
+ }
229
+ //# sourceMappingURL=azure-state-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-state-storage.js","sourceRoot":"","sources":["../../src/infra/azure-state-storage.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/infra/config-loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,WAAW,EAAE,MAAM,SAAS,CAAA;AAExD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAS1D;AAUD,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAM9E"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/infra/config-loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,WAAW,EAAE,MAAM,SAAS,CAAA;AAExD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAS1D;AAUD,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,CAMtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/infra/config-loader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,4CASC;AAUD,0CAMC;AA7BD,6CAA8B;AAC9B,2CAA4B;AAC5B,mCAAwD;AAExD,SAAgB,gBAAgB,CAAC,GAAY;IAC3C,MAAM,MAAM,GAAG,yBAAiB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aACjC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;aAC7D,IAAI,CAAC,IAAI,CAAC,CAAA;QACb,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAA;AACpB,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,UAAkB;IAC9C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IACtD,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,UAAkB;IACtD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAA;IACzD,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,CAAA;IAC5C,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAA;AAC9B,CAAC"}
1
+ {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/infra/config-loader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,4CASC;AAUD,0CAQC;AA/BD,6CAA8B;AAC9B,2CAA4B;AAC5B,mCAAwD;AAExD,SAAgB,gBAAgB,CAAC,GAAY;IAC3C,MAAM,MAAM,GAAG,yBAAiB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aACjC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;aAC7D,IAAI,CAAC,IAAI,CAAC,CAAA;QACb,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAA;AACpB,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,UAAkB;IAC9C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IACtD,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC;AAEM,KAAK,UAAU,eAAe,CACnC,UAAkB;IAElB,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAA;IACzD,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,CAAA;IAC5C,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAA;AAC9B,CAAC"}
@@ -45,7 +45,7 @@ function generateSeed() {
45
45
  async function writeFuelYml(projectRoot, config, projectName) {
46
46
  const output = {
47
47
  ...config,
48
- ...(projectName ? { name: projectName } : {}),
48
+ ...(projectName ? { name: projectName } : {})
49
49
  };
50
50
  await fs.writeFile(path.join(projectRoot, 'fuel.yml'), YAML.stringify(output), 'utf-8');
51
51
  }
@@ -1,4 +1,4 @@
1
- import { Credentials, CredentialKey } from './types';
1
+ import { Credentials, CredentialKey, Deployment } from './types';
2
2
  /**
3
3
  * Resolve credentials by merging sources in priority order:
4
4
  * 1. CLI flag overrides (highest)
@@ -7,5 +7,5 @@ import { Credentials, CredentialKey } from './types';
7
7
  *
8
8
  * Sources are merged per-key — e.g., AWS keys from env + GITHUB_TOKEN from file = valid.
9
9
  */
10
- export declare function resolveCredentials(searchDir?: string, overrides?: Partial<Record<CredentialKey, string>>): Promise<Credentials>;
10
+ export declare function resolveCredentials(searchDir?: string, overrides?: Partial<Record<CredentialKey, string>>, deployment?: Deployment): Promise<Credentials>;
11
11
  //# sourceMappingURL=credentials.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/infra/credentials.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAA4B,aAAa,EAAE,MAAM,SAAS,CAAA;AAgB9E;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,GACjD,OAAO,CAAC,WAAW,CAAC,CAkCtB"}
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/infra/credentials.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EAEX,aAAa,EACb,UAAU,EAEX,MAAM,SAAS,CAAA;AAkBhB;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,EAClD,UAAU,GAAE,UAAkB,GAC7B,OAAO,CAAC,WAAW,CAAC,CAqCtB"}
@@ -61,7 +61,8 @@ async function tryReadCredentialsFile(credPath) {
61
61
  *
62
62
  * Sources are merged per-key — e.g., AWS keys from env + GITHUB_TOKEN from file = valid.
63
63
  */
64
- async function resolveCredentials(searchDir, overrides) {
64
+ async function resolveCredentials(searchDir, overrides, deployment = 'ecs') {
65
+ const requiredKeys = (0, types_1.requiredCredentialKeysFor)(deployment);
65
66
  // Collect file values from searchDir and CWD
66
67
  const credPath = searchDir
67
68
  ? path.join(searchDir, '.fuel-credentials')
@@ -83,10 +84,13 @@ async function resolveCredentials(searchDir, overrides) {
83
84
  process.env[key] ||
84
85
  undefined;
85
86
  }
86
- const missing = types_1.REQUIRED_CREDENTIAL_KEYS.filter((k) => !resolved[k]);
87
+ const missing = requiredKeys.filter((k) => !resolved[k]);
87
88
  if (missing.length > 0) {
88
- throw new Error(`Missing credentials: ${missing.join(', ')}\n` +
89
- `Provide them via CLI flags, .fuel-credentials file, or environment variables.`);
89
+ const missingGitHubOnly = missing.every((k) => k.startsWith('GITHUB_'));
90
+ const hint = missingGitHubOnly
91
+ ? 'Run "fuel auth:init" to set up GitHub credentials interactively (guides you to a token with the right permissions), or provide them via CLI flags, .fuel-credentials, or environment variables.'
92
+ : 'Provide them via CLI flags, .fuel-credentials file, or environment variables.';
93
+ throw new Error(`Missing credentials: ${missing.join(', ')}\n${hint}`);
90
94
  }
91
95
  return resolved;
92
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/infra/credentials.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,gDAqCC;AA/DD,2CAA4B;AAC5B,6CAA8B;AAC9B,mCAA8E;AAE9E,KAAK,UAAU,sBAAsB,CAAC,QAAgB;IACpD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,EAAE,CAAA;IAC/C,IAAI,CAAC;QACH,MAAM,IAAI,GAA2B,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAChE,MAAM,MAAM,GAA2C,EAAE,CAAA;QACzD,KAAK,MAAM,GAAG,IAAI,gCAAwB,EAAE,CAAC;YAC3C,IAAI,IAAI,CAAC,GAAG,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QACxC,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,kBAAkB,CACtC,SAAkB,EAClB,SAAkD;IAElD,6CAA6C;IAC7C,MAAM,QAAQ,GAAG,SAAS;QACxB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC;QAC3C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACrC,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,QAAQ,CAAC,CAAA;IAEzD,wDAAwD;IACxD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,IAAI,SAAS,GAA2C,EAAE,CAAA;IAC1D,IAAI,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,GAAG,EAAE,CAAC;QACjD,SAAS,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAC7E,CAAC;IAED,iEAAiE;IACjE,MAAM,QAAQ,GAA2C,EAAE,CAAA;IAC3D,KAAK,MAAM,GAAG,IAAI,gCAAwB,EAAE,CAAC;QAC3C,QAAQ,CAAC,GAAG,CAAC;YACX,SAAS,EAAE,CAAC,GAAG,CAAC;gBAChB,UAAU,CAAC,GAAG,CAAC;gBACf,SAAS,CAAC,GAAG,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;gBAChB,SAAS,CAAA;IACb,CAAC;IAED,MAAM,OAAO,GAAG,gCAAwB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IACpE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,wBAAwB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAC5C,+EAA+E,CAClF,CAAA;IACH,CAAC;IAED,OAAO,QAAuB,CAAA;AAChC,CAAC"}
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/infra/credentials.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,gDAyCC;AA3ED,2CAA4B;AAC5B,6CAA8B;AAC9B,mCAMgB;AAEhB,KAAK,UAAU,sBAAsB,CACnC,QAAgB;IAEhB,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,EAAE,CAAA;IAC/C,IAAI,CAAC;QACH,MAAM,IAAI,GAA2B,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAChE,MAAM,MAAM,GAA2C,EAAE,CAAA;QACzD,KAAK,MAAM,GAAG,IAAI,gCAAwB,EAAE,CAAC;YAC3C,IAAI,IAAI,CAAC,GAAG,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QACxC,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,kBAAkB,CACtC,SAAkB,EAClB,SAAkD,EAClD,aAAyB,KAAK;IAE9B,MAAM,YAAY,GAAG,IAAA,iCAAyB,EAAC,UAAU,CAAC,CAAA;IAE1D,6CAA6C;IAC7C,MAAM,QAAQ,GAAG,SAAS;QACxB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC;QAC3C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACrC,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,QAAQ,CAAC,CAAA;IAEzD,wDAAwD;IACxD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,IAAI,SAAS,GAA2C,EAAE,CAAA;IAC1D,IAAI,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,GAAG,EAAE,CAAC;QACjD,SAAS,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAC7E,CAAC;IAED,iEAAiE;IACjE,MAAM,QAAQ,GAA2C,EAAE,CAAA;IAC3D,KAAK,MAAM,GAAG,IAAI,gCAAwB,EAAE,CAAC;QAC3C,QAAQ,CAAC,GAAG,CAAC;YACX,SAAS,EAAE,CAAC,GAAG,CAAC;gBAChB,UAAU,CAAC,GAAG,CAAC;gBACf,SAAS,CAAC,GAAG,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;gBAChB,SAAS,CAAA;IACb,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IACxD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAA;QACvE,MAAM,IAAI,GAAG,iBAAiB;YAC5B,CAAC,CAAC,iMAAiM;YACnM,CAAC,CAAC,+EAA+E,CAAA;QACnF,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;IACxE,CAAC;IAED,OAAO,QAAuB,CAAA;AAChC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"dependency-checker.d.ts","sourceRoot":"","sources":["../../src/infra/dependency-checker.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,gBAAgB,CAAA;AAEhE,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,cAAc,CAAA;CAC/B;AAaD,eAAO,MAAM,oBAAoB,QAAO,cAMvC,CAAA;AAED,eAAO,MAAM,wBAAwB,QAAO,IAM3C,CAAA;AAED,eAAO,MAAM,yBAAyB,QAAO,IAM5C,CAAA;AAED,eAAO,MAAM,wBAAwB,QAAO,sBAK3C,CAAA"}
1
+ {"version":3,"file":"dependency-checker.d.ts","sourceRoot":"","sources":["../../src/infra/dependency-checker.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,gBAAgB,CAAA;AAEhE,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,cAAc,CAAA;CAC/B;AAeD,eAAO,MAAM,oBAAoB,QAAO,cAMvC,CAAA;AAED,eAAO,MAAM,wBAAwB,QAAO,IAM3C,CAAA;AAED,eAAO,MAAM,yBAAyB,QAAO,IAM5C,CAAA;AAED,eAAO,MAAM,wBAAwB,QAAO,sBAK3C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"dependency-checker.js","sourceRoot":"","sources":["../../src/infra/dependency-checker.ts"],"names":[],"mappings":";;;AAAA,iDAAwC;AAQxC,MAAM,GAAG,GAAG,CAAC,OAAe,EAAU,EAAE,CACtC,IAAA,wBAAQ,EAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;AAE7E,MAAM,MAAM,GAAG,CAAC,OAAe,EAAgD,EAAE;IAC/E,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAA;IACtB,CAAC;AACH,CAAC,CAAA;AAEM,MAAM,oBAAoB,GAAG,GAAmB,EAAE;IACvD,IAAI,MAAM,CAAC,wBAAwB,CAAC,CAAC,EAAE;QAAE,OAAO,gBAAgB,CAAA;IAChE,IAAI,MAAM,CAAC,0BAA0B,CAAC,CAAC,EAAE;QAAE,OAAO,gBAAgB,CAAA;IAClE,MAAM,IAAI,KAAK,CACb,4HAA4H,CAC7H,CAAA;AACH,CAAC,CAAA;AANY,QAAA,oBAAoB,wBAMhC;AAEM,MAAM,wBAAwB,GAAG,GAAS,EAAE;IACjD,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AANY,QAAA,wBAAwB,4BAMpC;AAEM,MAAM,yBAAyB,GAAG,GAAS,EAAE;IAClD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,4FAA4F,CAC7F,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AANY,QAAA,yBAAyB,6BAMrC;AAEM,MAAM,wBAAwB,GAAG,GAA2B,EAAE;IACnE,IAAA,gCAAwB,GAAE,CAAA;IAC1B,IAAA,iCAAyB,GAAE,CAAA;IAC3B,MAAM,cAAc,GAAG,IAAA,4BAAoB,GAAE,CAAA;IAC7C,OAAO,EAAE,cAAc,EAAE,CAAA;AAC3B,CAAC,CAAA;AALY,QAAA,wBAAwB,4BAKpC"}
1
+ {"version":3,"file":"dependency-checker.js","sourceRoot":"","sources":["../../src/infra/dependency-checker.ts"],"names":[],"mappings":";;;AAAA,iDAAwC;AAQxC,MAAM,GAAG,GAAG,CAAC,OAAe,EAAU,EAAE,CACtC,IAAA,wBAAQ,EAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;AAE7E,MAAM,MAAM,GAAG,CACb,OAAe,EAC+B,EAAE;IAChD,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAA;IACtB,CAAC;AACH,CAAC,CAAA;AAEM,MAAM,oBAAoB,GAAG,GAAmB,EAAE;IACvD,IAAI,MAAM,CAAC,wBAAwB,CAAC,CAAC,EAAE;QAAE,OAAO,gBAAgB,CAAA;IAChE,IAAI,MAAM,CAAC,0BAA0B,CAAC,CAAC,EAAE;QAAE,OAAO,gBAAgB,CAAA;IAClE,MAAM,IAAI,KAAK,CACb,4HAA4H,CAC7H,CAAA;AACH,CAAC,CAAA;AANY,QAAA,oBAAoB,wBAMhC;AAEM,MAAM,wBAAwB,GAAG,GAAS,EAAE;IACjD,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AANY,QAAA,wBAAwB,4BAMpC;AAEM,MAAM,yBAAyB,GAAG,GAAS,EAAE;IAClD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,4FAA4F,CAC7F,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AANY,QAAA,yBAAyB,6BAMrC;AAEM,MAAM,wBAAwB,GAAG,GAA2B,EAAE;IACnE,IAAA,gCAAwB,GAAE,CAAA;IAC1B,IAAA,iCAAyB,GAAE,CAAA;IAC3B,MAAM,cAAc,GAAG,IAAA,4BAAoB,GAAE,CAAA;IAC7C,OAAO,EAAE,cAAc,EAAE,CAAA;AAC3B,CAAC,CAAA;AALY,QAAA,wBAAwB,4BAKpC"}
@@ -0,0 +1,9 @@
1
+ import { Deployment } from './types';
2
+ /**
3
+ * Infers the deployment provider from an already-generated /infra folder,
4
+ * for flows that need it before fuel.yml/the remote secret has been read
5
+ * (e.g. `--tofu-only`, `infra:pull`). Based on which provider block
6
+ * providers.tf declares.
7
+ */
8
+ export declare function detectDeploymentFromInfraDir(infraDir: string): Promise<Deployment>;
9
+ //# sourceMappingURL=deployment-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-detect.d.ts","sourceRoot":"","sources":["../../src/infra/deployment-detect.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEpC;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC,CAOrB"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.detectDeploymentFromInfraDir = detectDeploymentFromInfraDir;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs-extra"));
39
+ /**
40
+ * Infers the deployment provider from an already-generated /infra folder,
41
+ * for flows that need it before fuel.yml/the remote secret has been read
42
+ * (e.g. `--tofu-only`, `infra:pull`). Based on which provider block
43
+ * providers.tf declares.
44
+ */
45
+ async function detectDeploymentFromInfraDir(infraDir) {
46
+ const providersPath = path.join(infraDir, 'providers.tf');
47
+ if (!(await fs.pathExists(providersPath))) {
48
+ return 'ecs';
49
+ }
50
+ const content = await fs.readFile(providersPath, 'utf-8');
51
+ return content.includes('azurerm') ? 'azure' : 'ecs';
52
+ }
53
+ //# sourceMappingURL=deployment-detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-detect.js","sourceRoot":"","sources":["../../src/infra/deployment-detect.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,oEASC;AAnBD,2CAA4B;AAC5B,6CAA8B;AAG9B;;;;;GAKG;AACI,KAAK,UAAU,4BAA4B,CAChD,QAAgB;IAEhB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;IACzD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;IACzD,OAAO,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;AACtD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"git-client.d.ts","sourceRoot":"","sources":["../../src/infra/git-client.ts"],"names":[],"mappings":"AAgCA,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWtF;AAED,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAarF;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,IAAI,CAAC,CAoCf"}
1
+ {"version":3,"file":"git-client.d.ts","sourceRoot":"","sources":["../../src/infra/git-client.ts"],"names":[],"mappings":"AAgCA,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAqBlB;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,IAAI,CAAC,CAmCf"}
@@ -52,17 +52,13 @@ async function pushToRemote(projectDir, githubToken, branches, forcePush) {
52
52
  await spawnSimple('git', ['remote', 'set-url', 'origin', authUrl], projectDir);
53
53
  try {
54
54
  for (const branch of branches) {
55
- // Create local branch if it doesn't exist (non-main branches)
56
- const branchCheck = await spawnQuiet('git', ['rev-parse', '--verify', branch], projectDir);
57
- if (branchCheck.code !== 0) {
58
- const createResult = await spawnSimple('git', ['branch', branch], projectDir);
59
- if (createResult.code !== 0) {
60
- throw new Error(`Failed to create local branch: ${branch}`);
61
- }
62
- }
55
+ // Push the current HEAD directly to the remote branch via an explicit
56
+ // refspec (HEAD:<branch>). This avoids depending on a local branch ref —
57
+ // which would not advance between successive pushes — so the second push
58
+ // of a two-phase deploy lands as a clean fast-forward on the remote.
63
59
  const pushArgs = forcePush
64
- ? ['push', '--force', '-u', 'origin', branch]
65
- : ['push', '-u', 'origin', branch];
60
+ ? ['push', '--force', '-u', 'origin', `HEAD:${branch}`]
61
+ : ['push', '-u', 'origin', `HEAD:${branch}`];
66
62
  const pushResult = await spawnSimple('git', pushArgs, projectDir);
67
63
  if (pushResult.code !== 0) {
68
64
  throw new Error(`Failed to push branch: ${branch}`);