@factiii/stack 0.1.23 → 0.1.25

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 (159) hide show
  1. package/README.md +81 -60
  2. package/bin/{factiii → stack} +12 -12
  3. package/dist/cli/check-config.js +1 -1
  4. package/dist/cli/check-config.js.map +1 -1
  5. package/dist/cli/deploy-secrets.d.ts.map +1 -1
  6. package/dist/cli/deploy-secrets.js +11 -11
  7. package/dist/cli/deploy-secrets.js.map +1 -1
  8. package/dist/cli/deploy.d.ts.map +1 -1
  9. package/dist/cli/deploy.js +19 -9
  10. package/dist/cli/deploy.js.map +1 -1
  11. package/dist/cli/dev-sync.d.ts.map +1 -1
  12. package/dist/cli/dev-sync.js +10 -9
  13. package/dist/cli/dev-sync.js.map +1 -1
  14. package/dist/cli/execute-plugin-command.d.ts.map +1 -1
  15. package/dist/cli/execute-plugin-command.js +7 -7
  16. package/dist/cli/execute-plugin-command.js.map +1 -1
  17. package/dist/cli/fix.d.ts.map +1 -1
  18. package/dist/cli/fix.js +24 -4
  19. package/dist/cli/fix.js.map +1 -1
  20. package/dist/cli/init.d.ts +3 -1
  21. package/dist/cli/init.d.ts.map +1 -1
  22. package/dist/cli/init.js +114 -71
  23. package/dist/cli/init.js.map +1 -1
  24. package/dist/cli/pr-check.d.ts.map +1 -1
  25. package/dist/cli/pr-check.js +5 -4
  26. package/dist/cli/pr-check.js.map +1 -1
  27. package/dist/cli/scan.d.ts +6 -6
  28. package/dist/cli/scan.d.ts.map +1 -1
  29. package/dist/cli/scan.js +20 -19
  30. package/dist/cli/scan.js.map +1 -1
  31. package/dist/cli/secrets.d.ts.map +1 -1
  32. package/dist/cli/secrets.js +17 -16
  33. package/dist/cli/secrets.js.map +1 -1
  34. package/dist/cli/undeploy.d.ts.map +1 -1
  35. package/dist/cli/undeploy.js +4 -4
  36. package/dist/cli/undeploy.js.map +1 -1
  37. package/dist/cli/upgrade.d.ts +1 -1
  38. package/dist/cli/upgrade.js +5 -5
  39. package/dist/cli/upgrade.js.map +1 -1
  40. package/dist/cli/validate.js +1 -1
  41. package/dist/cli/validate.js.map +1 -1
  42. package/dist/constants/config-files.d.ts +17 -0
  43. package/dist/constants/config-files.d.ts.map +1 -0
  44. package/dist/constants/config-files.js +73 -0
  45. package/dist/constants/config-files.js.map +1 -0
  46. package/dist/generators/{generate-factiii-auto.d.ts → generate-stack-auto.d.ts} +4 -4
  47. package/dist/generators/generate-stack-auto.d.ts.map +1 -0
  48. package/dist/generators/{generate-factiii-auto.js → generate-stack-auto.js} +15 -13
  49. package/dist/generators/generate-stack-auto.js.map +1 -0
  50. package/dist/generators/{generate-factiii-yml.d.ts → generate-stack-yml.d.ts} +5 -5
  51. package/dist/generators/generate-stack-yml.d.ts.map +1 -0
  52. package/dist/generators/{generate-factiii-yml.js → generate-stack-yml.js} +16 -15
  53. package/dist/generators/generate-stack-yml.js.map +1 -0
  54. package/dist/generators/index.d.ts +2 -2
  55. package/dist/generators/index.d.ts.map +1 -1
  56. package/dist/generators/index.js +5 -5
  57. package/dist/generators/index.js.map +1 -1
  58. package/dist/plugins/pipelines/aws/index.d.ts.map +1 -1
  59. package/dist/plugins/pipelines/aws/index.js +17 -6
  60. package/dist/plugins/pipelines/aws/index.js.map +1 -1
  61. package/dist/plugins/pipelines/aws/policies/bootstrap-policy.json +135 -0
  62. package/dist/plugins/pipelines/aws/prod.d.ts.map +1 -1
  63. package/dist/plugins/pipelines/aws/prod.js +17 -2
  64. package/dist/plugins/pipelines/aws/prod.js.map +1 -1
  65. package/dist/plugins/pipelines/aws/scanfix/credentials.d.ts.map +1 -1
  66. package/dist/plugins/pipelines/aws/scanfix/credentials.js +40 -13
  67. package/dist/plugins/pipelines/aws/scanfix/credentials.js.map +1 -1
  68. package/dist/plugins/pipelines/aws/scanfix/ec2.d.ts.map +1 -1
  69. package/dist/plugins/pipelines/aws/scanfix/ec2.js +7 -3
  70. package/dist/plugins/pipelines/aws/scanfix/ec2.js.map +1 -1
  71. package/dist/plugins/pipelines/aws/scanfix/iam.js +2 -2
  72. package/dist/plugins/pipelines/aws/scanfix/iam.js.map +1 -1
  73. package/dist/plugins/pipelines/aws/scanfix/rds.js +2 -2
  74. package/dist/plugins/pipelines/aws/scanfix/rds.js.map +1 -1
  75. package/dist/plugins/pipelines/factiii/index.js +1 -1
  76. package/dist/plugins/pipelines/factiii/index.js.map +1 -1
  77. package/dist/plugins/pipelines/factiii/pr-check.d.ts +1 -1
  78. package/dist/plugins/pipelines/factiii/pr-check.js +1 -1
  79. package/dist/plugins/pipelines/factiii/prod.d.ts.map +1 -1
  80. package/dist/plugins/pipelines/factiii/prod.js +3 -3
  81. package/dist/plugins/pipelines/factiii/prod.js.map +1 -1
  82. package/dist/plugins/pipelines/factiii/scanfix/config.d.ts +1 -1
  83. package/dist/plugins/pipelines/factiii/scanfix/config.d.ts.map +1 -1
  84. package/dist/plugins/pipelines/factiii/scanfix/config.js +10 -11
  85. package/dist/plugins/pipelines/factiii/scanfix/config.js.map +1 -1
  86. package/dist/plugins/pipelines/factiii/scanfix/secrets.js +6 -6
  87. package/dist/plugins/pipelines/factiii/scanfix/secrets.js.map +1 -1
  88. package/dist/plugins/pipelines/factiii/scanfix/workflows.d.ts.map +1 -1
  89. package/dist/plugins/pipelines/factiii/scanfix/workflows.js +29 -25
  90. package/dist/plugins/pipelines/factiii/scanfix/workflows.js.map +1 -1
  91. package/dist/plugins/pipelines/factiii/staging.d.ts +1 -1
  92. package/dist/plugins/pipelines/factiii/staging.d.ts.map +1 -1
  93. package/dist/plugins/pipelines/factiii/staging.js +3 -2
  94. package/dist/plugins/pipelines/factiii/staging.js.map +1 -1
  95. package/dist/plugins/pipelines/factiii/utils/workflows.js +15 -15
  96. package/dist/plugins/pipelines/factiii/utils/workflows.js.map +1 -1
  97. package/dist/plugins/pipelines/factiii/workflows/factiii-cicd-prod.yml +11 -8
  98. package/dist/plugins/pipelines/factiii/workflows/factiii-cicd-staging.yml +11 -8
  99. package/dist/plugins/pipelines/factiii/workflows/factiii-command.yml +10 -8
  100. package/dist/plugins/pipelines/factiii/workflows/factiii-deploy.yml +17 -13
  101. package/dist/plugins/pipelines/factiii/workflows/factiii-dev-sync.yml +13 -11
  102. package/dist/plugins/pipelines/factiii/workflows/factiii-fix.yml +13 -11
  103. package/dist/plugins/pipelines/factiii/workflows/factiii-pr-check.yml +10 -7
  104. package/dist/plugins/pipelines/factiii/workflows/factiii-scan.yml +18 -11
  105. package/dist/plugins/pipelines/factiii/workflows/factiii-undeploy.yml +9 -8
  106. package/dist/plugins/pipelines/factiii/workflows/stack-cicd-prod.yml +115 -0
  107. package/dist/plugins/pipelines/factiii/workflows/stack-cicd-staging.yml +120 -0
  108. package/dist/plugins/pipelines/factiii/workflows/stack-command.yml +132 -0
  109. package/dist/plugins/pipelines/factiii/workflows/stack-deploy.yml +202 -0
  110. package/dist/plugins/pipelines/factiii/workflows/stack-dev-sync.yml +181 -0
  111. package/dist/plugins/pipelines/factiii/workflows/stack-fix.yml +177 -0
  112. package/dist/plugins/pipelines/factiii/workflows/stack-pr-check.yml +106 -0
  113. package/dist/plugins/pipelines/factiii/workflows/stack-scan.yml +182 -0
  114. package/dist/plugins/pipelines/factiii/workflows/stack-undeploy.yml +96 -0
  115. package/dist/plugins/servers/mac/scanfix/containers.js +1 -1
  116. package/dist/plugins/servers/mac/scanfix/containers.js.map +1 -1
  117. package/dist/scanfix/fixes/pnpm.d.ts.map +1 -1
  118. package/dist/scanfix/fixes/pnpm.js +2 -2
  119. package/dist/scanfix/fixes/pnpm.js.map +1 -1
  120. package/dist/scripts/generate-all.d.ts.map +1 -1
  121. package/dist/scripts/generate-all.js +9 -8
  122. package/dist/scripts/generate-all.js.map +1 -1
  123. package/dist/scripts/get-repo-name.d.ts +1 -1
  124. package/dist/scripts/get-repo-name.js +5 -3
  125. package/dist/scripts/get-repo-name.js.map +1 -1
  126. package/dist/scripts/validate-env-files.js +7 -1
  127. package/dist/scripts/validate-env-files.js.map +1 -1
  128. package/dist/scripts/validate-example-values.d.ts +1 -1
  129. package/dist/scripts/validate-example-values.js +3 -2
  130. package/dist/scripts/validate-example-values.js.map +1 -1
  131. package/dist/scripts/validate-stack-yml.d.ts +6 -0
  132. package/dist/scripts/validate-stack-yml.d.ts.map +1 -0
  133. package/dist/scripts/{validate-factiii-yml.js → validate-stack-yml.js} +15 -11
  134. package/dist/scripts/validate-stack-yml.js.map +1 -0
  135. package/dist/utils/config-validator.d.ts +2 -2
  136. package/dist/utils/config-validator.d.ts.map +1 -1
  137. package/dist/utils/config-validator.js +7 -6
  138. package/dist/utils/config-validator.js.map +1 -1
  139. package/dist/utils/config-writer.d.ts +16 -0
  140. package/dist/utils/config-writer.d.ts.map +1 -0
  141. package/dist/utils/config-writer.js +95 -0
  142. package/dist/utils/config-writer.js.map +1 -0
  143. package/dist/utils/deployment-report.js +4 -4
  144. package/dist/utils/deployment-report.js.map +1 -1
  145. package/dist/utils/ssh-helper.js +6 -6
  146. package/dist/utils/ssh-helper.js.map +1 -1
  147. package/dist/utils/template-generator.js +1 -1
  148. package/dist/utils/version-check.d.ts +1 -1
  149. package/dist/utils/version-check.d.ts.map +1 -1
  150. package/dist/utils/version-check.js +9 -8
  151. package/dist/utils/version-check.js.map +1 -1
  152. package/package.json +9 -3
  153. package/dist/generators/generate-factiii-auto.d.ts.map +0 -1
  154. package/dist/generators/generate-factiii-auto.js.map +0 -1
  155. package/dist/generators/generate-factiii-yml.d.ts.map +0 -1
  156. package/dist/generators/generate-factiii-yml.js.map +0 -1
  157. package/dist/scripts/validate-factiii-yml.d.ts +0 -6
  158. package/dist/scripts/validate-factiii-yml.d.ts.map +0 -1
  159. package/dist/scripts/validate-factiii-yml.js.map +0 -1
