-
Notifications
You must be signed in to change notification settings - Fork 0
135 lines (119 loc) · 5.11 KB
/
Copy pathdeploy.yml
File metadata and controls
135 lines (119 loc) · 5.11 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
name: Deploy
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: 'pip'
- name: Run tests
run: |
pip install -r requirements.txt
pip install pytest
if python -m pytest --collect-only -q >/dev/null 2>&1; then
pytest --tb=short
else
echo "No tests found, skipping"
fi
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create deployment
id: deployment
uses: actions/github-script@v7
with:
script: |
const deployment = await github.rest.repos.createDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.sha,
environment: 'production',
auto_merge: false,
required_contexts: [],
description: `Deploy ${context.sha.substring(0, 7)} to production`
});
return deployment.data.id;
- name: Deploy to server
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
APP_NAME="${{ github.event.repository.name }}"
cd /opt/apps/${APP_NAME}
git pull origin main
# Verify app .env exists
if [ ! -f deploy/.env ]; then
echo "ERROR: deploy/.env not found. Create it from deploy/env.template first."
exit 1
fi
# Create app-specific database if it doesn't exist
APP_DB=$(echo "${APP_NAME}" | tr '-' '_')_db
docker compose -f /opt/platform/docker-compose.yml exec -T postgres \
psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = '${APP_DB}'" | grep -q 1 \
|| docker compose -f /opt/platform/docker-compose.yml exec -T postgres \
psql -U postgres -c "CREATE DATABASE ${APP_DB}"
# Source per-app credentials and update deploy/.env if available
CREDENTIALS_FILE="/opt/platform/credentials/${APP_NAME}.env"
if [ -f "$CREDENTIALS_FILE" ]; then
echo "Using per-app credentials from $CREDENTIALS_FILE"
source "$CREDENTIALS_FILE"
# Update DATABASE_URL with per-app user credentials
sed -i "s|^DATABASE_URL=.*|DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@postgres:5432/${APP_DB}|" deploy/.env
# Update S3 credentials with per-app MinIO user
sed -i "s|^S3_ACCESS_KEY=.*|S3_ACCESS_KEY=${S3_ACCESS_KEY}|" deploy/.env
sed -i "s|^S3_SECRET_KEY=.*|S3_SECRET_KEY=${S3_SECRET_KEY}|" deploy/.env
# Update S3 bucket name
sed -i "s|^S3_BUCKET=.*|S3_BUCKET=${APP_NAME}-uploads|" deploy/.env
echo "deploy/.env updated with per-app credentials"
else
echo "WARNING: Per-app credentials not found at $CREDENTIALS_FILE"
echo "Run create-app-credentials.sh ${APP_NAME} for isolated credentials."
echo "Falling back to existing deploy/.env credentials."
fi
# Build and start app containers (project name = app name for predictable container names)
docker compose -p ${APP_NAME} -f deploy/docker-compose.yml up -d --build
# Run database migrations
docker compose -p ${APP_NAME} -f deploy/docker-compose.yml exec -T app alembic -c app/alembic.ini upgrade head
# Health check
bash scripts/health-check.sh https://${{ secrets.APP_DOMAIN }}/health
# Generate rendered Caddyfile for platform Caddy
cat > /opt/platform/caddy-apps/${APP_NAME}.caddy <<CADDYEOF
${{ secrets.APP_DOMAIN }} {
reverse_proxy ${APP_NAME}-app-1:8000
}
CADDYEOF
docker compose -f /opt/platform/docker-compose.yml exec -T caddy caddy reload --config /etc/caddy/Caddyfile
- name: Update deployment status (success)
if: success()
uses: actions/github-script@v7
with:
script: |
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: ${{ steps.deployment.outputs.result }},
state: 'success',
environment_url: `https://${{ secrets.APP_DOMAIN }}`,
description: 'Deployment succeeded'
});
- name: Update deployment status (failure)
if: failure()
uses: actions/github-script@v7
with:
script: |
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: ${{ steps.deployment.outputs.result }},
state: 'failure',
description: 'Deployment failed'
});