Merge branch 'v1'

This commit is contained in:
Lyda
2025-08-21 11:59:21 +08:00
17 changed files with 3448 additions and 53 deletions

View File

@@ -0,0 +1,804 @@
name: 测试 Cache State Action
on:
workflow_dispatch:
inputs:
test_scope:
description: '选择测试范围'
required: true
default: 'basic'
type: choice
options:
- basic
- operations
- edge-cases
- expiry
- delete
- full
- stress
test_prefix:
description: '测试缓存前缀'
required: false
default: 'test-state'
clean_cache:
description: '清理测试缓存'
required: false
default: false
type: boolean
env:
TEST_RUN_ID: ${{ github.run_id }}
TEST_RUN_NUMBER: ${{ github.run_number }}
jobs:
# 基础功能测试
test-basic-operations:
if: ${{ inputs.test_scope == 'basic' || inputs.test_scope == 'full' }}
runs-on: ubuntu-latest
outputs:
test-value: ${{ steps.basic-test.outputs.state-value }}
cache-hit: ${{ steps.basic-test.outputs.cache-hit }}
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 基础 get-or-set 操作测试
id: basic-test
uses: actions/xgj/cache-state@v1
with:
state-key: 'basic-test-${{ env.TEST_RUN_ID }}'
state-value: 'test-value-${{ env.TEST_RUN_NUMBER }}'
default-value: 'default-value'
cache-prefix: ${{ inputs.test_prefix }}
action: 'get-or-set'
- name: 验证基础操作结果
run: |
echo "🔍 验证基础操作结果..."
echo "状态值: ${{ steps.basic-test.outputs.state-value }}"
echo "缓存命中: ${{ steps.basic-test.outputs.cache-hit }}"
echo "使用默认值: ${{ steps.basic-test.outputs.used-default }}"
echo "缓存键: ${{ steps.basic-test.outputs.cache-key }}"
# 验证输出值不为空
if [[ -z "${{ steps.basic-test.outputs.state-value }}" ]]; then
echo "❌ 状态值为空"
exit 1
fi
# 验证缓存键格式
if [[ "${{ steps.basic-test.outputs.cache-key }}" =~ ^ubuntu-latest-.*-basic-test-.* ]]; then
echo "✅ 缓存键格式正确"
else
echo "❌ 缓存键格式不正确: ${{ steps.basic-test.outputs.cache-key }}"
exit 1
fi
echo "✅ 基础操作测试通过"
# 操作类型专项测试
test-operation-types:
if: ${{ inputs.test_scope == 'operations' || inputs.test_scope == 'full' }}
runs-on: ubuntu-latest
strategy:
matrix:
operation: [get, set, get-or-set]
include:
- operation: get
test_key: 'get-test'
test_value: ''
expected_default: 'true'
- operation: set
test_key: 'set-test'
test_value: 'set-value'
expected_default: 'false'
- operation: get-or-set
test_key: 'get-or-set-test'
test_value: 'get-or-set-value'
expected_default: 'false'
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 测试 ${{ matrix.operation }} 操作
id: operation-test
uses: actions/xgj/cache-state@v1
with:
state-key: '${{ matrix.test_key }}-${{ env.TEST_RUN_ID }}'
state-value: ${{ matrix.test_value }}
default-value: 'operation-default'
cache-prefix: ${{ inputs.test_prefix }}
action: ${{ matrix.operation }}
- name: 验证 ${{ matrix.operation }} 操作结果
run: |
echo "🎯 验证 ${{ matrix.operation }} 操作结果..."
echo "状态值: ${{ steps.operation-test.outputs.state-value }}"
echo "缓存命中: ${{ steps.operation-test.outputs.cache-hit }}"
echo "使用默认值: ${{ steps.operation-test.outputs.used-default }}"
# 验证操作特定的逻辑
case "${{ matrix.operation }}" in
"get")
if [[ "${{ steps.operation-test.outputs.used-default }}" == "${{ matrix.expected_default }}" ]]; then
echo "✅ get 操作正确使用默认值"
else
echo "❌ get 操作默认值行为异常"
exit 1
fi
;;
"set")
if [[ "${{ steps.operation-test.outputs.state-value }}" == "${{ matrix.test_value }}" ]]; then
echo "✅ set 操作正确设置值"
else
echo "❌ set 操作值不匹配"
exit 1
fi
;;
"get-or-set")
if [[ -n "${{ steps.operation-test.outputs.state-value }}" ]]; then
echo "✅ get-or-set 操作返回了值"
else
echo "❌ get-or-set 操作未返回值"
exit 1
fi
;;
esac
echo "✅ ${{ matrix.operation }} 操作测试通过"
# 缓存行为测试
test-cache-behavior:
if: ${{ inputs.test_scope == 'operations' || inputs.test_scope == 'full' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 第一次设置状态
id: first-set
uses: actions/xgj/cache-state@v1
with:
state-key: 'cache-behavior-test-${{ env.TEST_RUN_ID }}'
state-value: 'first-value'
cache-prefix: ${{ inputs.test_prefix }}
action: 'set'
- name: 第一次获取状态
id: first-get
uses: actions/xgj/cache-state@v1
with:
state-key: 'cache-behavior-test-${{ env.TEST_RUN_ID }}'
default-value: 'should-not-use'
cache-prefix: ${{ inputs.test_prefix }}
action: 'get'
- name: 验证缓存命中
run: |
echo "🗄️ 验证缓存行为..."
echo "第一次设置缓存命中: ${{ steps.first-set.outputs.cache-hit }}"
echo "第一次获取缓存命中: ${{ steps.first-get.outputs.cache-hit }}"
echo "获取到的值: ${{ steps.first-get.outputs.state-value }}"
echo "是否使用默认值: ${{ steps.first-get.outputs.used-default }}"
# 验证设置操作不应该命中缓存(第一次)
if [[ "${{ steps.first-set.outputs.cache-hit }}" == "false" ]]; then
echo "✅ 第一次设置正确未命中缓存"
else
echo "❌ 第一次设置不应该命中缓存"
exit 1
fi
# 验证获取操作应该命中缓存
if [[ "${{ steps.first-get.outputs.cache-hit }}" == "true" ]]; then
echo "✅ 获取操作正确命中缓存"
else
echo "❌ 获取操作应该命中缓存"
exit 1
fi
# 验证获取到的值正确
if [[ "${{ steps.first-get.outputs.state-value }}" == "first-value" ]]; then
echo "✅ 获取到正确的缓存值"
else
echo "❌ 缓存值不匹配,期望: first-value实际: ${{ steps.first-get.outputs.state-value }}"
exit 1
fi
# 验证没有使用默认值
if [[ "${{ steps.first-get.outputs.used-default }}" == "false" ]]; then
echo "✅ 正确未使用默认值"
else
echo "❌ 不应该使用默认值"
exit 1
fi
echo "✅ 缓存行为测试通过"
- name: 更新缓存状态
id: update-cache
uses: actions/xgj/cache-state@v1
with:
state-key: 'cache-behavior-test-${{ env.TEST_RUN_ID }}'
state-value: 'updated-value'
cache-prefix: ${{ inputs.test_prefix }}
action: 'set'
- name: 验证缓存更新
id: verify-update
uses: actions/xgj/cache-state@v1
with:
state-key: 'cache-behavior-test-${{ env.TEST_RUN_ID }}'
default-value: 'should-not-use'
cache-prefix: ${{ inputs.test_prefix }}
action: 'get'
- name: 验证更新结果
run: |
echo "🔄 验证缓存更新..."
echo "更新后的值: ${{ steps.verify-update.outputs.state-value }}"
if [[ "${{ steps.verify-update.outputs.state-value }}" == "updated-value" ]]; then
echo "✅ 缓存更新成功"
else
echo "❌ 缓存更新失败,期望: updated-value实际: ${{ steps.verify-update.outputs.state-value }}"
exit 1
fi
# 边界情况测试
test-edge-cases:
if: ${{ inputs.test_scope == 'edge-cases' || inputs.test_scope == 'full' }}
runs-on: ubuntu-latest
strategy:
matrix:
edge_case:
- name: empty-values
state_key: 'empty-test'
state_value: ''
default_value: ''
- name: special-chars
state_key: 'special-chars-@#$%^&*()'
state_value: 'value-with-special-!@#$%^&*()'
default_value: 'default-!@#$'
- name: long-values
state_key: 'long-value-test'
state_value: 'this-is-a-very-long-value-that-contains-multiple-words-and-hyphens-to-test-handling-of-long-strings'
default_value: 'long-default-value'
- name: unicode
state_key: 'unicode-test-中文-🚀'
state_value: 'unicode-value-测试-🎯'
default_value: 'unicode-default-默认值'
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 测试边界情况 - ${{ matrix.edge_case.name }}
id: edge-test
uses: actions/xgj/cache-state@v1
with:
state-key: '${{ matrix.edge_case.state_key }}-${{ env.TEST_RUN_ID }}'
state-value: ${{ matrix.edge_case.state_value }}
default-value: ${{ matrix.edge_case.default_value }}
cache-prefix: ${{ inputs.test_prefix }}
action: 'get-or-set'
- name: 验证边界情况 - ${{ matrix.edge_case.name }}
run: |
echo "🔬 验证边界情况: ${{ matrix.edge_case.name }}"
echo "状态值: '${{ steps.edge-test.outputs.state-value }}'"
echo "缓存命中: ${{ steps.edge-test.outputs.cache-hit }}"
echo "使用默认值: ${{ steps.edge-test.outputs.used-default }}"
echo "缓存键: ${{ steps.edge-test.outputs.cache-key }}"
# 验证操作没有失败
if [[ "$?" -eq 0 ]]; then
echo "✅ 边界情况 ${{ matrix.edge_case.name }} 处理成功"
else
echo "❌ 边界情况 ${{ matrix.edge_case.name }} 处理失败"
exit 1
fi
# 并发测试
test-concurrent:
if: ${{ inputs.test_scope == 'stress' || inputs.test_scope == 'full' }}
runs-on: ubuntu-latest
strategy:
matrix:
worker: [1, 2, 3, 4, 5]
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 并发操作测试 - Worker ${{ matrix.worker }}
id: concurrent-test
uses: actions/xgj/cache-state@v1
with:
state-key: 'concurrent-test-${{ matrix.worker }}'
state-value: 'worker-${{ matrix.worker }}-value-${{ env.TEST_RUN_ID }}'
default-value: 'concurrent-default-${{ matrix.worker }}'
cache-prefix: ${{ inputs.test_prefix }}
action: 'get-or-set'
- name: 验证并发操作
run: |
echo "🔀 并发操作 Worker ${{ matrix.worker }} 结果:"
echo "状态值: ${{ steps.concurrent-test.outputs.state-value }}"
echo "缓存命中: ${{ steps.concurrent-test.outputs.cache-hit }}"
echo "使用默认值: ${{ steps.concurrent-test.outputs.used-default }}"
# 验证值包含正确的 worker 标识
if [[ "${{ steps.concurrent-test.outputs.state-value }}" =~ worker-${{ matrix.worker }} ]]; then
echo "✅ Worker ${{ matrix.worker }} 值正确"
else
echo "❌ Worker ${{ matrix.worker }} 值异常"
exit 1
fi
# 过期时间测试
test-expiry:
if: ${{ inputs.test_scope == 'expiry' || inputs.test_scope == 'full' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 测试基础过期功能 - 短期缓存
id: short-expiry
uses: actions/xgj/cache-state@v1
with:
state-key: 'short-expiry-test-${{ github.run_id }}'
state-value: 'short-value'
default-value: 'default-short'
expiry-seconds: '120' # 2分钟
cache-prefix: ${{ inputs.test_prefix }}
- name: 验证短期缓存设置
run: |
echo "🕐 短期缓存测试结果:"
echo "状态值: ${{ steps.short-expiry.outputs.state-value }}"
echo "缓存命中: ${{ steps.short-expiry.outputs.cache-hit }}"
echo "过期状态: ${{ steps.short-expiry.outputs.expired }}"
echo "缓存键: ${{ steps.short-expiry.outputs.cache-key }}"
# 验证缓存键包含时间窗口
if [[ "${{ steps.short-expiry.outputs.cache-key }}" =~ -[0-9]+$ ]]; then
echo "✅ 缓存键包含时间窗口标识"
else
echo "❌ 缓存键缺少时间窗口标识"
exit 1
fi
- name: 测试永不过期缓存
id: no-expiry
uses: actions/xgj/cache-state@v1
with:
state-key: 'no-expiry-test-${{ github.run_id }}'
state-value: 'permanent-value'
default-value: 'default-permanent'
expiry-seconds: '0' # 永不过期
cache-prefix: ${{ inputs.test_prefix }}
- name: 验证永不过期缓存
run: |
echo "♾️ 永不过期缓存测试结果:"
echo "状态值: ${{ steps.no-expiry.outputs.state-value }}"
echo "缓存命中: ${{ steps.no-expiry.outputs.cache-hit }}"
echo "过期状态: ${{ steps.no-expiry.outputs.expired }}"
echo "缓存键: ${{ steps.no-expiry.outputs.cache-key }}"
# 验证缓存键不包含时间窗口
if [[ ! "${{ steps.no-expiry.outputs.cache-key }}" =~ -[0-9]+$ ]]; then
echo "✅ 永不过期缓存键格式正确"
else
echo "❌ 永不过期缓存键不应包含时间窗口"
exit 1
fi
# 验证过期状态
if [[ "${{ steps.no-expiry.outputs.expired }}" == "false" ]]; then
echo "✅ 永不过期缓存过期状态正确"
else
echo "❌ 永不过期缓存不应显示为过期"
exit 1
fi
- name: 测试不同过期时间的缓存键差异
run: |
echo "🔍 测试不同过期时间的缓存键生成..."
# 记录当前时间窗口
CURRENT_TIME=$(date +%s)
WINDOW_120=$((CURRENT_TIME / 120))
WINDOW_300=$((CURRENT_TIME / 300))
echo "当前时间: ${CURRENT_TIME}"
echo "120秒窗口: ${WINDOW_120}"
echo "300秒窗口: ${WINDOW_300}"
# 如果时间窗口不同,说明过期时间影响了缓存键
if [[ ${WINDOW_120} != ${WINDOW_300} ]]; then
echo "✅ 不同过期时间产生不同的时间窗口"
else
echo " 当前时间点两个时间窗口相同(正常情况)"
fi
- name: 测试过期状态判断
id: expiry-check
uses: actions/xgj/cache-state@v1
with:
state-key: 'non-existent-expiry-test'
default-value: 'fallback-value'
expiry-seconds: '60'
action: 'get'
cache-prefix: ${{ inputs.test_prefix }}
- name: 验证过期状态判断
run: |
echo "🔎 过期状态判断测试:"
echo "状态值: ${{ steps.expiry-check.outputs.state-value }}"
echo "缓存命中: ${{ steps.expiry-check.outputs.cache-hit }}"
echo "过期状态: ${{ steps.expiry-check.outputs.expired }}"
echo "使用默认值: ${{ steps.expiry-check.outputs.used-default }}"
# 对于不存在的缓存,应该标记为过期(如果设置了过期时间)
if [[ "${{ steps.expiry-check.outputs.cache-hit }}" == "false" && "${{ steps.expiry-check.outputs.expired }}" == "true" ]]; then
echo "✅ 正确识别缓存未命中为过期状态"
else
echo "❌ 过期状态判断异常"
exit 1
fi
- name: 测试各种过期时间值
run: |
echo "⏱️ 测试不同过期时间的行为..."
# 测试不同的过期时间值
for expiry in 30 60 300 3600; do
echo "测试过期时间: ${expiry}秒"
# 计算预期的时间窗口
CURRENT_TIME=$(date +%s)
EXPECTED_WINDOW=$((CURRENT_TIME / expiry))
echo " 当前时间: ${CURRENT_TIME}"
echo " 预期时间窗口: ${EXPECTED_WINDOW}"
done
# 删除功能测试
test-delete-operations:
if: ${{ inputs.test_scope == 'delete' || inputs.test_scope == 'full' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置测试状态
id: setup-delete-test
uses: actions/xgj/cache-state@v1
with:
state-key: 'delete-test-${{ github.run_id }}'
state-value: 'value-to-delete'
cache-prefix: ${{ inputs.test_prefix }}
action: 'set'
- name: 验证状态已设置
id: verify-before-delete
uses: actions/xgj/cache-state@v1
with:
state-key: 'delete-test-${{ github.run_id }}'
default-value: 'not-found'
cache-prefix: ${{ inputs.test_prefix }}
action: 'get'
- name: 验证设置成功
run: |
echo "🔍 验证设置成功:"
echo "获取的值: ${{ steps.verify-before-delete.outputs.state-value }}"
echo "缓存命中: ${{ steps.verify-before-delete.outputs.cache-hit }}"
if [[ "${{ steps.verify-before-delete.outputs.cache-hit }}" == "true" && "${{ steps.verify-before-delete.outputs.state-value }}" == "value-to-delete" ]]; then
echo "✅ 状态设置验证成功"
else
echo "❌ 状态设置验证失败"
exit 1
fi
- name: 执行删除操作
id: delete-operation
uses: actions/xgj/cache-state@v1
with:
state-key: 'delete-test-${{ github.run_id }}'
cache-prefix: ${{ inputs.test_prefix }}
action: 'del'
- name: 验证删除操作
run: |
echo "🗑️ 验证删除操作:"
echo "删除标志: ${{ steps.delete-operation.outputs.deleted }}"
echo "状态值: ${{ steps.delete-operation.outputs.state-value }}"
if [[ "${{ steps.delete-operation.outputs.deleted }}" == "true" ]]; then
echo "✅ 删除操作执行成功"
else
echo "❌ 删除操作标志异常"
exit 1
fi
if [[ -z "${{ steps.delete-operation.outputs.state-value }}" ]]; then
echo "✅ 删除后状态值为空"
else
echo "❌ 删除后状态值应为空"
exit 1
fi
- name: 验证删除效果
id: verify-after-delete
uses: actions/xgj/cache-state@v1
with:
state-key: 'delete-test-${{ github.run_id }}'
default-value: 'default-after-delete'
cache-prefix: ${{ inputs.test_prefix }}
action: 'get'
- name: 验证删除生效
run: |
echo "🔎 验证删除生效:"
echo "获取的值: ${{ steps.verify-after-delete.outputs.state-value }}"
echo "缓存命中: ${{ steps.verify-after-delete.outputs.cache-hit }}"
echo "使用默认值: ${{ steps.verify-after-delete.outputs.used-default }}"
if [[ "${{ steps.verify-after-delete.outputs.cache-hit }}" == "false" && "${{ steps.verify-after-delete.outputs.used-default }}" == "true" ]]; then
echo "✅ 删除生效,正确使用默认值"
else
echo "❌ 删除未生效"
exit 1
fi
if [[ "${{ steps.verify-after-delete.outputs.state-value }}" == "default-after-delete" ]]; then
echo "✅ 获取到正确的默认值"
else
echo "❌ 默认值不正确"
exit 1
fi
- name: 测试删除不存在的状态
id: delete-nonexistent
uses: actions/xgj/cache-state@v1
with:
state-key: 'nonexistent-delete-test-${{ github.run_id }}'
cache-prefix: ${{ inputs.test_prefix }}
action: 'del'
- name: 验证删除不存在状态的行为
run: |
echo "🔍 验证删除不存在状态:"
echo "删除标志: ${{ steps.delete-nonexistent.outputs.deleted }}"
if [[ "${{ steps.delete-nonexistent.outputs.deleted }}" == "true" ]]; then
echo "✅ 删除不存在的状态也正确标记为已删除"
else
echo "❌ 删除不存在状态的标志异常"
exit 1
fi
- name: 测试删除后重新设置
id: reset-after-delete
uses: actions/xgj/cache-state@v1
with:
state-key: 'delete-test-${{ github.run_id }}'
state-value: 'new-value-after-delete'
cache-prefix: ${{ inputs.test_prefix }}
action: 'set'
- name: 验证删除后重新设置
id: verify-reset
uses: actions/xgj/cache-state@v1
with:
state-key: 'delete-test-${{ github.run_id }}'
default-value: 'should-not-use'
cache-prefix: ${{ inputs.test_prefix }}
action: 'get'
- name: 验证重新设置效果
run: |
echo "🔄 验证重新设置效果:"
echo "获取的值: ${{ steps.verify-reset.outputs.state-value }}"
echo "缓存命中: ${{ steps.verify-reset.outputs.cache-hit }}"
if [[ "${{ steps.verify-reset.outputs.cache-hit }}" == "true" && "${{ steps.verify-reset.outputs.state-value }}" == "new-value-after-delete" ]]; then
echo "✅ 删除后重新设置成功"
else
echo "❌ 删除后重新设置失败"
exit 1
fi
# 错误处理测试
test-error-handling:
if: ${{ inputs.test_scope == 'edge-cases' || inputs.test_scope == 'full' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 测试无效操作类型
id: invalid-action
continue-on-error: true
uses: actions/xgj/cache-state@v1
with:
state-key: 'error-test-invalid-action'
action: 'invalid-action'
cache-prefix: ${{ inputs.test_prefix }}
- name: 验证错误处理
run: |
echo "🚨 验证错误处理..."
if [[ "${{ steps.invalid-action.outcome }}" == "failure" ]]; then
echo "✅ 无效操作类型正确被拒绝"
else
echo "❌ 无效操作类型应该失败"
exit 1
fi
- name: 测试空状态键
id: empty-key
continue-on-error: true
uses: actions/xgj/cache-state@v1
with:
state-key: ''
cache-prefix: ${{ inputs.test_prefix }}
- name: 验证空键处理
run: |
if [[ "${{ steps.empty-key.outcome }}" == "failure" ]]; then
echo "✅ 空状态键正确被拒绝"
else
echo "❌ 空状态键应该失败"
exit 1
fi
- name: 测试 set 操作无值
id: set-no-value
continue-on-error: true
uses: actions/xgj/cache-state@v1
with:
state-key: 'set-no-value-test'
action: 'set'
cache-prefix: ${{ inputs.test_prefix }}
- name: 验证 set 无值处理
run: |
if [[ "${{ steps.set-no-value.outcome }}" == "failure" ]]; then
echo "✅ set 操作无值正确被拒绝"
else
echo "❌ set 操作无值应该失败"
exit 1
fi
# 清理测试缓存
cleanup-test-cache:
if: ${{ inputs.clean_cache && always() }}
needs: [test-basic-operations, test-operation-types, test-cache-behavior, test-edge-cases, test-concurrent, test-error-handling]
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 清理测试缓存
run: |
echo "🧹 清理测试缓存..."
# 通过设置空值来清理各种测试缓存
TEST_KEYS=(
"basic-test-${{ env.TEST_RUN_ID }}"
"get-test-${{ env.TEST_RUN_ID }}"
"set-test-${{ env.TEST_RUN_ID }}"
"get-or-set-test-${{ env.TEST_RUN_ID }}"
"cache-behavior-test-${{ env.TEST_RUN_ID }}"
)
for key in "${TEST_KEYS[@]}"; do
echo "清理缓存键: ${key}"
# 这里可以使用 cache-state action 设置空值来清理
done
echo "✅ 测试缓存清理完成"
# 测试总结
test-summary:
needs: [test-basic-operations, test-operation-types, test-cache-behavior, test-edge-cases, test-expiry, test-delete-operations, test-concurrent, test-error-handling]
if: always()
runs-on: ubuntu-latest
steps:
- name: 生成测试报告
run: |
echo "## 🧪 Cache State Action 测试报告" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 测试配置" >> $GITHUB_STEP_SUMMARY
echo "- **测试范围**: ${{ inputs.test_scope }}" >> $GITHUB_STEP_SUMMARY
echo "- **缓存前缀**: ${{ inputs.test_prefix }}" >> $GITHUB_STEP_SUMMARY
echo "- **清理缓存**: ${{ inputs.clean_cache }}" >> $GITHUB_STEP_SUMMARY
echo "- **运行 ID**: ${{ env.TEST_RUN_ID }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 测试结果" >> $GITHUB_STEP_SUMMARY
# 检查各个任务的结果
if [[ "${{ needs.test-basic-operations.result }}" == "success" ]]; then
echo "- ✅ 基础操作测试: 通过" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.test-basic-operations.result }}" == "skipped" ]]; then
echo "- ⏭️ 基础操作测试: 跳过" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ 基础操作测试: 失败" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.test-operation-types.result }}" == "success" ]]; then
echo "- ✅ 操作类型测试: 通过" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.test-operation-types.result }}" == "skipped" ]]; then
echo "- ⏭️ 操作类型测试: 跳过" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ 操作类型测试: 失败" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.test-cache-behavior.result }}" == "success" ]]; then
echo "- ✅ 缓存行为测试: 通过" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.test-cache-behavior.result }}" == "skipped" ]]; then
echo "- ⏭️ 缓存行为测试: 跳过" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ 缓存行为测试: 失败" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.test-edge-cases.result }}" == "success" ]]; then
echo "- ✅ 边界情况测试: 通过" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.test-edge-cases.result }}" == "skipped" ]]; then
echo "- ⏭️ 边界情况测试: 跳过" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ 边界情况测试: 失败" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.test-concurrent.result }}" == "success" ]]; then
echo "- ✅ 并发测试: 通过" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.test-concurrent.result }}" == "skipped" ]]; then
echo "- ⏭️ 并发测试: 跳过" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ 并发测试: 失败" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.test-expiry.result }}" == "success" ]]; then
echo "- ✅ 过期时间测试: 通过" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.test-expiry.result }}" == "skipped" ]]; then
echo "- ⏭️ 过期时间测试: 跳过" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ 过期时间测试: 失败" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.test-delete-operations.result }}" == "success" ]]; then
echo "- ✅ 删除功能测试: 通过" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.test-delete-operations.result }}" == "skipped" ]]; then
echo "- ⏭️ 删除功能测试: 跳过" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ 删除功能测试: 失败" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.test-error-handling.result }}" == "success" ]]; then
echo "- ✅ 错误处理测试: 通过" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.test-error-handling.result }}" == "skipped" ]]; then
echo "- ⏭️ 错误处理测试: 跳过" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ 错误处理测试: 失败" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 关键数据" >> $GITHUB_STEP_SUMMARY
echo "- **基础测试值**: ${{ needs.test-basic-operations.outputs.test-value }}" >> $GITHUB_STEP_SUMMARY
echo "- **基础测试缓存命中**: ${{ needs.test-basic-operations.outputs.cache-hit }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 建议" >> $GITHUB_STEP_SUMMARY
echo "- 如果测试失败,请检查 action.yml 中的步骤逻辑" >> $GITHUB_STEP_SUMMARY
echo "- 确保 GitHub Actions 缓存功能正常工作" >> $GITHUB_STEP_SUMMARY
echo "- 检查特殊字符和 Unicode 的处理" >> $GITHUB_STEP_SUMMARY
echo "- 验证并发场景下的缓存一致性" >> $GITHUB_STEP_SUMMARY
echo "- 过期时间功能依赖时间窗口机制,注意时区影响" >> $GITHUB_STEP_SUMMARY
echo "- 删除功能通过标记实现,被删除的状态会立即失效" >> $GITHUB_STEP_SUMMARY
echo "- 缓存最多保存7天过期时间不会超过此限制" >> $GITHUB_STEP_SUMMARY

