@salte-common/terraflow 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +278 -0
  3. package/RELEASE_SUMMARY.md +53 -0
  4. package/STANDARDS_COMPLIANCE.md +85 -0
  5. package/bin/terraflow.js +3 -0
  6. package/bin/tf.js +3 -0
  7. package/dist/commands/apply.d.ts +7 -0
  8. package/dist/commands/apply.js +12 -0
  9. package/dist/commands/base.d.ts +7 -0
  10. package/dist/commands/base.js +12 -0
  11. package/dist/commands/config.d.ts +25 -0
  12. package/dist/commands/config.js +354 -0
  13. package/dist/commands/destroy.d.ts +7 -0
  14. package/dist/commands/destroy.js +12 -0
  15. package/dist/commands/init.d.ts +68 -0
  16. package/dist/commands/init.js +131 -0
  17. package/dist/commands/plan.d.ts +7 -0
  18. package/dist/commands/plan.js +12 -0
  19. package/dist/core/backend-state.d.ts +25 -0
  20. package/dist/core/backend-state.js +77 -0
  21. package/dist/core/config.d.ts +83 -0
  22. package/dist/core/config.js +295 -0
  23. package/dist/core/context.d.ts +52 -0
  24. package/dist/core/context.js +192 -0
  25. package/dist/core/environment.d.ts +62 -0
  26. package/dist/core/environment.js +205 -0
  27. package/dist/core/errors.d.ts +22 -0
  28. package/dist/core/errors.js +36 -0
  29. package/dist/core/plugin-loader.d.ts +21 -0
  30. package/dist/core/plugin-loader.js +136 -0
  31. package/dist/core/terraform.d.ts +45 -0
  32. package/dist/core/terraform.js +247 -0
  33. package/dist/core/validator.d.ts +103 -0
  34. package/dist/core/validator.js +304 -0
  35. package/dist/index.d.ts +7 -0
  36. package/dist/index.js +184 -0
  37. package/dist/plugins/auth/aws-assume-role.d.ts +10 -0
  38. package/dist/plugins/auth/aws-assume-role.js +110 -0
  39. package/dist/plugins/auth/azure-service-principal.d.ts +10 -0
  40. package/dist/plugins/auth/azure-service-principal.js +99 -0
  41. package/dist/plugins/auth/gcp-service-account.d.ts +10 -0
  42. package/dist/plugins/auth/gcp-service-account.js +105 -0
  43. package/dist/plugins/backends/azurerm.d.ts +10 -0
  44. package/dist/plugins/backends/azurerm.js +117 -0
  45. package/dist/plugins/backends/gcs.d.ts +10 -0
  46. package/dist/plugins/backends/gcs.js +75 -0
  47. package/dist/plugins/backends/local.d.ts +11 -0
  48. package/dist/plugins/backends/local.js +37 -0
  49. package/dist/plugins/backends/s3.d.ts +10 -0
  50. package/dist/plugins/backends/s3.js +185 -0
  51. package/dist/plugins/secrets/aws-secrets.d.ts +12 -0
  52. package/dist/plugins/secrets/aws-secrets.js +125 -0
  53. package/dist/plugins/secrets/azure-keyvault.d.ts +12 -0
  54. package/dist/plugins/secrets/azure-keyvault.js +178 -0
  55. package/dist/plugins/secrets/env.d.ts +24 -0
  56. package/dist/plugins/secrets/env.js +62 -0
  57. package/dist/plugins/secrets/gcp-secret-manager.d.ts +12 -0
  58. package/dist/plugins/secrets/gcp-secret-manager.js +157 -0
  59. package/dist/templates/application/go/go.mod.template +4 -0
  60. package/dist/templates/application/go/main.template +8 -0
  61. package/dist/templates/application/go/test.template +11 -0
  62. package/dist/templates/application/javascript/main.template +14 -0
  63. package/dist/templates/application/javascript/test.template +8 -0
  64. package/dist/templates/application/python/main.template +13 -0
  65. package/dist/templates/application/python/requirements.txt.template +3 -0
  66. package/dist/templates/application/python/test.template +8 -0
  67. package/dist/templates/application/typescript/main.template +14 -0
  68. package/dist/templates/application/typescript/test.template +8 -0
  69. package/dist/templates/application/typescript/tsconfig.json.template +20 -0
  70. package/dist/templates/config/README.md.template +82 -0
  71. package/dist/templates/config/env.example.template +22 -0
  72. package/dist/templates/config/gitignore.template +40 -0
  73. package/dist/templates/config/tfwconfig.yml.template +69 -0
  74. package/dist/templates/templates/application/go/go.mod.template +4 -0
  75. package/dist/templates/templates/application/go/main.template +8 -0
  76. package/dist/templates/templates/application/go/test.template +11 -0
  77. package/dist/templates/templates/application/javascript/main.template +14 -0
  78. package/dist/templates/templates/application/javascript/test.template +8 -0
  79. package/dist/templates/templates/application/python/main.template +13 -0
  80. package/dist/templates/templates/application/python/requirements.txt.template +3 -0
  81. package/dist/templates/templates/application/python/test.template +8 -0
  82. package/dist/templates/templates/application/typescript/main.template +14 -0
  83. package/dist/templates/templates/application/typescript/test.template +8 -0
  84. package/dist/templates/templates/application/typescript/tsconfig.json.template +20 -0
  85. package/dist/templates/templates/config/README.md.template +82 -0
  86. package/dist/templates/templates/config/env.example.template +22 -0
  87. package/dist/templates/templates/config/gitignore.template +40 -0
  88. package/dist/templates/templates/config/tfwconfig.yml.template +69 -0
  89. package/dist/templates/templates/terraform/aws/_init.tf.template +24 -0
  90. package/dist/templates/templates/terraform/aws/inputs.tf.template +11 -0
  91. package/dist/templates/templates/terraform/azure/_init.tf.template +19 -0
  92. package/dist/templates/templates/terraform/azure/inputs.tf.template +11 -0
  93. package/dist/templates/templates/terraform/gcp/_init.tf.template +20 -0
  94. package/dist/templates/templates/terraform/gcp/inputs.tf.template +16 -0
  95. package/dist/templates/templates/terraform/locals.tf.template +9 -0
  96. package/dist/templates/templates/terraform/main.tf.template +8 -0
  97. package/dist/templates/templates/terraform/modules/inputs.tf.template +5 -0
  98. package/dist/templates/templates/terraform/modules/main.tf.template +2 -0
  99. package/dist/templates/templates/terraform/modules/outputs.tf.template +2 -0
  100. package/dist/templates/templates/terraform/outputs.tf.template +6 -0
  101. package/dist/templates/terraform/aws/_init.tf.template +24 -0
  102. package/dist/templates/terraform/aws/inputs.tf.template +11 -0
  103. package/dist/templates/terraform/azure/_init.tf.template +19 -0
  104. package/dist/templates/terraform/azure/inputs.tf.template +11 -0
  105. package/dist/templates/terraform/gcp/_init.tf.template +20 -0
  106. package/dist/templates/terraform/gcp/inputs.tf.template +16 -0
  107. package/dist/templates/terraform/locals.tf.template +9 -0
  108. package/dist/templates/terraform/main.tf.template +8 -0
  109. package/dist/templates/terraform/modules/inputs.tf.template +5 -0
  110. package/dist/templates/terraform/modules/main.tf.template +2 -0
  111. package/dist/templates/terraform/modules/outputs.tf.template +2 -0
  112. package/dist/templates/terraform/outputs.tf.template +6 -0
  113. package/dist/types/config.d.ts +92 -0
  114. package/dist/types/config.js +6 -0
  115. package/dist/types/context.d.ts +59 -0
  116. package/dist/types/context.js +6 -0
  117. package/dist/types/index.d.ts +7 -0
  118. package/dist/types/index.js +23 -0
  119. package/dist/types/plugins.d.ts +77 -0
  120. package/dist/types/plugins.js +6 -0
  121. package/dist/utils/cloud.d.ts +43 -0
  122. package/dist/utils/cloud.js +150 -0
  123. package/dist/utils/git.d.ts +88 -0
  124. package/dist/utils/git.js +258 -0
  125. package/dist/utils/logger.d.ts +67 -0
  126. package/dist/utils/logger.js +121 -0
  127. package/dist/utils/scaffolding.d.ts +92 -0
  128. package/dist/utils/scaffolding.js +338 -0
  129. package/dist/utils/templates.d.ts +25 -0
  130. package/dist/utils/templates.js +70 -0
  131. package/package.json +60 -0
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * Environment secrets plugin
4
+ * No-op plugin for when users manage secrets via .env files
5
+ *
6
+ * This plugin does not fetch secrets from an external service.
7
+ * Instead, it allows users to manage TF_VAR_* environment variables
8
+ * directly in their .env file or existing environment variables.
9
+ *
10
+ * The .env file is loaded by EnvironmentSetup.loadEnvFile() which
11
+ * does NOT automatically convert variables to TF_VAR_* prefix.
12
+ * Users must manage the TF_VAR_* prefix themselves in .env files.
13
+ *
14
+ * This plugin returns an empty object because:
15
+ * - Secrets come from .env file (loaded separately)
16
+ * - Secrets come from existing environment variables (already available)
17
+ * - No automatic conversion or fetching is performed
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.envSecrets = void 0;
21
+ /**
22
+ * Environment secrets plugin
23
+ * Default and simplest secrets provider - no-op
24
+ */
25
+ exports.envSecrets = {
26
+ name: 'env',
27
+ /**
28
+ * Validate secrets configuration
29
+ * Always succeeds - no configuration required for env plugin
30
+ * @param _config - Secrets configuration (ignored)
31
+ */
32
+ validate: async (_config) => {
33
+ // No validation needed - env plugin is always valid
34
+ // Users manage secrets directly in .env file or environment variables
35
+ return Promise.resolve();
36
+ },
37
+ /**
38
+ * Retrieve secrets
39
+ * Returns empty object because secrets come from .env file or existing env vars
40
+ *
41
+ * This plugin does NOT:
42
+ * - Fetch secrets from external services
43
+ * - Convert environment variables to TF_VAR_* prefix
44
+ * - Load .env files (handled by EnvironmentSetup.loadEnvFile())
45
+ *
46
+ * Users must:
47
+ * - Manage TF_VAR_* prefix themselves in .env files
48
+ * - Set environment variables with TF_VAR_* prefix directly
49
+ * - Or use config.variables section for automatic conversion
50
+ *
51
+ * @param _config - Secrets configuration (ignored)
52
+ * @param _context - Execution context (ignored)
53
+ * @returns Empty object - secrets come from .env or existing env vars
54
+ */
55
+ getSecrets: async (_config, _context) => {
56
+ // Return empty object - secrets are already in environment
57
+ // .env file is loaded separately by EnvironmentSetup.loadEnvFile()
58
+ // Existing TF_VAR_* environment variables pass through unchanged
59
+ return {};
60
+ },
61
+ };
62
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * GCP Secret Manager plugin
3
+ * Retrieves secrets from GCP Secret Manager and converts them to TF_VAR_* environment variables
4
+ *
5
+ * CONVENTION: Every key in the secret automatically becomes TF_VAR_{key}
6
+ */
7
+ import type { SecretsPlugin } from '../../types';
8
+ /**
9
+ * GCP Secret Manager secrets plugin
10
+ */
11
+ export declare const gcpSecretManager: SecretsPlugin;
12
+ //# sourceMappingURL=gcp-secret-manager.d.ts.map
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /**
3
+ * GCP Secret Manager plugin
4
+ * Retrieves secrets from GCP Secret Manager and converts them to TF_VAR_* environment variables
5
+ *
6
+ * CONVENTION: Every key in the secret automatically becomes TF_VAR_{key}
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.gcpSecretManager = void 0;
10
+ const child_process_1 = require("child_process");
11
+ const errors_1 = require("../../core/errors");
12
+ const logger_1 = require("../../utils/logger");
13
+ /**
14
+ * Process secret value and convert to TF_VAR_* format
15
+ */
16
+ function processSecretValue(secretName, secretValue) {
17
+ // Try to parse as JSON
18
+ let secretData;
19
+ try {
20
+ const parsed = JSON.parse(secretValue);
21
+ if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
22
+ secretData = parsed;
23
+ }
24
+ else {
25
+ // Not a JSON object, treat the entire secret value as a single key
26
+ secretData = { [secretName]: secretValue };
27
+ }
28
+ }
29
+ catch {
30
+ // Not valid JSON, treat the entire secret value as a single key
31
+ secretData = { [secretName]: secretValue };
32
+ }
33
+ // Convert all keys to TF_VAR_{key} format
34
+ const tfVars = {};
35
+ for (const key in secretData) {
36
+ if (Object.prototype.hasOwnProperty.call(secretData, key)) {
37
+ const value = secretData[key];
38
+ const tfVarKey = `TF_VAR_${key}`;
39
+ // Convert value to string
40
+ if (value === null || value === undefined) {
41
+ tfVars[tfVarKey] = '';
42
+ }
43
+ else if (typeof value === 'string') {
44
+ tfVars[tfVarKey] = value;
45
+ }
46
+ else if (typeof value === 'number' || typeof value === 'boolean') {
47
+ tfVars[tfVarKey] = String(value);
48
+ }
49
+ else {
50
+ // For objects/arrays, convert to JSON string
51
+ tfVars[tfVarKey] = JSON.stringify(value);
52
+ }
53
+ }
54
+ }
55
+ logger_1.Logger.info(`✅ Loaded ${Object.keys(tfVars).length} Terraform variables from GCP Secret Manager`);
56
+ return tfVars;
57
+ }
58
+ /**
59
+ * GCP Secret Manager secrets plugin
60
+ */
61
+ exports.gcpSecretManager = {
62
+ name: 'gcp-secret-manager',
63
+ /**
64
+ * Validate GCP Secret Manager configuration
65
+ * @param config - Secrets configuration
66
+ * @throws {ConfigError} If configuration is invalid
67
+ */
68
+ validate: async (config) => {
69
+ if (!config.config) {
70
+ throw new errors_1.ConfigError('GCP Secret Manager requires configuration');
71
+ }
72
+ const gcpConfig = config.config;
73
+ // secret_name is required
74
+ if (!gcpConfig.secret_name) {
75
+ throw new errors_1.ConfigError('GCP Secret Manager requires "secret_name" configuration');
76
+ }
77
+ // project_id should be set (from config, context, or GCLOUD_PROJECT env)
78
+ const projectId = gcpConfig.project_id ||
79
+ process.env.GCLOUD_PROJECT ||
80
+ process.env.GCP_PROJECT ||
81
+ process.env.GOOGLE_CLOUD_PROJECT;
82
+ if (!projectId && !process.env.GOOGLE_APPLICATION_CREDENTIALS) {
83
+ // Warning but not error - GCP SDK can detect project from credentials
84
+ logger_1.Logger.debug('GCP project_id not specified, will attempt to auto-detect from credentials');
85
+ }
86
+ },
87
+ /**
88
+ * Retrieve secrets from GCP Secret Manager
89
+ * All keys are automatically prefixed with TF_VAR_
90
+ * @param config - Secrets configuration
91
+ * @param context - Execution context
92
+ * @returns Record of environment variable key-value pairs (prefixed with TF_VAR_)
93
+ */
94
+ getSecrets: async (config, context) => {
95
+ if (!config.config) {
96
+ throw new errors_1.ConfigError('GCP Secret Manager requires configuration');
97
+ }
98
+ const gcpConfig = config.config;
99
+ const secretName = gcpConfig.secret_name;
100
+ try {
101
+ // Determine project ID: config > context > env
102
+ let projectId = gcpConfig.project_id ||
103
+ context.cloud.gcpProjectId ||
104
+ process.env.GCLOUD_PROJECT ||
105
+ process.env.GCP_PROJECT ||
106
+ process.env.GOOGLE_CLOUD_PROJECT;
107
+ if (!projectId) {
108
+ // Try to get project ID from gcloud config
109
+ try {
110
+ const detectedProjectId = (0, child_process_1.execSync)('gcloud config get-value project', {
111
+ encoding: 'utf8',
112
+ stdio: ['pipe', 'pipe', 'pipe'],
113
+ }).trim();
114
+ if (detectedProjectId) {
115
+ logger_1.Logger.debug(`Detected GCP project ID: ${detectedProjectId}`);
116
+ projectId = detectedProjectId;
117
+ }
118
+ }
119
+ catch {
120
+ // Continue to error
121
+ }
122
+ if (!projectId) {
123
+ throw new errors_1.ConfigError('GCP project_id is required. Set it in config, GCLOUD_PROJECT environment variable, or run "gcloud config set project PROJECT_ID".');
124
+ }
125
+ }
126
+ logger_1.Logger.debug(`Fetching secret "${secretName}" from GCP Secret Manager (project: ${projectId})`);
127
+ // Fetch secret using gcloud CLI
128
+ const result = (0, child_process_1.execSync)(`gcloud secrets versions access latest --secret="${secretName}" --project="${projectId}"`, {
129
+ encoding: 'utf8',
130
+ stdio: ['pipe', 'pipe', 'pipe'],
131
+ });
132
+ const secretValue = result.trim();
133
+ return processSecretValue(secretName, secretValue);
134
+ }
135
+ catch (error) {
136
+ if (error instanceof errors_1.ConfigError) {
137
+ throw error;
138
+ }
139
+ // Handle specific GCP CLI errors
140
+ if (error instanceof Error) {
141
+ const errorMessage = error.message;
142
+ if (errorMessage.includes('PERMISSION_DENIED') || errorMessage.includes('403')) {
143
+ throw new errors_1.ConfigError(`Access denied when fetching secret "${secretName}". Ensure your GCP credentials have permission to access this secret.`);
144
+ }
145
+ if (errorMessage.includes('NOT_FOUND') || errorMessage.includes('404')) {
146
+ throw new errors_1.ConfigError(`Secret "${secretName}" not found in GCP Secret Manager.`);
147
+ }
148
+ if (errorMessage.includes('UNAUTHENTICATED') || errorMessage.includes('401')) {
149
+ throw new errors_1.ConfigError(`Authentication failed when accessing GCP Secret Manager. Ensure you have logged in with 'gcloud auth login' and have valid credentials.`);
150
+ }
151
+ throw new errors_1.ConfigError(`Failed to fetch secret "${secretName}" from GCP Secret Manager: ${errorMessage}. Ensure gcloud CLI is installed, you are logged in with 'gcloud auth login', and have valid permissions.`);
152
+ }
153
+ throw new errors_1.ConfigError(`Failed to fetch secret "${secretName}": ${String(error)}`);
154
+ }
155
+ },
156
+ };
157
+ //# sourceMappingURL=gcp-secret-manager.js.map
@@ -0,0 +1,4 @@
1
+ module <project-name>
2
+
3
+ go 1.21
4
+
@@ -0,0 +1,8 @@
1
+ package main
2
+
3
+ import "fmt"
4
+
5
+ func main() {
6
+ fmt.Println("Hello from <project-name>!")
7
+ }
8
+
@@ -0,0 +1,11 @@
1
+ package main
2
+
3
+ import "testing"
4
+
5
+ func TestMain(t *testing.T) {
6
+ // Test that main function exists and can be called
7
+ // Note: main() cannot be called directly in tests
8
+ // This is a placeholder test
9
+ t.Log("Main function test placeholder")
10
+ }
11
+
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Main application entry point
3
+ */
4
+
5
+ function main() {
6
+ console.log('Hello from <project-name>!');
7
+ }
8
+
9
+ if (require.main === module) {
10
+ main();
11
+ }
12
+
13
+ module.exports = { main };
14
+
@@ -0,0 +1,8 @@
1
+ const { main } = require('../main/index');
2
+
3
+ describe('<project-name>', () => {
4
+ it('should run main function', () => {
5
+ expect(() => main()).not.toThrow();
6
+ });
7
+ });
8
+
@@ -0,0 +1,13 @@
1
+ """
2
+ Main application entry point
3
+ """
4
+
5
+
6
+ def main():
7
+ """Main function"""
8
+ print('Hello from <project-name>!')
9
+
10
+
11
+ if __name__ == '__main__':
12
+ main()
13
+
@@ -0,0 +1,3 @@
1
+ # Python dependencies
2
+ pytest>=7.0.0
3
+
@@ -0,0 +1,8 @@
1
+ import pytest
2
+ from src.main.index import main
3
+
4
+
5
+ def test_main_function():
6
+ """Test that main function runs without error"""
7
+ assert main() is None
8
+
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Main application entry point
3
+ */
4
+
5
+ function main(): void {
6
+ console.log('Hello from <project-name>!');
7
+ }
8
+
9
+ if (require.main === module) {
10
+ main();
11
+ }
12
+
13
+ export { main };
14
+
@@ -0,0 +1,8 @@
1
+ import { main } from '../main/index';
2
+
3
+ describe('<project-name>', () => {
4
+ it('should run main function', () => {
5
+ expect(() => main()).not.toThrow();
6
+ });
7
+ });
8
+
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": ["ES2020"],
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }
20
+
@@ -0,0 +1,82 @@
1
+ # <project-name>
2
+
3
+ Infrastructure as Code project managed with [Terraflow](https://github.com/salte-common/terraflow).
4
+
5
+ ## Prerequisites
6
+
7
+ - [Terraform](https://www.terraform.io/downloads) >= 1.0
8
+ - [Node.js](https://nodejs.org/) >= 18.x
9
+ - [Terraflow](https://www.npmjs.com/package/terraflow): `npm install -g terraflow`
10
+ - Cloud provider credentials (<provider>)
11
+
12
+ ## Getting Started
13
+
14
+ 1. Copy `.env.example` to `.env` and configure your credentials:
15
+ ```bash
16
+ cp .env.example .env
17
+ # Edit .env with your credentials
18
+ ```
19
+
20
+ 2. Review and update `.tfwconfig.yml` with your backend configuration
21
+
22
+ 3. Initialize Terraform:
23
+ ```bash
24
+ terraflow init
25
+ ```
26
+
27
+ 4. Plan your infrastructure:
28
+ ```bash
29
+ terraflow plan
30
+ ```
31
+
32
+ 5. Apply your infrastructure:
33
+ ```bash
34
+ terraflow apply
35
+ ```
36
+
37
+ ## Project Structure
38
+
39
+ - `src/` - Application source code
40
+ - `main/` - Main application code
41
+ - `test/` - Test files
42
+ - `terraform/` - Infrastructure as Code
43
+ - `modules/` - Reusable Terraform modules
44
+ - `_init.tf` - Provider and backend configuration
45
+ - `*.tf` - Main terraform configuration
46
+ - `.tfwconfig.yml` - Terraflow configuration
47
+ - `.env` - Local environment variables (not committed)
48
+
49
+ ## Terraflow Commands
50
+
51
+ ```bash
52
+ # Initialize terraform and workspace
53
+ terraflow init
54
+
55
+ # Plan changes
56
+ terraflow plan
57
+
58
+ # Apply changes
59
+ terraflow apply
60
+
61
+ # Destroy infrastructure
62
+ terraflow destroy
63
+
64
+ # Show current configuration
65
+ terraflow config show
66
+ ```
67
+
68
+ ## Workspace Management
69
+
70
+ Terraflow automatically derives workspace names from your git branch:
71
+ - Main branch → `main` workspace
72
+ - Feature branches (e.g., `feature/new-api`) → hostname-based workspace
73
+ - Can be overridden with `--workspace` flag
74
+
75
+ ## Configuration
76
+
77
+ See `.tfwconfig.yml` for all available options and the [documentation](https://github.com/salte-common/terraflow/blob/main/docs/configuration.md) for detailed configuration reference.
78
+
79
+ ## License
80
+
81
+ MIT
82
+
@@ -0,0 +1,22 @@
1
+ # AWS Credentials (for S3 backend and AWS provider)
2
+ # AWS_ACCESS_KEY_ID=your_access_key
3
+ # AWS_SECRET_ACCESS_KEY=your_secret_key
4
+ # AWS_REGION=us-east-1
5
+
6
+ # Azure Credentials (for Azure backend and provider)
7
+ # ARM_CLIENT_ID=your_client_id
8
+ # ARM_CLIENT_SECRET=your_client_secret
9
+ # ARM_SUBSCRIPTION_ID=your_subscription_id
10
+ # ARM_TENANT_ID=your_tenant_id
11
+
12
+ # GCP Credentials (for GCS backend and GCP provider)
13
+ # GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
14
+ # GCP_PROJECT_ID=your-project-id
15
+
16
+ # Terraflow Configuration
17
+ # TERRAFLOW_WORKSPACE=development
18
+ # TERRAFLOW_SKIP_COMMIT_CHECK=false
19
+
20
+ # Terraform Variables (TF_VAR_*)
21
+ # TF_VAR_environment=development
22
+
@@ -0,0 +1,40 @@
1
+ # Terraform
2
+ **/.terraform/*
3
+ *.tfstate
4
+ *.tfstate.*
5
+ *.tfvars
6
+ .terraform.lock.hcl
7
+
8
+ # Terraflow
9
+ .terraflow/
10
+
11
+ # Environment
12
+ .env
13
+
14
+ # Language-specific (adjust based on --language)
15
+ # Node.js:
16
+ node_modules/
17
+ npm-debug.log*
18
+ dist/
19
+
20
+ # Python:
21
+ __pycache__/
22
+ *.py[cod]
23
+ venv/
24
+ .pytest_cache/
25
+ *.egg-info/
26
+
27
+ # Go:
28
+ *.exe
29
+ *.dll
30
+ *.so
31
+ *.dylib
32
+ vendor/
33
+
34
+ # IDE
35
+ .vscode/
36
+ .idea/
37
+ *.swp
38
+ *.swo
39
+ .DS_Store
40
+
@@ -0,0 +1,69 @@
1
+ # Terraflow configuration
2
+ # See: https://github.com/salte-common/terraflow/blob/main/docs/configuration.md
3
+
4
+ # Working directory for terraform files
5
+ working-dir: ./terraform
6
+
7
+ # Workspace derivation strategy
8
+ workspace_strategy:
9
+ - cli
10
+ - env
11
+ - tag
12
+ - branch
13
+ - hostname
14
+
15
+ # Backend configuration (adjust for your provider)
16
+ backend:
17
+ type: <provider> # local, s3, azurerm, or gcs
18
+ config:
19
+ # Template variables are supported: ${VAR_NAME}
20
+ # See documentation for available template variables
21
+
22
+ # Uncomment and configure based on your provider:
23
+
24
+ # AWS S3 Backend:
25
+ # bucket: ${AWS_REGION}-${AWS_ACCOUNT_ID}-terraform-state
26
+ # key: ${GITHUB_REPOSITORY}
27
+ # region: ${AWS_REGION}
28
+ # dynamodb_table: terraform-statelock
29
+ # encrypt: true
30
+
31
+ # Azure Backend:
32
+ # storage_account_name: mystorageaccount
33
+ # container_name: tfstate
34
+ # key: terraform.tfstate
35
+
36
+ # GCP Backend:
37
+ # bucket: my-gcs-bucket
38
+ # prefix: terraform/state
39
+
40
+ # Uncomment to configure secrets from secret manager
41
+ # secrets:
42
+ # provider: env # env | aws-secrets | azure-keyvault | gcp-secret-manager
43
+ # config:
44
+ # # AWS Secrets Manager:
45
+ # # region: us-east-1
46
+ # # secret_name: <project-name>/terraform-vars
47
+ #
48
+ # # Azure Key Vault:
49
+ # # vault_name: my-keyvault
50
+ #
51
+ # # GCP Secret Manager:
52
+ # # project_id: my-project
53
+
54
+ # Terraform variables
55
+ variables:
56
+ environment: development
57
+
58
+ # Validations
59
+ validations:
60
+ require_git_commit: true
61
+ # allowed_workspaces:
62
+ # - development
63
+ # - staging
64
+ # - production
65
+
66
+ # Logging
67
+ logging:
68
+ level: info
69
+
@@ -0,0 +1,4 @@
1
+ module <project-name>
2
+
3
+ go 1.21
4
+
@@ -0,0 +1,8 @@
1
+ package main
2
+
3
+ import "fmt"
4
+
5
+ func main() {
6
+ fmt.Println("Hello from <project-name>!")
7
+ }
8
+
@@ -0,0 +1,11 @@
1
+ package main
2
+
3
+ import "testing"
4
+
5
+ func TestMain(t *testing.T) {
6
+ // Test that main function exists and can be called
7
+ // Note: main() cannot be called directly in tests
8
+ // This is a placeholder test
9
+ t.Log("Main function test placeholder")
10
+ }
11
+
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Main application entry point
3
+ */
4
+
5
+ function main() {
6
+ console.log('Hello from <project-name>!');
7
+ }
8
+
9
+ if (require.main === module) {
10
+ main();
11
+ }
12
+
13
+ module.exports = { main };
14
+
@@ -0,0 +1,8 @@
1
+ const { main } = require('../main/index');
2
+
3
+ describe('<project-name>', () => {
4
+ it('should run main function', () => {
5
+ expect(() => main()).not.toThrow();
6
+ });
7
+ });
8
+
@@ -0,0 +1,13 @@
1
+ """
2
+ Main application entry point
3
+ """
4
+
5
+
6
+ def main():
7
+ """Main function"""
8
+ print('Hello from <project-name>!')
9
+
10
+
11
+ if __name__ == '__main__':
12
+ main()
13
+
@@ -0,0 +1,3 @@
1
+ # Python dependencies
2
+ pytest>=7.0.0
3
+
@@ -0,0 +1,8 @@
1
+ import pytest
2
+ from src.main.index import main
3
+
4
+
5
+ def test_main_function():
6
+ """Test that main function runs without error"""
7
+ assert main() is None
8
+
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Main application entry point
3
+ */
4
+
5
+ function main(): void {
6
+ console.log('Hello from <project-name>!');
7
+ }
8
+
9
+ if (require.main === module) {
10
+ main();
11
+ }
12
+
13
+ export { main };
14
+