Files
Handbook/.github/workflows/main.yml
T

176 lines
7.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Build and Deploy VuePress
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build VuePress site
run: yarn docs:build
- name: Get runner public IP
id: ip
run: echo "ipaddr=$(curl -s https://api.ipify.org)" >> $GITHUB_OUTPUT
- name: Add IP to Aliyun Security Group
env:
ALIYUN_ACCESS_KEY_ID: ${{ secrets.ALIYUN_ACCESS_KEY_ID }}
ALIYUN_ACCESS_KEY_SECRET: ${{ secrets.ALIYUN_ACCESS_KEY_SECRET }}
ALIYUN_REGION: ${{ secrets.ALIYUN_REGION }}
ALIYUN_SECURITY_GROUP_ID: ${{ secrets.ALIYUN_SECURITY_GROUP_ID }}
SERVER_SSH_PORT: ${{ secrets.SERVER_PORT }}
RUNNER_IP: ${{ steps.ip.outputs.ipaddr }}
run: |
pip install aliyun-python-sdk-core aliyun-python-sdk-ecs
python3 << 'EOF'
import os
import sys
from aliyunsdkcore.client import AcsClient
from aliyunsdkecs.request.v20140526 import AuthorizeSecurityGroupRequest
client = AcsClient(
os.environ['ALIYUN_ACCESS_KEY_ID'],
os.environ['ALIYUN_ACCESS_KEY_SECRET'],
os.environ['ALIYUN_REGION']
)
request = AuthorizeSecurityGroupRequest.AuthorizeSecurityGroupRequest()
request.set_SecurityGroupId(os.environ['ALIYUN_SECURITY_GROUP_ID'])
request.set_IpProtocol('tcp')
request.set_PortRange(f"{os.environ['SERVER_SSH_PORT']}/{os.environ['SERVER_SSH_PORT']}")
request.set_SourceCidrIp(f"{os.environ['RUNNER_IP']}/32")
request.set_Description('GitHub Actions temporary access')
try:
response = client.do_action_with_exception(request)
print(f"✓ Added {os.environ['RUNNER_IP']} to security group")
except Exception as e:
if 'InvalidPermission.Duplicate' in str(e):
print(f"✓ Rule already exists for {os.environ['RUNNER_IP']}")
else:
print(f"✗ Error: {e}")
sys.exit(1)
EOF
- name: Deploy to Aliyun Server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
port: ${{ secrets.SERVER_PORT }}
source: "docs/.vuepress/dist/*"
target: ${{ secrets.DEPLOY_PATH }}
strip_components: 3
overwrite: true
rm: true
- name: Set Permissions
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
port: ${{ secrets.SERVER_PORT }}
script: |
# 先设置所有者(这样后续操作才有权限)
chown -R ${{ secrets.SERVER_USER }}:${{ secrets.SERVER_USER }} ${{ secrets.DEPLOY_PATH }}
# 目录权限:755 - 允许进入和列出
find ${{ secrets.DEPLOY_PATH }} -type d -exec chmod 755 {} \;
# 文件权限:644 - 只读
find ${{ secrets.DEPLOY_PATH }} -type f -exec chmod 644 {} \;
- name: Remove IP from Aliyun Security Group
if: always()
env:
ALIYUN_ACCESS_KEY_ID: ${{ secrets.ALIYUN_ACCESS_KEY_ID }}
ALIYUN_ACCESS_KEY_SECRET: ${{ secrets.ALIYUN_ACCESS_KEY_SECRET }}
ALIYUN_REGION: ${{ secrets.ALIYUN_REGION }}
ALIYUN_SECURITY_GROUP_ID: ${{ secrets.ALIYUN_SECURITY_GROUP_ID }}
SERVER_SSH_PORT: ${{ secrets.SERVER_PORT }}
RUNNER_IP: ${{ steps.ip.outputs.ipaddr }}
run: |
pip install aliyun-python-sdk-core aliyun-python-sdk-ecs
python3 << 'EOF'
import os
from aliyunsdkcore.client import AcsClient
from aliyunsdkecs.request.v20140526 import RevokeSecurityGroupRequest
client = AcsClient(
os.environ['ALIYUN_ACCESS_KEY_ID'],
os.environ['ALIYUN_ACCESS_KEY_SECRET'],
os.environ['ALIYUN_REGION']
)
request = RevokeSecurityGroupRequest.RevokeSecurityGroupRequest()
request.set_SecurityGroupId(os.environ['ALIYUN_SECURITY_GROUP_ID'])
request.set_IpProtocol('tcp')
request.set_PortRange(f"{os.environ['SERVER_SSH_PORT']}/{os.environ['SERVER_SSH_PORT']}")
request.set_SourceCidrIp(f"{os.environ['RUNNER_IP']}/32")
try:
response = client.do_action_with_exception(request)
print(f"✓ Removed {os.environ['RUNNER_IP']} from security group")
except Exception as e:
print(f"⚠ Warning: Failed to remove rule: {e}")
EOF
- name: Notify Success to WeChat
if: success()
env:
COMMIT_MSG: ${{ github.event.head_commit.message }}
run: |
curl "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${{ secrets.WECHAT_WEBHOOK_KEY }}" \
-H 'Content-Type: application/json' \
-d "{
\"msgtype\": \"markdown\",
\"markdown\": {
\"content\": \"## ✅ 部署成功\n> 项目:**Handbook (VuePress)**\n> 分支:\\\`${{ github.ref_name }}\\\`\n> 提交者:${{ github.actor }}\n> 提交信息:${COMMIT_MSG}\n> 状态:已成功部署到生产环境\"
}
}"
- name: Get Job Logs
if: failure()
id: logs
run: |
ERROR_LOGS=$(cat $GITHUB_STEP_SUMMARY 2>/dev/null || echo "无法获取错误日志")
echo "logs<<EOF" >> $GITHUB_OUTPUT
echo "$ERROR_LOGS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Notify Failure to WeChat
if: failure()
env:
WORKFLOW_NAME: ${{ github.workflow }}
RUN_ID: ${{ github.run_id }}
JOB_NAME: ${{ github.job }}
run: |
FAILED_STEP=$(echo "${{ toJSON(job) }}" | jq -r '.steps[] | select(.conclusion=="failure") | .name' | head -1 || echo "未知步骤")
curl "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${{ secrets.WECHAT_WEBHOOK_KEY }}" \
-H 'Content-Type: application/json' \
-d "{
\"msgtype\": \"markdown\",
\"markdown\": {
\"content\": \"## ❌ 部署失败\n> 项目:**Handbook (VuePress)**\n> 分支:\\\`${{ github.ref_name }}\\\`\n> 提交者:${{ github.actor }}\n> 提交信息:${{ github.event.head_commit.message }}\n> 失败步骤:${FAILED_STEP}\n> Run ID:${RUN_ID}\n\n查看完整日志请前往 GitHub Actions\"
}
}"