313
cache-state/README.md Normal file
View File

@@ -0,0 +1,313 @@
# 状态缓存管理 (Cache State)
利用 GitHub Actions 缓存机制缓存和管理状态信息的复合 Action支持默认值设置和多种操作模式。
## ✨ 功能特性
- 🗄️ **状态缓存**: 利用 GitHub Actions 缓存机制持久化状态信息
- 🔍 **智能获取**: 支持获取缓存状态,未命中时自动使用默认值
- 💾 **灵活设置**: 支持设置新的状态值到缓存
- 🗑️ **状态删除**: 支持删除缓存状态,实现状态清理
- 🔄 **自动管理**: 提供 get-or-set 模式,自动处理缓存逻辑
-**过期控制**: 支持设置缓存过期时间,基于时间窗口自动过期
- 📊 **状态透明**: 清晰告知是否命中缓存、是否使用默认值、是否过期、是否删除
- 🔒 **安全设计**: 避免在日志中暴露敏感信息
- 🔄 **向后兼容**: 兼容旧版本的缓存格式
## 📋 输入参数
| 参数名 | 描述 | 必需 | 默认值 |
| ---------------- | ----------------------------------------------------------------------- | ---- | ------------ |
| `state-key` | 状态键名,用于标识缓存的状态 | ✅ | - |
| `state-value` | 要存储的状态值(用于 set 和 get-or-set 操作) | ❌ | `''` |
| `default-value` | 默认值(当缓存未命中时使用) | ❌ | `''` |
| `cache-prefix` | 缓存前缀名称 | ❌ | `state` |
| `expiry-seconds` | 过期时间。0 表示依赖 GitHub Actions 缓存默认生命周期(最多 7 天) | ❌ | `0` |
| `action` | 操作类型:`get``set``get-or-set``del` | ❌ | `get-or-set` |
## 📤 输出参数
| 参数名 | 描述 |
| -------------- | ----------------------------------- |
| `state-value` | 最终的状态值 |
| `cache-hit` | 是否命中缓存 (true/false) |
| `used-default` | 是否使用了默认值 (true/false) |
| `expired` | 缓存是否因过期而未命中 (true/false) |
| `deleted` | 是否执行了删除操作 (true/false) |
| `cache-key` | 使用的缓存键 |
## 🎯 操作模式
### 1. `get` - 获取模式
只获取缓存中的状态值,如果缓存未命中则使用默认值。
### 2. `set` - 设置模式
将新的状态值存储到缓存中。
### 3. `get-or-set` - 获取或设置模式(默认)
先尝试获取缓存值,如果未命中则:
- 如果提供了 `state-value`,则使用并缓存该值
- 如果未提供 `state-value`,则使用 `default-value`
### 4. `del` - 删除模式
删除缓存中的状态值。通过写入删除标记实现,后续访问将视为缓存未命中。
## ⏰ 过期时间机制
过期时间基于**时间窗口**实现:
- `expiry-seconds` 为 0使用基础缓存键依赖 GitHub Actions 缓存默认生命周期(最多 7 天)
- `expiry-seconds` 大于 0缓存键包含时间窗口标识实现自定义过期时间
- 时间窗口计算:`当前时间戳 / 过期秒数`,同一窗口内的请求共享缓存
## 🚀 使用示例
### 基础用法 - 获取或设置部署版本
```yaml
- name: 管理部署版本状态
id: version-state
uses: actions/xgj/cache-state@v1
with:
state-key: "deployment-version"
state-value: "v1.2.3"
default-value: "v1.0.0"
action: "get-or-set"
- name: 使用版本信息
run: |
echo "当前版本: ${{ steps.version-state.outputs.state-value }}"
if [[ "${{ steps.version-state.outputs.used-default }}" == "true" ]]; then
echo "⚠️ 使用了默认版本,可能需要特殊处理"
fi
```
### 获取已存在的状态
```yaml
- name: 获取构建状态
id: build-state
uses: actions/xgj/cache-state@v1
with:
state-key: "last-build-status"
default-value: "unknown"
action: "get"
- name: 根据构建状态决定操作
run: |
if [[ "${{ steps.build-state.outputs.state-value }}" == "success" ]]; then
echo "上次构建成功,执行增量操作"
else
echo "上次构建失败或未知,执行完整构建"
fi
```
### 设置新状态
```yaml
- name: 记录构建状态
uses: actions/xgj/cache-state@v1
with:
state-key: "last-build-status"
state-value: "success"
action: "set"
```
### 删除状态
```yaml
- name: 清理构建状态
id: cleanup-state
uses: actions/xgj/cache-state@v1
with:
state-key: "last-build-status"
action: "del"
- name: 验证删除结果
run: |
echo "删除操作: ${{ steps.cleanup-state.outputs.deleted }}"
if [[ "${{ steps.cleanup-state.outputs.deleted }}" == "true" ]]; then
echo "✅ 状态已成功删除"
fi
```
### 过期时间使用
```yaml
- name: 设置临时会话1小时过期
id: temp-session
uses: actions/xgj/cache-state@v1
with:
state-key: "user-session-${{ github.actor }}"
state-value: "session-${{ github.run_id }}"
default-value: "no-session"
expiry-seconds: "3600" # 1小时后过期
action: "get-or-set"
- name: 处理会话状态
run: |
echo "会话状态: ${{ steps.temp-session.outputs.state-value }}"
echo "缓存过期: ${{ steps.temp-session.outputs.expired }}"
if [[ "${{ steps.temp-session.outputs.expired }}" == "true" ]]; then
echo "⏰ 会话已过期,使用新会话"
elif [[ "${{ steps.temp-session.outputs.cache-hit }}" == "true" ]]; then
echo "✅ 会话仍然有效"
fi
```
### 环境配置管理
```yaml
- name: 管理环境配置
id: env-config
uses: actions/xgj/cache-state@v1
with:
state-key: "environment-${{ github.ref_name }}"
state-value: ${{ inputs.environment }}
default-value: "development"
cache-prefix: "env-config"
- name: 应用环境配置
run: |
echo "目标环境: ${{ steps.env-config.outputs.state-value }}"
if [[ "${{ steps.env-config.outputs.cache-hit }}" == "true" ]]; then
echo "✅ 使用缓存的环境配置"
else
echo "⚠️ 首次设置或更新环境配置"
fi
```
### 多状态管理
```yaml
jobs:
setup:
runs-on: ubuntu-latest
outputs:
db-version: ${{ steps.db-state.outputs.state-value }}
api-version: ${{ steps.api-state.outputs.state-value }}
steps:
- name: 管理数据库版本
id: db-state
uses: actions/xgj/cache-state@v1
with:
state-key: "database-version"
default-value: "1.0"
- name: 管理API版本
id: api-state
uses: actions/xgj/cache-state@v1
with:
state-key: "api-version"
default-value: "2.0"
deploy:
needs: setup
runs-on: ubuntu-latest
steps:
- name: 部署应用
run: |
echo "部署数据库版本: ${{ needs.setup.outputs.db-version }}"
echo "部署API版本: ${{ needs.setup.outputs.api-version }}"
```
## 🔍 高级用法
### 条件逻辑处理
```yaml
- name: 检查发布状态
id: release-check
uses: actions/xgj/cache-state@v1
with:
state-key: "release-status-${{ github.sha }}"
default-value: "pending"
- name: 根据发布状态执行不同操作
run: |
case "${{ steps.release-check.outputs.state-value }}" in
"completed")
echo "发布已完成,跳过"
;;
"pending"|*)
echo "开始发布流程"
# 执行发布操作
;;
esac
- name: 更新发布状态为完成
if: success()
uses: actions/xgj/cache-state@v1
with:
state-key: "release-status-${{ github.sha }}"
state-value: "completed"
action: "set"
```
### 错误状态管理
```yaml
- name: 检查上次操作状态
id: last-operation
uses: actions/xgj/cache-state@v1
with:
state-key: "last-operation-${{ github.workflow }}"
default-value: "none"
- name: 清理可能的错误状态
if: steps.last-operation.outputs.state-value == 'failed'
run: |
echo "检测到上次操作失败,执行清理..."
# 执行清理操作
- name: 记录操作开始
uses: actions/xgj/cache-state@v1
with:
state-key: "last-operation-${{ github.workflow }}"
state-value: "running"
action: "set"
# ... 主要操作 ...
- name: 记录操作成功
if: success()
uses: actions/xgj/cache-state@v1
with:
state-key: "last-operation-${{ github.workflow }}"
state-value: "success"
action: "set"
- name: 记录操作失败
if: failure()
uses: actions/xgj/cache-state@v1
with:
state-key: "last-operation-${{ github.workflow }}"
state-value: "failed"
action: "set"
```
## ⚠️ 注意事项
1. **缓存生命周期**: GitHub Actions 缓存有生命周期限制,长期状态可能会被清理
2. **并发安全**: 多个并发作业修改同一状态键时可能产生竞争条件
3. **敏感信息**: 避免在状态值中存储敏感信息,缓存是可见的
4. **状态键命名**: 使用清晰的状态键名,避免冲突
5. **默认值处理**: 合理设置默认值,确保 `used-default` 输出被正确处理
## 🎨 最佳实践
- 使用有意义的状态键名,如 `deployment-version-${environment}`
- 合理设置缓存前缀以避免不同用途的状态冲突
- 在关键流程中检查 `used-default` 输出以确保逻辑正确
- 定期清理不再需要的状态(可通过设置空值实现)
- 在并发环境中使用唯一的状态键(如包含 commit SHA
## 🤝 贡献
欢迎提出 Issues 和 Pull Requests 来改进这个 Action

292
cache-state/action.yml Normal file
View File

@@ -0,0 +1,292 @@
name: '状态缓存管理'
description: '利用GitHub Actions缓存机制缓存和管理状态信息支持默认值设置'
branding:
icon: 'database'
color: 'orange'
inputs:
state-key:
description: '状态键名(用于标识缓存的状态)'
required: true
state-value:
description: '要存储的状态值(用于 set 和 get-or-set 操作)'
required: false
default: ''
default-value:
description: '默认值(当缓存未命中时使用)'
required: false
default: ''
cache-prefix:
description: '缓存前缀名称'
required: false
default: 'state'
expiry-seconds:
description: '过期时间。0 表示依赖 GitHub Actions 缓存默认生命周期最多7天'
required: false
default: '0'
action:
description: '操作类型get获取, set设置, get-or-set获取或设置, del删除'
required: false
default: 'get-or-set'
outputs:
state-value:
description: '最终的状态值'
value: ${{ steps.result.outputs.value }}
cache-hit:
description: '是否命中缓存 (true/false)'
value: ${{ steps.cache-get.outputs.cache-hit || steps.cache-set.outputs.cache-hit }}
used-default:
description: '是否使用了默认值 (true/false)'
value: ${{ steps.result.outputs.used-default }}
expired:
description: '缓存是否因过期而未命中 (true/false)'
value: ${{ steps.result.outputs.expired }}
deleted:
description: '是否执行了删除操作 (true/false)'
value: ${{ steps.result.outputs.deleted }}
cache-key:
description: '使用的缓存键'
value: ${{ steps.cache-key.outputs.key }}
runs:
using: 'composite'
steps:
- name: 验证输入参数
shell: bash
run: |
# 验证 action 参数
case "${{ inputs.action }}" in
"get"|"set"|"get-or-set"|"del")
echo "✅ 操作类型有效: ${{ inputs.action }}"
;;
*)
echo "❌ 无效的操作类型: ${{ inputs.action }}"
echo " 支持的操作类型: get, set, get-or-set, del"
exit 1
;;
esac
# 验证必需参数
if [[ -z "${{ inputs.state-key }}" ]]; then
echo "❌ state-key 参数不能为空"
exit 1
fi
# 验证过期时间参数
if ! [[ "${{ inputs.expiry-seconds }}" =~ ^[0-9]+$ ]]; then
echo "❌ expiry-seconds 必须是非负整数"
exit 1
fi
# 对于 set 操作,验证 state-value
if [[ "${{ inputs.action }}" == "set" && -z "${{ inputs.state-value }}" ]]; then
echo "❌ set 操作需要提供 state-value 参数"
exit 1
fi
echo "✅ 输入参数验证通过"
if [[ "${{ inputs.expiry-seconds }}" == "0" ]]; then
echo " - 过期时间: 使用默认生命周期最多7天"
else
echo " - 过期时间: ${{ inputs.expiry-seconds }}秒"
fi
- name: 生成缓存键
id: cache-key
shell: bash
run: |
# 清理状态键,移除特殊字符以确保安全性
STATE_KEY_CLEAN=$(echo "${{ inputs.state-key }}" | sed 's/[^a-zA-Z0-9._-]/_/g')
# 处理过期时间
EXPIRY_SECONDS="${{ inputs.expiry-seconds }}"
if [[ "${EXPIRY_SECONDS}" == "0" ]]; then
# 使用默认生命周期,使用基础缓存键
CACHE_KEY="${{ runner.os }}-${{ inputs.cache-prefix }}-${STATE_KEY_CLEAN}"
echo "🔑 生成缓存键(默认生命周期): ${CACHE_KEY}"
else
# 计算时间窗口,实现自动过期
CURRENT_TIME=$(date +%s)
TIME_WINDOW=$((CURRENT_TIME / EXPIRY_SECONDS))
CACHE_KEY="${{ runner.os }}-${{ inputs.cache-prefix }}-${STATE_KEY_CLEAN}-${TIME_WINDOW}"
echo "🔑 生成缓存键(${EXPIRY_SECONDS}秒过期): ${CACHE_KEY}"
echo "⏰ 时间窗口: ${TIME_WINDOW}"
fi
echo "key=${CACHE_KEY}" >> $GITHUB_OUTPUT
- name: 获取缓存状态
id: cache-get
if: inputs.action == 'get' || inputs.action == 'get-or-set' || inputs.action == 'del'
uses: actions/cache/restore@v4
with:
path: .cache-state-${{ inputs.state-key }}
key: ${{ steps.cache-key.outputs.key }}
- name: 读取缓存的状态值
id: read-cached
if: inputs.action == 'get' || inputs.action == 'get-or-set' || inputs.action == 'del'
shell: bash
run: |
CACHE_FILE=".cache-state-${{ inputs.state-key }}"
if [[ "${{ steps.cache-get.outputs.cache-hit }}" == "true" && -f "${CACHE_FILE}" ]]; then
CACHED_VALUE=$(cat "${CACHE_FILE}" 2>/dev/null || echo "")
# 检查是否是删除标记
if [[ "${CACHED_VALUE}" == "__DELETED__" ]]; then
echo "value=" >> $GITHUB_OUTPUT
echo "🗑️ 检测到删除标记,视为缓存未命中"
else
echo "value=${CACHED_VALUE}" >> $GITHUB_OUTPUT
echo "✅ 成功读取缓存值"
fi
else
echo "value=" >> $GITHUB_OUTPUT
echo "⚠️ 缓存未命中或文件不存在"
fi
- name: 处理状态值逻辑
id: result
shell: bash
run: |
USED_DEFAULT="false"
EXPIRED="false"
DELETED="false"
FINAL_VALUE=""
# 判断是否因过期而未命中缓存
if [[ "${{ steps.cache-get.outputs.cache-hit }}" != "true" && "${{ inputs.expiry-seconds }}" != "0" ]]; then
EXPIRED="true"
fi
case "${{ inputs.action }}" in
"get")
if [[ "${{ steps.cache-get.outputs.cache-hit }}" == "true" && -n "${{ steps.read-cached.outputs.value }}" ]]; then
FINAL_VALUE="${{ steps.read-cached.outputs.value }}"
echo "✅ 获取模式: 使用缓存值"
else
FINAL_VALUE="${{ inputs.default-value }}"
USED_DEFAULT="true"
if [[ "${EXPIRED}" == "true" ]]; then
echo "⚠️ 获取模式: 缓存已过期,使用默认值"
else
echo "⚠️ 获取模式: 缓存未命中,使用默认值"
fi
fi
;;
"set")
FINAL_VALUE="${{ inputs.state-value }}"
echo "✅ 设置模式: 将存储新的状态值"
;;
"get-or-set")
if [[ "${{ steps.cache-get.outputs.cache-hit }}" == "true" && -n "${{ steps.read-cached.outputs.value }}" ]]; then
FINAL_VALUE="${{ steps.read-cached.outputs.value }}"
echo "✅ 获取或设置模式: 使用缓存值"
else
if [[ -n "${{ inputs.state-value }}" ]]; then
FINAL_VALUE="${{ inputs.state-value }}"
if [[ "${EXPIRED}" == "true" ]]; then
echo "⚠️ 获取或设置模式: 缓存已过期,使用提供的新值"
else
echo "⚠️ 获取或设置模式: 缓存未命中,使用提供的新值"
fi
else
FINAL_VALUE="${{ inputs.default-value }}"
USED_DEFAULT="true"
if [[ "${EXPIRED}" == "true" ]]; then
echo "⚠️ 获取或设置模式: 缓存已过期,使用默认值"
else
echo "⚠️ 获取或设置模式: 缓存未命中,使用默认值"
fi
fi
fi
;;
"del")
DELETED="true"
FINAL_VALUE=""
if [[ "${{ steps.cache-get.outputs.cache-hit }}" == "true" && -n "${{ steps.read-cached.outputs.value }}" ]]; then
echo "🗑️ 删除模式: 删除现有缓存状态"
else
echo "🗑️ 删除模式: 状态不存在,执行删除标记"
fi
;;
esac
echo "value=${FINAL_VALUE}" >> $GITHUB_OUTPUT
echo "used-default=${USED_DEFAULT}" >> $GITHUB_OUTPUT
echo "expired=${EXPIRED}" >> $GITHUB_OUTPUT
echo "deleted=${DELETED}" >> $GITHUB_OUTPUT
- name: 保存状态到缓存
if: (inputs.action == 'set') || (inputs.action == 'get-or-set' && steps.cache-get.outputs.cache-hit != 'true') || (inputs.action == 'del')
shell: bash
run: |
CACHE_FILE=".cache-state-${{ inputs.state-key }}"
if [[ "${{ inputs.action }}" == "del" ]]; then
# 删除操作:写入删除标记
echo "__DELETED__" > "${CACHE_FILE}"
echo "🗑️ 删除标记已写入临时文件"
else
# 设置操作:写入实际值
echo "${{ steps.result.outputs.value }}" > "${CACHE_FILE}"
echo "✅ 状态值已写入临时文件"
fi
- name: 缓存状态值
id: cache-set
if: (inputs.action == 'set') || (inputs.action == 'get-or-set' && steps.cache-get.outputs.cache-hit != 'true') || (inputs.action == 'del')
uses: actions/cache/save@v4
with:
path: .cache-state-${{ inputs.state-key }}
key: ${{ steps.cache-key.outputs.key }}
- name: 清理临时文件
if: always()
shell: bash
run: |
CACHE_FILE=".cache-state-${{ inputs.state-key }}"
if [[ -f "${CACHE_FILE}" ]]; then
rm -f "${CACHE_FILE}"
echo "🧹 清理临时文件完成"
fi
- name: 操作总结
shell: bash
run: |
echo "📊 状态缓存操作总结:"
echo " - 操作类型: ${{ inputs.action }}"
echo " - 状态键名: ${{ inputs.state-key }}"
echo " - 缓存键名: ${{ steps.cache-key.outputs.key }}"
echo " - 缓存命中: ${{ steps.cache-get.outputs.cache-hit || steps.cache-set.outputs.cache-hit || 'N/A' }}"
echo " - 使用默认值: ${{ steps.result.outputs.used-default }}"
echo " - 缓存过期: ${{ steps.result.outputs.expired }}"
echo " - 执行删除: ${{ steps.result.outputs.deleted }}"
echo " - 过期时间: ${{ inputs.expiry-seconds }}秒"
if [[ "${{ steps.result.outputs.used-default }}" == "true" ]]; then
echo " ⚠️ 注意: 使用了默认值,这可能影响后续流程"
fi
if [[ "${{ steps.result.outputs.expired }}" == "true" ]]; then
echo " ⏰ 注意: 缓存因过期而失效"
fi
if [[ "${{ steps.result.outputs.deleted }}" == "true" ]]; then
echo " 🗑️ 注意: 已执行删除操作,状态已被清除"
fi