@@ -47,19 +47,20 @@ jobs:
47
47
  - name: Read config
48
48
  id: config
49
49
  run: |
50
- if [ ! -f "factiii.yml" ]; then
51
- echo "❌ factiii.yml not found"
50
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
51
+ if [ ! -f "$CONFIG_FILE" ]; then
52
+ echo "❌ stack.yml or factiii.yml not found"
52
53
  exit 1
53
54
  fi
54
55
 
55
- REPO_NAME=$(yq eval '.name' factiii.yml)
56
+ REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
56
57
 
57
58
  if [ "${{ inputs.environment }}" == "staging" ]; then
58
- HOST=$(yq eval '.environments.staging.domain // ""' factiii.yml)
59
- SSH_USER=$(yq eval '.environments.staging.ssh_user // "ubuntu"' factiii.yml)
59
+ HOST=$(yq eval '.staging.domain // ""' "$CONFIG_FILE")
60
+ SSH_USER=$(yq eval '.staging.ssh_user // "ubuntu"' "$CONFIG_FILE")
60
61
  else
61
- HOST=$(yq eval '.environments.prod.domain // ""' factiii.yml)
62
- SSH_USER=$(yq eval '.environments.prod.ssh_user // "ubuntu"' factiii.yml)
62
+ HOST=$(yq eval '.prod.domain // ""' "$CONFIG_FILE")
63
+ SSH_USER=$(yq eval '.prod.ssh_user // "ubuntu"' "$CONFIG_FILE")
63
64
  fi
