@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.
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +285 -6
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/scan.d.ts.map +1 -1
- package/dist/cli/scan.js +28 -13
- package/dist/cli/scan.js.map +1 -1
- package/dist/constants/config-files.d.ts +6 -0
- package/dist/constants/config-files.d.ts.map +1 -1
- package/dist/constants/config-files.js +16 -1
- package/dist/constants/config-files.js.map +1 -1
- package/dist/plugins/pipelines/factiii/index.d.ts +5 -3
- package/dist/plugins/pipelines/factiii/index.d.ts.map +1 -1
- package/dist/plugins/pipelines/factiii/index.js +14 -77
- package/dist/plugins/pipelines/factiii/index.js.map +1 -1
- package/dist/plugins/pipelines/factiii/scanfix/env-files.d.ts +12 -0
- package/dist/plugins/pipelines/factiii/scanfix/env-files.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/env-files.js +310 -0
- package/dist/plugins/pipelines/factiii/scanfix/env-files.js.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/local-config.d.ts +7 -0
- package/dist/plugins/pipelines/factiii/scanfix/local-config.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/local-config.js +70 -0
- package/dist/plugins/pipelines/factiii/scanfix/local-config.js.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/workflows.d.ts.map +1 -1
- package/dist/plugins/pipelines/factiii/scanfix/workflows.js +10 -24
- package/dist/plugins/pipelines/factiii/scanfix/workflows.js.map +1 -1
- package/dist/plugins/pipelines/factiii/utils/workflows.d.ts.map +1 -1
- package/dist/plugins/pipelines/factiii/utils/workflows.js +5 -20
- package/dist/plugins/pipelines/factiii/utils/workflows.js.map +1 -1
- package/dist/plugins/pipelines/factiii/workflows/stack-ci.yml +56 -0
- package/dist/plugins/pipelines/factiii/workflows/stack-cicd-prod.yml +35 -96
- package/dist/utils/config-helpers.d.ts +15 -0
- package/dist/utils/config-helpers.d.ts.map +1 -1
- package/dist/utils/config-helpers.js +57 -5
- package/dist/utils/config-helpers.js.map +1 -1
- package/package.json +1 -1
- package/dist/plugins/pipelines/factiii/workflows/factiii-cicd-prod.yml +0 -115
- package/dist/plugins/pipelines/factiii/workflows/factiii-cicd-staging.yml +0 -120
- package/dist/plugins/pipelines/factiii/workflows/factiii-command.yml +0 -132
- package/dist/plugins/pipelines/factiii/workflows/factiii-deploy.yml +0 -202
- package/dist/plugins/pipelines/factiii/workflows/factiii-dev-sync.yml +0 -181
- package/dist/plugins/pipelines/factiii/workflows/factiii-fix.yml +0 -178
- package/dist/plugins/pipelines/factiii/workflows/factiii-pr-check.yml +0 -106
- package/dist/plugins/pipelines/factiii/workflows/factiii-scan.yml +0 -183
- package/dist/plugins/pipelines/factiii/workflows/factiii-undeploy.yml +0 -96
- package/dist/plugins/pipelines/factiii/workflows/stack-cicd-staging.yml +0 -120
- package/dist/plugins/pipelines/factiii/workflows/stack-command.yml +0 -132
- package/dist/plugins/pipelines/factiii/workflows/stack-deploy.yml +0 -202
- package/dist/plugins/pipelines/factiii/workflows/stack-dev-sync.yml +0 -181
- package/dist/plugins/pipelines/factiii/workflows/stack-fix.yml +0 -177
- package/dist/plugins/pipelines/factiii/workflows/stack-pr-check.yml +0 -106
- package/dist/plugins/pipelines/factiii/workflows/stack-scan.yml +0 -182
- package/dist/plugins/pipelines/factiii/workflows/stack-undeploy.yml +0 -96
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
name: Factiii 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 factiii-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 factiii 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
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
name: Factiii 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 factiii-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 factiii 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: Factiii Command
|
|
2
|
-
|
|
3
|
-
# Generated by @factiii/stack v{VERSION}
|
|
4
|
-
# INFRASTRUCTURE: Run plugin commands on remote servers
|
|
5
|
-
# Run: npx factiii 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: factiii $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 factiii $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: Factiii Deploy
|
|
2
|
-
|
|
3
|
-
# Generated by @factiii/stack v{VERSION}
|
|
4
|
-
# INFRASTRUCTURE: Manual deployment triggered via CLI
|
|
5
|
-
# Run: npx factiii deploy --staging or npx factiii deploy --prod
|
|
6
|
-
# For auto-deploy on push, see factiii-cicd-staging.yml / factiii-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 factiii 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 factiii 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 factiii 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
|