View File

@@ -0,0 +1,77 @@
# 基础使用示例
# 演示如何使用 cache-state action 进行基本的状态管理
name: Cache State - 基础使用示例
on:
workflow_dispatch:
inputs:
version:
description: '要设置的版本号'
required: false
default: 'v1.0.0'
jobs:
demo-basic-usage:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 获取或设置应用版本
id: app-version
uses: .actions/xgj/cache-state@v1
with:
state-key: 'application-version'
state-value: ${{ github.event.inputs.version }}
default-value: 'v0.1.0'
action: 'get-or-set'
- name: 显示版本信息
run: |
echo "🏷️ 应用版本: ${{ steps.app-version.outputs.state-value }}"
echo "💾 缓存命中: ${{ steps.app-version.outputs.cache-hit }}"
echo "🔄 使用默认值: ${{ steps.app-version.outputs.used-default }}"
echo "🔑 缓存键: ${{ steps.app-version.outputs.cache-key }}"
- name: 基于版本信息的条件操作
run: |
if [[ "${{ steps.app-version.outputs.used-default }}" == "true" ]]; then
echo "⚠️ 使用了默认版本,可能是首次运行"
echo "执行初始化操作..."
else
echo "✅ 使用了已有版本或新设置的版本"
echo "执行常规操作..."
fi
- name: 记录构建状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-build-status'
state-value: 'success'
action: 'set'
- name: 获取构建历史
id: build-history
uses: .actions/xgj/cache-state@v1
with:
state-key: 'build-count'
state-value: '1'
default-value: '0'
action: 'get-or-set'
- name: 更新构建计数
run: |
CURRENT_COUNT=${{ steps.build-history.outputs.state-value }}
NEW_COUNT=$((CURRENT_COUNT + 1))
echo "当前构建次数: ${CURRENT_COUNT}"
echo "新的构建次数: ${NEW_COUNT}"
- name: 保存新的构建计数
uses: .actions/xgj/cache-state@v1
with:
state-key: 'build-count'
state-value: ${{ env.NEW_COUNT }}
action: 'set'
env:
NEW_COUNT: ${{ steps.build-history.outputs.state-value == '0' && '1' || format('{0}', steps.build-history.outputs.state-value + 1) }}

