-
Notifications
You must be signed in to change notification settings - Fork 0
192 lines (179 loc) · 8.14 KB
/
deploy-api.yml
File metadata and controls
192 lines (179 loc) · 8.14 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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# Deploy FastAPI (api/) to the VPS — venv + systemd + Nginx reload.
# MariaDB may be remote (e.g. o2switch): DATABASE_URL in secrets.
# On the VPS: install xvfb + xauth and run Uvicorn under xvfb-run (headed Chromium if VINTED_BROWSER_HEADLESS=false).
# Optional secret VINTED_BROWSER_HEADLESS: missing → true (legacy); false → less likely flagged by Vinted on Xvfb.
name: Deploy API (FastAPI)
on:
push:
branches: [main]
paths:
- 'api/**'
- '.github/workflows/deploy-api.yml'
pull_request:
branches: [main]
paths:
- 'api/**'
workflow_dispatch:
concurrency:
group: goupixdex-api-${{ github.ref }}
cancel-in-progress: true
jobs:
lint-pr:
name: Sanity check (PR — sans déploiement)
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: |
api
sparse-checkout-cone-mode: true
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install deps & import check
run: |
python -m pip install --upgrade pip
pip install -r api/requirements.txt
cd api && PYTHONPATH=. python -c "import main; print('import ok')"
deploy:
name: Deploy API
if: github.event_name == 'workflow_dispatch' || github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: Checkout (api only)
uses: actions/checkout@v4
with:
fetch-depth: 1
sparse-checkout: |
api
sparse-checkout-cone-mode: true
- name: Write api/.env for upload
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
SEED_USER_EMAIL: ${{ secrets.SEED_USER_EMAIL }}
SEED_USER_PASSWORD: ${{ secrets.SEED_USER_PASSWORD }}
SEED_MARGIN_PERCENT: ${{ secrets.SEED_MARGIN_PERCENT }}
SEED_DEV_ARTICLES: ${{ secrets.SEED_DEV_ARTICLES }}
SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
SUPABASE_API_KEY: ${{ secrets.SUPABASE_API_KEY }}
SUPABASE_STORAGE_BUCKET: ${{ secrets.SUPABASE_STORAGE_BUCKET }}
POKE_WALLET_API_KEY: ${{ secrets.POKE_WALLET_API_KEY }}
POKE_WALLET_BASE_URL: ${{ secrets.POKE_WALLET_BASE_URL }}
POKE_WALLET_PROXY_SECRET: ${{ secrets.POKE_WALLET_PROXY_SECRET }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
VINTED_EMAIL_OR_USERNAME: ${{ secrets.VINTED_EMAIL_OR_USERNAME }}
VINTED_PASSWORD: ${{ secrets.VINTED_PASSWORD }}
CORS_ORIGINS: ${{ secrets.CORS_ORIGINS }}
VINTED_CHROME_EXECUTABLE: ${{ secrets.VINTED_CHROME_EXECUTABLE }}
VINTED_BROWSER_HEADLESS: ${{ secrets.VINTED_BROWSER_HEADLESS }}
EBAY_CLIENT_ID: ${{ secrets.EBAY_CLIENT_ID }}
EBAY_CLIENT_SECRET: ${{ secrets.EBAY_CLIENT_SECRET }}
EBAY_REDIRECT_URI: ${{ secrets.EBAY_REDIRECT_URI }}
EBAY_USE_SANDBOX: ${{ secrets.EBAY_USE_SANDBOX }}
EBAY_FR_FULFILLMENT_CARRIER_CODE: ${{ secrets.EBAY_FR_FULFILLMENT_CARRIER_CODE }}
EBAY_FR_FULFILLMENT_SERVICE_CODE: ${{ secrets.EBAY_FR_FULFILLMENT_SERVICE_CODE }}
run: |
set -euo pipefail
f=api/.env
CHROME_PATH="${VINTED_CHROME_EXECUTABLE:-/usr/bin/chromium}"
{
echo "DATABASE_URL=${DATABASE_URL}"
echo "JWT_SECRET=${JWT_SECRET}"
echo "SEED_USER_EMAIL=${SEED_USER_EMAIL:-}"
echo "SEED_USER_PASSWORD=${SEED_USER_PASSWORD:-}"
echo "SEED_MARGIN_PERCENT=${SEED_MARGIN_PERCENT:-60}"
echo "SEED_DEV_ARTICLES=${SEED_DEV_ARTICLES:-0}"
echo "SUPABASE_URL=${SUPABASE_URL:-}"
echo "SUPABASE_API_KEY=${SUPABASE_API_KEY:-}"
echo "SUPABASE_STORAGE_BUCKET=${SUPABASE_STORAGE_BUCKET:-GoupixDex}"
echo "POKE_WALLET_API_KEY=${POKE_WALLET_API_KEY:-}"
echo "POKE_WALLET_BASE_URL=${POKE_WALLET_BASE_URL:-https://api.pokewallet.io}"
echo "POKE_WALLET_PROXY_SECRET=${POKE_WALLET_PROXY_SECRET:-}"
echo "GROQ_API_KEY=${GROQ_API_KEY:-}"
echo "VINTED_EMAIL_OR_USERNAME=${VINTED_EMAIL_OR_USERNAME:-}"
echo "VINTED_PASSWORD=${VINTED_PASSWORD:-}"
echo "CORS_ORIGINS=${CORS_ORIGINS:-*}"
echo "VINTED_BROWSER_HEADLESS=${VINTED_BROWSER_HEADLESS:-true}"
echo "VINTED_CHROME_EXECUTABLE=${CHROME_PATH}"
echo "EBAY_CLIENT_ID=${EBAY_CLIENT_ID:-}"
echo "EBAY_CLIENT_SECRET=${EBAY_CLIENT_SECRET:-}"
echo "EBAY_REDIRECT_URI=${EBAY_REDIRECT_URI:-}"
echo "EBAY_USE_SANDBOX=${EBAY_USE_SANDBOX:-true}"
echo "EBAY_FR_FULFILLMENT_CARRIER_CODE=${EBAY_FR_FULFILLMENT_CARRIER_CODE:-Colissimo}"
echo "EBAY_FR_FULFILLMENT_SERVICE_CODE=${EBAY_FR_FULFILLMENT_SERVICE_CODE:-FR_ColiposteColissimo}"
} > "$f"
- name: Pack api tree
run: tar -czf api-bundle.tar.gz api
- name: Upload to VPS
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: api-bundle.tar.gz
target: ${{ secrets.DEPLOY_API_DIR }}
- name: Extract, venv, systemd, nginx
uses: appleboy/ssh-action@v1.0.3
env:
DEPLOY_API_DIR: ${{ secrets.DEPLOY_API_DIR }}
API_SYSTEMD_SERVICE: ${{ secrets.API_SYSTEMD_SERVICE }}
API_PORT: ${{ secrets.API_APP_PORT }}
DEPLOY_USER: ${{ secrets.SSH_USERNAME }}
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
envs: DEPLOY_API_DIR,API_SYSTEMD_SERVICE,API_PORT,DEPLOY_USER
script_stop: true
script: |
set -euo pipefail
TARGET="${DEPLOY_API_DIR%/}"
SVC="${API_SYSTEMD_SERVICE:-goupixdex-api.service}"
PORT="${API_PORT:-8000}"
mkdir -p "$TARGET"
rm -rf "$TARGET/api"
tar -xzf "$TARGET/api-bundle.tar.gz" -C "$TARGET"
rm -f "$TARGET/api-bundle.tar.gz"
APP_ROOT="$TARGET/api"
sudo chown -R "$USER:$USER" "$APP_ROOT" || true
sudo apt-get update -y
sudo apt-get install -y python3-venv python3-pip chromium fonts-liberation xvfb xauth
if [ ! -x "$APP_ROOT/.venv/bin/python" ]; then
python3 -m venv "$APP_ROOT/.venv"
fi
. "$APP_ROOT/.venv/bin/activate"
python -m pip install --upgrade pip wheel
pip install -r "$APP_ROOT/requirements.txt" --no-cache-dir
deactivate
# SQL migrations (files not already recorded in schema_migrations)
"$APP_ROOT/.venv/bin/python" "$APP_ROOT/migrations/run_migrations.py"
# Bootstrap DB if empty tables (user / margins; articles only if SEED_DEV_ARTICLES=1 on the VPS)
"$APP_ROOT/.venv/bin/python" "$APP_ROOT/seeders/conditional_seed.py"
sudo tee "/etc/systemd/system/${SVC}" > /dev/null <<EOF
[Unit]
Description=GoupixDex FastAPI (Uvicorn)
After=network.target
[Service]
Type=simple
User=${DEPLOY_USER}
WorkingDirectory=${APP_ROOT}
EnvironmentFile=${APP_ROOT}/.env
# Affichage virtuel : Chromium avec VINTED_BROWSER_HEADLESS=false a besoin d'un DISPLAY (xauth requis pour xvfb-run).
ExecStart=/usr/bin/xvfb-run -a --server-args="-screen 0 1920x1080x24" ${APP_ROOT}/.venv/bin/uvicorn main:app --host 127.0.0.1 --port ${PORT} --workers 1 --proxy-headers
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable "$SVC"
sudo systemctl restart "$SVC"
sudo systemctl --no-pager --full status "$SVC" || true
sudo nginx -t
sudo systemctl reload nginx