Repository navigation
178 lines (160 loc) · 7.76 KB
/
Copy pathdeploy.yml
File metadata and controls
178 lines (160 loc) · 7.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
name: Deploy
on:
workflow_run:
workflows: ["CI"]
branches: [main]
types:
- completed
workflow_dispatch: {}
jobs:
deploy:
name: Deploy to Production
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
environment: production
steps:
- name: Write production env file and deploy via docker compose
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_SSH_KEY }}
envs: DATABASE_URL,JWT_SECRET,API_KEY_PEPPER,PLATFORM_SECRET_KEY,ARBITRATOR_SECRET_KEY,WALLET_ENCRYPTION_KEY,WALLET_SECRET_LOCAL_KEK,OPS_API_KEY,UNSUBSCRIBE_SECRET,IMPACT_SIGNING_SECRET,USDC_ISSUER,STELLAR_NETWORK,STELLAR_HORIZON_URL,FRONTEND_URL,DEPLOY_PATH,SENTRY_RELEASE
script: |
set -euo pipefail
cd "$DEPLOY_PATH"
# Record current HEAD before any changes — used by the rollback step.
git rev-parse HEAD > .previous-deploy-sha
echo "Pre-deploy SHA: $(cat .previous-deploy-sha)"
# Preserve any local modifications (no-op on a clean tree).
git stash --include-untracked
git fetch origin main
# --ff-only refuses to proceed if the local branch has diverged
# (e.g. a force-push landed or a local commit exists), failing
# explicitly instead of silently overwriting local state.
git checkout main
git pull --ff-only origin main || {
echo "ERROR: Fast-forward failed — local branch has diverged from origin/main."
echo "Manual intervention required. Restoring stashed changes."
git stash pop || true
exit 1
}
git rev-parse HEAD > .previous-deploy-sha
echo "Pre-deploy SHA: $(cat .previous-deploy-sha)"
# Preserve any local modifications (no-op on a clean tree).
git stash --include-untracked
git fetch origin main
# --ff-only refuses to proceed if the local branch has diverged
# (e.g. a force-push landed or a local commit exists), failing
# explicitly instead of silently overwriting local state.
git checkout main
git pull --ff-only origin main || {
echo "ERROR: Fast-forward failed — local branch has diverged from origin/main."
echo "Manual intervention required. Restoring stashed changes."
git stash pop || true
exit 1
}
printf '%s\n' "NODE_ENV=production" \
"DATABASE_URL=${DATABASE_URL}" \
"JWT_SECRET=${JWT_SECRET}" \
"API_KEY_PEPPER=${API_KEY_PEPPER}" \
"PLATFORM_SECRET_KEY=${PLATFORM_SECRET_KEY}" \
"ARBITRATOR_SECRET_KEY=${ARBITRATOR_SECRET_KEY}" \
"WALLET_ENCRYPTION_KEY=${WALLET_ENCRYPTION_KEY}" \
"WALLET_SECRET_LOCAL_KEK=${WALLET_SECRET_LOCAL_KEK}" \
"OPS_API_KEY=${OPS_API_KEY}" \
"UNSUBSCRIBE_SECRET=${UNSUBSCRIBE_SECRET}" \
"IMPACT_SIGNING_SECRET=${IMPACT_SIGNING_SECRET}" \
"USDC_ISSUER=${USDC_ISSUER}" \
"STELLAR_NETWORK=${STELLAR_NETWORK}" \
"STELLAR_HORIZON_URL=${STELLAR_HORIZON_URL}" \
"FRONTEND_URL=${FRONTEND_URL}" \
"SENTRY_RELEASE=${SENTRY_RELEASE}" \
> backend/.env
export SENTRY_RELEASE="${SENTRY_RELEASE}"
docker compose -f docker-compose.prod.yml up -d --build
docker compose -f docker-compose.prod.yml exec -T backend node db/migrate.js
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
API_KEY_PEPPER: ${{ secrets.API_KEY_PEPPER }}
PLATFORM_SECRET_KEY: ${{ secrets.PLATFORM_SECRET_KEY }}
ARBITRATOR_SECRET_KEY: ${{ secrets.ARBITRATOR_SECRET_KEY }}
WALLET_ENCRYPTION_KEY: ${{ secrets.WALLET_ENCRYPTION_KEY }}
WALLET_SECRET_LOCAL_KEK: ${{ secrets.WALLET_SECRET_LOCAL_KEK }}
OPS_API_KEY: ${{ secrets.OPS_API_KEY }}
UNSUBSCRIBE_SECRET: ${{ secrets.UNSUBSCRIBE_SECRET }}
IMPACT_SIGNING_SECRET: ${{ secrets.IMPACT_SIGNING_SECRET }}
USDC_ISSUER: ${{ secrets.USDC_ISSUER }}
STELLAR_NETWORK: ${{ secrets.STELLAR_NETWORK }}
STELLAR_HORIZON_URL: ${{ secrets.STELLAR_HORIZON_URL }}
FRONTEND_URL: ${{ secrets.FRONTEND_URL }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
SENTRY_RELEASE: ${{ github.sha }}
- name: Wait for backend to become healthy
run: |
for i in $(seq 1 10); do
if curl -fsS "${{ secrets.DEPLOY_HEALTH_URL }}/health"; then
echo "Health check passed"
exit 0
fi
echo "Health check attempt $i failed, retrying in 5s..."
sleep 5
done
echo "Health check failed after 10 attempts"
exit 1
- name: Rollback on health check failure
if: failure()
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_SSH_KEY }}
envs: DATABASE_URL,JWT_SECRET,API_KEY_PEPPER,PLATFORM_SECRET_KEY,ARBITRATOR_SECRET_KEY,WALLET_ENCRYPTION_KEY,WALLET_SECRET_LOCAL_KEK,OPS_API_KEY,UNSUBSCRIBE_SECRET,IMPACT_SIGNING_SECRET,USDC_ISSUER,STELLAR_NETWORK,STELLAR_HORIZON_URL,FRONTEND_URL,DEPLOY_PATH,SENTRY_RELEASE
script: |
set -euo pipefail
cd "$DEPLOY_PATH"
if [ ! -f .previous-deploy-sha ]; then
echo "No previous deploy SHA recorded; skipping rollback"
exit 0
fi
PREVIOUS_SHA=$(cat .previous-deploy-sha)
echo "Rolling back to previous deployment SHA: $PREVIOUS_SHA"
git reset --hard "$PREVIOUS_SHA"
docker compose -f docker-compose.prod.yml up -d --build
docker compose -f docker-compose.prod.yml exec -T backend node db/migrate.js
echo "Rolled back and redeployed $PREVIOUS_SHA"
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
API_KEY_PEPPER: ${{ secrets.API_KEY_PEPPER }}
PLATFORM_SECRET_KEY: ${{ secrets.PLATFORM_SECRET_KEY }}
ARBITRATOR_SECRET_KEY: ${{ secrets.ARBITRATOR_SECRET_KEY }}
WALLET_ENCRYPTION_KEY: ${{ secrets.WALLET_ENCRYPTION_KEY }}
WALLET_SECRET_LOCAL_KEK: ${{ secrets.WALLET_SECRET_LOCAL_KEK }}
OPS_API_KEY: ${{ secrets.OPS_API_KEY }}
UNSUBSCRIBE_SECRET: ${{ secrets.UNSUBSCRIBE_SECRET }}
IMPACT_SIGNING_SECRET: ${{ secrets.IMPACT_SIGNING_SECRET }}
USDC_ISSUER: ${{ secrets.USDC_ISSUER }}
STELLAR_NETWORK: ${{ secrets.STELLAR_NETWORK }}
STELLAR_HORIZON_URL: ${{ secrets.STELLAR_HORIZON_URL }}
FRONTEND_URL: ${{ secrets.FRONTEND_URL }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
SENTRY_RELEASE: ${{ github.sha }}
- name: Notify Slack on rollback
if: failure()
uses: 8398a7/action-slack@v3
with:
status: failure
fields: repo,commit,author
text: Deployment failed health check and was automatically rolled back to the previous release on ${{ secrets.DEPLOY_HOST }}.
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
- name: Post deploy status to Slack
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: Deployment to production completed.
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
if: success()