@factiii/stack 0.1.25 → 0.1.27

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 (52) hide show
  1. package/dist/cli/init.d.ts.map +1 -1
  2. package/dist/cli/init.js +285 -6
  3. package/dist/cli/init.js.map +1 -1
  4. package/dist/cli/scan.d.ts.map +1 -1
  5. package/dist/cli/scan.js +28 -13
  6. package/dist/cli/scan.js.map +1 -1
  7. package/dist/constants/config-files.d.ts +6 -0
  8. package/dist/constants/config-files.d.ts.map +1 -1
  9. package/dist/constants/config-files.js +16 -1
  10. package/dist/constants/config-files.js.map +1 -1
  11. package/dist/plugins/pipelines/factiii/index.d.ts +5 -3
  12. package/dist/plugins/pipelines/factiii/index.d.ts.map +1 -1
  13. package/dist/plugins/pipelines/factiii/index.js +14 -77
  14. package/dist/plugins/pipelines/factiii/index.js.map +1 -1
  15. package/dist/plugins/pipelines/factiii/scanfix/env-files.d.ts +12 -0
  16. package/dist/plugins/pipelines/factiii/scanfix/env-files.d.ts.map +1 -0
  17. package/dist/plugins/pipelines/factiii/scanfix/env-files.js +310 -0
  18. package/dist/plugins/pipelines/factiii/scanfix/env-files.js.map +1 -0
  19. package/dist/plugins/pipelines/factiii/scanfix/local-config.d.ts +7 -0
  20. package/dist/plugins/pipelines/factiii/scanfix/local-config.d.ts.map +1 -0
  21. package/dist/plugins/pipelines/factiii/scanfix/local-config.js +70 -0
  22. package/dist/plugins/pipelines/factiii/scanfix/local-config.js.map +1 -0
  23. package/dist/plugins/pipelines/factiii/scanfix/workflows.d.ts.map +1 -1
  24. package/dist/plugins/pipelines/factiii/scanfix/workflows.js +10 -24
  25. package/dist/plugins/pipelines/factiii/scanfix/workflows.js.map +1 -1
  26. package/dist/plugins/pipelines/factiii/utils/workflows.d.ts.map +1 -1
  27. package/dist/plugins/pipelines/factiii/utils/workflows.js +5 -20
  28. package/dist/plugins/pipelines/factiii/utils/workflows.js.map +1 -1
  29. package/dist/plugins/pipelines/factiii/workflows/stack-ci.yml +56 -0
  30. package/dist/plugins/pipelines/factiii/workflows/stack-cicd-prod.yml +35 -96
  31. package/dist/utils/config-helpers.d.ts +15 -0
  32. package/dist/utils/config-helpers.d.ts.map +1 -1
  33. package/dist/utils/config-helpers.js +57 -5
  34. package/dist/utils/config-helpers.js.map +1 -1
  35. package/package.json +1 -1
  36. package/dist/plugins/pipelines/factiii/workflows/factiii-cicd-prod.yml +0 -115
  37. package/dist/plugins/pipelines/factiii/workflows/factiii-cicd-staging.yml +0 -120
  38. package/dist/plugins/pipelines/factiii/workflows/factiii-command.yml +0 -132
  39. package/dist/plugins/pipelines/factiii/workflows/factiii-deploy.yml +0 -202
  40. package/dist/plugins/pipelines/factiii/workflows/factiii-dev-sync.yml +0 -181
  41. package/dist/plugins/pipelines/factiii/workflows/factiii-fix.yml +0 -178
  42. package/dist/plugins/pipelines/factiii/workflows/factiii-pr-check.yml +0 -106
  43. package/dist/plugins/pipelines/factiii/workflows/factiii-scan.yml +0 -183
  44. package/dist/plugins/pipelines/factiii/workflows/factiii-undeploy.yml +0 -96
  45. package/dist/plugins/pipelines/factiii/workflows/stack-cicd-staging.yml +0 -120
  46. package/dist/plugins/pipelines/factiii/workflows/stack-command.yml +0 -132
  47. package/dist/plugins/pipelines/factiii/workflows/stack-deploy.yml +0 -202
  48. package/dist/plugins/pipelines/factiii/workflows/stack-dev-sync.yml +0 -181
  49. package/dist/plugins/pipelines/factiii/workflows/stack-fix.yml +0 -177
  50. package/dist/plugins/pipelines/factiii/workflows/stack-pr-check.yml +0 -106
  51. package/dist/plugins/pipelines/factiii/workflows/stack-scan.yml +0 -182
  52. package/dist/plugins/pipelines/factiii/workflows/stack-undeploy.yml +0 -96
