Files
xgj/cache-state/action.yml

298 lines
11 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: '状态缓存管理'
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.result.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"
CACHE_HIT="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 }}"
CACHE_HIT="true"
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 }}"
CACHE_HIT="true"
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
CACHE_HIT="true"
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
echo "cache-hit=${CACHE_HIT}" >> $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.result.outputs.cache-hit }}"
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