@swovohq/fuel 0.2.0-alpha.3 → 0.2.0-alpha.30

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 (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +231 -0
  3. package/dist/bin/fuel.js +150 -55
  4. package/dist/bin/fuel.js.map +1 -1
  5. package/dist/commands/config-verify.d.ts +4 -0
  6. package/dist/commands/config-verify.d.ts.map +1 -0
  7. package/dist/commands/config-verify.js +66 -0
  8. package/dist/commands/config-verify.js.map +1 -0
  9. package/dist/commands/create-app.d.ts +7 -2
  10. package/dist/commands/create-app.d.ts.map +1 -1
  11. package/dist/commands/create-app.js +84 -49
  12. package/dist/commands/create-app.js.map +1 -1
  13. package/dist/commands/infra-deploy.d.ts +5 -0
  14. package/dist/commands/infra-deploy.d.ts.map +1 -1
  15. package/dist/commands/infra-deploy.js +59 -15
  16. package/dist/commands/infra-deploy.js.map +1 -1
  17. package/dist/commands/infra-destroy.d.ts +2 -0
  18. package/dist/commands/infra-destroy.d.ts.map +1 -1
  19. package/dist/commands/infra-destroy.js +5 -6
  20. package/dist/commands/infra-destroy.js.map +1 -1
  21. package/dist/commands/infra-init.d.ts +1 -0
  22. package/dist/commands/infra-init.d.ts.map +1 -1
  23. package/dist/commands/infra-init.js +99 -14
  24. package/dist/commands/infra-init.js.map +1 -1
  25. package/dist/commands/migrate-init.d.ts.map +1 -1
  26. package/dist/commands/migrate-init.js +28 -12
  27. package/dist/commands/migrate-init.js.map +1 -1
  28. package/dist/engines/template-source.d.ts.map +1 -1
  29. package/dist/engines/template-source.js +14 -1
  30. package/dist/engines/template-source.js.map +1 -1
  31. package/dist/infra/config-loader.d.ts.map +1 -1
  32. package/dist/infra/config-loader.js +10 -2
  33. package/dist/infra/config-loader.js.map +1 -1
  34. package/dist/infra/config-writer.d.ts +2 -7
  35. package/dist/infra/config-writer.d.ts.map +1 -1
  36. package/dist/infra/config-writer.js +5 -11
  37. package/dist/infra/config-writer.js.map +1 -1
  38. package/dist/infra/credentials.d.ts +10 -2
  39. package/dist/infra/credentials.d.ts.map +1 -1
  40. package/dist/infra/credentials.js +44 -25
  41. package/dist/infra/credentials.js.map +1 -1
  42. package/dist/infra/git-client.d.ts +2 -0
  43. package/dist/infra/git-client.d.ts.map +1 -1
  44. package/dist/infra/git-client.js +56 -2
  45. package/dist/infra/git-client.js.map +1 -1
  46. package/dist/infra/github-client.d.ts +6 -0
  47. package/dist/infra/github-client.d.ts.map +1 -0
  48. package/dist/infra/github-client.js +36 -0
  49. package/dist/infra/github-client.js.map +1 -0
  50. package/dist/infra/orchestrator.d.ts +5 -2
  51. package/dist/infra/orchestrator.d.ts.map +1 -1
  52. package/dist/infra/orchestrator.js +96 -68
  53. package/dist/infra/orchestrator.js.map +1 -1
  54. package/dist/infra/port-utils.d.ts +4 -0
  55. package/dist/infra/port-utils.d.ts.map +1 -0
  56. package/dist/infra/port-utils.js +77 -0
  57. package/dist/infra/port-utils.js.map +1 -0
  58. package/dist/infra/preflight.d.ts +1 -1
  59. package/dist/infra/preflight.d.ts.map +1 -1
  60. package/dist/infra/preflight.js +4 -4
  61. package/dist/infra/preflight.js.map +1 -1
  62. package/dist/infra/s3-state-bucket.d.ts +1 -1
  63. package/dist/infra/s3-state-bucket.d.ts.map +1 -1
  64. package/dist/infra/s3-state-bucket.js +21 -26
  65. package/dist/infra/s3-state-bucket.js.map +1 -1
  66. package/dist/infra/secrets-manager-client.d.ts.map +1 -1
  67. package/dist/infra/secrets-manager-client.js +35 -1
  68. package/dist/infra/secrets-manager-client.js.map +1 -1
  69. package/dist/infra/template-engine.d.ts +1 -1
  70. package/dist/infra/template-engine.d.ts.map +1 -1
  71. package/dist/infra/template-engine.js +16 -29
  72. package/dist/infra/template-engine.js.map +1 -1
  73. package/dist/infra/tofu-runner.d.ts +5 -8
  74. package/dist/infra/tofu-runner.d.ts.map +1 -1
  75. package/dist/infra/tofu-runner.js +42 -80
  76. package/dist/infra/tofu-runner.js.map +1 -1
  77. package/package.json +6 -2
  78. package/schema/fuel.schema.json +158 -0
@@ -1,9 +1,4 @@
1
- import { InfraConfig, Credentials } from './types';
2
- export interface FuelConfig extends InfraConfig {
3
- seed: string;
4
- aws_region?: string;
5
- github_org?: string;
6
- }
1
+ import { InfraConfig } from './types';
7
2
  export declare function generateSeed(): string;
8
- export declare function writeFuelConfig(projectRoot: string, config: InfraConfig, projectName?: string, existingSeed?: string, credentials?: Credentials): Promise<FuelConfig>;
3
+ export declare function writeFuelYml(projectRoot: string, config: InfraConfig, projectName?: string): Promise<void>;
9
4
  //# sourceMappingURL=config-writer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-writer.d.ts","sourceRoot":"","sources":["../../src/infra/config-writer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAElD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,UAAU,CAAC,CAiBrB"}
1
+ {"version":3,"file":"config-writer.d.ts","sourceRoot":"","sources":["../../src/infra/config-writer.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAErC,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf"}
@@ -34,25 +34,19 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.generateSeed = generateSeed;
37
- exports.writeFuelConfig = writeFuelConfig;
37
+ exports.writeFuelYml = writeFuelYml;
38
38
  const fs = __importStar(require("fs-extra"));
39
39
  const path = __importStar(require("path"));
40
40
  const crypto = __importStar(require("crypto"));
41
+ const YAML = __importStar(require("yaml"));
41
42
  function generateSeed() {
42
43
  return crypto.randomBytes(12).toString('hex'); // 24 hex chars
43
44
  }
44
- async function writeFuelConfig(projectRoot, config, projectName, existingSeed, credentials) {
45
- const seed = existingSeed ?? generateSeed();
46
- const fuelConfig = {
45
+ async function writeFuelYml(projectRoot, config, projectName) {
46
+ const output = {
47
47
  ...config,
48
48
  ...(projectName ? { name: projectName } : {}),
49
- seed,
50
- ...(credentials ? {
51
- aws_region: credentials.AWS_REGION,
52
- github_org: credentials.GITHUB_ORGANIZATION,
53
- } : {}),
54
49
  };
55
- await fs.writeJson(path.join(projectRoot, 'fuel.config.json'), fuelConfig, { spaces: 2 });
56
- return fuelConfig;
50
+ await fs.writeFile(path.join(projectRoot, 'fuel.yml'), YAML.stringify(output), 'utf-8');
57
51
  }
58
52
  //# sourceMappingURL=config-writer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-writer.js","sourceRoot":"","sources":["../../src/infra/config-writer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,oCAEC;AAED,0CAuBC;AAtCD,6CAA8B;AAC9B,2CAA4B;AAC5B,+CAAgC;AAShC,SAAgB,YAAY;IAC1B,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA,CAAC,eAAe;AAC/D,CAAC;AAEM,KAAK,UAAU,eAAe,CACnC,WAAmB,EACnB,MAAmB,EACnB,WAAoB,EACpB,YAAqB,EACrB,WAAyB;IAEzB,MAAM,IAAI,GAAG,YAAY,IAAI,YAAY,EAAE,CAAA;IAC3C,MAAM,UAAU,GAAe;QAC7B,GAAG,MAAM;QACT,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,IAAI;QACJ,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;YAChB,UAAU,EAAE,WAAW,CAAC,UAAU;YAClC,UAAU,EAAE,WAAW,CAAC,mBAAmB;SAC5C,CAAC,CAAC,CAAC,EAAE,CAAC;KACR,CAAA;IACD,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,EAC1C,UAAU,EACV,EAAE,MAAM,EAAE,CAAC,EAAE,CACd,CAAA;IACD,OAAO,UAAU,CAAA;AACnB,CAAC"}
1
+ {"version":3,"file":"config-writer.js","sourceRoot":"","sources":["../../src/infra/config-writer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,oCAEC;AAED,oCAcC;AAxBD,6CAA8B;AAC9B,2CAA4B;AAC5B,+CAAgC;AAChC,2CAA4B;AAG5B,SAAgB,YAAY;IAC1B,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA,CAAC,eAAe;AAC/D,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,WAAmB,EACnB,MAAmB,EACnB,WAAoB;IAEpB,MAAM,MAAM,GAAgB;QAC1B,GAAG,MAAM;QACT,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9C,CAAA;IACD,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,EAClC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EACtB,OAAO,CACR,CAAA;AACH,CAAC"}
@@ -1,3 +1,11 @@
1
- import { Credentials } from './types';
2
- export declare function resolveCredentials(searchDir?: string): Promise<Credentials>;
1
+ import { Credentials, CredentialKey } from './types';
2
+ /**
3
+ * Resolve credentials by merging sources in priority order:
4
+ * 1. CLI flag overrides (highest)
5
+ * 2. .fuel-credentials file (searchDir, then CWD fallback)
6
+ * 3. Environment variables (lowest)
7
+ *
8
+ * Sources are merged per-key — e.g., AWS keys from env + GITHUB_TOKEN from file = valid.
9
+ */
10
+ export declare function resolveCredentials(searchDir?: string, overrides?: Partial<Record<CredentialKey, string>>): Promise<Credentials>;
3
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,EAA2C,MAAM,SAAS,CAAA;AAe9E,wBAAsB,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAmCjF"}
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"}
@@ -37,38 +37,57 @@ exports.resolveCredentials = resolveCredentials;
37
37
  const path = __importStar(require("path"));
38
38
  const fs = __importStar(require("fs-extra"));
39
39
  const types_1 = require("./types");
40
- async function readCredentialsFile(credPath) {
41
- const file = await fs.readJson(credPath);
42
- const missing = types_1.REQUIRED_CREDENTIAL_KEYS.filter((k) => !file[k]);
43
- if (missing.length > 0) {
44
- throw new Error(`Missing keys in .fuel-credentials: ${missing.join(', ')}`);
40
+ async function tryReadCredentialsFile(credPath) {
41
+ if (!(await fs.pathExists(credPath)))
42
+ return {};
43
+ try {
44
+ const file = await fs.readJson(credPath);
45
+ const result = {};
46
+ for (const key of types_1.REQUIRED_CREDENTIAL_KEYS) {
47
+ if (file[key])
48
+ result[key] = file[key];
49
+ }
50
+ return result;
45
51
  }
46
- return Object.fromEntries(types_1.REQUIRED_CREDENTIAL_KEYS.map((k) => [k, file[k]]));
47
- }
48
- async function resolveCredentials(searchDir) {
49
- // Priority 1: ALL keys present in env
50
- const envValues = types_1.REQUIRED_CREDENTIAL_KEYS.map((k) => process.env[k]);
51
- if (envValues.every(Boolean)) {
52
- return Object.fromEntries(types_1.REQUIRED_CREDENTIAL_KEYS.map((k, i) => [k, envValues[i]]));
52
+ catch {
53
+ return {};
53
54
  }
54
- // Priority 2: .fuel-credentials JSON file in searchDir (or CWD if no searchDir)
55
+ }
56
+ /**
57
+ * Resolve credentials by merging sources in priority order:
58
+ * 1. CLI flag overrides (highest)
59
+ * 2. .fuel-credentials file (searchDir, then CWD fallback)
60
+ * 3. Environment variables (lowest)
61
+ *
62
+ * Sources are merged per-key — e.g., AWS keys from env + GITHUB_TOKEN from file = valid.
63
+ */
64
+ async function resolveCredentials(searchDir, overrides) {
65
+ // Collect file values from searchDir and CWD
55
66
  const credPath = searchDir
56
67
  ? path.join(searchDir, '.fuel-credentials')
57
68
  : path.resolve('.fuel-credentials');
58
- if (await fs.pathExists(credPath)) {
59
- return readCredentialsFile(credPath);
60
- }
61
- // Priority 3: fallback to CWD when searchDir was provided and differs from CWD
69
+ const fileValues = await tryReadCredentialsFile(credPath);
70
+ // Fallback to CWD if searchDir was provided and differs
62
71
  const cwd = process.cwd();
72
+ let cwdValues = {};
63
73
  if (searchDir && path.resolve(searchDir) !== cwd) {
64
- const cwdCredPath = path.resolve('.fuel-credentials');
65
- if (await fs.pathExists(cwdCredPath)) {
66
- return readCredentialsFile(cwdCredPath);
67
- }
74
+ cwdValues = await tryReadCredentialsFile(path.resolve('.fuel-credentials'));
75
+ }
76
+ // Merge per-key: overrides → file (searchDir) → file (CWD) → env
77
+ const resolved = {};
78
+ for (const key of types_1.REQUIRED_CREDENTIAL_KEYS) {
79
+ resolved[key] =
80
+ overrides?.[key] ||
81
+ fileValues[key] ||
82
+ cwdValues[key] ||
83
+ process.env[key] ||
84
+ undefined;
85
+ }
86
+ const missing = types_1.REQUIRED_CREDENTIAL_KEYS.filter((k) => !resolved[k]);
87
+ 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.`);
68
90
  }
69
- // Neither source complete
70
- const missingFromEnv = types_1.REQUIRED_CREDENTIAL_KEYS.filter((k) => !process.env[k]);
71
- throw new Error(`Credentials not found. Missing env vars: ${missingFromEnv.join(', ')}\n` +
72
- `Or create a .fuel-credentials JSON file with those keys.`);
91
+ return resolved;
73
92
  }
74
93
  //# sourceMappingURL=credentials.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/infra/credentials.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,gDAmCC;AApDD,2CAA4B;AAC5B,6CAA8B;AAC9B,mCAA8E;AAE9E,KAAK,UAAU,mBAAmB,CAAC,QAAgB;IACjD,MAAM,IAAI,GAA2B,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAChE,MAAM,OAAO,GAAG,gCAAwB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAChE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,sCAAsC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3D,CAAA;IACH,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CACvB,gCAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CACnC,CAAA;AAClB,CAAC;AAEM,KAAK,UAAU,kBAAkB,CAAC,SAAkB;IACzD,sCAAsC;IACtC,MAAM,SAAS,GAAG,gCAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IACrE,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,WAAW,CACvB,gCAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAW,CAAC,CAAC,CACrD,CAAA;IAClB,CAAC;IAED,gFAAgF;IAChF,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;IAErC,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,mBAAmB,CAAC,QAAQ,CAAC,CAAA;IACtC,CAAC;IAED,+EAA+E;IAC/E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,IAAI,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,GAAG,EAAE,CAAC;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;QACrD,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACrC,OAAO,mBAAmB,CAAC,WAAW,CAAC,CAAA;QACzC,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,MAAM,cAAc,GAAG,gCAAwB,CAAC,MAAM,CACpD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CACvB,CAAA;IACD,MAAM,IAAI,KAAK,CACb,4CAA4C,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QACvE,0DAA0D,CAC7D,CAAA;AACH,CAAC"}
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,2 +1,4 @@
1
1
  export declare function wireGitRemote(projectDir: string, repoUrl: string): Promise<void>;
2
+ export declare function commitAll(projectDir: string, message: string): Promise<boolean>;
3
+ export declare function pushToRemote(projectDir: string, githubToken: string, branches: string[], forcePush?: boolean): Promise<void>;
2
4
  //# sourceMappingURL=git-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-client.d.ts","sourceRoot":"","sources":["../../src/infra/git-client.ts"],"names":[],"mappings":"AAeA,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUtF"}
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,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.wireGitRemote = wireGitRemote;
4
+ exports.commitAll = commitAll;
5
+ exports.pushToRemote = pushToRemote;
4
6
  const child_process_1 = require("child_process");
5
7
  function spawnSimple(cmd, args, cwd) {
6
8
  return new Promise((resolve) => {
@@ -10,13 +12,65 @@ function spawnSimple(cmd, args, cwd) {
10
12
  });
11
13
  });
12
14
  }
15
+ function spawnQuiet(cmd, args, cwd) {
16
+ return new Promise((resolve) => {
17
+ const proc = (0, child_process_1.spawn)(cmd, args, { cwd, stdio: ['pipe', 'pipe', 'pipe'] });
18
+ let stdout = '';
19
+ proc.stdout.on('data', (chunk) => {
20
+ stdout += chunk.toString();
21
+ });
22
+ proc.on('close', (code) => {
23
+ resolve({ code: code ?? 1, stdout: stdout.trim() });
24
+ });
25
+ });
26
+ }
13
27
  async function wireGitRemote(projectDir, repoUrl) {
14
- const setUrlResult = await spawnSimple('git', ['remote', 'set-url', 'origin', repoUrl], projectDir);
28
+ // Try set-url quietly it fails if origin doesn't exist yet
29
+ const setUrlResult = await spawnQuiet('git', ['remote', 'set-url', 'origin', repoUrl], projectDir);
15
30
  if (setUrlResult.code !== 0) {
16
- const addResult = await spawnSimple('git', ['remote', 'add', 'origin', repoUrl], projectDir);
31
+ const addResult = await spawnQuiet('git', ['remote', 'add', 'origin', repoUrl], projectDir);
17
32
  if (addResult.code !== 0) {
18
33
  throw new Error(`Failed to set git remote origin to ${repoUrl}`);
19
34
  }
20
35
  }
21
36
  }
37
+ async function commitAll(projectDir, message) {
38
+ await spawnSimple('git', ['add', '-A'], projectDir);
39
+ const diffResult = await spawnQuiet('git', ['diff', '--cached', '--quiet'], projectDir);
40
+ if (diffResult.code === 0) {
41
+ return false;
42
+ }
43
+ const commitResult = await spawnSimple('git', ['commit', '-m', message], projectDir);
44
+ if (commitResult.code !== 0) {
45
+ throw new Error(`Failed to commit: ${message}`);
46
+ }
47
+ return true;
48
+ }
49
+ async function pushToRemote(projectDir, githubToken, branches, forcePush) {
50
+ const { stdout: originalUrl } = await spawnQuiet('git', ['remote', 'get-url', 'origin'], projectDir);
51
+ const authUrl = originalUrl.replace('https://github.com/', `https://x-access-token:${githubToken}@github.com/`);
52
+ await spawnSimple('git', ['remote', 'set-url', 'origin', authUrl], projectDir);
53
+ try {
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
+ }
63
+ const pushArgs = forcePush
64
+ ? ['push', '--force', '-u', 'origin', branch]
65
+ : ['push', '-u', 'origin', branch];
66
+ const pushResult = await spawnSimple('git', pushArgs, projectDir);
67
+ if (pushResult.code !== 0) {
68
+ throw new Error(`Failed to push branch: ${branch}`);
69
+ }
70
+ }
71
+ }
72
+ finally {
73
+ await spawnSimple('git', ['remote', 'set-url', 'origin', originalUrl], projectDir);
74
+ }
75
+ }
22
76
  //# sourceMappingURL=git-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-client.js","sourceRoot":"","sources":["../../src/infra/git-client.ts"],"names":[],"mappings":";;AAeA,sCAUC;AAzBD,iDAAqC;AAErC,SAAS,WAAW,CAClB,GAAW,EACX,IAAc,EACd,GAAW;IAEX,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,IAAA,qBAAK,EAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;QACxD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAmB,EAAE,EAAE;YACvC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;QAC9B,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAEM,KAAK,UAAU,aAAa,CAAC,UAAkB,EAAE,OAAe;IACrE,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,CAAA;IAEnG,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,CAAA;QAE5F,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,OAAO,EAAE,CAAC,CAAA;QAClE,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"git-client.js","sourceRoot":"","sources":["../../src/infra/git-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function createGitHubRepo(token: string, org: string, name: string): Promise<{
2
+ name: string;
3
+ htmlUrl: string;
4
+ }>;
5
+ export declare function setBranchProtection(token: string, owner: string, repo: string, branch: string): Promise<void>;
6
+ //# sourceMappingURL=github-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-client.d.ts","sourceRoot":"","sources":["../../src/infra/github-client.ts"],"names":[],"mappings":"AAEA,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAY5C;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAmBf"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createGitHubRepo = createGitHubRepo;
4
+ exports.setBranchProtection = setBranchProtection;
5
+ const rest_1 = require("@octokit/rest");
6
+ async function createGitHubRepo(token, org, name) {
7
+ const octokit = new rest_1.Octokit({ auth: token });
8
+ const { data } = await octokit.rest.repos.createInOrg({
9
+ org,
10
+ name,
11
+ auto_init: false,
12
+ visibility: 'private',
13
+ description: 'FUEL Monorepo — generated by Fuel CLI',
14
+ });
15
+ return { name: data.name, htmlUrl: data.html_url };
16
+ }
17
+ async function setBranchProtection(token, owner, repo, branch) {
18
+ const octokit = new rest_1.Octokit({ auth: token });
19
+ await octokit.rest.repos.updateBranchProtection({
20
+ owner,
21
+ repo,
22
+ branch,
23
+ enforce_admins: false,
24
+ required_pull_request_reviews: {
25
+ required_approving_review_count: 1,
26
+ dismiss_stale_reviews: true,
27
+ },
28
+ required_status_checks: {
29
+ strict: true,
30
+ contexts: ['Title matches Jira Issue'],
31
+ },
32
+ restrictions: null,
33
+ allow_deletions: false,
34
+ });
35
+ }
36
+ //# sourceMappingURL=github-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-client.js","sourceRoot":"","sources":["../../src/infra/github-client.ts"],"names":[],"mappings":";;AAEA,4CAgBC;AAED,kDAwBC;AA5CD,wCAAuC;AAEhC,KAAK,UAAU,gBAAgB,CACpC,KAAa,EACb,GAAW,EACX,IAAY;IAEZ,MAAM,OAAO,GAAG,IAAI,cAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAE5C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QACpD,GAAG;QACH,IAAI;QACJ,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,uCAAuC;KACrD,CAAC,CAAA;IAEF,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAA;AACpD,CAAC;AAEM,KAAK,UAAU,mBAAmB,CACvC,KAAa,EACb,KAAa,EACb,IAAY,EACZ,MAAc;IAEd,MAAM,OAAO,GAAG,IAAI,cAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAE5C,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC;QAC9C,KAAK;QACL,IAAI;QACJ,MAAM;QACN,cAAc,EAAE,KAAK;QACrB,6BAA6B,EAAE;YAC7B,+BAA+B,EAAE,CAAC;YAClC,qBAAqB,EAAE,IAAI;SAC5B;QACD,sBAAsB,EAAE;YACtB,MAAM,EAAE,IAAI;YACZ,QAAQ,EAAE,CAAC,0BAA0B,CAAC;SACvC;QACD,YAAY,EAAE,IAAI;QAClB,eAAe,EAAE,KAAK;KACvB,CAAC,CAAA;AACJ,CAAC"}
@@ -1,7 +1,10 @@
1
1
  import { InfraConfig, Credentials } from './types';
2
2
  export interface OrchestratorOptions {
3
- skipCompensation?: boolean;
3
+ destroyOnFailure?: boolean;
4
4
  planOnly?: boolean;
5
+ targetBranch?: string;
6
+ forcePush?: boolean;
7
+ skipBranchProtection?: boolean;
5
8
  }
6
- export declare function runInfraOrchestrator(targetRoot: string, appName: string, config: InfraConfig, credentials: Credentials, options?: OrchestratorOptions): Promise<void>;
9
+ export declare function runInfraOrchestrator(targetRoot: string, _appName: string, config: InfraConfig, credentials: Credentials, options?: OrchestratorOptions): Promise<void>;
7
10
  //# sourceMappingURL=orchestrator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/infra/orchestrator.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AA8FlD,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA8Ef"}
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/infra/orchestrator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAqDlD,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA0Jf"}
@@ -37,48 +37,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.runInfraOrchestrator = runInfraOrchestrator;
40
- const crypto = __importStar(require("crypto"));
41
- const fs = __importStar(require("fs"));
42
40
  const path = __importStar(require("path"));
43
41
  const chalk_1 = __importDefault(require("chalk"));
44
42
  const tofu_runner_1 = require("./tofu-runner");
45
43
  const secrets_manager_client_1 = require("./secrets-manager-client");
44
+ const config_writer_1 = require("./config-writer");
46
45
  const git_client_1 = require("./git-client");
46
+ const github_client_1 = require("./github-client");
47
+ const github_secrets_client_1 = require("./github-secrets-client");
47
48
  const subprocess_1 = require("./subprocess");
48
49
  const s3_state_bucket_1 = require("./s3-state-bucket");
49
50
  function slugify(name) {
50
51
  return name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
51
52
  }
52
- function buildDestroyArgs(completedPasses, credentials, tofuVars) {
53
- const targets = [];
54
- if (completedPasses.includes(1)) {
55
- targets.push('-target=module.ecr', '-target=module.github_repo');
56
- }
57
- if (completedPasses.includes(2)) {
58
- targets.push('-target=module.github_actions');
59
- }
60
- return [
61
- 'destroy',
62
- '-var-file=default.tfvars',
63
- '-auto-approve',
64
- `-var=github_token=${credentials.GITHUB_TOKEN}`,
65
- `-var=github_username=${credentials.GITHUB_USERNAME}`,
66
- `-var=aws_access_key_id=${credentials.AWS_ACCESS_KEY_ID}`,
67
- `-var=aws_secret_access_key=${credentials.AWS_SECRET_ACCESS_KEY}`,
68
- `-var=aws_region=${credentials.AWS_REGION}`,
69
- `-var=github_organization=${credentials.GITHUB_ORGANIZATION}`,
70
- `-var=db_password=${tofuVars.db_password}`,
71
- `-var=db_username=${tofuVars.db_username}`,
72
- `-var=db_name=${tofuVars.db_name}`,
73
- `-var=skip_ecs=true`,
74
- ...targets,
75
- ];
76
- }
77
- async function runCompensation(infraDir, credentials, tofuVars, completedPasses) {
78
- if (completedPasses.length === 0)
79
- return;
80
- console.log(chalk_1.default.red('\n--- Cleaning up partial resources ---'));
81
- const args = buildDestroyArgs(completedPasses, credentials, tofuVars);
53
+ async function runCompensation(infraDir, credentials, tofuVars) {
54
+ console.log(chalk_1.default.red('\n--- Cleaning up AWS resources ---'));
55
+ const args = (0, tofu_runner_1.buildDestroyArgs)(credentials, tofuVars);
82
56
  const awsEnv = {
83
57
  AWS_ACCESS_KEY_ID: credentials.AWS_ACCESS_KEY_ID,
84
58
  AWS_SECRET_ACCESS_KEY: credentials.AWS_SECRET_ACCESS_KEY,
@@ -86,19 +60,12 @@ async function runCompensation(infraDir, credentials, tofuVars, completedPasses)
86
60
  };
87
61
  const { code } = await (0, subprocess_1.spawnStreaming)(args, infraDir, awsEnv);
88
62
  if (code !== 0) {
89
- console.error(chalk_1.default.red('Compensation destroy failed. Manually delete these resources:'));
90
- if (completedPasses.includes(1)) {
91
- console.error(chalk_1.default.red(' - ECR repository (module.ecr)'));
92
- console.error(chalk_1.default.red(' - GitHub repository (module.github_repo)'));
93
- }
94
- if (completedPasses.includes(2)) {
95
- console.error(chalk_1.default.red(' - GitHub Actions config (module.github_actions)'));
96
- }
63
+ console.error(chalk_1.default.red('Compensation destroy failed. Manually delete AWS resources.'));
97
64
  process.exit(1);
98
65
  }
99
- console.log(chalk_1.default.green('Partial resources cleaned up'));
66
+ console.log(chalk_1.default.green('AWS resources cleaned up'));
100
67
  }
101
- function printOutputTable(albDns, ecrUrl, githubRepoUrl, dbUsername, dbPassword) {
68
+ function printOutputTable(albDns, ecrUrl, githubRepoUrl) {
102
69
  const divider = chalk_1.default.gray('─'.repeat(60));
103
70
  console.log('\n' + divider);
104
71
  console.log(chalk_1.default.bold(' Deployment Complete'));
@@ -106,76 +73,137 @@ function printOutputTable(albDns, ecrUrl, githubRepoUrl, dbUsername, dbPassword)
106
73
  console.log(` ${chalk_1.default.dim('ALB DNS')} ${albDns}`);
107
74
  console.log(` ${chalk_1.default.dim('ECR URL')} ${ecrUrl}`);
108
75
  console.log(` ${chalk_1.default.dim('GitHub Repo')} ${githubRepoUrl}`);
109
- console.log(` ${chalk_1.default.dim('DB Username')} ${dbUsername}`);
110
- console.log(` ${chalk_1.default.dim('DB Password')} ${dbPassword} ${chalk_1.default.yellow("Save these — they won't be shown again")}`);
111
76
  console.log(divider);
112
77
  console.log(chalk_1.default.cyan('\n Next steps:'));
113
- console.log(' Push to main to trigger your first deploy.\n');
78
+ console.log(' Your code has been pushed. Your first deploy will start shortly.\n');
114
79
  }
115
- async function runInfraOrchestrator(targetRoot, appName, config, credentials, options) {
80
+ async function runInfraOrchestrator(targetRoot, _appName, config, credentials, options) {
116
81
  const infraDir = path.join(targetRoot, 'infra');
82
+ const repoName = `${config.name}-monorepo`;
117
83
  // Generate TofuVars
118
84
  const tofuVars = {
119
- db_password: crypto.randomBytes(32).toString('hex'),
120
85
  db_username: slugify(config.name),
121
86
  db_name: slugify(config.name),
87
+ github_repo_name: repoName,
122
88
  };
123
89
  // Ensure S3 state bucket exists (before Tofu init)
124
90
  console.log(chalk_1.default.cyan('--- Ensuring state bucket exists ---'));
125
- const suffix = await (0, s3_state_bucket_1.loadOrCreateSuffix)(targetRoot);
91
+ const suffix = (0, s3_state_bucket_1.deriveSuffix)(config.name);
126
92
  const bucketName = (0, s3_state_bucket_1.buildStateBucketName)(config.name, suffix);
127
93
  await (0, s3_state_bucket_1.ensureStateBucket)(credentials, bucketName);
128
94
  // Write secret to AWS Secrets Manager (before Tofu — Tofu reads it via data.tf)
129
95
  const secretName = `${config.name}-infrastructure-variables`;
130
- const fuelConfigPath = path.join(targetRoot, 'fuel.config.json');
131
- const fuelConfigContents = JSON.parse(fs.readFileSync(fuelConfigPath, 'utf-8'));
96
+ const secretPayload = {
97
+ ...config,
98
+ seed: (0, config_writer_1.generateSeed)(),
99
+ aws_region: credentials.AWS_REGION,
100
+ github_org: credentials.GITHUB_ORGANIZATION,
101
+ };
132
102
  console.log(chalk_1.default.cyan('--- Writing infrastructure secret ---'));
133
- await (0, secrets_manager_client_1.putSecret)(credentials, secretName, fuelConfigContents);
103
+ await (0, secrets_manager_client_1.putSecret)(credentials, secretName, secretPayload);
134
104
  console.log(chalk_1.default.green('Secret written to AWS Secrets Manager'));
135
105
  // SIGINT compensation setup
136
- const state = { tofuStarted: false, completedPasses: [] };
106
+ const state = { tofuStarted: false };
137
107
  const sigintHandler = async () => {
138
- if (options?.skipCompensation) {
139
- console.log(chalk_1.default.yellow('\nInterrupted — partial resources preserved.'));
140
- console.log(chalk_1.default.yellow('Re-run "fuel infra:deploy" to resume.\n'));
141
- }
142
- else {
108
+ if (options?.destroyOnFailure) {
143
109
  console.log(chalk_1.default.yellow('\nInterrupted — running compensation...'));
144
- if (state.tofuStarted && state.completedPasses.length > 0) {
145
- await runCompensation(infraDir, credentials, tofuVars, state.completedPasses);
110
+ if (state.tofuStarted) {
111
+ await runCompensation(infraDir, credentials, tofuVars);
146
112
  }
147
113
  }
114
+ else {
115
+ console.log(chalk_1.default.yellow('\nInterrupted — partial resources preserved.'));
116
+ console.log(chalk_1.default.yellow('Re-run "fuel infra:deploy" to resume.\n'));
117
+ }
148
118
  process.exit(1);
149
119
  };
150
120
  process.once('SIGINT', sigintHandler);
151
121
  try {
152
- // Run Tofu three-pass sequence
122
+ // Step 1: Create GitHub repo (skip in plan-only mode)
123
+ if (!options?.planOnly) {
124
+ console.log(chalk_1.default.cyan('--- Creating GitHub repository ---'));
125
+ try {
126
+ await (0, github_client_1.createGitHubRepo)(credentials.GITHUB_TOKEN, credentials.GITHUB_ORGANIZATION, repoName);
127
+ console.log(chalk_1.default.green(`✓ Repository created: ${credentials.GITHUB_ORGANIZATION}/${repoName}`));
128
+ }
129
+ catch (err) {
130
+ // If repo already exists (422), continue — it may be a re-run
131
+ if (err?.status === 422) {
132
+ console.log(chalk_1.default.yellow(`Repository ${credentials.GITHUB_ORGANIZATION}/${repoName} already exists, continuing...`));
133
+ }
134
+ else {
135
+ throw err;
136
+ }
137
+ }
138
+ }
139
+ // Step 2: Single Tofu apply (all AWS resources)
153
140
  state.tofuStarted = true;
154
- const result = await (0, tofu_runner_1.runTofuSequence)(infraDir, credentials, tofuVars, {
141
+ const result = await (0, tofu_runner_1.runTofuApply)(infraDir, credentials, tofuVars, {
155
142
  planOnly: options?.planOnly,
156
143
  });
157
- state.completedPasses = result.completedPasses;
158
144
  if (options?.planOnly) {
159
145
  console.log(chalk_1.default.green('\n Plan complete — no resources were created.\n'));
160
146
  return;
161
147
  }
162
- // Wire git remote
148
+ // Step 3: Set GitHub Actions secrets
149
+ console.log(chalk_1.default.cyan('--- Setting GitHub Actions secrets ---'));
150
+ const roleArn = result.outputs['oidc_role_arn'].value;
151
+ const secrets = {
152
+ AWS_REGION: credentials.AWS_REGION,
153
+ AWS_ROLE_ARN: roleArn,
154
+ PROJECT_NAME: config.name,
155
+ };
156
+ await (0, github_secrets_client_1.setRepoSecrets)(credentials.GITHUB_TOKEN, credentials.GITHUB_ORGANIZATION, repoName, secrets);
157
+ console.log(chalk_1.default.green('✓ GitHub Actions secrets configured'));
158
+ // Step 4: Push code
163
159
  const githubRepoUrl = result.outputs['github_http_repo_url'].value;
164
160
  await (0, git_client_1.wireGitRemote)(targetRoot, githubRepoUrl);
165
161
  console.log(chalk_1.default.green('Git remote origin set'));
162
+ const committed = await (0, git_client_1.commitAll)(targetRoot, 'Add infrastructure configuration');
163
+ if (committed) {
164
+ console.log(chalk_1.default.green('Infrastructure files committed'));
165
+ }
166
+ const allBranches = [...new Set(config.apps.map(app => app.branch))];
167
+ const branches = options?.targetBranch
168
+ ? allBranches.filter(b => b === options.targetBranch)
169
+ : allBranches;
170
+ try {
171
+ await (0, git_client_1.pushToRemote)(targetRoot, credentials.GITHUB_TOKEN, branches, options?.forcePush);
172
+ console.log(chalk_1.default.green(`Code pushed to: ${branches.join(', ')}`));
173
+ }
174
+ catch {
175
+ console.log(chalk_1.default.yellow(`Warning: automatic push failed. Push manually: git push -u origin ${branches.join(' ')}`));
176
+ }
177
+ // Step 5: Branch protections
178
+ if (!options?.skipBranchProtection) {
179
+ console.log(chalk_1.default.cyan('--- Applying branch protections ---'));
180
+ for (const branch of branches) {
181
+ try {
182
+ await (0, github_client_1.setBranchProtection)(credentials.GITHUB_TOKEN, credentials.GITHUB_ORGANIZATION, repoName, branch);
183
+ console.log(chalk_1.default.green(`✓ Branch protection set for: ${branch}`));
184
+ }
185
+ catch {
186
+ console.log(chalk_1.default.yellow(`Warning: could not set branch protection for ${branch}`));
187
+ }
188
+ }
189
+ }
190
+ else {
191
+ console.log(chalk_1.default.yellow('--- Skipping branch protections (--skip-branch-protection) ---'));
192
+ }
166
193
  // Print output table
167
194
  const albDns = result.outputs['alb_dns'].value;
168
195
  const ecrUrl = result.outputs['ecr_url'].value;
169
- printOutputTable(albDns, ecrUrl, githubRepoUrl, tofuVars.db_username, tofuVars.db_password);
196
+ printOutputTable(albDns, ecrUrl, githubRepoUrl);
170
197
  }
171
198
  catch (err) {
172
- if (err instanceof tofu_runner_1.TofuPassError) {
173
- if (options?.skipCompensation) {
199
+ if (err instanceof tofu_runner_1.TofuApplyError) {
200
+ if (options?.destroyOnFailure) {
201
+ await runCompensation(infraDir, credentials, tofuVars);
202
+ }
203
+ else {
174
204
  console.log(chalk_1.default.yellow('\n Partial resources preserved. Fix the issue and re-run:'));
175
205
  console.log(chalk_1.default.yellow(' fuel infra:deploy\n'));
176
- process.exit(1);
177
206
  }
178
- await runCompensation(infraDir, credentials, tofuVars, err.completedPasses);
179
207
  process.exit(1);
180
208
  }
181
209
  throw err;