Files
xgj/cache-state/examples/error-handling.yml

378 lines
12 KiB
YAML

# 错误处理和恢复示例
# 演示如何使用状态缓存进行错误处理、状态恢复和重试逻辑
name: Cache State - 错误处理示例
on:
workflow_dispatch:
inputs:
simulate_error:
description: '模拟错误类型'
required: false
default: 'none'
type: choice
options:
- none
- network_error
- build_failure
- deployment_error
recovery_mode:
description: '恢复模式'
required: false
default: 'auto'
type: choice
options:
- auto
- manual
- skip
jobs:
initialize-operation:
runs-on: ubuntu-latest
outputs:
operation-id: ${{ steps.operation-setup.outputs.operation-id }}
should-continue: ${{ steps.check-previous.outputs.should-continue }}
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置操作ID
id: operation-setup
run: |
OPERATION_ID="op-$(date +%s)-${{ github.run_number }}"
echo "operation-id=${OPERATION_ID}" >> $GITHUB_OUTPUT
echo "🆔 操作ID: ${OPERATION_ID}"
- name: 检查上次操作状态
id: last-operation
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-operation-status'
default-value: 'none'
action: 'get'
cache-prefix: 'operation'
- name: 检查是否有失败的操作需要恢复
id: check-previous
run: |
LAST_STATUS="${{ steps.last-operation.outputs.state-value }}"
RECOVERY_MODE="${{ github.event.inputs.recovery_mode }}"
echo "🔍 检查上次操作状态: ${LAST_STATUS}"
echo "🔧 恢复模式: ${RECOVERY_MODE}"
if [[ "${LAST_STATUS}" == "failed" || "${LAST_STATUS}" == "partial" ]]; then
echo "⚠️ 检测到失败的操作需要处理"
case "${RECOVERY_MODE}" in
"auto")
echo "🔄 自动恢复模式,将继续操作"
echo "should-continue=true" >> $GITHUB_OUTPUT
;;
"manual")
echo "✋ 手动恢复模式,需要人工干预"
echo "should-continue=false" >> $GITHUB_OUTPUT
exit 1
;;
"skip")
echo "⏭️ 跳过恢复,开始新操作"
echo "should-continue=true" >> $GITHUB_OUTPUT
;;
esac
else
echo "✅ 没有失败的操作,正常继续"
echo "should-continue=true" >> $GITHUB_OUTPUT
fi
- name: 记录操作开始
if: steps.check-previous.outputs.should-continue == 'true'
uses: .actions/xgj/cache-state@v1
with:
state-key: 'current-operation-id'
state-value: ${{ steps.operation-setup.outputs.operation-id }}
action: 'set'
cache-prefix: 'operation'
- name: 记录操作状态为进行中
if: steps.check-previous.outputs.should-continue == 'true'
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-operation-status'
state-value: 'running'
action: 'set'
cache-prefix: 'operation'
build-with-retry:
needs: initialize-operation
if: needs.initialize-operation.outputs.should-continue == 'true'
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 检查构建重试状态
id: retry-status
uses: .actions/xgj/cache-state@v1
with:
state-key: 'build-retry-count-${{ needs.initialize-operation.outputs.operation-id }}'
default-value: '0'
action: 'get'
cache-prefix: 'retry'
- name: 准备构建重试
id: prepare-retry
run: |
CURRENT_RETRY=${{ steps.retry-status.outputs.state-value }}
MAX_RETRIES=3
echo "🔄 当前重试次数: ${CURRENT_RETRY}/${MAX_RETRIES}"
if [[ ${CURRENT_RETRY} -ge ${MAX_RETRIES} ]]; then
echo "❌ 已达到最大重试次数"
echo "can-retry=false" >> $GITHUB_OUTPUT
exit 1
else
echo "✅ 可以继续重试"
echo "can-retry=true" >> $GITHUB_OUTPUT
echo "next-retry=$((CURRENT_RETRY + 1))" >> $GITHUB_OUTPUT
fi
- name: 模拟构建过程
id: build
run: |
echo "🔨 开始构建过程..."
# 根据输入模拟不同类型的错误
case "${{ github.event.inputs.simulate_error }}" in
"build_failure")
echo "❌ 模拟构建失败"
exit 1
;;
"network_error")
echo "🌐 模拟网络错误"
sleep 2
exit 1
;;
*)
echo "✅ 构建成功"
;;
esac
- name: 更新重试计数(失败时)
if: failure()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'build-retry-count-${{ needs.initialize-operation.outputs.operation-id }}'
state-value: ${{ steps.prepare-retry.outputs.next-retry }}
action: 'set'
cache-prefix: 'retry'
- name: 记录构建失败状态
if: failure()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'build-status-${{ needs.initialize-operation.outputs.operation-id }}'
state-value: 'failed'
action: 'set'
cache-prefix: 'build'
- name: 记录构建失败时间
if: failure()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'build-failure-time-${{ needs.initialize-operation.outputs.operation-id }}'
state-value: ${{ github.event.head_commit.timestamp }}
action: 'set'
cache-prefix: 'build'
- name: 清理重试计数(成功时)
if: success()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'build-retry-count-${{ needs.initialize-operation.outputs.operation-id }}'
state-value: ''
action: 'set'
cache-prefix: 'retry'
- name: 记录构建成功状态
if: success()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'build-status-${{ needs.initialize-operation.outputs.operation-id }}'
state-value: 'success'
action: 'set'
cache-prefix: 'build'
deploy-with-rollback:
needs: [initialize-operation, build-with-retry]
if: success()
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 获取上次成功的部署版本
id: last-deploy
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-successful-deployment'
default-value: 'v1.0.0'
action: 'get'
cache-prefix: 'deploy'
- name: 备份当前部署状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deployment-backup-${{ needs.initialize-operation.outputs.operation-id }}'
state-value: ${{ steps.last-deploy.outputs.state-value }}
action: 'set'
cache-prefix: 'backup'
- name: 模拟部署过程
id: deploy
run: |
echo "🚀 开始部署..."
echo "📦 部署版本: ${{ github.sha }}"
echo "🔙 备份版本: ${{ steps.last-deploy.outputs.state-value }}"
# 模拟部署错误
if [[ "${{ github.event.inputs.simulate_error }}" == "deployment_error" ]]; then
echo "❌ 模拟部署失败"
exit 1
fi
echo "✅ 部署成功"
- name: 记录部署成功
if: success()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-successful-deployment'
state-value: ${{ github.sha }}
action: 'set'
cache-prefix: 'deploy'
- name: 清理备份(成功时)
if: success()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deployment-backup-${{ needs.initialize-operation.outputs.operation-id }}'
state-value: ''
action: 'set'
cache-prefix: 'backup'
- name: 执行回滚(失败时)
if: failure()
run: |
echo "🔄 部署失败,开始回滚..."
ROLLBACK_VERSION="${{ steps.last-deploy.outputs.state-value }}"
echo "回滚到版本: ${ROLLBACK_VERSION}"
# 这里执行实际的回滚操作
echo "✅ 回滚完成"
- name: 记录回滚状态
if: failure()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'rollback-executed-${{ needs.initialize-operation.outputs.operation-id }}'
state-value: 'true'
action: 'set'
cache-prefix: 'rollback'
finalize-operation:
needs: [initialize-operation, build-with-retry, deploy-with-rollback]
if: always() && needs.initialize-operation.outputs.should-continue == 'true'
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 确定最终操作状态
id: final-status
run: |
BUILD_RESULT="${{ needs.build-with-retry.result }}"
DEPLOY_RESULT="${{ needs.deploy-with-rollback.result }}"
echo "🔍 构建结果: ${BUILD_RESULT}"
echo "🔍 部署结果: ${DEPLOY_RESULT}"
if [[ "${BUILD_RESULT}" == "success" && "${DEPLOY_RESULT}" == "success" ]]; then
FINAL_STATUS="success"
elif [[ "${BUILD_RESULT}" == "failure" ]]; then
FINAL_STATUS="build_failed"
elif [[ "${DEPLOY_RESULT}" == "failure" ]]; then
FINAL_STATUS="deploy_failed"
elif [[ "${BUILD_RESULT}" == "success" && "${DEPLOY_RESULT}" == "skipped" ]]; then
FINAL_STATUS="partial"
else
FINAL_STATUS="unknown"
fi
echo "final-status=${FINAL_STATUS}" >> $GITHUB_OUTPUT
echo "🏁 最终状态: ${FINAL_STATUS}"
- name: 记录最终操作状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-operation-status'
state-value: ${{ steps.final-status.outputs.final-status }}
action: 'set'
cache-prefix: 'operation'
- name: 记录操作完成时间
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-operation-time'
state-value: ${{ github.event.head_commit.timestamp }}
action: 'set'
cache-prefix: 'operation'
- name: 生成错误处理报告
run: |
echo "📋 错误处理和恢复报告"
echo "========================"
echo "操作ID: ${{ needs.initialize-operation.outputs.operation-id }}"
echo "最终状态: ${{ steps.final-status.outputs.final-status }}"
echo "模拟错误类型: ${{ github.event.inputs.simulate_error }}"
echo "恢复模式: ${{ github.event.inputs.recovery_mode }}"
echo ""
case "${{ steps.final-status.outputs.final-status }}" in
"success")
echo "✅ 操作成功完成"
;;
"build_failed")
echo "❌ 构建失败,请检查构建日志"
;;
"deploy_failed")
echo "❌ 部署失败,已执行回滚"
;;
"partial")
echo "⚠️ 部分完成,可能需要手动干预"
;;
*)
echo "❓ 状态未知,需要进一步调查"
;;
esac
cleanup-expired-states:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 清理过期的重试状态
run: |
echo "🧹 清理过期的状态信息..."
# 这里可以实现清理逻辑
# 例如,清理超过一定时间的重试计数、备份等临时状态
- name: 清理示例 - 重置错误计数
uses: .actions/xgj/cache-state@v1
with:
state-key: 'error-count-global'
state-value: '0'
action: 'set'
cache-prefix: 'cleanup'