|
9005
|
7291
|
6
|
5
|
339ea969ec2633756fb1a155d47723d0f61396a4
|
0
|
构建并推送镜像
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
build-and-push:
name: 构建并推送镜像
runs-on: ubuntu-latest
if: >-
always() && (
needs.quality-check.result == 'success' ||
needs.quality-check.result == 'skipped'
)
steps:
- name: 检出代码
uses: actions/checkout@v4
- id: version
name: 获取版本号
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
else
VERSION=${{ github.sha }}
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "short_sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 登录容器仓库
uses: docker/login-action@v3
with:
password: ${{ secrets.GITHUB_TOKEN }}
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
- id: meta-api
name: 后端镜像元数据
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-api
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 构建并推送后端镜像
uses: docker/build-push-action@v5
with:
build-args: |
NODE_ENV=production
cache-from: type=gha
cache-to: type=gha,mode=max
context: ./backend
labels: ${{ steps.meta-api.outputs.labels }}
push: "true"
tags: ${{ steps.meta-api.outputs.tags }}
- id: meta-frontend
name: 前端镜像元数据
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-frontend
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 构建并推送前端镜像
uses: docker/build-push-action@v5
with:
build-args: |
VITE_API_BASE_URL=/v1
cache-from: type=gha
cache-to: type=gha,mode=max
context: ./frontend
labels: ${{ steps.meta-frontend.outputs.labels }}
push: "true"
tags: ${{ steps.meta-frontend.outputs.tags }}
timeout-minutes: "20"
outputs:
api-image: ${{ steps.meta-api.outputs.tags }}
frontend-image: ${{ steps.meta-frontend.outputs.tags }}
version: ${{ steps.version.outputs.version }}
permissions:
contents: read
packages: write
...
|
build-and-push
|
["quality-check"]
|
["ubuntu-latest"]
|
7788
|
4
|
1774229562
|
1774229563
|
1774229062
|
1774229563
|
|
1
|
|
0
|
Edit
Delete
|
|
9212
|
7417
|
6
|
5
|
67078f9a95f53530156ad27027eafe15a3126e89
|
0
|
构建并推送镜像
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
build-and-push:
name: 构建并推送镜像
runs-on: ubuntu-latest
if: >-
always() && (
needs.quality-check.result == 'success' ||
needs.quality-check.result == 'skipped'
)
steps:
- name: 检出代码
uses: actions/checkout@v4
- id: version
name: 获取版本号
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
else
VERSION=${{ github.sha }}
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "short_sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 登录容器仓库
uses: docker/login-action@v3
with:
password: ${{ secrets.GITHUB_TOKEN }}
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
- id: meta-api
name: 后端镜像元数据
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-api
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 构建并推送后端镜像
uses: docker/build-push-action@v5
with:
build-args: |
NODE_ENV=production
cache-from: type=gha
cache-to: type=gha,mode=max
context: ./backend
labels: ${{ steps.meta-api.outputs.labels }}
push: "true"
tags: ${{ steps.meta-api.outputs.tags }}
- id: meta-frontend
name: 前端镜像元数据
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-frontend
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 构建并推送前端镜像
uses: docker/build-push-action@v5
with:
build-args: |
VITE_API_BASE_URL=/v1
cache-from: type=gha
cache-to: type=gha,mode=max
context: ./frontend
labels: ${{ steps.meta-frontend.outputs.labels }}
push: "true"
tags: ${{ steps.meta-frontend.outputs.tags }}
timeout-minutes: "20"
outputs:
api-image: ${{ steps.meta-api.outputs.tags }}
frontend-image: ${{ steps.meta-frontend.outputs.tags }}
version: ${{ steps.version.outputs.version }}
permissions:
contents: read
packages: write
...
|
build-and-push
|
["quality-check"]
|
["ubuntu-latest"]
|
7982
|
4
|
1774263614
|
1774263614
|
1774262376
|
1774263615
|
|
1
|
|
0
|
Edit
Delete
|
|
15516
|
10823
|
6
|
5
|
bd59e5501292cb061719f669c7a7b7afd4f1a0b7
|
0
|
构建并推送镜像
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
build-and-push:
name: 构建并推送镜像
runs-on: ubuntu-latest
if: >-
always() && (
needs.quality-check.result == 'success' ||
needs.quality-check.result == 'skipped'
)
steps:
- name: 检出代码
uses: actions/checkout@v4
- id: version
name: 获取版本号
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
else
VERSION=${{ github.sha }}
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "short_sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 登录容器仓库
uses: docker/login-action@v3
with:
password: ${{ secrets.GITHUB_TOKEN }}
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
- id: meta-api
name: 后端镜像元数据
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-api
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 构建并推送后端镜像
uses: docker/build-push-action@v5
with:
build-args: |
NODE_ENV=production
cache-from: type=gha
cache-to: type=gha,mode=max
context: ./backend
labels: ${{ steps.meta-api.outputs.labels }}
push: "true"
tags: ${{ steps.meta-api.outputs.tags }}
- id: meta-frontend
name: 前端镜像元数据
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-frontend
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 构建并推送前端镜像
uses: docker/build-push-action@v5
with:
build-args: |
VITE_API_BASE_URL=/v1
cache-from: type=gha
cache-to: type=gha,mode=max
context: ./frontend
labels: ${{ steps.meta-frontend.outputs.labels }}
push: "true"
tags: ${{ steps.meta-frontend.outputs.tags }}
timeout-minutes: "20"
outputs:
api-image: ${{ steps.meta-api.outputs.tags }}
frontend-image: ${{ steps.meta-frontend.outputs.tags }}
version: ${{ steps.version.outputs.version }}
permissions:
contents: read
packages: write
...
|
build-and-push
|
["quality-check"]
|
["ubuntu-latest"]
|
12841
|
4
|
1775186036
|
1775186036
|
1775181686
|
1775186036
|
|
1
|
|
0
|
Edit
Delete
|
|
15522
|
10824
|
6
|
5
|
84c900df1e544e4eb7070be9278918676c4aec69
|
0
|
构建并推送镜像
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
build-and-push:
name: 构建并推送镜像
runs-on: ubuntu-latest
if: >-
always() && (
needs.quality-check.result == 'success' ||
needs.quality-check.result == 'skipped'
)
steps:
- name: 检出代码
uses: actions/checkout@v4
- id: version
name: 获取版本号
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
else
VERSION=${{ github.sha }}
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "short_sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 登录容器仓库
uses: docker/login-action@v3
with:
password: ${{ secrets.GITHUB_TOKEN }}
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
- id: meta-api
name: 后端镜像元数据
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-api
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 构建并推送后端镜像
uses: docker/build-push-action@v5
with:
build-args: |
NODE_ENV=production
cache-from: type=gha
cache-to: type=gha,mode=max
context: ./backend
labels: ${{ steps.meta-api.outputs.labels }}
push: "true"
tags: ${{ steps.meta-api.outputs.tags }}
- id: meta-frontend
name: 前端镜像元数据
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-frontend
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: 构建并推送前端镜像
uses: docker/build-push-action@v5
with:
build-args: |
VITE_API_BASE_URL=/v1
cache-from: type=gha
cache-to: type=gha,mode=max
context: ./frontend
labels: ${{ steps.meta-frontend.outputs.labels }}
push: "true"
tags: ${{ steps.meta-frontend.outputs.tags }}
timeout-minutes: "20"
outputs:
api-image: ${{ steps.meta-api.outputs.tags }}
frontend-image: ${{ steps.meta-frontend.outputs.tags }}
version: ${{ steps.version.outputs.version }}
permissions:
contents: read
packages: write
...
|
build-and-push
|
["quality-check"]
|
["ubuntu-latest"]
|
12843
|
4
|
1775186040
|
1775186040
|
1775181686
|
1775186040
|
|
1
|
|
0
|
Edit
Delete
|
|
7841
|
6703
|
6
|
5
|
e112d45af414e4862c0328abad7c4df74d3c1dbf
|
0
|
自动回滚
|
0
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
0
|
3
|
0
|
1773832744
|
1773831749
|
1773832744
|
|
0
|
|
0
|
Edit
Delete
|
|
7903
|
6713
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
6843
|
4
|
1773833402
|
1773833402
|
1773832744
|
1773833402
|
|
1
|
|
0
|
Edit
Delete
|
|
8266
|
6996
|
6
|
5
|
bd59e5501292cb061719f669c7a7b7afd4f1a0b7
|
0
|
自动回滚
|
0
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
0
|
3
|
0
|
1773913345
|
1773912912
|
1773913345
|
|
0
|
|
0
|
Edit
Delete
|
|
8324
|
7004
|
6
|
5
|
01a8ea9191c28b210d2abb3db3cbc65db42fc801
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
7208
|
4
|
1773914284
|
1773914284
|
1773913345
|
1773914284
|
|
1
|
|
0
|
Edit
Delete
|
|
8459
|
7069
|
6
|
5
|
9771b23ae7aaee164f15f9c4ccbdb18eb68fc71f
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
7323
|
4
|
1773930010
|
1773930011
|
1773929408
|
1773930011
|
|
1
|
|
0
|
Edit
Delete
|
|
8568
|
7114
|
6
|
5
|
979d9c81063fbda12f1445bf80b0c0027b0fbac2
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
7424
|
4
|
1773940824
|
1773940824
|
1773939780
|
1773940824
|
|
1
|
|
0
|
Edit
Delete
|
|
8757
|
7232
|
6
|
5
|
0900b15d607e5c78f97fec16a73357ad4f814390
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
7604
|
4
|
1774222052
|
1774222052
|
1774220985
|
1774222052
|
|
1
|
|
0
|
Edit
Delete
|
|
8833
|
7249
|
6
|
5
|
80c2bdb2f93a19aa53d16ded06387b70c6084bf8
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
7668
|
4
|
1774223490
|
1774223490
|
1774223019
|
1774223491
|
|
1
|
|
0
|
Edit
Delete
|
|
8904
|
7261
|
6
|
5
|
df7b6f46170cb46db4771dd1e07991b0b13d90a0
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
7728
|
4
|
1774223984
|
1774223984
|
1774223517
|
1774223984
|
|
1
|
|
0
|
Edit
Delete
|
|
9008
|
7291
|
6
|
5
|
339ea969ec2633756fb1a155d47723d0f61396a4
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
7821
|
4
|
1774229665
|
1774229665
|
1774229062
|
1774229665
|
|
1
|
|
0
|
Edit
Delete
|
|
9215
|
7417
|
6
|
5
|
67078f9a95f53530156ad27027eafe15a3126e89
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
8018
|
4
|
1774263723
|
1774263723
|
1774262376
|
1774263723
|
|
1
|
|
0
|
Edit
Delete
|
|
15519
|
10823
|
6
|
5
|
bd59e5501292cb061719f669c7a7b7afd4f1a0b7
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
12865
|
4
|
1775186343
|
1775186343
|
1775181686
|
1775186344
|
|
1
|
|
0
|
Edit
Delete
|
|
15525
|
10824
|
6
|
5
|
84c900df1e544e4eb7070be9278918676c4aec69
|
0
|
自动回滚
|
1
|
name: Deploy
"on":
push:
branc name: Deploy
"on":
push:
branches: [main]
tags: ['v*']
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
- rollback
skip_tests:
description: '跳过测试(紧急修复时使用)'
required: false
default: false
type: boolean
env:
IMAGE_PREFIX: ${{ github.repository_owner }}/juhi
NODE_VERSION: "20"
PNPM_VERSION: "8"
REGISTRY: ghcr.io
jobs:
auto-rollback:
name: 自动回滚
runs-on: ubuntu-latest
if: failure() && needs.deploy-production.result == 'failure'
steps:
- name: 配置 SSH
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
- name: 配置 SSH Known Hosts
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: 执行自动回滚
run: |
ssh $USER@$HOST << 'EOF'
cd /opt/juhi
echo "=========================================="
echo "检测到部署失败,执行自动回滚..."
echo "=========================================="
# 使用项目回滚脚本
if [ -f "./scripts/rollback.sh" ]; then
chmod +x ./scripts/rollback.sh
./scripts/rollback.sh --confirm -y
else
# 备用回滚逻辑:读取最近一条部署历史
PREV_LINE=$(tail -1 .deploy-history 2>/dev/null)
PREV_API_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f2)
PREV_FRONTEND_IMAGE=$(echo "$PREV_LINE" | cut -d'|' -f3)
if [ -n "$PREV_API_IMAGE" ] && [ "$PREV_API_IMAGE" != "none" ]; then
echo "回滚到: API=$PREV_API_IMAGE, Frontend=$PREV_FRONTEND_IMAGE"
export API_IMAGE="$PREV_API_IMAGE"
export FRONTEND_IMAGE="$PREV_FRONTEND_IMAGE"
docker compose -f docker-compose.prod.yml up -d --no-deps api frontend
# 健康检查(带重试)
RETRY=0
MAX_RETRY=12
until curl -sf http://localhost:3000/health > /dev/null 2>&1; do
RETRY=$((RETRY + 1))
if [ $RETRY -ge $MAX_RETRY ]; then
echo "回滚后健康检查失败(60s),请手动介入"
docker compose -f docker-compose.prod.yml logs --tail=30 api
exit 1
fi
sleep 5
done
echo "回滚成功!"
else
echo "无法获取上一版本信息,需要手动回滚"
echo "部署历史:"
cat .deploy-history 2>/dev/null || echo "(空)"
exit 1
fi
fi
EOF
env:
HOST: ${{ secrets.PRODUCTION_HOST }}
USER: ${{ secrets.PRODUCTION_USER }}
- if: always()
name: 发送回滚通知
uses: 8398a7/action-slack@v3
with:
custom_payload: |
{
"attachments": [{
"color": "${{ job.status == 'success' && 'warning' || 'danger' }}",
"title": "生产环境自动回滚",
"text": "部署失败触发自动回滚\n回滚状态: ${{ job.status }}",
"fields": [
{ "title": "环境", "value": "Production", "short": true },
{ "title": "触发者", "value": "${{ github.actor }}", "short": true },
{ "title": "版本", "value": "${{ needs.build-and-push.outputs.version }}", "short": true }
]
}]
}
status: custom
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
timeout-minutes: "10"
...
|
auto-rollback
|
["deploy-production"]
|
["ubuntu-latest"]
|
12866
|
4
|
1775186345
|
1775186345
|
1775181686
|
1775186346
|
|
1
|
|
0
|
Edit
Delete
|
|
7831
|
6702
|
6
|
5
|
e112d45af414e4862c0328abad7c4df74d3c1dbf
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
6744
|
2
|
1773832182
|
1773832208
|
1773831748
|
1773832209
|
|
0
|
|
0
|
Edit
Delete
|
|
7893
|
6712
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
6772
|
2
|
1773832815
|
1773832838
|
1773832743
|
1773832838
|
|
0
|
|
0
|
Edit
Delete
|
|
8148
|
6903
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
7030
|
2
|
1773885615
|
1773885635
|
1773885613
|
1773885635
|
|
0
|
|
0
|
Edit
Delete
|
|
8449
|
7068
|
6
|
5
|
9771b23ae7aaee164f15f9c4ccbdb18eb68fc71f
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
7263
|
2
|
1773929449
|
1773929475
|
1773929407
|
1773929475
|
|
0
|
|
0
|
Edit
Delete
|
|
8558
|
7113
|
6
|
5
|
979d9c81063fbda12f1445bf80b0c0027b0fbac2
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
7362
|
2
|
1773939813
|
1773939835
|
1773939780
|
1773939835
|
|
0
|
|
0
|
Edit
Delete
|
|
8747
|
7231
|
6
|
5
|
0900b15d607e5c78f97fec16a73357ad4f814390
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
7541
|
2
|
1774221023
|
1774221046
|
1774220984
|
1774221046
|
|
0
|
|
0
|
Edit
Delete
|
|
8998
|
7290
|
6
|
5
|
339ea969ec2633756fb1a155d47723d0f61396a4
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
7759
|
2
|
1774229096
|
1774229117
|
1774229062
|
1774229118
|
|
0
|
|
0
|
Edit
Delete
|
|
9071
|
7309
|
6
|
5
|
339ea969ec2633756fb1a155d47723d0f61396a4
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
7832
|
2
|
1774231245
|
1774231267
|
1774231240
|
1774231267
|
|
0
|
|
0
|
Edit
Delete
|
|
9201
|
7415
|
6
|
5
|
67078f9a95f53530156ad27027eafe15a3126e89
|
0
|
🔒 多租户安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
tenant-security:
name: "\U0001F512 多租户安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: tenant-audit
name: "\U0001F50D 多租户隔离检查"
run: |
cd backend
npm run audit:tenant 2>&1 | tee tenant-audit.log
# 检查是否有 P0 级别问题
if grep -q "P0" tenant-audit.log; then
echo "has_p0_issues=true" >> $GITHUB_OUTPUT
else
echo "has_p0_issues=false" >> $GITHUB_OUTPUT
fi
- name: "\U0001F4CA 上传审计报告"
uses: actions/upload-artifact@v4
with:
name: tenant-security-report
path: backend/tenant-audit.log
- if: steps.tenant-audit.outputs.has_p0_issues == 'true'
name: ❌ P0 问题阻断
run: |
echo "::error::发现 P0 级别多租户安全问题,禁止合并!"
exit 1
timeout-minutes: "15"
...
|
tenant-security
|
null
|
["ubuntu-latest"]
|
7950
|
2
|
1774262461
|
1774262552
|
1774262375
|
1774262552
|
|
0
|
|
0
|
Edit
Delete
|
|
7835
|
6702
|
6
|
5
|
e112d45af414e4862c0328abad7c4df74d3c1dbf
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
6767
|
2
|
1773832753
|
1773832777
|
1773831748
|
1773832777
|
|
1
|
|
0
|
Edit
Delete
|
|
7897
|
6712
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
6799
|
2
|
1773833274
|
1773833278
|
1773832743
|
1773833278
|
|
1
|
|
0
|
Edit
Delete
|
|
8152
|
6903
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
7034
|
2
|
1773885803
|
1773885833
|
1773885613
|
1773885833
|
|
1
|
|
0
|
Edit
Delete
|
|
8453
|
7068
|
6
|
5
|
9771b23ae7aaee164f15f9c4ccbdb18eb68fc71f
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
7288
|
2
|
1773929904
|
1773929908
|
1773929407
|
1773929909
|
|
1
|
|
0
|
Edit
Delete
|
|
8562
|
7113
|
6
|
5
|
979d9c81063fbda12f1445bf80b0c0027b0fbac2
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
7387
|
2
|
1773940491
|
1773940581
|
1773939780
|
1773940582
|
|
1
|
|
0
|
Edit
Delete
|
|
8751
|
7231
|
6
|
5
|
0900b15d607e5c78f97fec16a73357ad4f814390
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
7567
|
2
|
1774221626
|
1774221656
|
1774220984
|
1774221657
|
|
1
|
|
0
|
Edit
Delete
|
|
9002
|
7290
|
6
|
5
|
339ea969ec2633756fb1a155d47723d0f61396a4
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
7786
|
2
|
1774229556
|
1774229560
|
1774229062
|
1774229560
|
|
1
|
|
0
|
Edit
Delete
|
|
9075
|
7309
|
6
|
5
|
339ea969ec2633756fb1a155d47723d0f61396a4
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
7841
|
2
|
1774231445
|
1774231450
|
1774231240
|
1774231450
|
|
1
|
|
0
|
Edit
Delete
|
|
9205
|
7415
|
6
|
5
|
67078f9a95f53530156ad27027eafe15a3126e89
|
0
|
📋 安全报告汇总
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
security-report:
name: "\U0001F4CB 安全报告汇总"
runs-on: ubuntu-latest
if: always()
steps:
- name: "\U0001F4E5 下载所有报告"
uses: actions/download-artifact@v4
with:
path: reports
- name: "\U0001F4DD 生成综合报告"
run: "cat << 'EOF' > security-summary.md\n# \U0001F512 数据库安全审计报告\n\n**执行时间**: $(date '+%Y-%m-%d %H:%M:%S')\n**触发方式**: ${{ github.event_name }}\n**分支**: ${{ github.ref_name }}\n\n## 审计结果汇总\n\n| 检查项 | 状态 |\n|--------|------|\n| 多租户安全 | ${{ needs.tenant-security.result == 'success' && '✅ 通过' || '❌ 失败' }} |\n| N+1 查询 | ${{ needs.n1-query-detection.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| RLS 覆盖 | ${{ needs.rls-coverage.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n| 权限配置 | ${{ needs.permission-security.result == 'success' && '✅ 通过' || '⚠️ 警告' }} |\n\n## 详细报告\n\n请下载 Artifacts 查看各项检查的详细报告。\n\n## 修复指南\n\n- [多租户安全修复指南](docs/MULTI-TENANT-SECURITY.md)\n- [N+1 查询优化指南](docs/N+1-QUERY-OPTIMIZATION.md)\n- [RLS 策略配置指南](docs/RLS-POLICY-GUIDE.md)\nEOF\n"
- name: "\U0001F4CA 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- if: github.event_name == 'pull_request'
name: "\U0001F4AC PR 评论"
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('security-summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
...
|
security-report
|
["tenant-security","n1-query-detection ["tenant-security","n1-query-detection","rls-coverage","permission-security"]...
|
["ubuntu-latest"]
|
7978
|
2
|
1774263604
|
1774263608
|
1774262375
|
1774263608
|
|
1
|
|
0
|
Edit
Delete
|
|
7833
|
6702
|
6
|
5
|
e112d45af414e4862c0328abad7c4df74d3c1dbf
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
6746
|
2
|
1773832230
|
1773832250
|
1773831748
|
1773832251
|
|
0
|
|
0
|
Edit
Delete
|
|
7895
|
6712
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
6774
|
2
|
1773832860
|
1773832881
|
1773832743
|
1773832881
|
|
0
|
|
0
|
Edit
Delete
|
|
8150
|
6903
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
7032
|
2
|
1773885739
|
1773885770
|
1773885613
|
1773885770
|
|
0
|
|
0
|
Edit
Delete
|
|
8451
|
7068
|
6
|
5
|
9771b23ae7aaee164f15f9c4ccbdb18eb68fc71f
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
7265
|
2
|
1773929497
|
1773929518
|
1773929407
|
1773929519
|
|
0
|
|
0
|
Edit
Delete
|
|
8560
|
7113
|
6
|
5
|
979d9c81063fbda12f1445bf80b0c0027b0fbac2
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
7364
|
2
|
1773939861
|
1773939880
|
1773939780
|
1773939881
|
|
0
|
|
0
|
Edit
Delete
|
|
8749
|
7231
|
6
|
5
|
0900b15d607e5c78f97fec16a73357ad4f814390
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
7543
|
2
|
1774221067
|
1774221089
|
1774220984
|
1774221089
|
|
0
|
|
0
|
Edit
Delete
|
|
9000
|
7290
|
6
|
5
|
339ea969ec2633756fb1a155d47723d0f61396a4
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
7761
|
2
|
1774229139
|
1774229160
|
1774229062
|
1774229161
|
|
0
|
|
0
|
Edit
Delete
|
|
9073
|
7309
|
6
|
5
|
339ea969ec2633756fb1a155d47723d0f61396a4
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
7834
|
2
|
1774231289
|
1774231311
|
1774231240
|
1774231311
|
|
0
|
|
0
|
Edit
Delete
|
|
9203
|
7415
|
6
|
5
|
67078f9a95f53530156ad27027eafe15a3126e89
|
0
|
🛡️ RLS 覆盖分析
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
rls-coverage:
name: "\U0001F6E1️ RLS 覆盖分析"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: rls-analysis
name: "\U0001F50D RLS 策略分析"
run: |
cd backend
npm run rls:analyze 2>&1 | tee rls-analysis.log
# 提取覆盖率
COVERAGE=$(grep -oP 'RLS 覆盖率: \K[\d.]+%' rls-analysis.log || echo "0%")
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: "\U0001F4CA 上传 RLS 分析报告"
uses: actions/upload-artifact@v4
with:
name: rls-coverage-report
path: backend/rls-analysis.log
- name: "\U0001F4C8 RLS 覆盖率检查"
run: |
COVERAGE="${{ steps.rls-analysis.outputs.coverage }}"
echo "当前 RLS 覆盖率: $COVERAGE"
# 提取数字部分
PERCENT=$(echo $COVERAGE | grep -oP '[\d.]+' || echo "0")
if (( $(echo "$PERCENT < 80" | bc -l) )); then
echo "::warning::RLS 覆盖率低于 80%,建议增加 RLS 策略"
fi
timeout-minutes: "10"
...
|
rls-coverage
|
null
|
["ubuntu-latest"]
|
7952
|
2
|
1774262643
|
1774262673
|
1774262375
|
1774262673
|
|
0
|
|
0
|
Edit
Delete
|
|
7834
|
6702
|
6
|
5
|
e112d45af414e4862c0328abad7c4df74d3c1dbf
|
0
|
🔐 权限安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
permission-security:
name: "\U0001F510 权限安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: permission-audit
name: "\U0001F50D 权限配置审计"
run: |
cd backend
npm run audit:permission --json 2>&1 | tee permission-audit.json
continue-on-error: true
- name: "\U0001F4CA 上传权限审计报告"
uses: actions/upload-artifact@v4
with:
name: permission-audit-report
path: backend/permission-audit.json
timeout-minutes: "10"
...
|
permission-security
|
null
|
["ubuntu-latest"]
|
6747
|
2
|
1773832251
|
1773832272
|
1773831748
|
1773832272
|
|
0
|
|
0
|
Edit
Delete
|
|
7896
|
6712
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
🔐 权限安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
permission-security:
name: "\U0001F510 权限安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: permission-audit
name: "\U0001F50D 权限配置审计"
run: |
cd backend
npm run audit:permission --json 2>&1 | tee permission-audit.json
continue-on-error: true
- name: "\U0001F4CA 上传权限审计报告"
uses: actions/upload-artifact@v4
with:
name: permission-audit-report
path: backend/permission-audit.json
timeout-minutes: "10"
...
|
permission-security
|
null
|
["ubuntu-latest"]
|
6775
|
2
|
1773832881
|
1773832901
|
1773832743
|
1773832902
|
|
0
|
|
0
|
Edit
Delete
|
|
8151
|
6903
|
6
|
5
|
b7eb415d7a9689f1efec941bcb2dcd7d098e9c28
|
0
|
🔐 权限安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
permission-security:
name: "\U0001F510 权限安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: permission-audit
name: "\U0001F50D 权限配置审计"
run: |
cd backend
npm run audit:permission --json 2>&1 | tee permission-audit.json
continue-on-error: true
- name: "\U0001F4CA 上传权限审计报告"
uses: actions/upload-artifact@v4
with:
name: permission-audit-report
path: backend/permission-audit.json
timeout-minutes: "10"
...
|
permission-security
|
null
|
["ubuntu-latest"]
|
7033
|
2
|
1773885770
|
1773885800
|
1773885613
|
1773885800
|
|
0
|
|
0
|
Edit
Delete
|
|
8452
|
7068
|
6
|
5
|
9771b23ae7aaee164f15f9c4ccbdb18eb68fc71f
|
0
|
🔐 权限安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
permission-security:
name: "\U0001F510 权限安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: permission-audit
name: "\U0001F50D 权限配置审计"
run: |
cd backend
npm run audit:permission --json 2>&1 | tee permission-audit.json
continue-on-error: true
- name: "\U0001F4CA 上传权限审计报告"
uses: actions/upload-artifact@v4
with:
name: permission-audit-report
path: backend/permission-audit.json
timeout-minutes: "10"
...
|
permission-security
|
null
|
["ubuntu-latest"]
|
7266
|
2
|
1773929519
|
1773929538
|
1773929407
|
1773929538
|
|
0
|
|
0
|
Edit
Delete
|
|
8561
|
7113
|
6
|
5
|
979d9c81063fbda12f1445bf80b0c0027b0fbac2
|
0
|
🔐 权限安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
permission-security:
name: "\U0001F510 权限安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: permission-audit
name: "\U0001F50D 权限配置审计"
run: |
cd backend
npm run audit:permission --json 2>&1 | tee permission-audit.json
continue-on-error: true
- name: "\U0001F4CA 上传权限审计报告"
uses: actions/upload-artifact@v4
with:
name: permission-audit-report
path: backend/permission-audit.json
timeout-minutes: "10"
...
|
permission-security
|
null
|
["ubuntu-latest"]
|
7365
|
2
|
1773939881
|
1773939900
|
1773939780
|
1773939900
|
|
0
|
|
0
|
Edit
Delete
|
|
8750
|
7231
|
6
|
5
|
0900b15d607e5c78f97fec16a73357ad4f814390
|
0
|
🔐 权限安全审计
|
1
|
name: Database Security Audit
"on":
pu name: Database Security Audit
"on":
push:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
pull_request:
branches: [main, develop]
paths:
- 'backend/src/**/*.ts'
- 'backend/prisma/**'
schedule:
# 每天凌晨 2 点执行完整审计
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
full_audit:
description: '执行完整审计(包含 RLS 迁移建议)'
required: false
default: 'false'
type: boolean
env:
NODE_VERSION: "18"
jobs:
permission-security:
name: "\U0001F510 权限安全审计"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 Checkout code"
uses: actions/checkout@v4
- name: "\U0001F7E2 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E6 Setup pnpm"
uses: pnpm/action-setup@v2
with:
version: "8"
- name: "\U0001F4E5 Install dependencies"
run: pnpm install --frozen-lockfile
- id: permission-audit
name: "\U0001F50D 权限配置审计"
run: |
cd backend
npm run audit:permission --json 2>&1 | tee permission-audit.json
continue-on-error: true
- name: "\U0001F4CA 上传权限审计报告"
uses: actions/upload-artifact@v4
with:
name: permission-audit-report
path: backend/permission-audit.json
timeout-minutes: "10"
...
|
permission-security
|
null
|
["ubuntu-latest"]
|
7544
|
2
|
1774221089
|
1774221109
|
1774220984
|
1774221109
|
|
0
|
|
0
|
Edit
Delete
|