various fixes
This commit is contained in:
15
.github/workflows/app-expo-deploy.yml
vendored
15
.github/workflows/app-expo-deploy.yml
vendored
@@ -7,11 +7,11 @@
|
||||
# - 若需兼容旧 32 位 ARM 设备,可将该属性改为 armeabi-v7a,arm64-v8a(体积会增大)。
|
||||
# - 若需用 x86 模拟器验证此 APK,需改回含 x86 的 ABI 或另建 job。
|
||||
#
|
||||
# 环境映射(按触发源自动推断):
|
||||
# main → dev (开发 + 内部测试)
|
||||
# v*.*.* → prod (正式发布 + GitHub Release 附带 APK)
|
||||
# 环境映射(与后端 api 一致:main → 预发 staging,tag → 生产 production):
|
||||
# push main → stage → node scripts/use-env.js staging → .env.staging
|
||||
# push v*.*.* → prod → node scripts/use-env.js production → .env.production
|
||||
#
|
||||
# 手动触发:workflow_dispatch 可选择 dev / stage / prod
|
||||
# 手动触发 workflow_dispatch:可选 dev / stage / prod(dev 用 .env.development,便于打内部测试包)
|
||||
#
|
||||
# Repository secrets(与 android-release.yml 共用同一套即可):
|
||||
# ANDROID_KEYSTORE_BASE64 / ANDROID_STORE_PASSWORD / ANDROID_KEY_ALIAS / ANDROID_KEY_PASSWORD
|
||||
@@ -72,7 +72,8 @@ jobs:
|
||||
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
echo "env=${{ github.event.inputs.environment }}"
|
||||
else
|
||||
echo "env=dev"
|
||||
# push 到 main(本 workflow 仅监听 main 与 tag)
|
||||
echo "env=stage"
|
||||
fi >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up Node.js
|
||||
@@ -86,8 +87,8 @@ jobs:
|
||||
working-directory: app-expo
|
||||
run: npm ci
|
||||
|
||||
- name: Quality checks (dev only)
|
||||
if: steps.env.outputs.env == 'dev'
|
||||
- name: Quality checks (non-prod)
|
||||
if: steps.env.outputs.env != 'prod'
|
||||
working-directory: app-expo
|
||||
run: |
|
||||
npm run format:check
|
||||
|
||||
65
.github/workflows/docker-build-deploy.yml
vendored
65
.github/workflows/docker-build-deploy.yml
vendored
@@ -1,15 +1,15 @@
|
||||
# API Docker:main → Dev 机(Repository secrets: DEV_*),Tag v*.*.* → Prod 机(PROD_*)
|
||||
# API Docker:main → Staging 机(Repository secrets: STAGING_*),Tag v*.*.* → Prod 机(PROD_*)
|
||||
# 在 Repo → Settings → Secrets and variables → Actions 中配置,无需 GitHub Environments。
|
||||
# 命名:DEV_SSH_HOST / DEV_SSH_USER / DEV_SSH_PRIVATE_KEY / DEV_SSH_PORT / DEV_DEPLOY_PATH
|
||||
# 命名:STAGING_SSH_HOST / STAGING_SSH_USER / STAGING_SSH_PRIVATE_KEY / STAGING_SSH_PORT / STAGING_DEPLOY_PATH
|
||||
# PROD_SSH_HOST / PROD_SSH_USER / PROD_SSH_PRIVATE_KEY / PROD_SSH_PORT / PROD_DEPLOY_PATH
|
||||
# 阿里云镜像仍为仓库级:ALIYUN_CR_USERNAME / ALIYUN_CR_PASSWORD
|
||||
#
|
||||
# 从旧版迁移:若仓库里仍是 SSH_HOST、SSH_PRIVATE_KEY、DEPLOY_PATH 等无前缀名称,
|
||||
# 请把「原机 / 内部测试」对应值复制为 DEV_*,「新生产机」填 PROD_*,并删除旧的无前缀 Secret。
|
||||
# 请把「预发机」对应值迁移为 STAGING_*,「新生产机」填 PROD_*,并删除旧的无前缀 Secret。
|
||||
#
|
||||
# 发布策略:
|
||||
# - merge / push 到 main:构建并部署到 Dev / 内部测试
|
||||
# - 手动创建并推送 tag vMAJOR.MINOR.PATCH:构建并部署到 Production
|
||||
# - merge / push 到 main:构建并部署到 Staging 机;使用仓库中的 api/.env.staging,上传后切换为运行时 .env
|
||||
# - 手动创建并推送 tag vMAJOR.MINOR.PATCH:构建并部署到 Production;使用仓库中的 api/.env.production,上传后切换为运行时 .env
|
||||
#
|
||||
# 注意:paths 过滤在 tag push 时按「被指向的 commit」判断;若该 commit 未改 api/ 与本 workflow,不会触发。
|
||||
# 此时可用 workflow_dispatch 选择对应 tag/ref 手动部署。
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
if [[ "$REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "target=prod" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "target=dev" >> "$GITHUB_OUTPUT"
|
||||
echo "target=staging" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Ensure production SSH secret is set
|
||||
@@ -135,28 +135,28 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Ensure development SSH secret is set
|
||||
- name: Ensure staging SSH secret is set
|
||||
if: steps.deploy_target.outputs.target != 'prod'
|
||||
env:
|
||||
DEV_SSH_PRIVATE_KEY: ${{ secrets.DEV_SSH_PRIVATE_KEY }}
|
||||
STAGING_SSH_PRIVATE_KEY: ${{ secrets.STAGING_SSH_PRIVATE_KEY }}
|
||||
run: |
|
||||
if [ -z "$DEV_SSH_PRIVATE_KEY" ]; then
|
||||
echo "::error::DEV_SSH_PRIVATE_KEY 未配置或为空,无法部署开发机。请在 Repository secrets 中设置 DEV_SSH_*。"
|
||||
if [ -z "$STAGING_SSH_PRIVATE_KEY" ]; then
|
||||
echo "::error::STAGING_SSH_PRIVATE_KEY 未配置或为空,无法部署 staging。请在 Repository secrets 中设置 STAGING_SSH_*。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 勿用 `prod && PROD_KEY || DEV_KEY`:PROD 为空时会错误回退到 DEV 密钥,导致连生产机报 Permission denied。
|
||||
# 勿用 `prod && PROD_KEY || STAGING_KEY`:PROD 为空时会错误回退到 staging 密钥,导致连生产机报 Permission denied。
|
||||
- name: Set up SSH (production)
|
||||
if: steps.deploy_target.outputs.target == 'prod'
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Set up SSH (development)
|
||||
- name: Set up SSH (staging)
|
||||
if: steps.deploy_target.outputs.target != 'prod'
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.DEV_SSH_PRIVATE_KEY }}
|
||||
ssh-private-key: ${{ secrets.STAGING_SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Export deploy connection env
|
||||
run: |
|
||||
@@ -169,10 +169,10 @@ jobs:
|
||||
} >> "$GITHUB_ENV"
|
||||
else
|
||||
{
|
||||
echo "SSH_HOST=${{ secrets.DEV_SSH_HOST }}"
|
||||
echo "SSH_USER=${{ secrets.DEV_SSH_USER }}"
|
||||
echo "SSH_PORT=${{ secrets.DEV_SSH_PORT || '22' }}"
|
||||
echo "COMPOSE_DIR=${{ secrets.DEV_DEPLOY_PATH || '/opt/life-echo' }}"
|
||||
echo "SSH_HOST=${{ secrets.STAGING_SSH_HOST }}"
|
||||
echo "SSH_USER=${{ secrets.STAGING_SSH_USER }}"
|
||||
echo "SSH_PORT=${{ secrets.STAGING_SSH_PORT || '22' }}"
|
||||
echo "COMPOSE_DIR=${{ secrets.STAGING_DEPLOY_PATH || '/opt/life-echo' }}"
|
||||
} >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
@@ -222,10 +222,32 @@ jobs:
|
||||
docker network inspect api_life-echo-network >/dev/null 2>&1 || docker network create api_life-echo-network
|
||||
"
|
||||
|
||||
echo "上传候选 compose、Caddyfile 与环境变量..."
|
||||
if [ "${{ steps.deploy_target.outputs.target }}" = "prod" ]; then
|
||||
ENV_SRC="api/.env.production"
|
||||
else
|
||||
ENV_SRC="api/.env.staging"
|
||||
fi
|
||||
if [ ! -f "$ENV_SRC" ]; then
|
||||
echo "::error::缺少 $ENV_SRC,无法部署。"
|
||||
exit 1
|
||||
fi
|
||||
if grep -Eq '=(your_|replace_with_|\\.{3}$)' "$ENV_SRC"; then
|
||||
echo "::error::$ENV_SRC 仍包含占位符值,请先完善环境文件。"
|
||||
exit 1
|
||||
fi
|
||||
if grep -Eq '^DATABASE_URL=.*@localhost:' "$ENV_SRC" || grep -Eq '^REDIS_URL=redis://localhost' "$ENV_SRC"; then
|
||||
echo "::error::$ENV_SRC 包含 localhost 数据库或 Redis 地址,容器内将无法连接。"
|
||||
exit 1
|
||||
fi
|
||||
if grep -Eq '^DATABASE_URL=.*@postgresql:' "$ENV_SRC"; then
|
||||
echo "::error::$ENV_SRC 仍引用过期主机名 postgresql;当前 compose 服务名应为 postgres。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "上传候选 compose、Caddyfile 与环境文件..."
|
||||
scp -P "$SSH_PORT" ./api/docker-compose.yml "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/docker-compose.candidate.yml"
|
||||
scp -P "$SSH_PORT" ./api/Caddyfile "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/Caddyfile.candidate"
|
||||
scp -P "$SSH_PORT" ./api/.env.production "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/.env.production.candidate"
|
||||
scp -P "$SSH_PORT" "$ENV_SRC" "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/.env.candidate"
|
||||
|
||||
ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
|
||||
set -euo pipefail
|
||||
@@ -255,9 +277,12 @@ jobs:
|
||||
if [ -f '.env.production' ]; then
|
||||
cp '.env.production' '.env.production.predeploy'
|
||||
fi
|
||||
if [ -f '.env' ]; then
|
||||
cp '.env' '.env.predeploy'
|
||||
fi
|
||||
mv 'docker-compose.candidate.yml' '$COMPOSE_FILE'
|
||||
mv 'Caddyfile.candidate' 'Caddyfile'
|
||||
mv '.env.production.candidate' '.env.production'
|
||||
mv '.env.candidate' '.env'
|
||||
docker-compose -f '$COMPOSE_FILE' up -d --remove-orphans
|
||||
echo '等待服务启动...'
|
||||
sleep 20
|
||||
|
||||
Reference in New Issue
Block a user