64
65
 
65
66
  echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
@@ -69,16 +70,17 @@ jobs:
69
70
  - name: Check if environment configured
70
71
  id: check_env
71
72
  run: |
73
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
72
74
  if [ "${{ inputs.environment }}" == "staging" ]; then
73
- HAS_ENV=$(yq eval '.environments.staging != null' factiii.yml)
75
+ HAS_ENV=$(yq eval '.staging != null' "$CONFIG_FILE")
74
76
  else
75
- HAS_ENV=$(yq eval '.environments.prod != null' factiii.yml)
77
+ HAS_ENV=$(yq eval '.prod != null' "$CONFIG_FILE")
76
78
  fi
77
79
 
78
80
  echo "has_env=$HAS_ENV" >> $GITHUB_OUTPUT
79
81
 
80
82
  if [ "$HAS_ENV" != "true" ]; then
81
- echo "⏭️ ${{ inputs.environment }} environment not configured in factiii.yml"
83
+ echo "⏭️ ${{ inputs.environment }} not configured in config"
82
84
  exit 1
83
85
  fi
84
86
 
@@ -137,7 +139,7 @@ jobs:
137
139
  ENVIRONMENT: ${{ inputs.environment }}
138
140
  run: |
139
141
  if [ -z "$HOST" ]; then
140
- echo "❌ Missing domain in factiii.yml: environments.$ENVIRONMENT.domain"
142
+ echo "❌ Missing domain in config: $ENVIRONMENT.domain"
141
143
  exit 1
142
144
  fi
143
145
 
@@ -37,10 +37,10 @@ jobs:
37
37
  run: |
38
38
  ENVS="[]"
39
39
 
40
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
40
41
  if [ "${{ inputs.environment }}" == "all" ]; then
41
- # Check which environments are configured
42
- HAS_STAGING=$(yq eval '.staging != null' factiii.yml)
43
- HAS_PROD=$(yq eval '.prod != null' factiii.yml)
42
+ HAS_STAGING=$(yq eval '.staging != null' "$CONFIG_FILE")
43
+ HAS_PROD=$(yq eval '.prod != null' "$CONFIG_FILE")
44
44
 