View File

@@ -0,0 +1,263 @@
# 删除功能演示
# 展示如何使用 cache-state action 的删除功能
name: Cache State - 删除功能演示
on:
workflow_dispatch:
inputs:
demo_type:
description: '演示类型'
required: true
default: 'basic'
type: choice
options:
- basic
- cleanup
- conditional
- batch
jobs:
demo-basic-delete:
if: ${{ inputs.demo_type == 'basic' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置测试状态
id: setup-state
uses: actions/xgj/cache-state@v1
with:
state-key: "demo-delete-test"
state-value: "test-value-${{ github.run_id }}"
action: "set"
- name: 验证状态已设置
id: verify-set
uses: actions/xgj/cache-state@v1
with:
state-key: "demo-delete-test"
default-value: "not-found"
action: "get"
- name: 显示设置结果
run: |
echo "设置的值: ${{ steps.verify-set.outputs.state-value }}"
echo "缓存命中: ${{ steps.verify-set.outputs.cache-hit }}"
if [[ "${{ steps.verify-set.outputs.cache-hit }}" == "true" ]]; then
echo "✅ 状态设置成功"
else
echo "❌ 状态设置失败"
exit 1
fi
- name: 删除状态
id: delete-state
uses: actions/xgj/cache-state@v1
with:
state-key: "demo-delete-test"
action: "del"
- name: 验证删除结果
run: |
echo "删除操作: ${{ steps.delete-state.outputs.deleted }}"
echo "缓存键: ${{ steps.delete-state.outputs.cache-key }}"
if [[ "${{ steps.delete-state.outputs.deleted }}" == "true" ]]; then
echo "✅ 删除操作执行成功"
else
echo "❌ 删除操作失败"
exit 1
fi
- name: 验证状态已删除
id: verify-deleted
uses: actions/xgj/cache-state@v1
with:
state-key: "demo-delete-test"
default-value: "fallback-value"
action: "get"
- name: 确认删除效果
run: |
echo "验证获取的值: ${{ steps.verify-deleted.outputs.state-value }}"
echo "缓存命中: ${{ steps.verify-deleted.outputs.cache-hit }}"
echo "使用默认值: ${{ steps.verify-deleted.outputs.used-default }}"
if [[ "${{ steps.verify-deleted.outputs.cache-hit }}" == "false" && "${{ steps.verify-deleted.outputs.used-default }}" == "true" ]]; then
echo "✅ 状态已成功删除,使用默认值"
else
echo "❌ 状态删除验证失败"
exit 1
fi
demo-cleanup-workflow:
if: ${{ inputs.demo_type == 'cleanup' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 创建多个测试状态
run: |
echo "创建多个测试状态用于清理演示..."
- name: 设置构建状态
uses: actions/xgj/cache-state@v1
with:
state-key: "build-status-${{ github.run_id }}"
state-value: "completed"
action: "set"
- name: 设置部署状态
uses: actions/xgj/cache-state@v1
with:
state-key: "deploy-status-${{ github.run_id }}"
state-value: "success"
action: "set"
- name: 设置测试状态
uses: actions/xgj/cache-state@v1
with:
state-key: "test-status-${{ github.run_id }}"
state-value: "passed"
action: "set"
- name: 模拟工作流结束后的清理
run: |
echo "🧹 开始清理工作流状态..."
- name: 清理构建状态
uses: actions/xgj/cache-state@v1
with:
state-key: "build-status-${{ github.run_id }}"
action: "del"
- name: 清理部署状态
uses: actions/xgj/cache-state@v1
with:
state-key: "deploy-status-${{ github.run_id }}"
action: "del"
- name: 清理测试状态
uses: actions/xgj/cache-state@v1
with:
state-key: "test-status-${{ github.run_id }}"
action: "del"
- name: 清理完成
run: |
echo "✅ 所有状态已清理完成"
demo-conditional-delete:
if: ${{ inputs.demo_type == 'conditional' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 检查现有状态
id: check-state
uses: actions/xgj/cache-state@v1
with:
state-key: "conditional-delete-test"
default-value: "none"
action: "get"
- name: 显示当前状态
run: |
echo "当前状态: ${{ steps.check-state.outputs.state-value }}"
echo "缓存命中: ${{ steps.check-state.outputs.cache-hit }}"
- name: 条件性删除 - 如果状态存在
if: ${{ steps.check-state.outputs.cache-hit == 'true' }}
id: conditional-delete
uses: actions/xgj/cache-state@v1
with:
state-key: "conditional-delete-test"
action: "del"
- name: 条件性设置 - 如果状态不存在
if: ${{ steps.check-state.outputs.cache-hit != 'true' }}
uses: actions/xgj/cache-state@v1
with:
state-key: "conditional-delete-test"
state-value: "newly-created-${{ github.run_id }}"
action: "set"
- name: 显示操作结果
run: |
if [[ "${{ steps.check-state.outputs.cache-hit }}" == "true" ]]; then
echo "🗑️ 执行了删除操作"
echo "删除结果: ${{ steps.conditional-delete.outputs.deleted }}"
else
echo "🆕 执行了创建操作"
fi
demo-batch-operations:
if: ${{ inputs.demo_type == 'batch' }}
runs-on: ubuntu-latest
strategy:
matrix:
operation: [create, delete]
state_id: [1, 2, 3]
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 批量创建状态
if: ${{ matrix.operation == 'create' }}
uses: actions/xgj/cache-state@v1
with:
state-key: "batch-state-${{ matrix.state_id }}"
state-value: "batch-value-${{ matrix.state_id }}-${{ github.run_id }}"
action: "set"
- name: 批量删除状态
if: ${{ matrix.operation == 'delete' }}
uses: actions/xgj/cache-state@v1
with:
state-key: "batch-state-${{ matrix.state_id }}"
action: "del"
- name: 显示操作结果
run: |
echo "操作: ${{ matrix.operation }}"
echo "状态ID: ${{ matrix.state_id }}"
echo "✅ 批量操作 ${{ matrix.operation }} 完成"
demo-summary:
needs: [demo-basic-delete, demo-cleanup-workflow, demo-conditional-delete, demo-batch-operations]
if: always()
runs-on: ubuntu-latest
steps:
- name: 生成演示总结
run: |
echo "## 🗑️ 删除功能演示总结" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 演示类型: ${{ inputs.demo_type }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
case "${{ inputs.demo_type }}" in
"basic")
echo "✅ **基础删除演示**: 展示了设置、删除、验证的完整流程" >> $GITHUB_STEP_SUMMARY
;;
"cleanup")
echo "✅ **清理工作流演示**: 展示了批量清理多个状态的用法" >> $GITHUB_STEP_SUMMARY
;;
"conditional")
echo "✅ **条件删除演示**: 展示了基于状态存在性的条件操作" >> $GITHUB_STEP_SUMMARY
;;
"batch")
echo "✅ **批量操作演示**: 展示了并行批量创建和删除状态" >> $GITHUB_STEP_SUMMARY
;;
esac
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 核心特性" >> $GITHUB_STEP_SUMMARY
echo "- 🗑️ **状态删除**: 通过删除标记实现状态清除" >> $GITHUB_STEP_SUMMARY
echo "- 🔄 **即时生效**: 删除后立即生效,后续访问使用默认值" >> $GITHUB_STEP_SUMMARY
echo "- 📊 **状态透明**: 通过 \`deleted\` 输出明确告知删除操作" >> $GITHUB_STEP_SUMMARY
echo "- 🛡️ **安全可靠**: 基于缓存覆盖机制,不会影响其他状态" >> $GITHUB_STEP_SUMMARY

View File

@@ -0,0 +1,200 @@
# 部署状态管理示例
# 演示如何在部署工作流中使用状态缓存来跟踪部署进度和状态
name: Cache State - 部署状态管理
on:
push:
branches: [main, develop]
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
force_deploy:
description: '强制部署(忽略上次部署状态)'
required: false
default: false
type: boolean
jobs:
check-deployment-state:
runs-on: ubuntu-latest
outputs:
should-deploy: ${{ steps.deploy-decision.outputs.should-deploy }}
last-deployed-sha: ${{ steps.last-deploy.outputs.state-value }}
environment: ${{ steps.env-state.outputs.state-value }}
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 获取环境配置
id: env-state
uses: .actions/xgj/cache-state@v1
with:
state-key: 'target-environment-${{ github.ref_name }}'
state-value: ${{ github.event.inputs.environment || 'staging' }}
default-value: 'staging'
cache-prefix: 'deploy-env'
- name: 检查上次部署的SHA
id: last-deploy
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-deployed-sha-${{ steps.env-state.outputs.state-value }}'
default-value: 'none'
action: 'get'
- name: 检查部署状态
id: deploy-status
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-status-${{ steps.env-state.outputs.state-value }}'
default-value: 'idle'
action: 'get'
- name: 决定是否需要部署
id: deploy-decision
run: |
FORCE_DEPLOY="${{ github.event.inputs.force_deploy }}"
LAST_SHA="${{ steps.last-deploy.outputs.state-value }}"
CURRENT_SHA="${{ github.sha }}"
DEPLOY_STATUS="${{ steps.deploy-status.outputs.state-value }}"
echo "🔍 部署决策分析:"
echo " - 强制部署: ${FORCE_DEPLOY}"
echo " - 上次部署SHA: ${LAST_SHA}"
echo " - 当前SHA: ${CURRENT_SHA}"
echo " - 部署状态: ${DEPLOY_STATUS}"
if [[ "${FORCE_DEPLOY}" == "true" ]]; then
echo "✅ 强制部署模式,将执行部署"
echo "should-deploy=true" >> $GITHUB_OUTPUT
elif [[ "${DEPLOY_STATUS}" == "deploying" ]]; then
echo "⚠️ 检测到正在进行的部署,跳过"
echo "should-deploy=false" >> $GITHUB_OUTPUT
elif [[ "${LAST_SHA}" != "${CURRENT_SHA}" || "${LAST_SHA}" == "none" ]]; then
echo "✅ 检测到新的变更,需要部署"
echo "should-deploy=true" >> $GITHUB_OUTPUT
else
echo " 没有新的变更,跳过部署"
echo "should-deploy=false" >> $GITHUB_OUTPUT
fi
deploy:
needs: check-deployment-state
if: needs.check-deployment-state.outputs.should-deploy == 'true'
runs-on: ubuntu-latest
environment: ${{ needs.check-deployment-state.outputs.environment }}
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 标记部署开始
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
state-value: 'deploying'
action: 'set'
- name: 记录部署开始时间
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-start-time-${{ needs.check-deployment-state.outputs.environment }}'
state-value: ${{ github.run_started_at }}
action: 'set'
- name: 模拟部署过程
run: |
echo "🚀 开始部署到 ${{ needs.check-deployment-state.outputs.environment }} 环境..."
echo "📦 部署版本: ${{ github.sha }}"
# 模拟部署步骤
for i in {1..5}; do
echo " 步骤 ${i}/5: 部署进行中..."
sleep 2
done
echo "✅ 部署完成!"
- name: 记录成功部署的SHA
if: success()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'last-deployed-sha-${{ needs.check-deployment-state.outputs.environment }}'
state-value: ${{ github.sha }}
action: 'set'
- name: 标记部署成功
if: success()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
state-value: 'success'
action: 'set'
- name: 记录部署完成时间
if: success()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-end-time-${{ needs.check-deployment-state.outputs.environment }}'
state-value: ${{ github.event.head_commit.timestamp }}
action: 'set'
- name: 标记部署失败
if: failure()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
state-value: 'failed'
action: 'set'
- name: 记录失败信息
if: failure()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-error-${{ needs.check-deployment-state.outputs.environment }}'
state-value: 'Deployment failed at ${{ github.event.head_commit.timestamp }}'
action: 'set'
post-deploy:
needs: [check-deployment-state, deploy]
if: always() && needs.check-deployment-state.outputs.should-deploy == 'true'
runs-on: ubuntu-latest
steps:
- name: 获取最终部署状态
id: final-status
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
default-value: 'unknown'
action: 'get'
- name: 部署状态总结
run: |
echo "📊 部署状态总结:"
echo " - 环境: ${{ needs.check-deployment-state.outputs.environment }}"
echo " - 最终状态: ${{ steps.final-status.outputs.state-value }}"
echo " - 部署SHA: ${{ github.sha }}"
if [[ "${{ steps.final-status.outputs.state-value }}" == "success" ]]; then
echo "🎉 部署成功完成!"
elif [[ "${{ steps.final-status.outputs.state-value }}" == "failed" ]]; then
echo "❌ 部署失败,请检查日志"
else
echo "⚠️ 部署状态未知"
fi
# 清理部署锁定状态(如果需要)
- name: 清理部署锁定
if: always()
uses: .actions/xgj/cache-state@v1
with:
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
state-value: 'idle'
action: 'set'

View File

@@ -0,0 +1,377 @@
# 错误处理和恢复示例
# 演示如何使用状态缓存进行错误处理、状态恢复和重试逻辑
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'

View File

@@ -0,0 +1,243 @@
# 过期时间功能演示
# 展示如何使用 cache-state action 的过期时间功能
name: Cache State - 过期时间演示
on:
workflow_dispatch:
inputs:
demo_type:
description: '演示类型'
required: true
default: 'basic'
type: choice
options:
- basic
- session
- build-lock
- rate-limit
jobs:
demo-basic-expiry:
if: ${{ inputs.demo_type == 'basic' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置短期缓存5分钟过期
id: short-cache
uses: actions/xgj/cache-state@v1
with:
state-key: "demo-short-cache"
state-value: "cached-at-${{ github.run_started_at }}"
default-value: "no-cache"
expiry-seconds: "300" # 5分钟
action: "get-or-set"
- name: 显示缓存状态
run: |
echo "缓存值: ${{ steps.short-cache.outputs.state-value }}"
echo "缓存命中: ${{ steps.short-cache.outputs.cache-hit }}"
echo "缓存过期: ${{ steps.short-cache.outputs.expired }}"
echo "使用默认值: ${{ steps.short-cache.outputs.used-default }}"
- name: 等待1分钟
run: sleep 60
- name: 再次获取缓存(应该仍然有效)
id: check-cache
uses: actions/xgj/cache-state@v1
with:
state-key: "demo-short-cache"
default-value: "expired"
expiry-seconds: "300"
action: "get"
- name: 验证缓存仍然有效
run: |
echo "再次获取的值: ${{ steps.check-cache.outputs.state-value }}"
echo "缓存命中: ${{ steps.check-cache.outputs.cache-hit }}"
if [[ "${{ steps.check-cache.outputs.cache-hit }}" == "true" ]]; then
echo "✅ 缓存在1分钟后仍然有效"
else
echo "❌ 缓存意外失效"
fi
demo-session-management:
if: ${{ inputs.demo_type == 'session' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 创建用户会话1小时过期
id: user-session
uses: actions/xgj/cache-state@v1
with:
state-key: "user-session-${{ github.actor }}"
state-value: "session-${{ github.run_id }}"
default-value: "no-session"
expiry-seconds: "3600" # 1小时
action: "get-or-set"
- name: 处理会话状态
run: |
SESSION_VALUE="${{ steps.user-session.outputs.state-value }}"
echo "用户: ${{ github.actor }}"
echo "会话状态: ${SESSION_VALUE}"
echo "缓存命中: ${{ steps.user-session.outputs.cache-hit }}"
echo "缓存过期: ${{ steps.user-session.outputs.expired }}"
if [[ "${{ steps.user-session.outputs.expired }}" == "true" ]]; then
echo "⏰ 会话已过期,创建新会话"
elif [[ "${{ steps.user-session.outputs.cache-hit }}" == "true" ]]; then
echo "✅ 会话仍然有效,继续使用"
else
echo "🆕 首次创建会话"
fi
- name: 模拟会话活动
run: |
echo "执行一些需要会话的操作..."
echo "会话ID: ${{ steps.user-session.outputs.state-value }}"
demo-build-lock:
if: ${{ inputs.demo_type == 'build-lock' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 检查构建锁定状态10分钟过期
id: build-lock
uses: actions/xgj/cache-state@v1
with:
state-key: "build-lock-${{ github.repository }}"
state-value: "locked-by-${{ github.run_id }}"
default-value: "unlocked"
expiry-seconds: "600" # 10分钟
action: "get-or-set"
- name: 处理构建锁定
run: |
LOCK_VALUE="${{ steps.build-lock.outputs.state-value }}"
echo "构建锁定状态: ${LOCK_VALUE}"
echo "缓存命中: ${{ steps.build-lock.outputs.cache-hit }}"
echo "缓存过期: ${{ steps.build-lock.outputs.expired }}"
if [[ "${LOCK_VALUE}" == "unlocked" ]]; then
echo "✅ 没有构建锁定,可以开始构建"
elif [[ "${LOCK_VALUE}" == "locked-by-${{ github.run_id }}" ]]; then
echo "✅ 当前运行获得了构建锁"
elif [[ "${{ steps.build-lock.outputs.expired }}" == "true" ]]; then
echo "⏰ 构建锁已过期,获得新锁"
else
echo "⚠️ 构建被其他运行锁定: ${LOCK_VALUE}"
echo "等待锁定过期或手动解锁"
exit 1
fi
- name: 模拟构建过程
run: |
echo "🔨 开始构建..."
sleep 30
echo "✅ 构建完成"
- name: 释放构建锁
if: always()
uses: actions/xgj/cache-state@v1
with:
state-key: "build-lock-${{ github.repository }}"
state-value: "unlocked"
expiry-seconds: "600"
action: "set"
demo-rate-limiting:
if: ${{ inputs.demo_type == 'rate-limit' }}
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 检查API调用限制1分钟窗口
id: api-limit
uses: actions/xgj/cache-state@v1
with:
state-key: "api-calls-${{ github.actor }}"
state-value: "1"
default-value: "0"
expiry-seconds: "60" # 1分钟窗口
action: "get-or-set"
- name: 处理速率限制
run: |
CALL_COUNT="${{ steps.api-limit.outputs.state-value }}"
MAX_CALLS=5
echo "当前调用次数: ${CALL_COUNT}/${MAX_CALLS}"
echo "缓存命中: ${{ steps.api-limit.outputs.cache-hit }}"
echo "缓存过期: ${{ steps.api-limit.outputs.expired }}"
if [[ "${{ steps.api-limit.outputs.expired }}" == "true" ]]; then
echo "⏰ 速率限制窗口已重置"
fi
if [[ ${CALL_COUNT} -le ${MAX_CALLS} ]]; then
echo "✅ 在速率限制内,可以继续调用"
else
echo "❌ 超出速率限制,请等待"
exit 1
fi
- name: 模拟API调用
run: |
echo "📡 调用API..."
sleep 5
echo "✅ API调用成功"
- name: 更新调用计数
if: success()
uses: actions/xgj/cache-state@v1
with:
state-key: "api-calls-${{ github.actor }}"
state-value: "${{ steps.api-limit.outputs.state-value + 1 }}"
expiry-seconds: "60"
action: "set"
demo-summary:
needs: [demo-basic-expiry, demo-session-management, demo-build-lock, demo-rate-limiting]
if: always()
runs-on: ubuntu-latest
steps:
- name: 生成演示总结
run: |
echo "## 🎯 过期时间功能演示总结" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 演示类型: ${{ inputs.demo_type }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
case "${{ inputs.demo_type }}" in
"basic")
echo "✅ **基础过期演示**: 展示了5分钟过期缓存的基本用法" >> $GITHUB_STEP_SUMMARY
;;
"session")
echo "✅ **会话管理演示**: 展示了1小时过期的用户会话管理" >> $GITHUB_STEP_SUMMARY
;;
"build-lock")
echo "✅ **构建锁定演示**: 展示了10分钟过期的构建锁定机制" >> $GITHUB_STEP_SUMMARY
;;
"rate-limit")
echo "✅ **速率限制演示**: 展示了1分钟窗口的API调用限制" >> $GITHUB_STEP_SUMMARY
;;
esac
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 核心特性" >> $GITHUB_STEP_SUMMARY
echo "- ⏰ **时间窗口过期**: 基于时间窗口的自动过期机制" >> $GITHUB_STEP_SUMMARY
echo "- 🔄 **简单实现**: 不依赖复杂工具使用基础shell命令" >> $GITHUB_STEP_SUMMARY
echo "- 📊 **状态透明**: 清晰显示缓存命中、过期状态" >> $GITHUB_STEP_SUMMARY
echo "- 🛡️ **安全可靠**: 利用GitHub Actions缓存的天然特性" >> $GITHUB_STEP_SUMMARY

View File

@@ -0,0 +1,326 @@
# 功能开关状态管理示例
# 演示如何使用状态缓存来管理功能开关、配置参数等动态配置
name: Cache State - 功能开关管理
on:
workflow_dispatch:
inputs:
feature_name:
description: '功能名称'
required: true
default: 'new-ui'
feature_enabled:
description: '是否启用功能'
required: false
default: true
type: boolean
rollout_percentage:
description: '灰度发布百分比 (0-100)'
required: false
default: '50'
environment:
description: '目标环境'
required: false
default: 'staging'
type: choice
options:
- development
- staging
- production
jobs:
manage-feature-flags:
runs-on: ubuntu-latest
outputs:
feature-state: ${{ steps.feature-flag.outputs.state-value }}
rollout-config: ${{ steps.rollout.outputs.state-value }}
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 获取或设置功能开关状态
id: feature-flag
uses: .actions/xgj/cache-state@v1
with:
state-key: 'feature-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
state-value: ${{ github.event.inputs.feature_enabled }}
default-value: 'false'
cache-prefix: 'feature-flags'
action: 'get-or-set'
- name: 管理灰度发布配置
id: rollout
uses: .actions/xgj/cache-state@v1
with:
state-key: 'rollout-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
state-value: ${{ github.event.inputs.rollout_percentage }}
default-value: '0'
cache-prefix: 'rollout-config'
action: 'get-or-set'
- name: 记录功能开关变更历史
uses: .actions/xgj/cache-state@v1
with:
state-key: 'feature-history-${{ github.event.inputs.feature_name }}'
state-value: '${{ github.event.inputs.environment }}:${{ github.event.inputs.feature_enabled }}:${{ github.run_started_at }}'
cache-prefix: 'feature-history'
action: 'set'
- name: 验证功能开关配置
run: |
FEATURE_ENABLED="${{ steps.feature-flag.outputs.state-value }}"
ROLLOUT_PERCENT="${{ steps.rollout.outputs.state-value }}"
echo "🎛️ 功能开关配置验证:"
echo " - 功能名称: ${{ github.event.inputs.feature_name }}"
echo " - 环境: ${{ github.event.inputs.environment }}"
echo " - 功能状态: ${FEATURE_ENABLED}"
echo " - 灰度百分比: ${ROLLOUT_PERCENT}%"
echo " - 缓存命中: ${{ steps.feature-flag.outputs.cache-hit }}"
# 验证配置合理性
if [[ "${FEATURE_ENABLED}" == "true" && "${ROLLOUT_PERCENT}" -gt 0 ]]; then
echo "✅ 功能配置有效"
elif [[ "${FEATURE_ENABLED}" == "false" ]]; then
echo " 功能已禁用"
else
echo "⚠️ 功能配置可能需要检查"
fi
apply-feature-configuration:
needs: manage-feature-flags
runs-on: ubuntu-latest
strategy:
matrix:
service: [api, frontend, mobile]
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 获取服务特定的功能配置
id: service-config
uses: .actions/xgj/cache-state@v1
with:
state-key: 'service-config-${{ matrix.service }}-${{ github.event.inputs.environment }}'
default-value: '{"features":{},"version":"1.0"}'
action: 'get'
cache-prefix: 'service-config'
- name: 应用功能配置到服务
run: |
SERVICE="${{ matrix.service }}"
FEATURE_NAME="${{ github.event.inputs.feature_name }}"
FEATURE_ENABLED="${{ needs.manage-feature-flags.outputs.feature-state }}"
ROLLOUT_PERCENT="${{ needs.manage-feature-flags.outputs.rollout-config }}"
echo "🔧 为 ${SERVICE} 服务应用功能配置:"
echo " - 功能: ${FEATURE_NAME}"
echo " - 状态: ${FEATURE_ENABLED}"
echo " - 灰度: ${ROLLOUT_PERCENT}%"
# 模拟配置应用过程
case "${SERVICE}" in
"api")
echo " 📡 API服务配置已更新"
;;
"frontend")
echo " 🌐 前端服务配置已更新"
;;
"mobile")
echo " 📱 移动端配置已更新"
;;
esac
- name: 更新服务配置状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'service-config-applied-${{ matrix.service }}'
state-value: '${{ github.event.inputs.feature_name }}:${{ needs.manage-feature-flags.outputs.feature-state }}'
cache-prefix: 'service-status'
action: 'set'
monitor-feature-metrics:
needs: [manage-feature-flags, apply-feature-configuration]
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 初始化功能监控指标
id: init-metrics
uses: .actions/xgj/cache-state@v1
with:
state-key: 'metrics-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
default-value: '{"users":0,"errors":0,"performance":100}'
action: 'get'
cache-prefix: 'feature-metrics'
- name: 模拟收集功能使用指标
run: |
echo "📊 收集功能使用指标..."
# 模拟指标收集
USERS_COUNT=$((RANDOM % 1000 + 100))
ERROR_COUNT=$((RANDOM % 10))
PERFORMANCE_SCORE=$((RANDOM % 20 + 80))
echo " - 用户数: ${USERS_COUNT}"
echo " - 错误数: ${ERROR_COUNT}"
echo " - 性能分数: ${PERFORMANCE_SCORE}"
# 保存到环境变量供后续步骤使用
echo "users_count=${USERS_COUNT}" >> $GITHUB_ENV
echo "error_count=${ERROR_COUNT}" >> $GITHUB_ENV
echo "performance_score=${PERFORMANCE_SCORE}" >> $GITHUB_ENV
- name: 更新功能监控指标
uses: .actions/xgj/cache-state@v1
with:
state-key: 'metrics-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
state-value: '{"users":${{ env.users_count }},"errors":${{ env.error_count }},"performance":${{ env.performance_score }}}'
cache-prefix: 'feature-metrics'
action: 'set'
- name: 分析指标异常
run: |
ERROR_COUNT=${{ env.error_count }}
PERFORMANCE_SCORE=${{ env.performance_score }}
echo "🔍 指标异常分析:"
if [[ ${ERROR_COUNT} -gt 5 ]]; then
echo "⚠️ 错误率偏高,可能需要回滚功能"
echo "alert=high_error_rate" >> $GITHUB_ENV
elif [[ ${PERFORMANCE_SCORE} -lt 70 ]]; then
echo "⚠️ 性能下降,需要关注"
echo "alert=performance_degradation" >> $GITHUB_ENV
else
echo "✅ 指标正常"
echo "alert=none" >> $GITHUB_ENV
fi
- name: 记录异常告警
if: env.alert != 'none'
uses: .actions/xgj/cache-state@v1
with:
state-key: 'alert-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
state-value: '${{ env.alert }}:${{ github.run_started_at }}'
cache-prefix: 'alerts'
action: 'set'
feature-rollback-if-needed:
needs: [manage-feature-flags, monitor-feature-metrics]
if: always()
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 检查是否需要回滚
id: check-rollback
uses: .actions/xgj/cache-state@v1
with:
state-key: 'alert-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
default-value: 'none'
action: 'get'
cache-prefix: 'alerts'
- name: 执行自动回滚
if: contains(steps.check-rollback.outputs.state-value, 'high_error_rate')
run: |
echo "🔄 检测到高错误率,执行自动回滚..."
echo "功能: ${{ github.event.inputs.feature_name }}"
echo "环境: ${{ github.event.inputs.environment }}"
- name: 禁用功能开关
if: contains(steps.check-rollback.outputs.state-value, 'high_error_rate')
uses: .actions/xgj/cache-state@v1
with:
state-key: 'feature-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
state-value: 'false'
cache-prefix: 'feature-flags'
action: 'set'
- name: 记录回滚操作
if: contains(steps.check-rollback.outputs.state-value, 'high_error_rate')
uses: .actions/xgj/cache-state@v1
with:
state-key: 'rollback-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
state-value: 'auto-rollback:${{ github.run_started_at }}'
cache-prefix: 'rollback-history'
action: 'set'
generate-feature-report:
needs: [manage-feature-flags, apply-feature-configuration, monitor-feature-metrics, feature-rollback-if-needed]
if: always()
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 收集所有功能状态
run: |
echo "📋 功能开关管理报告"
echo "===================="
echo "时间: $(date)"
echo "功能: ${{ github.event.inputs.feature_name }}"
echo "环境: ${{ github.event.inputs.environment }}"
echo ""
- name: 获取最终功能状态
id: final-state
uses: .actions/xgj/cache-state@v1
with:
state-key: 'feature-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
action: 'get'
cache-prefix: 'feature-flags'
- name: 获取监控指标
id: final-metrics
uses: .actions/xgj/cache-state@v1
with:
state-key: 'metrics-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
action: 'get'
cache-prefix: 'feature-metrics'
- name: 检查回滚历史
id: rollback-check
uses: .actions/xgj/cache-state@v1
with:
state-key: 'rollback-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
default-value: 'none'
action: 'get'
cache-prefix: 'rollback-history'
- name: 生成最终报告
run: |
echo "✅ 功能状态管理完成"
echo ""
echo "📊 最终状态:"
echo " - 功能状态: ${{ steps.final-state.outputs.state-value }}"
echo " - 监控指标: ${{ steps.final-metrics.outputs.state-value }}"
echo " - 回滚历史: ${{ steps.rollback-check.outputs.state-value }}"
echo ""
echo "🎯 下次运行时,这些状态将被保留并可以继续使用。"
cleanup-old-feature-states:
runs-on: ubuntu-latest
if: github.event.inputs.environment == 'development' # 只在开发环境清理
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 清理过期的功能状态
run: |
echo "🧹 清理开发环境的过期功能状态..."
# 这里可以实现清理逻辑
# 例如,清理超过一定时间的开发环境功能开关
- name: 重置开发环境告警
uses: .actions/xgj/cache-state@v1
with:
state-key: 'dev-alerts-cleared'
state-value: '${{ github.run_started_at }}'
cache-prefix: 'cleanup'
action: 'set'

View File

@@ -0,0 +1,290 @@
# 多环境状态管理示例
# 演示如何在多环境部署中使用状态缓存来管理不同环境的配置和状态
name: Cache State - 多环境管理
on:
workflow_dispatch:
inputs:
target_environments:
description: '目标环境(逗号分隔)'
required: true
default: 'dev,staging,production'
config_update:
description: '是否更新配置'
required: false
default: false
type: boolean
jobs:
setup-environments:
runs-on: ubuntu-latest
strategy:
matrix:
environment: [dev, staging, production]
outputs:
environments: ${{ steps.env-list.outputs.environments }}
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 环境特定配置
id: env-config
run: |
case "${{ matrix.environment }}" in
"dev")
echo "replicas=1" >> $GITHUB_OUTPUT
echo "resources=minimal" >> $GITHUB_OUTPUT
echo "debug=true" >> $GITHUB_OUTPUT
;;
"staging")
echo "replicas=2" >> $GITHUB_OUTPUT
echo "resources=standard" >> $GITHUB_OUTPUT
echo "debug=false" >> $GITHUB_OUTPUT
;;
"production")
echo "replicas=3" >> $GITHUB_OUTPUT
echo "resources=high" >> $GITHUB_OUTPUT
echo "debug=false" >> $GITHUB_OUTPUT
;;
esac
- name: 保存环境副本数配置
uses: .actions/xgj/cache-state@v1
with:
state-key: 'replicas-${{ matrix.environment }}'
state-value: ${{ steps.env-config.outputs.replicas }}
default-value: '1'
cache-prefix: 'env-config'
- name: 保存环境资源配置
uses: .actions/xgj/cache-state@v1
with:
state-key: 'resources-${{ matrix.environment }}'
state-value: ${{ steps.env-config.outputs.resources }}
default-value: 'minimal'
cache-prefix: 'env-config'
- name: 保存调试模式配置
uses: .actions/xgj/cache-state@v1
with:
state-key: 'debug-${{ matrix.environment }}'
state-value: ${{ steps.env-config.outputs.debug }}
default-value: 'true'
cache-prefix: 'env-config'
- name: 检查环境健康状态
id: health-check
uses: .actions/xgj/cache-state@v1
with:
state-key: 'health-status-${{ matrix.environment }}'
default-value: 'unknown'
action: 'get'
cache-prefix: 'health'
- name: 初始化环境健康状态
if: steps.health-check.outputs.state-value == 'unknown'
uses: .actions/xgj/cache-state@v1
with:
state-key: 'health-status-${{ matrix.environment }}'
state-value: 'healthy'
action: 'set'
cache-prefix: 'health'
- name: 环境配置总结
run: |
echo "🌍 环境 ${{ matrix.environment }} 配置:"
echo " - 副本数: ${{ steps.env-config.outputs.replicas }}"
echo " - 资源配置: ${{ steps.env-config.outputs.resources }}"
echo " - 调试模式: ${{ steps.env-config.outputs.debug }}"
echo " - 健康状态: ${{ steps.health-check.outputs.state-value }}"
compare-environments:
needs: setup-environments
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 获取开发环境配置
id: dev-config
uses: .actions/xgj/cache-state@v1
with:
state-key: 'replicas-dev'
action: 'get'
cache-prefix: 'env-config'
- name: 获取预发布环境配置
id: staging-config
uses: .actions/xgj/cache-state@v1
with:
state-key: 'replicas-staging'
action: 'get'
cache-prefix: 'env-config'
- name: 获取生产环境配置
id: prod-config
uses: .actions/xgj/cache-state@v1
with:
state-key: 'replicas-production'
action: 'get'
cache-prefix: 'env-config'
- name: 环境配置对比
run: |
echo "🔍 环境配置对比:"
echo " - 开发环境副本数: ${{ steps.dev-config.outputs.state-value }}"
echo " - 预发布环境副本数: ${{ steps.staging-config.outputs.state-value }}"
echo " - 生产环境副本数: ${{ steps.prod-config.outputs.state-value }}"
# 检查配置一致性
if [[ "${{ steps.dev-config.outputs.state-value }}" < "${{ steps.staging-config.outputs.state-value }}" ]] && \
[[ "${{ steps.staging-config.outputs.state-value }}" < "${{ steps.prod-config.outputs.state-value }}" ]]; then
echo "✅ 环境配置递增合理"
else
echo "⚠️ 环境配置可能需要检查"
fi
environment-health-monitor:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 模拟健康检查 - 开发环境
run: |
# 模拟健康检查逻辑
HEALTH_STATUS="healthy"
if [[ $((RANDOM % 10)) -eq 0 ]]; then
HEALTH_STATUS="unhealthy"
fi
echo "dev_health=${HEALTH_STATUS}" >> $GITHUB_ENV
- name: 更新开发环境健康状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'health-status-dev'
state-value: ${{ env.dev_health }}
action: 'set'
cache-prefix: 'health'
- name: 模拟健康检查 - 预发布环境
run: |
HEALTH_STATUS="healthy"
if [[ $((RANDOM % 15)) -eq 0 ]]; then
HEALTH_STATUS="degraded"
fi
echo "staging_health=${HEALTH_STATUS}" >> $GITHUB_ENV
- name: 更新预发布环境健康状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'health-status-staging'
state-value: ${{ env.staging_health }}
action: 'set'
cache-prefix: 'health'
- name: 模拟健康检查 - 生产环境
run: |
HEALTH_STATUS="healthy"
if [[ $((RANDOM % 20)) -eq 0 ]]; then
HEALTH_STATUS="critical"
fi
echo "prod_health=${HEALTH_STATUS}" >> $GITHUB_ENV
- name: 更新生产环境健康状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'health-status-production'
state-value: ${{ env.prod_health }}
action: 'set'
cache-prefix: 'health'
generate-environment-report:
needs: [setup-environments, environment-health-monitor]
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 收集所有环境状态
id: collect-status
run: |
echo "🔍 收集环境状态信息..."
# 创建状态收集脚本
cat > collect_status.sh << 'EOF'
#!/bin/bash
ENVIRONMENTS=("dev" "staging" "production")
echo "| 环境 | 副本数 | 资源配置 | 调试模式 | 健康状态 |"
echo "|------|--------|----------|----------|----------|"
for env in "${ENVIRONMENTS[@]}"; do
echo "| $env | - | - | - | - |"
done
EOF
chmod +x collect_status.sh
./collect_status.sh
- name: 获取开发环境完整状态
id: dev-status
run: |
echo "=== 开发环境状态 ==="
- name: 读取开发环境配置
uses: .actions/xgj/cache-state@v1
with:
state-key: 'replicas-dev'
action: 'get'
cache-prefix: 'env-config'
- name: 读取开发环境健康状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'health-status-dev'
action: 'get'
cache-prefix: 'health'
- name: 获取预发布环境完整状态
run: |
echo "=== 预发布环境状态 ==="
- name: 获取生产环境完整状态
run: |
echo "=== 生产环境状态 ==="
- name: 生成环境状态报告
run: |
echo "📊 多环境状态报告 - $(date)"
echo "=================================="
echo ""
echo "本次工作流程已完成以下操作:"
echo "✅ 环境配置初始化和更新"
echo "✅ 健康状态监控"
echo "✅ 配置对比分析"
echo ""
echo "所有环境状态已缓存,可供后续工作流使用。"
cleanup-old-states:
if: github.event.inputs.config_update == 'true'
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 清理过期的配置状态
run: |
echo "🧹 清理过期的配置状态..."
# 这里可以实现清理逻辑
# 例如,设置空值来清理特定的缓存状态
- name: 重置所有环境的临时状态
uses: .actions/xgj/cache-state@v1
with:
state-key: 'temp-maintenance-mode'
state-value: ''
action: 'set'
cache-prefix: 'maintenance'