@@ -1,96 +0,0 @@
1
- name: Factiii Undeploy
2
-
3
- # Generated by @factiii/stack v{VERSION}
4
- # Manual workflow to remove deployment from a server
5
- # Thin workflow - just SSH and call CLI
6
-
7
- on:
8
- workflow_dispatch:
9
- inputs:
10
- environment:
11
- description: 'Environment to undeploy'
12
- required: true
13
- type: choice
14
- options:
15
- - staging
16
- - prod
17
-
18
- jobs:
19
- undeploy:
20
- runs-on: ubuntu-latest
21
- steps:
22
- - name: Checkout code
23
- uses: actions/checkout@v4
24
-
25
- - name: Install yq
26
- run: |
27
- sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
28
- sudo chmod +x /usr/local/bin/yq
29
-
30
- - name: Read config
31
- id: config
32
- run: |
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"
36
- exit 1
37
- fi
38
-
39
- REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
40
-
41
- if [ "${{ inputs.environment }}" == "staging" ]; then
42
- HOST=$(yq eval '.staging.domain // ""' "$CONFIG_FILE")
43
- SSH_USER=$(yq eval '.staging.ssh_user // "ubuntu"' "$CONFIG_FILE")
44
- else
45
- HOST=$(yq eval '.prod.domain // ""' "$CONFIG_FILE")
46
- SSH_USER=$(yq eval '.prod.ssh_user // "ubuntu"' "$CONFIG_FILE")
47
- fi
48
-
49
- echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
50
- echo "host=$HOST" >> $GITHUB_OUTPUT
51
- echo "ssh_user=$SSH_USER" >> $GITHUB_OUTPUT
52
-
53
- - name: Setup SSH
54
- env:
55
- SSH_KEY: ${{ inputs.environment == 'staging' && secrets.STAGING_SSH || secrets.PROD_SSH }}
56
- run: |
57
- if [ -z "$SSH_KEY" ]; then
58
- echo "❌ Missing ${{ inputs.environment == 'staging' && 'STAGING_SSH' || 'PROD_SSH' }} secret"
59
- exit 1
60
- fi
61
-
62
- mkdir -p ~/.ssh
63
- echo "$SSH_KEY" > ~/.ssh/deploy_key
64
- chmod 600 ~/.ssh/deploy_key
65
-
66
- - name: Undeploy via CLI
67
- env:
68
- HOST: ${{ steps.config.outputs.host }}
69
- USER: ${{ steps.config.outputs.ssh_user }}
70
- REPO_NAME: ${{ steps.config.outputs.repo_name }}
71
- ENVIRONMENT: ${{ inputs.environment }}
72
- run: |
73
- if [ -z "$HOST" ]; then
74
- echo "❌ Missing domain in config: $ENVIRONMENT.domain"
75
- exit 1
76
- fi
77
-
78
- echo "🗑️ Undeploying from $ENVIRONMENT ($HOST)..."
79
-
80
- ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no "$USER@$HOST" bash -s << EOF
81
- set -e
82
- REPO_DIR=~/.factiii/$REPO_NAME
83
-
84
- if [ -d "\$REPO_DIR" ]; then
85
- cd \$REPO_DIR
86
- echo "🚀 Running undeploy..."
87
- export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" && \
88
- GITHUB_ACTIONS=true npx factiii undeploy --$ENVIRONMENT || true
89
- else
90
- echo "⚠️ Repo directory not found, nothing to undeploy"
91
- fi
92
- EOF
93
-
94
- rm -f ~/.ssh/deploy_key
95
- echo "✅ Undeploy complete!"
96
-
@@ -1,120 +0,0 @@
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
@@ -1,132 +0,0 @@
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
@@ -1,202 +0,0 @@
1
- name: Stack Deploy
2
-
3
- # Generated by @factiii/stack v{VERSION}
4
- # INFRASTRUCTURE: Manual deployment triggered via CLI
5
- # Run: npx stack deploy --staging or npx stack deploy --prod
6
- # For auto-deploy on push, see stack-cicd-staging.yml / stack-cicd-prod.yml
7
-
8
- on:
9
- workflow_dispatch:
10
- inputs:
11
- environment:
12
- description: 'Environment to deploy'
13
- required: true
14
- type: choice
15
- options:
16
- - staging
17
- - prod
18
-
19
- jobs:
20
- deploy:
21
- runs-on: ubuntu-latest
22
- steps:
23
- - name: Checkout code
24
- uses: actions/checkout@v4
25
-
26
- - name: Install yq
27
- run: |
28
- sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
29
- sudo chmod +x /usr/local/bin/yq
30
-
31
- - name: Read config
32
- id: config
33
- run: |
34
- CONFIG_FILE="stack.yml"
35
- if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
36
- if [ ! -f "$CONFIG_FILE" ]; then
37
- echo "❌ stack.yml or factiii.yml not found"
38
- exit 1
39
- fi
40
-
41
- REPO_NAME=$(yq eval '.name' "$CONFIG_FILE")
42
-
43
- if [ "${{ inputs.environment }}" == "staging" ]; then
44
- HOST=$(yq eval '.staging.domain // ""' "$CONFIG_FILE")
45
- SSH_USER=$(yq eval '.staging.ssh_user // "ubuntu"' "$CONFIG_FILE")
46
- else
47
- HOST=$(yq eval '.prod.domain // ""' "$CONFIG_FILE")
48
- SSH_USER=$(yq eval '.prod.ssh_user // "ubuntu"' "$CONFIG_FILE")
49
- fi
50
-
51
- echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
52
- echo "host=$HOST" >> $GITHUB_OUTPUT
53
- echo "ssh_user=$SSH_USER" >> $GITHUB_OUTPUT
54
-
55
- - name: Check if environment configured
56
- id: check_env
57
- run: |
58
- CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
59
- if [ "${{ inputs.environment }}" == "staging" ]; then
60
- HAS_ENV=$(yq eval '.staging != null' "$CONFIG_FILE")
61
- else
62
- HAS_ENV=$(yq eval '.prod != null' "$CONFIG_FILE")
63
- fi
64
-
65
- echo "has_env=$HAS_ENV" >> $GITHUB_OUTPUT
66
-
67
- if [ "$HAS_ENV" != "true" ]; then
68
- echo "⏭️ ${{ inputs.environment }} not configured in config"
69
- exit 1
70
- fi
71
-
72
- - name: Read staging config (for prod builds)
73
- if: steps.check_env.outputs.has_env == 'true' && inputs.environment == 'prod'
74
- id: staging_config
75
- run: |
76
- CONFIG_FILE="stack.yml"; if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="factiii.yml"; fi
77
- STAGING_HOST=$(yq eval '.staging.domain // ""' "$CONFIG_FILE")
78
- STAGING_SSH_USER=$(yq eval '.staging.ssh_user // "ubuntu"' "$CONFIG_FILE")
79
-
80
- echo "staging_host=$STAGING_HOST" >> $GITHUB_OUTPUT
81
- echo "staging_ssh_user=$STAGING_SSH_USER" >> $GITHUB_OUTPUT
82
-
83
- - name: Setup Node.js
84
- if: steps.check_env.outputs.has_env == 'true'
85
- uses: actions/setup-node@v4
86
- with:
87
- node-version: '20'
88
-
89
- - name: Load SSH keys from Ansible Vault
90
- if: steps.check_env.outputs.has_env == 'true'
91
- env:
92
- ANSIBLE_VAULT_PASSWORD: ${{ secrets.ANSIBLE_VAULT_PASSWORD }}
93
- run: |
94
- if [ -z "$ANSIBLE_VAULT_PASSWORD" ]; then
95
- echo "❌ Missing ANSIBLE_VAULT_PASSWORD secret (vault password)"
96
- exit 1
97
- fi
98
-
99
- npx stack secrets write-ssh-keys
100
-
101
- # Create deploy_key symlink for current environment
102
- if [ "${{ inputs.environment }}" == "staging" ]; then
103
- ln -sf ~/.ssh/staging_deploy_key ~/.ssh/deploy_key
104
- else
105
- ln -sf ~/.ssh/prod_deploy_key ~/.ssh/deploy_key
106
- fi
107
-
108
- - name: Build production image on staging (prod only)
109
- if: steps.check_env.outputs.has_env == 'true' && inputs.environment == 'prod'
110
- env:
111
- STAGING_HOST: ${{ steps.staging_config.outputs.staging_host }}
112
- STAGING_USER: ${{ steps.staging_config.outputs.staging_ssh_user }}
113
- REPO_NAME: ${{ steps.config.outputs.repo_name }}
114
- COMMIT_HASH: ${{ github.sha }}
115
- BRANCH: ${{ github.ref_name }}
116
- GITHUB_REPO: ${{ github.repository }}
117
- run: |
118
- if [ -z "$STAGING_HOST" ]; then
119
- echo "⚠️ Staging host not configured, skipping build step"
120
- exit 0
121
- fi
122
-
123
- echo "🔨 Building production image on staging server ($STAGING_HOST)..."
124
-
125
- ssh -i ~/.ssh/staging_deploy_key -o StrictHostKeyChecking=no "$STAGING_USER@$STAGING_HOST" \
126
- "export PATH=\"/opt/homebrew/bin:/usr/local/bin:\$PATH\" && \
127
- REPO_DIR=\"\$HOME/.factiii/$REPO_NAME\" && \
128
- if [ -d \"\$REPO_DIR\" ]; then \
129
- cd \"\$REPO_DIR\" && \
130
- GITHUB_ACTIONS=true COMMIT_HASH=$COMMIT_HASH BRANCH=$BRANCH GITHUB_REPO=$GITHUB_REPO \
131
- npx stack deploy --prod --commit $COMMIT_HASH --branch $BRANCH; \
132
- else \
133
- echo \"❌ Repo directory not found at \$REPO_DIR\"; \
134
- exit 1; \
135
- fi"
136
-
137
- BUILD_EXIT_CODE=$?
138
- if [ $BUILD_EXIT_CODE -ne 0 ]; then
139
- echo "❌ Build step failed with exit code $BUILD_EXIT_CODE"
140
- exit $BUILD_EXIT_CODE
141
- fi
142
-
143
- echo "✅ Production image built and pushed to ECR"
144
-
145
- - name: Deploy via CLI
146
- if: steps.check_env.outputs.has_env == 'true'
147
- env:
148
- HOST: ${{ steps.config.outputs.host }}
149
- USER: ${{ steps.config.outputs.ssh_user }}
150
- REPO_NAME: ${{ steps.config.outputs.repo_name }}
151
- ENVIRONMENT: ${{ inputs.environment }}
152
- COMMIT_HASH: ${{ github.sha }}
153
- BRANCH: ${{ github.ref_name }}
154
- GITHUB_REPO: ${{ github.repository }}
155
- STAGING_ENVS: ${{ inputs.environment == 'staging' && secrets.STAGING_ENVS || '' }}
156
- PROD_ENVS: ${{ inputs.environment == 'prod' && secrets.PROD_ENVS || '' }}
157
- run: |
158
- if [ -z "$HOST" ]; then
159
- echo "❌ Missing domain in config: $ENVIRONMENT.domain"
160
- exit 1
161
- fi
162
-
163
- echo "🚀 Deploying to $ENVIRONMENT ($HOST)..."
164
-
165
- # For prod, skip build step (already done in previous step)
166
- SKIP_BUILD_FLAG=""
167
- if [ "$ENVIRONMENT" == "prod" ]; then
168
- SKIP_BUILD_FLAG="SKIP_BUILD=true"
169
- fi
170
-
171
- # Prepare environment variables for SSH (base64 encode to handle special characters)
172
- ENV_VARS_EXPORT=""
173
- if [ "$ENVIRONMENT" == "staging" ] && [ -n "$STAGING_ENVS" ]; then
174
- ENV_VARS_B64=$(echo -n "$STAGING_ENVS" | base64 -w 0)
175
- ENV_VARS_EXPORT="STAGING_ENVS=\$(echo '$ENV_VARS_B64' | base64 -d) && export STAGING_ENVS && "
176
- elif [ "$ENVIRONMENT" == "prod" ] && [ -n "$PROD_ENVS" ]; then
177
- ENV_VARS_B64=$(echo -n "$PROD_ENVS" | base64 -w 0)
178
- ENV_VARS_EXPORT="PROD_ENVS=\$(echo '$ENV_VARS_B64' | base64 -d) && export PROD_ENVS && "
179
- fi
180
-
181
- ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no "$USER@$HOST" \
182
- "export PATH=\"/opt/homebrew/bin:/usr/local/bin:\$PATH\" && \
183
- REPO_DIR=\"\$HOME/.factiii/$REPO_NAME\" && \
184
- if [ -d \"\$REPO_DIR\" ]; then \
185
- cd \"\$REPO_DIR\" && \
186
- $ENV_VARS_EXPORT$SKIP_BUILD_FLAG GITHUB_ACTIONS=true COMMIT_HASH=$COMMIT_HASH BRANCH=$BRANCH GITHUB_REPO=$GITHUB_REPO \
187
- npx stack deploy --$ENVIRONMENT --commit $COMMIT_HASH --branch $BRANCH; \
188
- else \
189
- echo \"❌ Repo directory not found at \$REPO_DIR\"; \
190
- echo \"Run deployment first to clone the repository\"; \
191
- exit 1; \
192
- fi"
193
-
194
- DEPLOY_EXIT_CODE=$?
195
- rm -f ~/.ssh/deploy_key ~/.ssh/staging_deploy_key ~/.ssh/prod_deploy_key
196
-
197
- if [ $DEPLOY_EXIT_CODE -eq 0 ]; then
198
- echo "✅ Deployment complete!"
199
- else
200
- echo "❌ Deployment failed with exit code $DEPLOY_EXIT_CODE"
201
- exit $DEPLOY_EXIT_CODE
202
- fi