45
45
  if [ "$HAS_STAGING" == "true" ] && [ "$HAS_PROD" == "true" ]; then
46
46
  ENVS='["staging", "prod"]'
@@ -75,14 +75,15 @@ jobs:
75
75
  env:
76
76
  ENVIRONMENT: ${{ matrix.environment }}
77
77
  run: |
78
- if [ ! -f "factiii.yml" ]; then
79
- echo "❌ factiii.yml not found"
78
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
79
+ if [ ! -f "$CONFIG_FILE" ]; then
80
+ echo "❌ stack.yml or factiii.yml not found"
80
81
  exit 1
81
82
  fi
82
83
 
83
- REPO_NAME=$(yq eval '.name' factiii.yml)
84
- HOST=$(yq eval ".$ENVIRONMENT.domain // \"\"" factiii.yml)
85
- SSH_USER=$(yq eval ".$ENVIRONMENT.ssh_user // \"ubuntu\"" factiii.yml)
84
+ REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
85
+ HOST=$(yq eval ".$ENVIRONMENT.domain // \"\"" "$CONFIG_FILE")
86
+ SSH_USER=$(yq eval ".$ENVIRONMENT.ssh_user // \"ubuntu\"" "$CONFIG_FILE")
86
87
 
87
88
  echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
88
89
  echo "host=$HOST" >> $GITHUB_OUTPUT
@@ -93,11 +94,12 @@ jobs:
93
94
  env:
94
95
  ENVIRONMENT: ${{ matrix.environment }}
95
96
  run: |
96
- HAS_ENV=$(yq eval ".$ENVIRONMENT != null" factiii.yml)
97
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
98
+ HAS_ENV=$(yq eval ".$ENVIRONMENT != null" "$CONFIG_FILE")
97
99
  echo "has_env=$HAS_ENV" >> $GITHUB_OUTPUT
98
100
 
99
101
  if [ "$HAS_ENV" != "true" ]; then
100
- echo "⏭️ $ENVIRONMENT environment not configured in factiii.yml"
102
+ echo "⏭️ $ENVIRONMENT not configured"
101
103
  exit 0
102
104
  fi
103
105
 
@@ -153,7 +155,7 @@ jobs:
153
155
  ENVIRONMENT: ${{ matrix.environment }}
154
156
  run: |
155
157
  if [ -z "$HOST" ]; then
156
- echo "❌ Missing domain in factiii.yml: $ENVIRONMENT.domain"
158
+ echo "❌ Missing domain in config: $ENVIRONMENT.domain"
157
159
  exit 1
158
160
  fi
159
161
 
@@ -24,14 +24,16 @@ jobs:
24
24
  - name: Read config
25
25
  id: config
26
26
  run: |
27
- if [ ! -f "factiii.yml" ]; then
28
- echo " factiii.yml not found"
27
+ CONFIG_FILE="stack.yml"
28
+ if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
29
+ if [ ! -f "$CONFIG_FILE" ]; then
30
+ echo "❌ stack.yml or factiii.yml not found"
29
31
  exit 1
30
32
  fi
31
33
 
32
- REPO_NAME=$(yq eval '.name' factiii.yml)
33
- HOST=$(yq eval '.staging.domain // ""' factiii.yml)
34
- SSH_USER=$(yq eval '.staging.ssh_user // "ubuntu"' factiii.yml)
34
+ REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
35
+ HOST=$(yq eval '.staging.domain // ""' "$CONFIG_FILE")
36
+ SSH_USER=$(yq eval '.staging.ssh_user // "ubuntu"' "$CONFIG_FILE")
35
37
 
36
38
  echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
37
39
  echo "host=$HOST" >> $GITHUB_OUTPUT
@@ -40,7 +42,8 @@ jobs:
40
42
  - name: Check if staging configured
41
43
  id: check_staging
42
44
  run: |
43
- HAS_STAGING=$(yq eval '.staging != null' factiii.yml)
45
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
46
+ HAS_STAGING=$(yq eval '.staging != null' "$CONFIG_FILE")
44
47
  echo "has_staging=$HAS_STAGING" >> $GITHUB_OUTPUT
45
48
 
46
49
  if [ "$HAS_STAGING" != "true" ]; then
@@ -74,7 +77,7 @@ jobs:
74
77
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
75
78
  run: |
76
79
  if [ -z "$HOST" ]; then
77
- echo "❌ Missing staging.domain in factiii.yml"
80
+ echo "❌ Missing staging.domain in config"
78
81
  exit 1
79
82
  fi
80
83
 
@@ -35,12 +35,17 @@ jobs:
35
35
  - name: Determine environments
36
36
  id: set-matrix
37
37
  run: |
38
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
39
+ if [ ! -f "$CONFIG_FILE" ]; then
40
+ echo "matrix={\"environment\":[]}" >> $GITHUB_OUTPUT
41
+ echo "❌ stack.yml or factiii.yml not found"
42
+ exit 1
43
+ fi
38
44
  ENVS="[]"
39
45
 
40
46
  if [ "${{ inputs.environment }}" == "all" ]; then
