-
Notifications
You must be signed in to change notification settings - Fork 1
133 lines (113 loc) · 5.33 KB
/
Copy pathpreview.yml
File metadata and controls
133 lines (113 loc) · 5.33 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
name: Preview
on:
pull_request:
types: [opened, synchronize, reopened, closed]
jobs:
deploy-preview:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy preview environment
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
set -e
APP_NAME="${{ github.event.repository.name }}"
PR_NUMBER="${{ github.event.number }}"
PREVIEW_DOMAIN="pr-${PR_NUMBER}.preview.${{ secrets.PREVIEW_DOMAIN }}"
APP_DB=$(echo "${APP_NAME}" | tr '-' '_')_db
SCHEMA_NAME="pr_${PR_NUMBER}"
cd /opt/apps/${APP_NAME}
# Fetch and checkout the PR branch
git fetch origin pull/${PR_NUMBER}/head:pr-${PR_NUMBER} --force
git checkout pr-${PR_NUMBER}
# Create preview schema in the app's database
docker compose -f /opt/platform/docker-compose.yml exec -T postgres \
psql -U postgres -d ${APP_DB} -c "CREATE SCHEMA IF NOT EXISTS ${SCHEMA_NAME}"
# Read the app's .env and generate a preview-specific version
# with DATABASE_URL pointing to the PR schema
if [ ! -f deploy/.env ]; then
echo "ERROR: deploy/.env not found. Create it from deploy/env.template first."
exit 1
fi
# Generate preview .env with schema-aware DATABASE_URL
sed "s|^DATABASE_URL=.*|DATABASE_URL=postgresql://postgres:$(grep POSTGRES_PASSWORD /opt/platform/.env | cut -d= -f2)@postgres:5432/${APP_DB}?options=-csearch_path%3D${SCHEMA_NAME}|" \
deploy/.env > deploy/.env.pr-${PR_NUMBER}
# Build and start the app container (skip optional services like celery-worker)
docker compose -p ${APP_NAME}-pr-${PR_NUMBER} -f deploy/docker-compose.yml \
--env-file deploy/.env.pr-${PR_NUMBER} up -d --build app
# Run database migrations against the preview schema
docker compose -p ${APP_NAME}-pr-${PR_NUMBER} -f deploy/docker-compose.yml \
exec -T app alembic -c app/alembic.ini upgrade head
# Generate Caddyfile for preview domain
cat > /opt/platform/caddy-apps/${APP_NAME}-pr-${PR_NUMBER}.caddy <<CADDYEOF
${PREVIEW_DOMAIN} {
reverse_proxy ${APP_NAME}-pr-${PR_NUMBER}-app-1:8000
}
CADDYEOF
# Reload Caddy to pick up new route
docker compose -f /opt/platform/docker-compose.yml exec -T caddy \
caddy reload --config /etc/caddy/Caddyfile
# Switch back to main so production deploys aren't affected
git checkout main
- name: Post preview URL
uses: actions/github-script@v7
with:
script: |
const previewDomain = `pr-${{ github.event.number }}.preview.${{ secrets.PREVIEW_DOMAIN }}`;
const body = `Preview deployed: https://${previewDomain}\n\nHealth check: https://${previewDomain}/health`;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find(c => c.body.startsWith('Preview deployed:'));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
}
cleanup-preview:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- name: Clean up preview environment
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
set -e
APP_NAME="${{ github.event.repository.name }}"
PR_NUMBER="${{ github.event.number }}"
APP_DB=$(echo "${APP_NAME}" | tr '-' '_')_db
SCHEMA_NAME="pr_${PR_NUMBER}"
# Stop and remove preview containers
cd /opt/apps/${APP_NAME}
docker compose -p ${APP_NAME}-pr-${PR_NUMBER} -f deploy/docker-compose.yml down --rmi local || true
# Drop the preview schema
docker compose -f /opt/platform/docker-compose.yml exec -T postgres \
psql -U postgres -d ${APP_DB} -c "DROP SCHEMA IF EXISTS ${SCHEMA_NAME} CASCADE"
# Remove preview Caddyfile
rm -f /opt/platform/caddy-apps/${APP_NAME}-pr-${PR_NUMBER}.caddy
# Reload Caddy
docker compose -f /opt/platform/docker-compose.yml exec -T caddy \
caddy reload --config /etc/caddy/Caddyfile
# Clean up preview .env and branch
rm -f deploy/.env.pr-${PR_NUMBER}
git branch -D pr-${PR_NUMBER} || true