chore(deploy): 简化 nginx 路由 + 自动部署 nginx config + 删除 .github workflows
Deploy / deploy (push) Successful in 1m16s
Deploy / deploy (push) Successful in 1m16s
- nginx: /app/ → Flutter,/ 兜底 → 营销站,移除零散 location 块 - deploy.yml: 每次部署自动 scp nginx-jiu.conf 到服务器并 nginx -t reload - deploy.yml: Release 附件新增 configs.tar.gz(nginx/systemd/compose 配置) - 删除 .github/workflows/(已全部迁移到 .gitea/) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,13 @@ jobs:
|
|||||||
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
|
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
|
||||||
run: |
|
run: |
|
||||||
tar -czf web.tar.gz -C client/build web
|
tar -czf web.tar.gz -C client/build web
|
||||||
|
tar -czf configs.tar.gz \
|
||||||
|
deploy/nginx-jiu.conf \
|
||||||
|
deploy/jiu.service \
|
||||||
|
deploy/production.env.template \
|
||||||
|
deploy/setup-ec2.sh \
|
||||||
|
deploy/docker-compose.yml \
|
||||||
|
deploy/docker-compose.jiu.yml
|
||||||
VERSION="v$(date +%Y%m%d.%H%M)"
|
VERSION="v$(date +%Y%m%d.%H%M)"
|
||||||
COMMIT="${{ gitea.sha }}"
|
COMMIT="${{ gitea.sha }}"
|
||||||
COMMIT_MSG=$(git log -1 --pretty="%s" HEAD)
|
COMMIT_MSG=$(git log -1 --pretty="%s" HEAD)
|
||||||
@@ -53,6 +60,8 @@ jobs:
|
|||||||
-H "Authorization: token ${FORGEJO_TOKEN}" -F "attachment=@backend/jiu-server"
|
-H "Authorization: token ${FORGEJO_TOKEN}" -F "attachment=@backend/jiu-server"
|
||||||
curl -sf -X POST "${FORGEJO_URL}/api/v1/repos/${{ gitea.repository }}/releases/${RELEASE_ID}/assets" \
|
curl -sf -X POST "${FORGEJO_URL}/api/v1/repos/${{ gitea.repository }}/releases/${RELEASE_ID}/assets" \
|
||||||
-H "Authorization: token ${FORGEJO_TOKEN}" -F "attachment=@web.tar.gz"
|
-H "Authorization: token ${FORGEJO_TOKEN}" -F "attachment=@web.tar.gz"
|
||||||
|
curl -sf -X POST "${FORGEJO_URL}/api/v1/repos/${{ gitea.repository }}/releases/${RELEASE_ID}/assets" \
|
||||||
|
-H "Authorization: token ${FORGEJO_TOKEN}" -F "attachment=@configs.tar.gz"
|
||||||
echo "Release ${VERSION} created"
|
echo "Release ${VERSION} created"
|
||||||
|
|
||||||
- name: Setup SSH
|
- name: Setup SSH
|
||||||
@@ -72,6 +81,8 @@ jobs:
|
|||||||
client/build/web/ ${EC2_USER}@${EC2_HOST}:/tmp/jiu-web-new/
|
client/build/web/ ${EC2_USER}@${EC2_HOST}:/tmp/jiu-web-new/
|
||||||
rsync -avz --delete -e "ssh -i ~/.ssh/ec2_deploy.pem" \
|
rsync -avz --delete -e "ssh -i ~/.ssh/ec2_deploy.pem" \
|
||||||
web/ ${EC2_USER}@${EC2_HOST}:/tmp/jiu-marketing-new/
|
web/ ${EC2_USER}@${EC2_HOST}:/tmp/jiu-marketing-new/
|
||||||
|
scp -O -i ~/.ssh/ec2_deploy.pem deploy/nginx-jiu.conf \
|
||||||
|
${EC2_USER}@${EC2_HOST}:/tmp/nginx-jiu.conf
|
||||||
ssh -i ~/.ssh/ec2_deploy.pem ${EC2_USER}@${EC2_HOST} << 'ENDSSH'
|
ssh -i ~/.ssh/ec2_deploy.pem ${EC2_USER}@${EC2_HOST} << 'ENDSSH'
|
||||||
sudo systemctl stop jiu
|
sudo systemctl stop jiu
|
||||||
cp /tmp/jiu-server /opt/jiu/backend/jiu-server
|
cp /tmp/jiu-server /opt/jiu/backend/jiu-server
|
||||||
@@ -87,7 +98,8 @@ jobs:
|
|||||||
mkdir -p /opt/jiu/marketing
|
mkdir -p /opt/jiu/marketing
|
||||||
rsync -a --delete /tmp/jiu-marketing-new/ /opt/jiu/marketing/
|
rsync -a --delete /tmp/jiu-marketing-new/ /opt/jiu/marketing/
|
||||||
rm -rf /tmp/jiu-marketing-new
|
rm -rf /tmp/jiu-marketing-new
|
||||||
sudo nginx -s reload
|
sudo cp /tmp/nginx-jiu.conf /etc/nginx/conf.d/jiu.conf
|
||||||
|
sudo nginx -t && sudo nginx -s reload
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
||||||
- name: Cleanup SSH key
|
- name: Cleanup SSH key
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
name: DB Backup
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 18 * * *' # UTC 18:00 = 北京时间 02:00
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
backup:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Setup SSH
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/ec2.pem
|
|
||||||
chmod 600 ~/.ssh/ec2.pem
|
|
||||||
ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Dump MySQL to NAS
|
|
||||||
env:
|
|
||||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
|
||||||
EC2_USER: ${{ secrets.EC2_USER }}
|
|
||||||
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
BACKUP_DIR=/volume1/backups/jiu-db
|
|
||||||
mkdir -p $BACKUP_DIR
|
|
||||||
FILENAME="jiu_db_$(date +%Y%m%d_%H%M%S).sql.gz"
|
|
||||||
ssh -i ~/.ssh/ec2.pem ${EC2_USER}@${EC2_HOST} \
|
|
||||||
"docker exec jiu_mysql mysqldump -uroot -p${DB_PASSWORD} jiu_db" \
|
|
||||||
| gzip > ${BACKUP_DIR}/${FILENAME}
|
|
||||||
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
|
|
||||||
echo "Saved: ${BACKUP_DIR}/${FILENAME}"
|
|
||||||
|
|
||||||
- name: Cleanup SSH key
|
|
||||||
if: always()
|
|
||||||
run: rm -f ~/.ssh/ec2.pem
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches-ignore: [main]
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: backend/go.mod
|
|
||||||
cache-dependency-path: backend/go.sum
|
|
||||||
|
|
||||||
- name: Go tests
|
|
||||||
working-directory: backend
|
|
||||||
run: go test ./...
|
|
||||||
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Flutter tests
|
|
||||||
working-directory: client
|
|
||||||
run: flutter test
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
name: Deploy
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: backend/go.mod
|
|
||||||
cache-dependency-path: backend/go.sum
|
|
||||||
|
|
||||||
- name: Go tests
|
|
||||||
working-directory: backend
|
|
||||||
run: go test ./...
|
|
||||||
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Flutter tests
|
|
||||||
working-directory: client
|
|
||||||
run: flutter test
|
|
||||||
|
|
||||||
- name: Build backend (linux/amd64)
|
|
||||||
working-directory: backend
|
|
||||||
run: GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o jiu-server .
|
|
||||||
|
|
||||||
- name: Build Flutter Web
|
|
||||||
working-directory: client
|
|
||||||
run: flutter build web --release --dart-define=BASE_URL=https://jiu.51yanmei.com --dart-define=PUBLIC_URL=https://jiu.51yanmei.com
|
|
||||||
|
|
||||||
- name: Setup SSH
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/ec2.pem
|
|
||||||
chmod 600 ~/.ssh/ec2.pem
|
|
||||||
ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Deploy to EC2
|
|
||||||
env:
|
|
||||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
|
||||||
EC2_USER: ${{ secrets.EC2_USER }}
|
|
||||||
run: |
|
|
||||||
scp -i ~/.ssh/ec2.pem backend/jiu-server ${EC2_USER}@${EC2_HOST}:/tmp/jiu-server
|
|
||||||
rsync -avz --delete -e "ssh -i ~/.ssh/ec2.pem" \
|
|
||||||
client/build/web/ ${EC2_USER}@${EC2_HOST}:/tmp/jiu-web-new/
|
|
||||||
ssh -i ~/.ssh/ec2.pem ${EC2_USER}@${EC2_HOST} << 'ENDSSH'
|
|
||||||
sudo systemctl stop jiu
|
|
||||||
cp /tmp/jiu-server /opt/jiu/backend/jiu-server
|
|
||||||
chmod +x /opt/jiu/backend/jiu-server
|
|
||||||
sudo systemctl start jiu
|
|
||||||
for i in $(seq 1 30); do
|
|
||||||
curl -sf http://localhost:8080/health && break
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
rm -rf /opt/jiu/web-old
|
|
||||||
mv /opt/jiu/web /opt/jiu/web-old 2>/dev/null || true
|
|
||||||
mv /tmp/jiu-web-new /opt/jiu/web
|
|
||||||
sudo nginx -s reload
|
|
||||||
ENDSSH
|
|
||||||
|
|
||||||
- name: Cleanup SSH key
|
|
||||||
if: always()
|
|
||||||
run: rm -f ~/.ssh/ec2.pem
|
|
||||||
+5
-26
@@ -22,44 +22,23 @@ server {
|
|||||||
proxy_read_timeout 30s;
|
proxy_read_timeout 30s;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Flutter 管理端(/app/ 子路径)
|
# Flutter 管理端(仅 /app/ 前缀,不污染根路径)
|
||||||
location /app/ {
|
location /app/ {
|
||||||
alias /opt/jiu/web/;
|
alias /opt/jiu/web/;
|
||||||
index index.html;
|
index index.html;
|
||||||
try_files $uri $uri/ /app/index.html;
|
try_files $uri $uri/ /app/index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Flutter 公开商品扫码页(/product/:id → Flutter app)
|
# 扫码页(/scan/<id> → scan.html,JS 从 URL 读取 id)
|
||||||
location /product/ {
|
|
||||||
alias /opt/jiu/web/;
|
|
||||||
try_files $uri /app/index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 营销站点 — 精确路径
|
|
||||||
location = / {
|
|
||||||
root /opt/jiu/marketing;
|
|
||||||
try_files /index.html =404;
|
|
||||||
}
|
|
||||||
location ~ ^/(docs|download)(\.html)?$ {
|
|
||||||
root /opt/jiu/marketing;
|
|
||||||
try_files /$1.html =404;
|
|
||||||
}
|
|
||||||
location /features/ {
|
|
||||||
root /opt/jiu/marketing;
|
|
||||||
try_files $uri $uri.html =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 营销站点 — 扫码 HTML 页(保留旧链接兼容)
|
|
||||||
location /scan/ {
|
location /scan/ {
|
||||||
root /opt/jiu/marketing;
|
root /opt/jiu/marketing;
|
||||||
try_files /scan.html =404;
|
try_files /scan.html =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
# 营销静态资源(CSS / SVG / 图片等)
|
# 营销站点兜底(根路径及所有其他路径)
|
||||||
location /assets/ {
|
location / {
|
||||||
root /opt/jiu/marketing;
|
root /opt/jiu/marketing;
|
||||||
expires 7d;
|
try_files $uri $uri.html $uri/index.html /index.html;
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user