View File

@@ -5,8 +5,9 @@
## ✨ 特性
- 🚀 **智能缓存**: 自动缓存 node_modules避免重复安装
- 📦 **多包管理器支持**: 支持 npm、pnpm、yarn
- 📦 **多包管理器支持**: 支持 npm、pnpm、yarn,自动检测标准锁文件
- 🎯 **灵活配置**: 可自定义缓存前缀、安装命令等
- 🔑 **精确 hash 控制**: 支持自定义缓存 hash确保依赖变化时缓存失效
- 🔄 **Git 集成**: 可选的 git stash 功能
- 📊 **详细输出**: 提供缓存命中状态和使用的缓存 key
@@ -15,12 +16,12 @@
| 参数名 | 描述 | 是否必需 | 默认值 |
| ------------------- | ---------------------------- | -------- | -------------- |
| `package-manager` | 包管理器类型 (npm/pnpm/yarn) | 否 | `npm` |
| `lockfile-name` | lock 文件名称 | 否 | 自动检测 |
| `cache-prefix` | 缓存前缀名称 | 否 | `modules` |
| `node-modules-path` | node_modules 目录路径 | 否 | `node_modules` |
| `force-install` | 是否强制安装 | 否 | `false` |
| `enable-git-stash` | 安装后是否执行 git stash | 否 | `false` |
| `install-command` | 自定义安装命令(覆盖默认) | 否 | `''` |
| `cache-hash` | 缓存 hash 值(**推荐使用** | 否 | 自动计算 |
## 📤 输出参数
@@ -29,6 +30,25 @@
| `cache-hit` | 是否命中缓存 (true/false) |
| `cache-key` | 使用的缓存 key |
## 💡 重要提示
**强烈推荐使用 `cache-hash` 参数!**
使用 `cache-hash` 参数有以下优势:
-**精确控制**: 让你完全控制缓存失效的条件
-**环境兼容**: 避免在不同容器环境中 hash 计算不一致的问题
-**灵活组合**: 可以组合多个文件的 hash`package.json` + `package-lock.json` + `.nvmrc`
-**调试友好**: 在 workflow 中可以清楚看到使用的 hash 值
```yaml
# 推荐用法
with:
cache-hash: ${{ hashFiles('package-lock.json') }}
```
如果不提供 `cache-hash`action 会自动使用 `package.json` 作为 fallback但不如手动指定精确。
## 🚀 使用方法
### 基础用法 (npm)
@@ -78,6 +98,31 @@
install-command: "npm ci --only=production"
```
### 使用自定义缓存 hash推荐用法
```yaml
# 推荐手动指定缓存hash确保精确的缓存管理
- name: 安装npm依赖
uses: actions/xgj/npm-install@v1
with:
package-manager: "npm"
cache-hash: ${{ hashFiles('package-lock.json') }}
# pnpm项目
- name: 安装pnpm依赖
uses: actions/xgj/npm-install@v1
with:
package-manager: "pnpm"
cache-hash: ${{ hashFiles('pnpm-lock.yaml') }}
# 多文件hash组合
- name: 安装依赖多文件hash
uses: actions/xgj/npm-install@v1
with:
package-manager: "npm"
cache-hash: ${{ hashFiles('package.json', 'package-lock.json', '.nvmrc') }}
```
### 检查缓存状态
```yaml

View File

@@ -10,11 +10,7 @@ inputs:
required: false
default: 'npm'
lockfile-name:
description: 'lock文件名称'
required: false
default: 'package-lock.json'
cache-prefix:
description: '缓存前缀名称'
required: false
@@ -39,6 +35,11 @@ inputs:
description: '自定义安装命令(可选,会覆盖默认命令)'
required: false
default: ''
cache-hash:
description: '缓存hash值推荐使用hashFiles计算'
required: false
default: ""
outputs:
cache-hit:
@@ -52,50 +53,36 @@ outputs:
runs:
using: 'composite'
steps:
- name: 检测锁文件
id: detect-lockfile
shell: bash
run: |
LOCKFILE="${{ inputs.lockfile-name }}"
# 根据包管理器自动检测lock文件
if [[ "${{ inputs.package-manager }}" == "pnpm" ]]; then
LOCKFILE="pnpm-lock.yaml"
elif [[ "${{ inputs.package-manager }}" == "yarn" ]]; then
LOCKFILE="yarn.lock"
fi
# 如果用户没有指定lockfile-name且是npm则使用package-lock.json
if [[ "${{ inputs.lockfile-name }}" == "package-lock.json" && "${{ inputs.package-manager }}" != "npm" ]]; then
if [[ "${{ inputs.package-manager }}" == "pnpm" ]]; then
LOCKFILE="pnpm-lock.yaml"
elif [[ "${{ inputs.package-manager }}" == "yarn" ]]; then
LOCKFILE="yarn.lock"
fi
fi
echo "lockfile=${LOCKFILE}" >> $GITHUB_OUTPUT
echo "使用锁文件: ${LOCKFILE}"
- name: 生成缓存key
id: cache-key
shell: bash
env:
LOCKFILE_HASH: ${{ hashFiles(steps.detect-lockfile.outputs.lockfile) }}
FALLBACK_HASH: ${{ hashFiles('package.json') }}
run: |
LOCKFILE="${{ steps.detect-lockfile.outputs.lockfile }}"
# 截取hash的前12位
if [[ -n "${LOCKFILE_HASH}" && "${LOCKFILE_HASH}" != "" ]]; then
LOCKFILE_HASH_SHORT=$(echo "${LOCKFILE_HASH}" | head -c 12)
# 确定使用的hash值
if [[ -n "${{ inputs.cache-hash }}" && "${{ inputs.cache-hash }}" != "" ]]; then
CACHE_HASH="${{ inputs.cache-hash }}"
echo "✅ 使用用户传入的hash值"
elif [[ -n "${FALLBACK_HASH}" && "${FALLBACK_HASH}" != "" ]]; then
CACHE_HASH="${FALLBACK_HASH}"
echo "📝 未提供hash使用package.json作为fallback"
else
echo "⚠️ 警告: 无法计算锁文件hash使用默认值"
LOCKFILE_HASH_SHORT="no-lockfile"
CACHE_HASH=""
echo "⚠️ 警告: 无法获取hash值使用默认值"
fi
CACHE_KEY="${{ runner.os }}-${{ inputs.cache-prefix }}-${LOCKFILE_HASH_SHORT}"
# 截取hash的前12位
if [[ -n "${CACHE_HASH}" && "${CACHE_HASH}" != "" ]]; then
CACHE_HASH_SHORT=$(echo "${CACHE_HASH}" | head -c 12)
echo "✅ 成功计算缓存hash: ${CACHE_HASH_SHORT}"
else
CACHE_HASH_SHORT="no-hash"
echo "⚠️ 使用默认hash值: ${CACHE_HASH_SHORT}"
fi
CACHE_KEY="${{ runner.os }}-${{ inputs.cache-prefix }}-${CACHE_HASH_SHORT}"
echo "key=${CACHE_KEY}" >> $GITHUB_OUTPUT
echo "锁文件: ${LOCKFILE}"
echo "文件hash: ${LOCKFILE_HASH}"
echo "使用hash: ${CACHE_HASH}"
echo "缓存key: ${CACHE_KEY}"
- name: 拉取缓存依赖

View File

@@ -0,0 +1,107 @@
# 自定义缓存hash示例推荐用法
name: 自定义缓存hash示例
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
# 推荐用法手动计算hash并传入
- name: 安装npm依赖使用package-lock.json hash
uses: actions/xgj/npm-install@v1
with:
package-manager: 'npm'
cache-hash: ${{ hashFiles('package-lock.json') }}
- name: 运行linting
run: npm run lint
- name: 运行测试
run: npm test
test-pnpm:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置Node.js和pnpm
uses: actions/setup-node@v4
with:
node-version: '18'
- name: 安装pnpm
run: npm install -g pnpm
# pnpm项目示例
- name: 安装pnpm依赖
uses: actions/xgj/npm-install@v1
with:
package-manager: 'pnpm'
cache-hash: ${{ hashFiles('pnpm-lock.yaml') }}
- name: 运行测试
run: pnpm test
test-yarn:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置Node.js和Yarn
uses: actions/setup-node@v4
with:
node-version: '18'
- name: 启用Yarn
run: corepack enable yarn
# Yarn项目示例
- name: 安装yarn依赖
uses: actions/xgj/npm-install@v1
with:
package-manager: 'yarn'
cache-hash: ${{ hashFiles('yarn.lock') }}
- name: 运行测试
run: yarn test
# 多个锁文件的复杂项目示例
test-multi-lockfiles:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
# 组合多个文件的hash确保任何文件变化都会使缓存失效
- name: 安装依赖多文件hash
uses: actions/xgj/npm-install@v1
with:
package-manager: 'npm'
cache-hash: ${{ hashFiles('package.json', 'package-lock.json', '.nvmrc') }}
- name: 运行测试
run: npm test

View File

@@ -8,6 +8,7 @@
- 🔄 **版本分支检测**:识别版本分支(如 `v1.2.x`)并提取版本信息
- 🆕 **常规分支处理**:对于非版本分支提供基础信息
- 🎯 **灵活的版本前缀**:支持自定义版本前缀(默认为 `v`
- 🔧 **版本格式转换**:自动生成横线格式的版本号(如 `v1.2.3``v1-2-3`
- 📤 **环境变量输出**:自动设置环境变量供后续步骤使用
- 📊 **详细的输出信息**:提供完整的引用信息和触发状态
@@ -25,6 +26,7 @@
| `ref-name` | 引用名称 | `v1.2.3``main``feature/xxx` |
| `is-version-trigger` | 是否为版本触发 | `true``false` |
| `trigger-version` | 触发的版本号(去除前缀) | `1.2.3` |
| `version-with-dash` | 版本号,点替换为横线 | `1-2-3` |
| `trigger-source` | 触发源 | `tag``branch` |
| `full-ref` | 完整的 Git 引用 | `refs/tags/v1.2.3` |
@@ -34,6 +36,7 @@ Action 会自动设置以下环境变量:
- `IS_VERSION_TRIGGER`: 是否为版本触发true/false
- `TRIGGER_VERSION`: 触发的版本号
- `VERSION_WITH_DASH`: 版本号,点替换为横线
- `TRIGGER_SOURCE`: 触发源tag/branch
## 使用示例
@@ -53,6 +56,7 @@ jobs:
outputs:
is-version-trigger: ${{ steps.version-info.outputs.is-version-trigger }}
trigger-version: ${{ steps.version-info.outputs.trigger-version }}
version-with-dash: ${{ steps.version-info.outputs.version-with-dash }}
trigger-source: ${{ steps.version-info.outputs.trigger-source }}
steps:
- name: 获取版本信息
@@ -63,6 +67,7 @@ jobs:
run: |
echo "是否版本触发: ${{ steps.version-info.outputs.is-version-trigger }}"
echo "版本号: ${{ steps.version-info.outputs.trigger-version }}"
echo "横线版本号: ${{ steps.version-info.outputs.version-with-dash }}"
echo "触发源: ${{ steps.version-info.outputs.trigger-source }}"
deploy:
@@ -73,6 +78,7 @@ jobs:
- name: 部署版本
run: |
echo "部署版本: ${{ needs.get-version-info.outputs.trigger-version }}"
echo "Docker标签: myapp:${{ needs.get-version-info.outputs.version-with-dash }}"
```
### 自定义版本前缀
@@ -152,6 +158,7 @@ jobs:
- `is-version-trigger`: `true`
- `trigger-version`: `1.2.3`
- `version-with-dash`: `v1-2-3`
- `trigger-source`: `tag`
### 版本分支触发
@@ -160,6 +167,7 @@ jobs:
- `is-version-trigger`: `true`
- `trigger-version`: `1.2.x`
- `version-with-dash`: `v1-2-x`
- `trigger-source`: `branch`
### 常规分支触发
@@ -168,14 +176,16 @@ jobs:
- `is-version-trigger`: `false`
- `trigger-version`: `""`
- `version-with-dash`: `""`
- `trigger-source`: `branch`
## 最佳实践
1. **条件部署**:使用 `is-version-trigger` 来决定是否执行生产部署
2. **版本标记**:在构建产物中使用 `trigger-version` 进行版本标记
3. **环境区分**:根据触发源选择不同的部署环境
4. **日志记录**:记录详细的版本信息用于追踪和调试
3. **Docker 标签**:使用 `version-with-dash` 作为 Docker 镜像标签(避免点号问题)
4. **环境区分**:根据触发源选择不同的部署环境
5. **日志记录**:记录详细的版本信息用于追踪和调试
## 注意事项

View File

@@ -7,6 +7,10 @@ inputs:
description: '版本前缀用于匹配版本标签或分支默认v'
required: false
default: 'v'
use-latest-version:
description: '在非版本触发时是否使用当前分支最新的版本标签默认false'
required: false
default: 'false'
outputs:
ref-type:
@@ -19,7 +23,7 @@ outputs:
description: '是否为版本触发true/false'
value: ${{ steps.get-version-info.outputs.is_version_trigger }}
trigger-version:
description: '触发的版本号(去除前缀后的版本'
description: '触发的版本号(标准化为v开头的格式'
value: ${{ steps.get-version-info.outputs.trigger_version }}
trigger-source:
description: '触发源tag/branch'
@@ -27,6 +31,9 @@ outputs:
full-ref:
description: '完整的 Git 引用'
value: ${{ steps.get-version-info.outputs.full_ref }}
version-with-dash:
description: '版本号点替换为横线例如v1.2.3 -> v1-2-3'
value: ${{ steps.get-version-info.outputs.version_with_dash }}
runs:
using: 'composite'
@@ -45,37 +52,81 @@ runs:
REF_NAME="${{ github.ref_name }}"
FULL_REF="${{ github.ref }}"
VERSION_PREFIX="${{ inputs.version-prefix }}"
USE_LATEST_VERSION="${{ inputs.use-latest-version }}"
# 判断是否为标签触发
if [[ "$REF_TYPE" == "tag" ]]; then
# 从标签名提取版本号 (v1.2.3 -> 1.2.3)
# 标准化版本号为v开头格式
if [[ "$REF_NAME" == ${VERSION_PREFIX}* ]]; then
TRIGGER_VERSION=${REF_NAME#${VERSION_PREFIX}}
else
TRIGGER_VERSION=$REF_NAME
else
TRIGGER_VERSION=${VERSION_PREFIX}$REF_NAME
fi
# 生成带横线的版本号
VERSION_WITH_DASH=$(echo "$TRIGGER_VERSION" | sed 's/\./-/g')
echo "🏷️ 标签触发: $REF_NAME"
echo "版本号: $TRIGGER_VERSION"
echo "标准化版本号: $TRIGGER_VERSION"
echo "横线版本号: $VERSION_WITH_DASH"
IS_VERSION_TRIGGER=true
TRIGGER_SOURCE=tag
elif [[ "$REF_TYPE" == "branch" && "$REF_NAME" == ${VERSION_PREFIX}* ]]; then
# 版本分支触发
TRIGGER_VERSION=${REF_NAME#${VERSION_PREFIX}}
TRIGGER_VERSION=$REF_NAME
# 生成带横线的版本号
VERSION_WITH_DASH=$(echo "$TRIGGER_VERSION" | sed 's/\./-/g')
echo "🔄 版本分支触发: $REF_NAME"
echo "版本号: $TRIGGER_VERSION"
echo "标准化版本号: $TRIGGER_VERSION"
echo "横线版本号: $VERSION_WITH_DASH"
IS_VERSION_TRIGGER=true
TRIGGER_SOURCE=branch
else
# 常规分支触发
echo "🆕 常规分支触发: $REF_NAME"
IS_VERSION_TRIGGER=false
TRIGGER_VERSION=""
if [[ "$USE_LATEST_VERSION" == "true" ]]; then
# 获取当前分支最新的版本标签
echo "🔍 查找最新版本标签..."
# 检查git仓库是否可用
if git rev-parse --git-dir > /dev/null 2>&1; then
LATEST_TAG=$(git tag --list "${VERSION_PREFIX}*" --sort=-version:refname 2>/dev/null | head -1)
if [[ -n "$LATEST_TAG" ]]; then
# 找到了版本标签,使用它
TRIGGER_VERSION=$LATEST_TAG
VERSION_WITH_DASH=$(echo "$TRIGGER_VERSION" | sed 's/\./-/g')
echo "📦 使用最新版本标签: $LATEST_TAG"
echo "标准化版本号: $TRIGGER_VERSION"
echo "横线版本号: $VERSION_WITH_DASH"
IS_VERSION_TRIGGER=true
else
# 没有找到版本标签
echo "⚠️ 未找到版本标签,使用空版本"
IS_VERSION_TRIGGER=false
TRIGGER_VERSION=""
VERSION_WITH_DASH=""
fi
else
# Git仓库不可用
echo "⚠️ Git仓库不可用使用空版本"
IS_VERSION_TRIGGER=false
TRIGGER_VERSION=""
VERSION_WITH_DASH=""
fi
else
# 不使用最新版本
IS_VERSION_TRIGGER=false
TRIGGER_VERSION=""
VERSION_WITH_DASH=""
fi
TRIGGER_SOURCE=branch
fi
# 设置环境变量
echo "IS_VERSION_TRIGGER=$IS_VERSION_TRIGGER" >> $GITHUB_ENV
echo "TRIGGER_VERSION=$TRIGGER_VERSION" >> $GITHUB_ENV
echo "VERSION_WITH_DASH=$VERSION_WITH_DASH" >> $GITHUB_ENV
echo "TRIGGER_SOURCE=$TRIGGER_SOURCE" >> $GITHUB_ENV
# 输出到 step outputs
@@ -84,6 +135,7 @@ runs:
echo "full_ref=$FULL_REF" >> $GITHUB_OUTPUT
echo "is_version_trigger=$IS_VERSION_TRIGGER" >> $GITHUB_OUTPUT
echo "trigger_version=$TRIGGER_VERSION" >> $GITHUB_OUTPUT
echo "version_with_dash=$VERSION_WITH_DASH" >> $GITHUB_OUTPUT
echo "trigger_source=$TRIGGER_SOURCE" >> $GITHUB_OUTPUT
branding:

View File

@@ -15,6 +15,7 @@ jobs:
outputs:
is-version-trigger: ${{ steps.version-info.outputs.is-version-trigger }}
trigger-version: ${{ steps.version-info.outputs.trigger-version }}
version-with-dash: ${{ steps.version-info.outputs.version-with-dash }}
trigger-source: ${{ steps.version-info.outputs.trigger-source }}
ref-type: ${{ steps.version-info.outputs.ref-type }}
ref-name: ${{ steps.version-info.outputs.ref-name }}
@@ -35,6 +36,7 @@ jobs:
echo "完整引用: ${{ steps.version-info.outputs.full-ref }}"
echo "是否版本触发: ${{ steps.version-info.outputs.is-version-trigger }}"
echo "触发版本号: ${{ steps.version-info.outputs.trigger-version }}"
echo "横线版本号: ${{ steps.version-info.outputs.version-with-dash }}"
echo "触发源: ${{ steps.version-info.outputs.trigger-source }}"
echo "================================"
@@ -43,6 +45,7 @@ jobs:
echo "========== 环境变量 =========="
echo "IS_VERSION_TRIGGER: ${IS_VERSION_TRIGGER}"
echo "TRIGGER_VERSION: ${TRIGGER_VERSION}"
echo "VERSION_WITH_DASH: ${VERSION_WITH_DASH}"
echo "TRIGGER_SOURCE: ${TRIGGER_SOURCE}"
echo "============================"
@@ -59,6 +62,8 @@ jobs:
if [[ "${{ needs.get-version-info.outputs.is-version-trigger }}" == "true" ]]; then
echo "✅ 这是一个版本发布触发"
echo "🚀 版本号: ${{ needs.get-version-info.outputs.trigger-version }}"
echo "🏷️ 横线版本号: ${{ needs.get-version-info.outputs.version-with-dash }}"
echo "🐳 Docker标签: myapp:${{ needs.get-version-info.outputs.version-with-dash }}"
echo "📦 触发源: ${{ needs.get-version-info.outputs.trigger-source }}"
else
echo " 这是一个常规分支推送"

View File

@@ -14,6 +14,7 @@ jobs:
outputs:
is-version-trigger: ${{ steps.version-info.outputs.is-version-trigger }}
trigger-version: ${{ steps.version-info.outputs.trigger-version }}
version-with-dash: ${{ steps.version-info.outputs.version-with-dash }}
trigger-source: ${{ steps.version-info.outputs.trigger-source }}
ref-name: ${{ steps.version-info.outputs.ref-name }}
deploy-staging: ${{ steps.deployment-strategy.outputs.deploy-staging }}
@@ -102,8 +103,11 @@ jobs:
- name: 部署到生产环境
run: |
echo "🚀 部署版本 ${{ needs.analyze.outputs.trigger-version }} 到生产环境"
echo "🐳 Docker标签: myapp:${{ needs.analyze.outputs.version-with-dash }}"
echo "触发源: ${{ needs.analyze.outputs.trigger-source }}"
# 生产部署逻辑
# docker build -t myapp:${{ needs.analyze.outputs.version-with-dash }} .
# docker push myapp:${{ needs.analyze.outputs.version-with-dash }}
echo "✅ 生产环境部署完成"
- name: 创建 Release