41
- # Check which environments are configured
42
- HAS_STAGING=$(yq eval '.environments.staging != null' factiii.yml)
43
- HAS_PROD=$(yq eval '.environments.prod != null' factiii.yml)
47
+ HAS_STAGING=$(yq eval '.staging != null' "$CONFIG_FILE")
48
+ HAS_PROD=$(yq eval '.prod != null' "$CONFIG_FILE")
44
49
 
45
50
  if [ "$HAS_STAGING" == "true" ] && [ "$HAS_PROD" == "true" ]; then
46
51
  ENVS='["staging", "prod"]'
@@ -75,14 +80,15 @@ jobs:
75
80
  env:
76
81
  ENVIRONMENT: ${{ matrix.environment }}
77
82
  run: |
78
- if [ ! -f "factiii.yml" ]; then
79
- echo "❌ factiii.yml not found"
83
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
84
+ if [ ! -f "$CONFIG_FILE" ]; then
85
+ echo "❌ stack.yml or factiii.yml not found"
80
86
  exit 1
81
87
  fi
82
88
 
83
- REPO_NAME=$(yq eval '.name' factiii.yml)
84
- HOST=$(yq eval ".environments.$ENVIRONMENT.domain // \"\"" factiii.yml)
85
- SSH_USER=$(yq eval ".environments.$ENVIRONMENT.ssh_user // \"ubuntu\"" factiii.yml)
89
+ REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
90
+ HOST=$(yq eval ".$ENVIRONMENT.domain // \"\"" "$CONFIG_FILE")
91
+ SSH_USER=$(yq eval ".$ENVIRONMENT.ssh_user // \"ubuntu\"" "$CONFIG_FILE")
86
92
 
87
93
  echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
88
94
  echo "host=$HOST" >> $GITHUB_OUTPUT
@@ -93,11 +99,12 @@ jobs:
93
99
  env:
94
100
  ENVIRONMENT: ${{ matrix.environment }}
95
101
  run: |
96
- HAS_ENV=$(yq eval ".environments.$ENVIRONMENT != null" factiii.yml)
102
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
103
+ HAS_ENV=$(yq eval ".$ENVIRONMENT != null" "$CONFIG_FILE")
97
104
  echo "has_env=$HAS_ENV" >> $GITHUB_OUTPUT
98
105
 
99
106
  if [ "$HAS_ENV" != "true" ]; then
100
- echo "⏭️ $ENVIRONMENT environment not configured in factiii.yml"
107
+ echo "⏭️ $ENVIRONMENT not configured"
101
108
  exit 0
102
109
  fi
103
110
 
@@ -153,7 +160,7 @@ jobs:
153
160
  ENVIRONMENT: ${{ matrix.environment }}
154
161
  run: |
155
162
  if [ -z "$HOST" ]; then
156
- echo "❌ Missing domain in factiii.yml: environments.$ENVIRONMENT.domain"
163
+ echo "❌ Missing domain in config: $ENVIRONMENT.domain"
157
164
  exit 1
158
165
  fi
159
166
 
@@ -30,19 +30,20 @@ jobs:
30
30
  - name: Read config
31
31
  id: config
32
32
  run: |
33
- if [ ! -f "factiii.yml" ]; then
34
- echo "❌ factiii.yml not found"
33
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
34
+ if [ ! -f "$CONFIG_FILE" ]; then
35
+ echo "❌ stack.yml or factiii.yml not found"
35
36
  exit 1
36
37
  fi
37
38
 
38
- REPO_NAME=$(yq eval '.name' factiii.yml)
39
+ REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
39
40
 
40
41
  if [ "${{ inputs.environment }}" == "staging" ]; then
41
- HOST=$(yq eval '.environments.staging.domain // ""' factiii.yml)
42
- SSH_USER=$(yq eval '.environments.staging.ssh_user // "ubuntu"' factiii.yml)
42
+ HOST=$(yq eval '.staging.domain // ""' "$CONFIG_FILE")
43
+ SSH_USER=$(yq eval '.staging.ssh_user // "ubuntu"' "$CONFIG_FILE")
43
44
  else
44
- HOST=$(yq eval '.environments.prod.domain // ""' factiii.yml)
45
- SSH_USER=$(yq eval '.environments.prod.ssh_user // "ubuntu"' factiii.yml)
45
+ HOST=$(yq eval '.prod.domain // ""' "$CONFIG_FILE")
46
+ SSH_USER=$(yq eval '.prod.ssh_user // "ubuntu"' "$CONFIG_FILE")
46
47
  fi
47
48
 
48
49
  echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
@@ -70,7 +71,7 @@ jobs:
70
71
  ENVIRONMENT: ${{ inputs.environment }}
71
72
  run: |
72
73
  if [ -z "$HOST" ]; then
73
- echo "❌ Missing domain in factiii.yml: environments.$ENVIRONMENT.domain"
74
+ echo "❌ Missing domain in config: $ENVIRONMENT.domain"
74
75
  exit 1
75
76
  fi
76
77
 
@@ -0,0 +1,115 @@
1
+ name: Stack CI/CD Prod
2
+
3
+ # Generated by @factiii/stack v{VERSION}
4
+ # CI/CD: Auto-deploy to prod on push to prod branch
5
+ # This is the app's CI/CD pipeline, NOT infrastructure management.
6
+ # For manual infrastructure operations, use stack-deploy.yml
7
+
8
+ on:
9
+ push:
10
+ branches:
11
+ - prod
12
+
13
+ jobs:
14
+ deploy:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Install yq
21
+ run: |
22
+ sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
23
+ sudo chmod +x /usr/local/bin/yq
24
+
25
+ - name: Read config
26
+ id: config
27
+ run: |
28
+ CONFIG_FILE="stack.yml"
29
+ if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
30
+ if [ ! -f "$CONFIG_FILE" ]; then
31
+ echo "❌ stack.yml or factiii.yml not found"
32
+ exit 1
33
+ fi
34
+
35
+ REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
36
+ HOST=$(yq eval '.prod.domain // ""' "$CONFIG_FILE")
37
+ SSH_USER=$(yq eval '.prod.ssh_user // "ubuntu"' "$CONFIG_FILE")
38
+
39
+ echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
40
+ echo "host=$HOST" >> $GITHUB_OUTPUT
41
+ echo "ssh_user=$SSH_USER" >> $GITHUB_OUTPUT
42
+
43
+ - name: Check if prod configured
44
+ id: check_prod
45
+ run: |
46
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
47
+ HAS_PROD=$(yq eval '.prod != null' "$CONFIG_FILE")
48
+ echo "has_prod=$HAS_PROD" >> $GITHUB_OUTPUT
49
+
50
+ if [ "$HAS_PROD" != "true" ]; then
51
+ echo "⏭️ Prod not configured - skipping deployment"
52
+ exit 0
53
+ fi
54
+
55
+ - name: Setup SSH
56
+ if: steps.check_prod.outputs.has_prod == 'true'
57
+ env:
58
+ SSH_KEY: ${{ secrets.PROD_SSH }}
59
+ run: |
60
+ if [ -z "$SSH_KEY" ]; then
61
+ echo "❌ Missing PROD_SSH secret"
62
+ exit 1
63
+ fi
64
+
65
+ mkdir -p ~/.ssh
66
+ echo "$SSH_KEY" > ~/.ssh/deploy_key
67
+ chmod 600 ~/.ssh/deploy_key
68
+
69
+ - name: Deploy via CLI
70
+ if: steps.check_prod.outputs.has_prod == 'true'
71
+ env:
72
+ HOST: ${{ steps.config.outputs.host }}
73
+ USER: ${{ steps.config.outputs.ssh_user }}
74
+ REPO_NAME: ${{ steps.config.outputs.repo_name }}
75
+ COMMIT_HASH: ${{ github.sha }}
76
+ BRANCH: ${{ github.ref_name }}
77
+ GITHUB_REPO: ${{ github.repository }}
78
+ PROD_ENVS: ${{ secrets.PROD_ENVS }}
79
+ run: |
80
+ if [ -z "$HOST" ]; then
81
+ echo "❌ Missing prod.domain in config"
82
+ exit 1
83
+ fi
84
+
85
+ echo "🚀 Deploying to prod ($HOST)..."
86
+
87
+ # Prepare environment variables for SSH (base64 encode to handle special characters)
88
+ ENV_VARS_EXPORT=""
89
+ if [ -n "$PROD_ENVS" ]; then
90
+ ENV_VARS_B64=$(echo -n "$PROD_ENVS" | base64 -w 0)
91
+ ENV_VARS_EXPORT="PROD_ENVS=\$(echo '$ENV_VARS_B64' | base64 -d) && export PROD_ENVS && "
92
+ fi
93
+
94
+ ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no "$USER@$HOST" \
95
+ "export PATH=\"/opt/homebrew/bin:/usr/local/bin:\$PATH\" && \
96
+ REPO_DIR=\"\$HOME/.factiii/$REPO_NAME\" && \
97
+ if [ -d \"\$REPO_DIR\" ]; then \
98
+ cd \"\$REPO_DIR\" && \
99
+ $ENV_VARS_EXPORT GITHUB_ACTIONS=true COMMIT_HASH=$COMMIT_HASH BRANCH=$BRANCH GITHUB_REPO=$GITHUB_REPO \
100
+ npx stack deploy --prod --commit $COMMIT_HASH --branch $BRANCH; \
101
+ else \
102
+ echo \"❌ Repo directory not found at \$REPO_DIR\"; \
103
+ echo \"Run deployment first to clone the repository\"; \
104
+ exit 1; \
105
+ fi"
106
+
107
+ DEPLOY_EXIT_CODE=$?
108
+ rm -f ~/.ssh/deploy_key
109
+
110
+ if [ $DEPLOY_EXIT_CODE -eq 0 ]; then
111
+ echo "✅ Prod deployment complete!"
112
+ else
113
+ echo "❌ Prod deployment failed with exit code $DEPLOY_EXIT_CODE"
114
+ exit $DEPLOY_EXIT_CODE
115
+ fi
@@ -0,0 +1,120 @@
1
+ name: Stack CI/CD Staging
2
+
3
+ # Generated by @factiii/stack v{VERSION}
4
+ # CI/CD: Auto-deploy to staging on push to main branch
5
+ # This is the app's CI/CD pipeline, NOT infrastructure management.
6
+ # For manual infrastructure operations, use stack-deploy.yml
7
+
8
+ on:
9
+ push:
10
+ branches:
11
+ - main
12
+
13
+ jobs:
14
+ deploy:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Install yq
21
+ run: |
22
+ sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
23
+ sudo chmod +x /usr/local/bin/yq
24
+
25
+ - name: Read config
26
+ id: config
27
+ run: |
28
+ CONFIG_FILE="stack.yml"
29
+ if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
30
+ if [ ! -f "$CONFIG_FILE" ]; then
31
+ echo "❌ stack.yml or factiii.yml not found"
32
+ exit 1
33
+ fi
34
+
35
+ REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
36
+ HOST=$(yq eval '.staging.domain // ""' "$CONFIG_FILE")
37
+ SSH_USER=$(yq eval '.staging.ssh_user // "ubuntu"' "$CONFIG_FILE")
38
+
39
+ echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
40
+ echo "host=$HOST" >> $GITHUB_OUTPUT
41
+ echo "ssh_user=$SSH_USER" >> $GITHUB_OUTPUT
42
+
43
+ - name: Check if staging configured
44
+ id: check_staging
45
+ run: |
46
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
47
+ HAS_STAGING=$(yq eval '.staging != null' "$CONFIG_FILE")
48
+ echo "has_staging=$HAS_STAGING" >> $GITHUB_OUTPUT
49
+
50
+ if [ "$HAS_STAGING" != "true" ]; then
51
+ echo "⏭️ Staging not configured - skipping deployment"
52
+ exit 0
53
+ fi
54
+
55
+ - name: Setup SSH
56
+ if: steps.check_staging.outputs.has_staging == 'true'
57
+ env:
58
+ SSH_KEY: ${{ secrets.STAGING_SSH }}
59
+ run: |
60
+ if [ -z "$SSH_KEY" ]; then
61
+ echo "❌ Missing STAGING_SSH secret"
62
+ exit 1
63
+ fi
64
+
65
+ mkdir -p ~/.ssh
66
+ echo "$SSH_KEY" > ~/.ssh/deploy_key
67
+ chmod 600 ~/.ssh/deploy_key
68
+
69
+ - name: Deploy via CLI
70
+ if: steps.check_staging.outputs.has_staging == 'true'
71
+ env:
72
+ HOST: ${{ steps.config.outputs.host }}
73
+ USER: ${{ steps.config.outputs.ssh_user }}
74
+ REPO_NAME: ${{ steps.config.outputs.repo_name }}
75
+ COMMIT_HASH: ${{ github.sha }}
76
+ BRANCH: ${{ github.ref_name }}
77
+ GITHUB_REPO: ${{ github.repository }}
78
+ STAGING_ENVS: ${{ secrets.STAGING_ENVS }}
79
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80
+ run: |
81
+ if [ -z "$HOST" ]; then
82
+ echo "❌ Missing staging.domain in config"
83
+ exit 1
84
+ fi
85
+
86
+ echo "🚀 Deploying to staging ($HOST)..."
87
+
88
+ # Prepare environment variables for SSH (base64 encode to handle special characters)
89
+ ENV_VARS_EXPORT=""
90
+ if [ -n "$STAGING_ENVS" ]; then
91
+ ENV_VARS_B64=$(echo -n "$STAGING_ENVS" | base64 -w 0)
92
+ ENV_VARS_EXPORT="STAGING_ENVS=\$(echo '$ENV_VARS_B64' | base64 -d) && export STAGING_ENVS && "
93
+ fi
94
+
95
+ # Base64 encode GITHUB_TOKEN for safe SSH transport
96
+ GITHUB_TOKEN_B64=$(echo -n "$GITHUB_TOKEN" | base64 -w 0)
97
+
98
+ ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no "$USER@$HOST" \
99
+ "export PATH=\"/opt/homebrew/bin:/usr/local/bin:\$PATH\" && \
100
+ export GITHUB_TOKEN=\$(echo \"$GITHUB_TOKEN_B64\" | base64 -d) && \
101
+ REPO_DIR=\"\$HOME/.factiii/$REPO_NAME\" && \
102
+ if [ -d \"\$REPO_DIR\" ]; then \
103
+ cd \"\$REPO_DIR\" && \
104
+ $ENV_VARS_EXPORT GITHUB_ACTIONS=true COMMIT_HASH=$COMMIT_HASH BRANCH=$BRANCH GITHUB_REPO=$GITHUB_REPO \
105
+ npx stack deploy --staging --commit $COMMIT_HASH --branch $BRANCH; \
106
+ else \
107
+ echo \"❌ Repo directory not found at \$REPO_DIR\"; \
108
+ echo \"Run deployment first to clone the repository\"; \
109
+ exit 1; \
110
+ fi"
111
+
112
+ DEPLOY_EXIT_CODE=$?
113
+ rm -f ~/.ssh/deploy_key
114
+
115
+ if [ $DEPLOY_EXIT_CODE -eq 0 ]; then
116
+ echo "✅ Staging deployment complete!"
117
+ else
118
+ echo "❌ Staging deployment failed with exit code $DEPLOY_EXIT_CODE"
119
+ exit $DEPLOY_EXIT_CODE
120
+ fi
@@ -0,0 +1,132 @@
1
+ name: Stack Command
2
+
3
+ # Generated by @factiii/stack v{VERSION}
4
+ # INFRASTRUCTURE: Run plugin commands on remote servers
5
+ # Run: npx stack db seed --staging (triggers this workflow)
6
+
7
+ on:
8
+ workflow_dispatch:
9
+ inputs:
10
+ category:
11
+ description: 'Command category (db, ops, backup)'
12
+ required: true
13
+ type: string
14
+ command:
15
+ description: 'Command to run (e.g., seed, migrate, logs)'
16
+ required: true
17
+ type: string
18
+ stage:
19
+ description: 'Target environment'
20
+ required: true
21
+ type: choice
22
+ options:
23
+ - staging
24
+ - prod
25
+ options:
26
+ description: 'Command options (JSON)'
27
+ required: false
28
+ default: '{}'
29
+
30
+ jobs:
31
+ run-command:
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - name: Checkout code
35
+ uses: actions/checkout@v4
36
+
37
+ - name: Install yq
38
+ run: |
39
+ sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
40
+ sudo chmod +x /usr/local/bin/yq
41
+
42
+ - name: Read config
43
+ id: config
44
+ env:
45
+ STAGE: ${{ inputs.stage }}
46
+ run: |
47
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
48
+ if [ ! -f "$CONFIG_FILE" ]; then
49
+ echo "❌ stack.yml or factiii.yml not found"
50
+ exit 1
51
+ fi
52
+
53
+ REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
54
+ HOST=$(yq eval ".$STAGE.domain // \"\"" "$CONFIG_FILE")
55
+ SSH_USER=$(yq eval ".$STAGE.ssh_user // \"ubuntu\"" "$CONFIG_FILE")
56
+
57
+ echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
58
+ echo "host=$HOST" >> $GITHUB_OUTPUT
59
+ echo "ssh_user=$SSH_USER" >> $GITHUB_OUTPUT
60
+
61
+ - name: Check environment configured
62
+ env:
63
+ STAGE: ${{ inputs.stage }}
64
+ run: |
65
+ CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
66
+ HAS_ENV=$(yq eval ".$STAGE != null" "$CONFIG_FILE")
67
+ if [ "$HAS_ENV" != "true" ]; then
68
+ echo "$STAGE not configured in config"
69
+ exit 1
70
+ fi
71
+
72
+ - name: Check SSH secret
73
+ env:
74
+ STAGE: ${{ inputs.stage }}
75
+ SSH_KEY: ${{ inputs.stage == 'staging' && secrets.STAGING_SSH || secrets.PROD_SSH }}
76
+ run: |
77
+ if [ -z "$SSH_KEY" ]; then
78
+ SECRET_NAME="${STAGE^^}_SSH"
79
+ echo "${SECRET_NAME} secret not found"
80
+ echo "Add it at: https://github.com/${{ github.repository }}/settings/secrets/actions"
81
+ exit 1
82
+ fi
83
+
84
+ - name: Setup SSH
85
+ env:
86
+ SSH_KEY: ${{ inputs.stage == 'staging' && secrets.STAGING_SSH || secrets.PROD_SSH }}
87
+ run: |
88
+ mkdir -p ~/.ssh
89
+ echo "$SSH_KEY" > ~/.ssh/deploy_key
90
+ chmod 600 ~/.ssh/deploy_key
91
+
92
+ - name: Run command via SSH
93
+ env:
94
+ HOST: ${{ steps.config.outputs.host }}
95
+ USER: ${{ steps.config.outputs.ssh_user }}
96
+ REPO_NAME: ${{ steps.config.outputs.repo_name }}
97
+ CATEGORY: ${{ inputs.category }}
98
+ COMMAND: ${{ inputs.command }}
99
+ STAGE: ${{ inputs.stage }}
100
+ run: |
101
+ if [ -z "$HOST" ]; then
102
+ echo "Missing domain in config: $STAGE.domain"
103
+ exit 1
104
+ fi
105
+
106
+ echo "Running: stack $CATEGORY $COMMAND --$STAGE"
107
+ echo "Server: $USER@$HOST"
108
+ echo ""
109
+
110
+ ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no -o ConnectTimeout=10 -o ServerAliveInterval=60 -o ServerAliveCountMax=5 "$USER@$HOST" \
111
+ "export PATH=\"/opt/homebrew/bin:/usr/local/bin:\$PATH\" && \
112
+ REPO_DIR=\"\$HOME/.factiii/$REPO_NAME\" && \
113
+ if [ -d \"\$REPO_DIR\" ]; then \
114
+ cd \"\$REPO_DIR\" && \
115
+ GITHUB_ACTIONS=true npx stack $CATEGORY $COMMAND --$STAGE; \
116
+ else \
117
+ echo \"Repo directory not found at \$REPO_DIR\"; \
118
+ echo \"Run deployment first to clone the repository\"; \
119
+ exit 1; \
120
+ fi"
121
+
122
+ EXIT_CODE=$?
123
+ rm -f ~/.ssh/deploy_key
124
+
125
+ if [ $EXIT_CODE -eq 0 ]; then
126
+ echo ""
127
+ echo "Command completed successfully"
128
+ else
129
+ echo ""
130
+ echo "Command failed with exit code $EXIT_CODE"
131
+ exit $EXIT_CODE
132
+ fi