mirror of
https://git.bjxgj.com/xgj/xgj-actions.git
synced 2025-10-14 06:33:37 +08:00
Compare commits
19 Commits
main
...
2fe7c6809c
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2fe7c6809c | ||
![]() |
06298f9e15 | ||
![]() |
d35b42c064 | ||
![]() |
af648e65f2 | ||
![]() |
c3e927c596 | ||
![]() |
9e3ffa7ea2 | ||
![]() |
64403850ee | ||
![]() |
86d6bb988f | ||
![]() |
7366d46959 | ||
![]() |
8a16a8bec5 | ||
![]() |
5c47db3ee2 | ||
![]() |
6fff7a90e1 | ||
![]() |
b53d899f41 | ||
![]() |
1949a48d96 | ||
![]() |
d17dea4ca0 | ||
![]() |
ee024ce50d | ||
![]() |
77dcc1bed2 | ||
![]() |
1299feac14 | ||
![]() |
210d257b44 |
@@ -365,226 +365,226 @@ jobs:
|
||||
fi
|
||||
|
||||
# 过期时间测试
|
||||
test-expiry:
|
||||
if: ${{ inputs.test_scope == 'expiry' || inputs.test_scope == 'full' }}
|
||||
runs-on: ubuntu-node-20
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: actions/checkout@v4
|
||||
# test-expiry:
|
||||
# if: ${{ inputs.test_scope == 'expiry' || inputs.test_scope == 'full' }}
|
||||
# runs-on: ubuntu-node-20
|
||||
# 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: 测试基础过期功能 - 短期缓存
|
||||
# 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 }}"
|
||||
# - 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 }}"
|
||||
|
||||
# 验证缓存键包含时间窗口(永不过期缓存键格式:Linux-test-state-short-expiry-test-1038,有过期时间格式:Linux-test-state-short-expiry-test-1038-12345)
|
||||
# 检查是否有额外的时间窗口后缀(在run_id之后)
|
||||
if [[ "${{ steps.short-expiry.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
echo "✅ 缓存键包含时间窗口标识"
|
||||
else
|
||||
echo "❌ 缓存键缺少时间窗口标识: ${{ steps.short-expiry.outputs.cache-key }}"
|
||||
echo "期望格式: Linux-test-state-short-expiry-test-{run_id}-{time_window}"
|
||||
exit 1
|
||||
fi
|
||||
# # 验证缓存键包含时间窗口(永不过期缓存键格式:Linux-test-state-short-expiry-test-1038,有过期时间格式:Linux-test-state-short-expiry-test-1038-12345)
|
||||
# # 检查是否有额外的时间窗口后缀(在run_id之后)
|
||||
# if [[ "${{ steps.short-expiry.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
# echo "✅ 缓存键包含时间窗口标识"
|
||||
# else
|
||||
# echo "❌ 缓存键缺少时间窗口标识: ${{ steps.short-expiry.outputs.cache-key }}"
|
||||
# echo "期望格式: Linux-test-state-short-expiry-test-{run_id}-{time_window}"
|
||||
# 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: 测试永不过期缓存
|
||||
# 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 }}"
|
||||
# - 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 }}"
|
||||
|
||||
# 验证缓存键不包含时间窗口(永不过期应该只有一个数字后缀run_id,而不是两个数字后缀)
|
||||
if [[ "${{ steps.no-expiry.outputs.cache-key }}" =~ -[0-9]+$ ]] && [[ ! "${{ steps.no-expiry.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
echo "✅ 永不过期缓存键格式正确"
|
||||
else
|
||||
echo "❌ 永不过期缓存键格式错误: ${{ steps.no-expiry.outputs.cache-key }}"
|
||||
echo "期望格式: Linux-test-state-no-expiry-test-{run_id}(只有一个数字后缀)"
|
||||
exit 1
|
||||
fi
|
||||
# # 验证缓存键不包含时间窗口(永不过期应该只有一个数字后缀run_id,而不是两个数字后缀)
|
||||
# if [[ "${{ steps.no-expiry.outputs.cache-key }}" =~ -[0-9]+$ ]] && [[ ! "${{ steps.no-expiry.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
# echo "✅ 永不过期缓存键格式正确"
|
||||
# else
|
||||
# echo "❌ 永不过期缓存键格式错误: ${{ steps.no-expiry.outputs.cache-key }}"
|
||||
# echo "期望格式: Linux-test-state-no-expiry-test-{run_id}(只有一个数字后缀)"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
# 验证过期状态
|
||||
if [[ "${{ steps.no-expiry.outputs.expired }}" == "false" ]]; then
|
||||
echo "✅ 永不过期缓存过期状态正确"
|
||||
else
|
||||
echo "❌ 永不过期缓存不应显示为过期"
|
||||
exit 1
|
||||
fi
|
||||
# # 验证过期状态
|
||||
# if [[ "${{ steps.no-expiry.outputs.expired }}" == "false" ]]; then
|
||||
# echo "✅ 永不过期缓存过期状态正确"
|
||||
# else
|
||||
# echo "❌ 永不过期缓存不应显示为过期"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
- name: 测试不同过期时间的缓存键差异
|
||||
run: |
|
||||
echo "🔍 测试不同过期时间的缓存键生成..."
|
||||
# - name: 测试不同过期时间的缓存键差异
|
||||
# run: |
|
||||
# echo "🔍 测试不同过期时间的缓存键生成..."
|
||||
|
||||
# 记录当前时间窗口
|
||||
CURRENT_TIME=$(date +%s)
|
||||
WINDOW_120=$((CURRENT_TIME / 120))
|
||||
WINDOW_300=$((CURRENT_TIME / 300))
|
||||
# # 记录当前时间窗口
|
||||
# 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}"
|
||||
# echo "当前时间: ${CURRENT_TIME}"
|
||||
# echo "120秒窗口: ${WINDOW_120}"
|
||||
# echo "300秒窗口: ${WINDOW_300}"
|
||||
|
||||
# 分析已测试的缓存键格式
|
||||
echo ""
|
||||
echo "📋 已测试的缓存键格式分析:"
|
||||
echo "短期缓存键: ${{ steps.short-expiry.outputs.cache-key }}"
|
||||
echo "永不过期键: ${{ steps.no-expiry.outputs.cache-key }}"
|
||||
# # 分析已测试的缓存键格式
|
||||
# echo ""
|
||||
# echo "📋 已测试的缓存键格式分析:"
|
||||
# echo "短期缓存键: ${{ steps.short-expiry.outputs.cache-key }}"
|
||||
# echo "永不过期键: ${{ steps.no-expiry.outputs.cache-key }}"
|
||||
|
||||
# 提取缓存键的最后两个数字段
|
||||
SHORT_KEY="${{ steps.short-expiry.outputs.cache-key }}"
|
||||
NO_EXPIRY_KEY="${{ steps.no-expiry.outputs.cache-key }}"
|
||||
# # 提取缓存键的最后两个数字段
|
||||
# SHORT_KEY="${{ steps.short-expiry.outputs.cache-key }}"
|
||||
# NO_EXPIRY_KEY="${{ steps.no-expiry.outputs.cache-key }}"
|
||||
|
||||
# 使用sed提取最后的数字段
|
||||
SHORT_LAST_NUM=$(echo "${SHORT_KEY}" | sed 's/.*-\([0-9]*\)$/\1/')
|
||||
NO_EXPIRY_LAST_NUM=$(echo "${NO_EXPIRY_KEY}" | sed 's/.*-\([0-9]*\)$/\1/')
|
||||
# # 使用sed提取最后的数字段
|
||||
# SHORT_LAST_NUM=$(echo "${SHORT_KEY}" | sed 's/.*-\([0-9]*\)$/\1/')
|
||||
# NO_EXPIRY_LAST_NUM=$(echo "${NO_EXPIRY_KEY}" | sed 's/.*-\([0-9]*\)$/\1/')
|
||||
|
||||
echo "短期缓存最后数字: ${SHORT_LAST_NUM}"
|
||||
echo "永不过期最后数字: ${NO_EXPIRY_LAST_NUM}"
|
||||
# echo "短期缓存最后数字: ${SHORT_LAST_NUM}"
|
||||
# echo "永不过期最后数字: ${NO_EXPIRY_LAST_NUM}"
|
||||
|
||||
# 如果时间窗口不同,说明过期时间影响了缓存键
|
||||
if [[ ${WINDOW_120} != ${WINDOW_300} ]]; then
|
||||
echo "✅ 不同过期时间产生不同的时间窗口"
|
||||
else
|
||||
echo "ℹ️ 当前时间点两个时间窗口相同(正常情况)"
|
||||
fi
|
||||
# # 如果时间窗口不同,说明过期时间影响了缓存键
|
||||
# if [[ ${WINDOW_120} != ${WINDOW_300} ]]; then
|
||||
# echo "✅ 不同过期时间产生不同的时间窗口"
|
||||
# else
|
||||
# echo "ℹ️ 当前时间点两个时间窗口相同(正常情况)"
|
||||
# fi
|
||||
|
||||
- name: 测试额外的过期时间缓存键
|
||||
id: extra-expiry-test
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'extra-expiry-validation'
|
||||
state-value: 'extra-value'
|
||||
default-value: 'extra-default'
|
||||
expiry-seconds: '300'
|
||||
action: 'set'
|
||||
cache-prefix: ${{ inputs.test_prefix }}
|
||||
# - name: 测试额外的过期时间缓存键
|
||||
# id: extra-expiry-test
|
||||
# uses: actions/xgj/cache-state@v1
|
||||
# with:
|
||||
# state-key: 'extra-expiry-validation'
|
||||
# state-value: 'extra-value'
|
||||
# default-value: 'extra-default'
|
||||
# expiry-seconds: '300'
|
||||
# action: 'set'
|
||||
# cache-prefix: ${{ inputs.test_prefix }}
|
||||
|
||||
- name: 验证额外过期测试的缓存键格式
|
||||
run: |
|
||||
echo "🔍 验证额外过期测试缓存键:"
|
||||
echo "额外过期测试键: ${{ steps.extra-expiry-test.outputs.cache-key }}"
|
||||
# - name: 验证额外过期测试的缓存键格式
|
||||
# run: |
|
||||
# echo "🔍 验证额外过期测试缓存键:"
|
||||
# echo "额外过期测试键: ${{ steps.extra-expiry-test.outputs.cache-key }}"
|
||||
|
||||
# 验证这个缓存键是否有时间窗口
|
||||
if [[ "${{ steps.extra-expiry-test.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
echo "✅ 额外过期测试缓存键包含时间窗口"
|
||||
else
|
||||
echo "❌ 额外过期测试缓存键缺少时间窗口: ${{ steps.extra-expiry-test.outputs.cache-key }}"
|
||||
fi
|
||||
# # 验证这个缓存键是否有时间窗口
|
||||
# if [[ "${{ steps.extra-expiry-test.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
# echo "✅ 额外过期测试缓存键包含时间窗口"
|
||||
# else
|
||||
# echo "❌ 额外过期测试缓存键缺少时间窗口: ${{ steps.extra-expiry-test.outputs.cache-key }}"
|
||||
# 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: 测试过期状态判断
|
||||
# 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 }}"
|
||||
echo "缓存键: ${{ steps.expiry-check.outputs.cache-key }}"
|
||||
# - 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 }}"
|
||||
# echo "缓存键: ${{ steps.expiry-check.outputs.cache-key }}"
|
||||
|
||||
# 验证缓存键包含时间窗口
|
||||
if [[ "${{ steps.expiry-check.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
echo "✅ 过期状态测试缓存键包含时间窗口"
|
||||
else
|
||||
echo "❌ 过期状态测试缓存键缺少时间窗口: ${{ steps.expiry-check.outputs.cache-key }}"
|
||||
exit 1
|
||||
fi
|
||||
# # 验证缓存键包含时间窗口
|
||||
# if [[ "${{ steps.expiry-check.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
# echo "✅ 过期状态测试缓存键包含时间窗口"
|
||||
# else
|
||||
# echo "❌ 过期状态测试缓存键缺少时间窗口: ${{ steps.expiry-check.outputs.cache-key }}"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
# 因为是新的状态键,应该返回默认值
|
||||
if [[ "${{ steps.expiry-check.outputs.state-value }}" == "fallback-value" ]]; then
|
||||
echo "✅ 过期测试返回了正确的默认值"
|
||||
else
|
||||
echo "❌ 过期测试没有返回默认值,实际值: ${{ steps.expiry-check.outputs.state-value }}"
|
||||
exit 1
|
||||
fi
|
||||
# # 因为是新的状态键,应该返回默认值
|
||||
# if [[ "${{ steps.expiry-check.outputs.state-value }}" == "fallback-value" ]]; then
|
||||
# echo "✅ 过期测试返回了正确的默认值"
|
||||
# else
|
||||
# echo "❌ 过期测试没有返回默认值,实际值: ${{ steps.expiry-check.outputs.state-value }}"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
# 检查是否正确标记为使用默认值
|
||||
if [[ "${{ steps.expiry-check.outputs.used-default }}" == "true" ]]; then
|
||||
echo "✅ 正确标记使用了默认值"
|
||||
else
|
||||
echo "❌ 没有正确标记使用默认值: ${{ steps.expiry-check.outputs.used-default }}"
|
||||
exit 1
|
||||
fi
|
||||
# # 检查是否正确标记为使用默认值
|
||||
# if [[ "${{ steps.expiry-check.outputs.used-default }}" == "true" ]]; then
|
||||
# echo "✅ 正确标记使用了默认值"
|
||||
# else
|
||||
# echo "❌ 没有正确标记使用默认值: ${{ steps.expiry-check.outputs.used-default }}"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
# 对于不存在的缓存且设置了过期时间,过期状态应该是false(因为缓存本身就不存在)
|
||||
if [[ "${{ steps.expiry-check.outputs.cache-hit }}" == "false" && "${{ steps.expiry-check.outputs.expired }}" == "false" ]]; then
|
||||
echo "✅ 正确处理不存在的缓存过期状态"
|
||||
else
|
||||
echo "ℹ️ 过期状态: ${{ steps.expiry-check.outputs.expired }},缓存命中: ${{ steps.expiry-check.outputs.cache-hit }}"
|
||||
echo "ℹ️ 不存在的缓存不应标记为过期,而是未命中"
|
||||
fi
|
||||
# # 对于不存在的缓存且设置了过期时间,过期状态应该是false(因为缓存本身就不存在)
|
||||
# if [[ "${{ steps.expiry-check.outputs.cache-hit }}" == "false" && "${{ steps.expiry-check.outputs.expired }}" == "false" ]]; then
|
||||
# echo "✅ 正确处理不存在的缓存过期状态"
|
||||
# else
|
||||
# echo "ℹ️ 过期状态: ${{ steps.expiry-check.outputs.expired }},缓存命中: ${{ steps.expiry-check.outputs.cache-hit }}"
|
||||
# echo "ℹ️ 不存在的缓存不应标记为过期,而是未命中"
|
||||
# fi
|
||||
|
||||
- name: 测试各种过期时间值
|
||||
run: |
|
||||
echo "⏱️ 过期时间功能总结..."
|
||||
# - name: 测试各种过期时间值
|
||||
# run: |
|
||||
# echo "⏱️ 过期时间功能总结..."
|
||||
|
||||
echo ""
|
||||
echo "📋 已完成的过期时间测试:"
|
||||
echo "✅ 短期缓存 (120秒): ${{ steps.short-expiry.outputs.cache-key }}"
|
||||
echo "✅ 永不过期 (0秒): ${{ steps.no-expiry.outputs.cache-key }}"
|
||||
echo "✅ 额外测试 (300秒): ${{ steps.extra-expiry-test.outputs.cache-key }}"
|
||||
echo "✅ 过期状态判断 (60秒): ${{ steps.expiry-check.outputs.cache-key }}"
|
||||
# echo ""
|
||||
# echo "📋 已完成的过期时间测试:"
|
||||
# echo "✅ 短期缓存 (120秒): ${{ steps.short-expiry.outputs.cache-key }}"
|
||||
# echo "✅ 永不过期 (0秒): ${{ steps.no-expiry.outputs.cache-key }}"
|
||||
# echo "✅ 额外测试 (300秒): ${{ steps.extra-expiry-test.outputs.cache-key }}"
|
||||
# echo "✅ 过期状态判断 (60秒): ${{ steps.expiry-check.outputs.cache-key }}"
|
||||
|
||||
echo ""
|
||||
echo "🔍 缓存键格式验证:"
|
||||
# echo ""
|
||||
# echo "🔍 缓存键格式验证:"
|
||||
|
||||
# 验证所有带过期时间的缓存键都有时间窗口
|
||||
KEYS_WITH_EXPIRY=(
|
||||
"${{ steps.short-expiry.outputs.cache-key }}"
|
||||
"${{ steps.extra-expiry-test.outputs.cache-key }}"
|
||||
"${{ steps.expiry-check.outputs.cache-key }}"
|
||||
)
|
||||
# # 验证所有带过期时间的缓存键都有时间窗口
|
||||
# KEYS_WITH_EXPIRY=(
|
||||
# "${{ steps.short-expiry.outputs.cache-key }}"
|
||||
# "${{ steps.extra-expiry-test.outputs.cache-key }}"
|
||||
# "${{ steps.expiry-check.outputs.cache-key }}"
|
||||
# )
|
||||
|
||||
for key in "${KEYS_WITH_EXPIRY[@]}"; do
|
||||
if [[ "$key" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
echo "✅ $key (包含时间窗口)"
|
||||
else
|
||||
echo "❌ $key (缺少时间窗口)"
|
||||
fi
|
||||
done
|
||||
# for key in "${KEYS_WITH_EXPIRY[@]}"; do
|
||||
# if [[ "$key" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
# echo "✅ $key (包含时间窗口)"
|
||||
# else
|
||||
# echo "❌ $key (缺少时间窗口)"
|
||||
# fi
|
||||
# done
|
||||
|
||||
# 验证永不过期的缓存键
|
||||
NO_EXPIRY_KEY="${{ steps.no-expiry.outputs.cache-key }}"
|
||||
if [[ "$NO_EXPIRY_KEY" =~ -[0-9]+$ ]] && [[ ! "$NO_EXPIRY_KEY" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
echo "✅ $NO_EXPIRY_KEY (永不过期,只有run_id)"
|
||||
else
|
||||
echo "❌ $NO_EXPIRY_KEY (永不过期格式错误)"
|
||||
fi
|
||||
# # 验证永不过期的缓存键
|
||||
# NO_EXPIRY_KEY="${{ steps.no-expiry.outputs.cache-key }}"
|
||||
# if [[ "$NO_EXPIRY_KEY" =~ -[0-9]+$ ]] && [[ ! "$NO_EXPIRY_KEY" =~ -[0-9]+-[0-9]+$ ]]; then
|
||||
# echo "✅ $NO_EXPIRY_KEY (永不过期,只有run_id)"
|
||||
# else
|
||||
# echo "❌ $NO_EXPIRY_KEY (永不过期格式错误)"
|
||||
# fi
|
||||
|
||||
echo ""
|
||||
echo "🎯 过期时间功能测试完成!"
|
||||
# echo ""
|
||||
# echo "🎯 过期时间功能测试完成!"
|
||||
|
||||
# 删除功能测试
|
||||
test-delete-operations:
|
||||
|
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
- name: 获取或设置应用版本
|
||||
id: app-version
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'application-version'
|
||||
state-value: ${{ github.event.inputs.version }}
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: 记录构建状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-build-status'
|
||||
state-value: 'success'
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
- name: 获取构建历史
|
||||
id: build-history
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'build-count'
|
||||
state-value: '1'
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
echo "新的构建次数: ${NEW_COUNT}"
|
||||
|
||||
- name: 保存新的构建计数
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'build-count'
|
||||
state-value: ${{ env.NEW_COUNT }}
|
||||
|
@@ -35,7 +35,7 @@ jobs:
|
||||
|
||||
- name: 获取环境配置
|
||||
id: env-state
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'target-environment-${{ github.ref_name }}'
|
||||
state-value: ${{ github.event.inputs.environment || 'staging' }}
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
|
||||
- name: 检查上次部署的SHA
|
||||
id: last-deploy
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-deployed-sha-${{ steps.env-state.outputs.state-value }}'
|
||||
default-value: 'none'
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
|
||||
- name: 检查部署状态
|
||||
id: deploy-status
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'deploy-status-${{ steps.env-state.outputs.state-value }}'
|
||||
default-value: 'idle'
|
||||
@@ -96,14 +96,14 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 标记部署开始
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'deploy-start-time-${{ needs.check-deployment-state.outputs.environment }}'
|
||||
state-value: ${{ github.run_started_at }}
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
|
||||
- name: 记录成功部署的SHA
|
||||
if: success()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-deployed-sha-${{ needs.check-deployment-state.outputs.environment }}'
|
||||
state-value: ${{ github.sha }}
|
||||
@@ -132,7 +132,7 @@ jobs:
|
||||
|
||||
- name: 标记部署成功
|
||||
if: success()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
|
||||
state-value: 'success'
|
||||
@@ -140,7 +140,7 @@ jobs:
|
||||
|
||||
- name: 记录部署完成时间
|
||||
if: success()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}
|
||||
@@ -148,7 +148,7 @@ jobs:
|
||||
|
||||
- name: 标记部署失败
|
||||
if: failure()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
|
||||
state-value: 'failed'
|
||||
@@ -156,7 +156,7 @@ jobs:
|
||||
|
||||
- name: 记录失败信息
|
||||
if: failure()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}'
|
||||
@@ -169,7 +169,7 @@ jobs:
|
||||
steps:
|
||||
- name: 获取最终部署状态
|
||||
id: final-status
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
|
||||
default-value: 'unknown'
|
||||
@@ -193,7 +193,7 @@ jobs:
|
||||
# 清理部署锁定状态(如果需要)
|
||||
- name: 清理部署锁定
|
||||
if: always()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'deploy-status-${{ needs.check-deployment-state.outputs.environment }}'
|
||||
state-value: 'idle'
|
||||
|
@@ -45,7 +45,7 @@ jobs:
|
||||
|
||||
- name: 检查上次操作状态
|
||||
id: last-operation
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-operation-status'
|
||||
default-value: 'none'
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
|
||||
- name: 记录操作开始
|
||||
if: steps.check-previous.outputs.should-continue == 'true'
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'current-operation-id'
|
||||
state-value: ${{ steps.operation-setup.outputs.operation-id }}
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
|
||||
- name: 记录操作状态为进行中
|
||||
if: steps.check-previous.outputs.should-continue == 'true'
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-operation-status'
|
||||
state-value: 'running'
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
|
||||
- name: 检查构建重试状态
|
||||
id: retry-status
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'build-retry-count-${{ needs.initialize-operation.outputs.operation-id }}'
|
||||
default-value: '0'
|
||||
@@ -160,7 +160,7 @@ jobs:
|
||||
|
||||
- name: 更新重试计数(失败时)
|
||||
if: failure()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}
|
||||
@@ -169,7 +169,7 @@ jobs:
|
||||
|
||||
- name: 记录构建失败状态
|
||||
if: failure()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'build-status-${{ needs.initialize-operation.outputs.operation-id }}'
|
||||
state-value: 'failed'
|
||||
@@ -178,7 +178,7 @@ jobs:
|
||||
|
||||
- name: 记录构建失败时间
|
||||
if: failure()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}
|
||||
@@ -187,7 +187,7 @@ jobs:
|
||||
|
||||
- name: 清理重试计数(成功时)
|
||||
if: success()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'build-retry-count-${{ needs.initialize-operation.outputs.operation-id }}'
|
||||
state-value: ''
|
||||
@@ -196,7 +196,7 @@ jobs:
|
||||
|
||||
- name: 记录构建成功状态
|
||||
if: success()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'build-status-${{ needs.initialize-operation.outputs.operation-id }}'
|
||||
state-value: 'success'
|
||||
@@ -213,7 +213,7 @@ jobs:
|
||||
|
||||
- name: 获取上次成功的部署版本
|
||||
id: last-deploy
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-successful-deployment'
|
||||
default-value: 'v1.0.0'
|
||||
@@ -221,7 +221,7 @@ jobs:
|
||||
cache-prefix: 'deploy'
|
||||
|
||||
- name: 备份当前部署状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}
|
||||
@@ -245,7 +245,7 @@ jobs:
|
||||
|
||||
- name: 记录部署成功
|
||||
if: success()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-successful-deployment'
|
||||
state-value: ${{ github.sha }}
|
||||
@@ -254,7 +254,7 @@ jobs:
|
||||
|
||||
- name: 清理备份(成功时)
|
||||
if: success()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'deployment-backup-${{ needs.initialize-operation.outputs.operation-id }}'
|
||||
state-value: ''
|
||||
@@ -273,7 +273,7 @@ jobs:
|
||||
|
||||
- name: 记录回滚状态
|
||||
if: failure()
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'rollback-executed-${{ needs.initialize-operation.outputs.operation-id }}'
|
||||
state-value: 'true'
|
||||
@@ -313,7 +313,7 @@ jobs:
|
||||
echo "🏁 最终状态: ${FINAL_STATUS}"
|
||||
|
||||
- name: 记录最终操作状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-operation-status'
|
||||
state-value: ${{ steps.final-status.outputs.final-status }}
|
||||
@@ -321,7 +321,7 @@ jobs:
|
||||
cache-prefix: 'operation'
|
||||
|
||||
- name: 记录操作完成时间
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'last-operation-time'
|
||||
state-value: ${{ github.event.head_commit.timestamp }}
|
||||
@@ -369,7 +369,7 @@ jobs:
|
||||
# 例如,清理超过一定时间的重试计数、备份等临时状态
|
||||
|
||||
- name: 清理示例 - 重置错误计数
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'error-count-global'
|
||||
state-value: '0'
|
||||
|
@@ -41,7 +41,7 @@ jobs:
|
||||
|
||||
- name: 获取或设置功能开关状态
|
||||
id: feature-flag
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
|
||||
- name: 管理灰度发布配置
|
||||
id: rollout
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
action: 'get-or-set'
|
||||
|
||||
- name: 记录功能开关变更历史
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}'
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
|
||||
- name: 获取服务特定的功能配置
|
||||
id: service-config
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'service-config-${{ matrix.service }}-${{ github.event.inputs.environment }}'
|
||||
default-value: '{"features":{},"version":"1.0"}'
|
||||
@@ -133,7 +133,7 @@ jobs:
|
||||
esac
|
||||
|
||||
- name: 更新服务配置状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}'
|
||||
@@ -149,7 +149,7 @@ jobs:
|
||||
|
||||
- name: 初始化功能监控指标
|
||||
id: init-metrics
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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}'
|
||||
@@ -175,7 +175,7 @@ jobs:
|
||||
echo "performance_score=${PERFORMANCE_SCORE}" >> $GITHUB_ENV
|
||||
|
||||
- name: 更新功能监控指标
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}}'
|
||||
@@ -202,7 +202,7 @@ jobs:
|
||||
|
||||
- name: 记录异常告警
|
||||
if: env.alert != 'none'
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}'
|
||||
@@ -219,7 +219,7 @@ jobs:
|
||||
|
||||
- name: 检查是否需要回滚
|
||||
id: check-rollback
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'alert-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
|
||||
default-value: 'none'
|
||||
@@ -235,7 +235,7 @@ jobs:
|
||||
|
||||
- name: 禁用功能开关
|
||||
if: contains(steps.check-rollback.outputs.state-value, 'high_error_rate')
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'feature-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
|
||||
state-value: 'false'
|
||||
@@ -244,7 +244,7 @@ jobs:
|
||||
|
||||
- name: 记录回滚操作
|
||||
if: contains(steps.check-rollback.outputs.state-value, 'high_error_rate')
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
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 }}'
|
||||
@@ -270,7 +270,7 @@ jobs:
|
||||
|
||||
- name: 获取最终功能状态
|
||||
id: final-state
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'feature-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
|
||||
action: 'get'
|
||||
@@ -278,7 +278,7 @@ jobs:
|
||||
|
||||
- name: 获取监控指标
|
||||
id: final-metrics
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'metrics-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
|
||||
action: 'get'
|
||||
@@ -286,7 +286,7 @@ jobs:
|
||||
|
||||
- name: 检查回滚历史
|
||||
id: rollback-check
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'rollback-${{ github.event.inputs.feature_name }}-${{ github.event.inputs.environment }}'
|
||||
default-value: 'none'
|
||||
@@ -318,7 +318,7 @@ jobs:
|
||||
# 例如,清理超过一定时间的开发环境功能开关
|
||||
|
||||
- name: 重置开发环境告警
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'dev-alerts-cleared'
|
||||
state-value: '${{ github.run_started_at }}'
|
||||
|
@@ -50,7 +50,7 @@ jobs:
|
||||
esac
|
||||
|
||||
- name: 保存环境副本数配置
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'replicas-${{ matrix.environment }}'
|
||||
state-value: ${{ steps.env-config.outputs.replicas }}
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
cache-prefix: 'env-config'
|
||||
|
||||
- name: 保存环境资源配置
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'resources-${{ matrix.environment }}'
|
||||
state-value: ${{ steps.env-config.outputs.resources }}
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
cache-prefix: 'env-config'
|
||||
|
||||
- name: 保存调试模式配置
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'debug-${{ matrix.environment }}'
|
||||
state-value: ${{ steps.env-config.outputs.debug }}
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
|
||||
- name: 检查环境健康状态
|
||||
id: health-check
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'health-status-${{ matrix.environment }}'
|
||||
default-value: 'unknown'
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
|
||||
- name: 初始化环境健康状态
|
||||
if: steps.health-check.outputs.state-value == 'unknown'
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'health-status-${{ matrix.environment }}'
|
||||
state-value: 'healthy'
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
|
||||
- name: 获取开发环境配置
|
||||
id: dev-config
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'replicas-dev'
|
||||
action: 'get'
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
|
||||
- name: 获取预发布环境配置
|
||||
id: staging-config
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'replicas-staging'
|
||||
action: 'get'
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
|
||||
- name: 获取生产环境配置
|
||||
id: prod-config
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'replicas-production'
|
||||
action: 'get'
|
||||
@@ -161,7 +161,7 @@ jobs:
|
||||
echo "dev_health=${HEALTH_STATUS}" >> $GITHUB_ENV
|
||||
|
||||
- name: 更新开发环境健康状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'health-status-dev'
|
||||
state-value: ${{ env.dev_health }}
|
||||
@@ -177,7 +177,7 @@ jobs:
|
||||
echo "staging_health=${HEALTH_STATUS}" >> $GITHUB_ENV
|
||||
|
||||
- name: 更新预发布环境健康状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'health-status-staging'
|
||||
state-value: ${{ env.staging_health }}
|
||||
@@ -193,7 +193,7 @@ jobs:
|
||||
echo "prod_health=${HEALTH_STATUS}" >> $GITHUB_ENV
|
||||
|
||||
- name: 更新生产环境健康状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'health-status-production'
|
||||
state-value: ${{ env.prod_health }}
|
||||
@@ -235,14 +235,14 @@ jobs:
|
||||
echo "=== 开发环境状态 ==="
|
||||
|
||||
- name: 读取开发环境配置
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'replicas-dev'
|
||||
action: 'get'
|
||||
cache-prefix: 'env-config'
|
||||
|
||||
- name: 读取开发环境健康状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'health-status-dev'
|
||||
action: 'get'
|
||||
@@ -282,7 +282,7 @@ jobs:
|
||||
# 例如,设置空值来清理特定的缓存状态
|
||||
|
||||
- name: 重置所有环境的临时状态
|
||||
uses: .actions/xgj/cache-state@v1
|
||||
uses: actions/xgj/cache-state@v1
|
||||
with:
|
||||
state-key: 'temp-maintenance-mode'
|
||||
state-value: ''
|
||||
|
@@ -10,17 +10,22 @@
|
||||
- 🔑 **精确 hash 控制**: 支持自定义缓存 hash,确保依赖变化时缓存失效
|
||||
- 🔄 **Git 集成**: 可选的 git stash 功能
|
||||
- 📊 **详细输出**: 提供缓存命中状态和使用的缓存 key
|
||||
- 🧰 **自动安装 pnpm**: 当选择 `package-manager: pnpm` 时,自动通过 `pnpm/action-setup@v4` 确保 pnpm 可用(可指定版本)
|
||||
- 🗜️ **缓存 pnpm 二进制**: 在安装前缓存 Corepack 的 pnpm 二进制目录,避免重复下载 pnpm 本体(对封闭/慢网环境更友好)
|
||||
|
||||
## 📋 输入参数
|
||||
|
||||
| 参数名 | 描述 | 是否必需 | 默认值 |
|
||||
| ------------------- | ---------------------------- | -------- | -------------- |
|
||||
| `package-manager` | 包管理器类型 (npm/pnpm/yarn) | 否 | `npm` |
|
||||
| `pnpm-version` | pnpm 版本(`package-manager: pnpm` 时生效) | 否 | `9` |
|
||||
| `cache-mode` | 缓存模式(`node_modules` 或 `store`) | 否 | `node_modules` |
|
||||
| `cache-prefix` | 缓存前缀名称 | 否 | `modules` |
|
||||
| `node-modules-path` | node_modules 目录路径 | 否 | `node_modules` |
|
||||
| `force-install` | 是否强制安装 | 否 | `false` |
|
||||
| `enable-git-stash` | 安装后是否执行 git stash | 否 | `false` |
|
||||
| `install-command` | 自定义安装命令(覆盖默认) | 否 | `''` |
|
||||
| `install-args` | 附加到默认安装命令的参数(当未提供 `install-command` 时生效) | 否 | `''` |
|
||||
| `cache-hash` | 缓存 hash 值(**推荐使用**) | 否 | 自动计算 |
|
||||
|
||||
## 📤 输出参数
|
||||
@@ -29,6 +34,7 @@
|
||||
| ----------- | ------------------------- |
|
||||
| `cache-hit` | 是否命中缓存 (true/false) |
|
||||
| `cache-key` | 使用的缓存 key |
|
||||
| `cache-path` | 缓存路径(用于调试与复用) |
|
||||
|
||||
## 💡 重要提示
|
||||
|
||||
@@ -65,6 +71,13 @@ with:
|
||||
uses: actions/xgj/npm-install@v1
|
||||
with:
|
||||
package-manager: "pnpm"
|
||||
# 可选:指定 pnpm 版本(默认 9)
|
||||
pnpm-version: "9"
|
||||
# 可选:切换为包管理器 store 缓存,提升复用率(首次仍需安装链接)
|
||||
# cache-mode: "store"
|
||||
# 可选:附加安装参数(当未设置 install-command 时生效)
|
||||
# 例如:保持锁文件严格、忽略可选依赖
|
||||
install-args: "--frozen-lockfile --no-optional"
|
||||
```
|
||||
|
||||
### 强制安装 + Git Stash
|
||||
@@ -98,6 +111,31 @@ with:
|
||||
install-command: "npm ci --only=production"
|
||||
```
|
||||
|
||||
### 仅附加参数(不覆盖命令)
|
||||
|
||||
```yaml
|
||||
# npm 示例:追加只生产依赖
|
||||
- name: 安装(npm,仅生产依赖)
|
||||
uses: actions/xgj/npm-install@v1
|
||||
with:
|
||||
package-manager: npm
|
||||
install-args: "--only=production"
|
||||
|
||||
# pnpm 示例:严格锁文件 + 忽略可选依赖
|
||||
- name: 安装(pnpm,严格锁文件)
|
||||
uses: actions/xgj/npm-install@v1
|
||||
with:
|
||||
package-manager: pnpm
|
||||
install-args: "--frozen-lockfile --no-optional"
|
||||
|
||||
# yarn 示例:纯安装(禁用脚本)
|
||||
- name: 安装(yarn,禁用脚本)
|
||||
uses: actions/xgj/npm-install@v1
|
||||
with:
|
||||
package-manager: yarn
|
||||
install-args: "--ignore-scripts"
|
||||
```
|
||||
|
||||
### 使用自定义缓存 hash(推荐用法)
|
||||
|
||||
```yaml
|
||||
@@ -177,8 +215,15 @@ jobs:
|
||||
|
||||
1. **缓存 Key 生成**: 根据包管理器类型和 lock 文件生成唯一的缓存 key
|
||||
2. **缓存检查**: 使用`actions/cache@v4`检查是否存在匹配的缓存
|
||||
3. **条件安装**: 仅在缓存未命中时执行依赖安装
|
||||
4. **可选操作**: 根据配置执行 git stash 等额外操作
|
||||
3. **自动安装 pnpm(如需)**: 当 `package-manager=pnpm` 时,使用 `pnpm/action-setup@v4` 确保 pnpm 已安装
|
||||
- 在此之前,本 Action 会使用 `actions/cache@v4` 缓存 Corepack 的 pnpm 二进制目录,命中后无需再次从外网拉取 pnpm 本体
|
||||
4. **缓存路径确定**:
|
||||
- 当 `cache-mode=node_modules` 时,缓存 `node_modules`(可用 `node-modules-path` 定义目录)。
|
||||
- 当 `cache-mode=store` 时,缓存包管理器的全局存储:`npm` → `~/.npm`,`pnpm` → 通过 `pnpm store path` 动态获取,`yarn` → `~/.cache/yarn`。
|
||||
5. **条件安装**: 仅在缓存未命中时执行依赖安装
|
||||
6. **可选操作**: 根据配置执行 git stash 等额外操作
|
||||
|
||||
> 说明:缓存 key 中包含 OS、包管理器(以及 pnpm 的版本)、缓存模式与自定义前缀,避免跨包管理器/模式的缓存误用。
|
||||
|
||||
## 🎯 最佳实践
|
||||
|
||||
@@ -189,6 +234,21 @@ jobs:
|
||||
- uses: actions/xgj/npm-install@v1
|
||||
with:
|
||||
package-manager: "pnpm" # 如果项目使用pnpm
|
||||
|
||||
### 1.1 选择合适的缓存模式
|
||||
|
||||
```yaml
|
||||
# 追求最快的安装且目录较稳定:缓存 node_modules(默认)
|
||||
- uses: actions/xgj/npm-install@v1
|
||||
with:
|
||||
package-manager: pnpm
|
||||
cache-mode: node_modules
|
||||
|
||||
# 追求更高的通用性和复用率:缓存包管理器 store(首次仍需 install 链接)
|
||||
- uses: actions/xgj/npm-install@v1
|
||||
with:
|
||||
package-manager: pnpm
|
||||
cache-mode: store
|
||||
```
|
||||
|
||||
### 2. 合理使用强制安装
|
||||
@@ -220,6 +280,10 @@ jobs:
|
||||
- name: 重建缓存
|
||||
if: steps.install.outputs.cache-hit != 'true'
|
||||
run: npm run build:cache
|
||||
|
||||
# 调试:打印缓存路径(可用于后续步骤复用路径)
|
||||
- name: 打印缓存路径
|
||||
run: echo "Cache path is: ${{ steps.install.outputs.cache-path }}"
|
||||
```
|
||||
|
||||
## 🚨 注意事项
|
||||
@@ -228,6 +292,21 @@ jobs:
|
||||
2. **缓存大小**: node_modules 可能很大,请关注 GitHub Actions 的缓存限制
|
||||
3. **Lock 文件**: 确保 lock 文件已提交到仓库,这是缓存 key 生成的基础
|
||||
4. **权限**: 某些自定义安装命令可能需要额外的权限
|
||||
5. **跨包管理器缓存隔离**: 缓存 key 与 restore-keys 均包含包管理器、版本(pnpm)与模式,切换包管理器/模式时会触发一次干净安装,避免污染
|
||||
|
||||
## 🛡️ 封闭网络/慢网优化
|
||||
|
||||
在网络较差或对外网络受限的环境中,建议:
|
||||
|
||||
- 本 Action 已默认缓存 pnpm 二进制(Corepack 缓存目录),首次成功后后续运行将跳过 pnpm 下载。
|
||||
- 缓存路径(按 OS 区分,Action 会全部尝试):
|
||||
- Linux: `~/.cache/corepack`
|
||||
- macOS: `~/Library/Caches/CorePack` 与 `~/Library/Caches/Corepack`
|
||||
- Windows: `C:\Users\runneradmin\AppData\Local\Corepack\cache`
|
||||
- 缓存 key:`${{ runner.os }}-corepack-pnpm-${{ inputs.pnpm-version }}`
|
||||
- 将 registry 指向内网镜像或近源镜像,并(如需)配置 `NODE_AUTH_TOKEN`。
|
||||
- 适当降低并发、调大超时与重试,例如设置:`pnpm config set network-concurrency 1` 与对应的 `npm config set network-timeout ...` 等。
|
||||
- 使用 `cache-mode: store` 并确保 `pnpm store path` 被缓存(Action 默认已处理)。首次成功安装后,后续基本本地链接即可。
|
||||
|
||||
## 🔍 故障排除
|
||||
|
||||
@@ -238,6 +317,11 @@ jobs:
|
||||
- lock 文件是否存在且已提交
|
||||
- package.json 或 lock 文件是否有变更
|
||||
- 缓存前缀是否与之前一致
|
||||
- 是否切换了包管理器或 `cache-mode`(切换会生成不同的 key 与前缀)
|
||||
|
||||
### pnpm store 路径
|
||||
|
||||
当 `cache-mode=store` 且 `package-manager=pnpm` 时,本 Action 会通过 `pnpm store path` 动态解析缓存目录;若命令不可用,则回退到 `~/.pnpm-store`。
|
||||
|
||||
### 安装失败
|
||||
|
||||
|
@@ -8,9 +8,23 @@ inputs:
|
||||
package-manager:
|
||||
description: '包管理器类型 (npm, pnpm, yarn)'
|
||||
required: false
|
||||
default: 'npm'
|
||||
default: 'pnpm'
|
||||
|
||||
pnpm-version:
|
||||
description: 'pnpm 版本(当 package-manager=pnpm 时生效)'
|
||||
required: false
|
||||
default: '10'
|
||||
|
||||
cache-mode:
|
||||
description: '缓存模式:node_modules 或 store'
|
||||
required: false
|
||||
default: 'store'
|
||||
|
||||
optimize-install-flags:
|
||||
description: '是否启用安装参数优化(pnpm+store时自动使用 --offline/--prefer-offline 与 --frozen-lockfile)(true/false)'
|
||||
required: false
|
||||
default: 'true'
|
||||
|
||||
|
||||
cache-prefix:
|
||||
description: '缓存前缀名称'
|
||||
required: false
|
||||
@@ -35,6 +49,16 @@ inputs:
|
||||
description: '自定义安装命令(可选,会覆盖默认命令)'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
install-args:
|
||||
description: '附加到默认安装命令的参数(当未提供 install-command 时生效)'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
clean-project-store:
|
||||
description: '在安装前清理项目根的 .pnpm-store 残留(true/false)'
|
||||
required: false
|
||||
default: 'false'
|
||||
|
||||
cache-hash:
|
||||
description: '缓存hash值(推荐使用hashFiles计算)'
|
||||
@@ -50,6 +74,10 @@ outputs:
|
||||
description: '使用的缓存key'
|
||||
value: ${{ steps.cache-key.outputs.key }}
|
||||
|
||||
cache-path:
|
||||
description: '缓存路径(用于调试与复用)'
|
||||
value: ${{ steps.cache-path.outputs.path }}
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
@@ -80,65 +108,170 @@ runs:
|
||||
echo "⚠️ 使用默认hash值: ${CACHE_HASH_SHORT}"
|
||||
fi
|
||||
|
||||
CACHE_KEY="${{ runner.os }}-${{ inputs.cache-prefix }}-${CACHE_HASH_SHORT}"
|
||||
# 生成包管理器后缀,避免不同包管理器/版本的缓存互相污染
|
||||
MANAGER="${{ inputs.package-manager }}"
|
||||
MANAGER_SUFFIX="$MANAGER"
|
||||
if [[ "$MANAGER" == "pnpm" && -n "${{ inputs.pnpm-version }}" && "${{ inputs.pnpm-version }}" != "" ]]; then
|
||||
MANAGER_SUFFIX="${MANAGER}-v${{ inputs.pnpm-version }}"
|
||||
fi
|
||||
|
||||
# 模式后缀,隔离不同缓存模式(node_modules vs store)
|
||||
MODE_SUFFIX="${{ inputs.cache-mode }}"
|
||||
if [[ -z "$MODE_SUFFIX" ]]; then MODE_SUFFIX="node_modules"; fi
|
||||
|
||||
# 构建缓存key:<OS>-<manager[-vX]>-<mode>-<prefix>-<hash>
|
||||
CACHE_KEY="${{ runner.os }}-${MANAGER_SUFFIX}-${MODE_SUFFIX}-${{ inputs.cache-prefix }}-${CACHE_HASH_SHORT}"
|
||||
# 恢复前缀:用于 restore-keys,防止不同包管理器/模式的回退误命中
|
||||
RESTORE_PREFIX="${{ runner.os }}-${MANAGER_SUFFIX}-${MODE_SUFFIX}-${{ inputs.cache-prefix }}-"
|
||||
echo "key=${CACHE_KEY}" >> $GITHUB_OUTPUT
|
||||
echo "restore-prefix=${RESTORE_PREFIX}" >> $GITHUB_OUTPUT
|
||||
echo "使用hash: ${CACHE_HASH}"
|
||||
echo "缓存key: ${CACHE_KEY}"
|
||||
|
||||
- name: 确保 pnpm 可用
|
||||
if: inputs.package-manager == 'pnpm'
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: ${{ inputs.pnpm-version }}
|
||||
run_install: false
|
||||
|
||||
- name: 确定缓存路径
|
||||
id: cache-path
|
||||
shell: bash
|
||||
run: |
|
||||
MODE="${{ inputs.cache-mode }}"
|
||||
MANAGER="${{ inputs.package-manager }}"
|
||||
if [[ -z "$MODE" ]]; then MODE="node_modules"; fi
|
||||
|
||||
if [[ "$MODE" == "node_modules" ]]; then
|
||||
CACHE_PATH="${{ inputs.node-modules-path }}"
|
||||
# 即使只缓存 node_modules,pnpm 也会使用 store。为避免在项目根生成 .pnpm-store,这里同样固定 PNPM_STORE_DIR
|
||||
if [[ "$MANAGER" == "pnpm" ]]; then
|
||||
DEFAULT_PNPM_STORE="${RUNNER_TEMP:-$HOME}/.pnpm-store"
|
||||
echo "PNPM_STORE_DIR=${DEFAULT_PNPM_STORE}" >> "$GITHUB_ENV"
|
||||
fi
|
||||
else
|
||||
case "$MANAGER" in
|
||||
"npm")
|
||||
# npm 的全局缓存目录
|
||||
CACHE_PATH="$HOME/.npm"
|
||||
;;
|
||||
"pnpm")
|
||||
# 固定 pnpm store 路径到 runner 的临时目录或 HOME,避免在项目根生成 .pnpm-store
|
||||
# 说明:一些仓库的 .npmrc 可能配置了 store-dir=.pnpm-store,会导致在工作目录创建 .pnpm-store
|
||||
# 这里通过设置 PNPM_STORE_DIR 环境变量进行覆盖,确保缓存路径稳定可控
|
||||
DEFAULT_PNPM_STORE="${RUNNER_TEMP:-$HOME}/.pnpm-store"
|
||||
# 将目录导出到环境,供后续安装步骤使用
|
||||
echo "PNPM_STORE_DIR=${DEFAULT_PNPM_STORE}" >> "$GITHUB_ENV"
|
||||
CACHE_PATH="${DEFAULT_PNPM_STORE}"
|
||||
;;
|
||||
"yarn")
|
||||
# yarn v1 默认缓存目录(yarn berry 采用不同机制,这里聚焦 v1 常见场景)
|
||||
CACHE_PATH="$HOME/.cache/yarn"
|
||||
;;
|
||||
*)
|
||||
echo "❌ 不支持的包管理器: $MANAGER"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
# 打印最终缓存目录,便于调试与确认
|
||||
echo "📁 最终缓存目录: ${CACHE_PATH}"
|
||||
if [[ "$MANAGER" == "pnpm" ]]; then
|
||||
echo "📦 PNPM_STORE_DIR=${PNPM_STORE_DIR:-$DEFAULT_PNPM_STORE}"
|
||||
fi
|
||||
echo "path=${CACHE_PATH}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 拉取缓存依赖
|
||||
id: cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ inputs.node-modules-path }}
|
||||
path: ${{ steps.cache-path.outputs.path }}
|
||||
key: ${{ steps.cache-key.outputs.key }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ inputs.cache-prefix }}-
|
||||
${{ steps.cache-key.outputs.restore-prefix }}
|
||||
|
||||
- name: 显示缓存状态
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${{ steps.cache.outputs.cache-hit }}" == "true" ]]; then
|
||||
echo "✅ 缓存命中,跳过依赖安装"
|
||||
if [[ "${{ inputs.cache-mode }}" == "store" ]]; then
|
||||
echo "✅ 缓存命中(store),将执行快速链接安装(不会下载包,仅链接)"
|
||||
else
|
||||
echo "✅ 缓存命中,跳过依赖安装"
|
||||
fi
|
||||
else
|
||||
echo "⚠️ 缓存未命中,开始安装依赖"
|
||||
fi
|
||||
|
||||
- name: 安装依赖
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
if: (inputs.cache-mode == 'node_modules' && steps.cache.outputs.cache-hit != 'true') || (inputs.cache-mode == 'store')
|
||||
shell: bash
|
||||
run: |
|
||||
# 若使用 pnpm,在本步骤内始终显式设置 PNPM_STORE_DIR(覆盖可能存在的相对配置)
|
||||
if [[ "${{ inputs.package-manager }}" == "pnpm" ]]; then
|
||||
if [[ "${{ inputs.cache-mode }}" == "store" ]]; then
|
||||
# store 模式:cache-path 的 path 即为期望的 store 目录
|
||||
export PNPM_STORE_DIR="${{ steps.cache-path.outputs.path }}"
|
||||
else
|
||||
# node_modules 模式:不要回退到 cache-path(那是 node_modules 目录),而是使用 RUNNER_TEMP/HOME
|
||||
export PNPM_STORE_DIR="${PNPM_STORE_DIR:-${RUNNER_TEMP:-$HOME}/.pnpm-store}"
|
||||
fi
|
||||
# 通过多通道环境变量覆盖(兼容不同版本/解析顺序)
|
||||
export npm_config_store_dir="${PNPM_STORE_DIR}"
|
||||
export PNPM_CONFIG_STORE_DIR="${PNPM_STORE_DIR}"
|
||||
echo "🧩 已设置 PNPM_STORE_DIR=${PNPM_STORE_DIR}"
|
||||
echo "🔎 pnpm 配置: store-dir=$(pnpm config get store-dir || echo '<unknown>')"
|
||||
fi
|
||||
|
||||
# 如果提供了自定义安装命令,使用自定义命令
|
||||
if [[ -n "${{ inputs.install-command }}" ]]; then
|
||||
echo "🔧 使用自定义安装命令: ${{ inputs.install-command }}"
|
||||
${{ inputs.install-command }}
|
||||
else
|
||||
INSTALL_ARGS="${{ inputs.install-args }}"
|
||||
if [[ -n "$INSTALL_ARGS" ]]; then
|
||||
echo "➕ 附加安装参数: $INSTALL_ARGS"
|
||||
fi
|
||||
# 根据模式与缓存命中优化安装参数(尽量离线加速)
|
||||
EXTRA_FLAGS=""
|
||||
if [[ "${{ inputs.optimize-install-flags }}" == "true" && "${{ inputs.package-manager }}" == "pnpm" && "${{ inputs.cache-mode }}" == "store" ]]; then
|
||||
if [[ "${{ steps.cache.outputs.cache-hit }}" == "true" ]]; then
|
||||
# 缓存命中:使用完全离线与锁定安装,避免网络请求
|
||||
EXTRA_FLAGS="--offline --frozen-lockfile"
|
||||
else
|
||||
# 缓存未命中:尽量离线,但允许必要网络;同时锁定避免解析差异
|
||||
EXTRA_FLAGS="--prefer-offline --frozen-lockfile"
|
||||
fi
|
||||
echo "⚡ pnpm安装优化参数: $EXTRA_FLAGS"
|
||||
fi
|
||||
# 根据包管理器选择安装命令
|
||||
case "${{ inputs.package-manager }}" in
|
||||
"npm")
|
||||
if [[ "${{ inputs.force-install }}" == "true" ]]; then
|
||||
echo "🔧 使用npm强制安装"
|
||||
npm install --force
|
||||
npm install --force ${INSTALL_ARGS}
|
||||
else
|
||||
echo "🔧 使用npm安装"
|
||||
npm install
|
||||
npm install ${INSTALL_ARGS}
|
||||
fi
|
||||
;;
|
||||
"pnpm")
|
||||
if [[ "${{ inputs.force-install }}" == "true" ]]; then
|
||||
echo "🔧 使用pnpm强制安装"
|
||||
pnpm install --force
|
||||
pnpm install --force ${EXTRA_FLAGS} ${INSTALL_ARGS}
|
||||
else
|
||||
echo "🔧 使用pnpm安装"
|
||||
pnpm install
|
||||
pnpm install ${EXTRA_FLAGS} ${INSTALL_ARGS}
|
||||
fi
|
||||
;;
|
||||
"yarn")
|
||||
if [[ "${{ inputs.force-install }}" == "true" ]]; then
|
||||
echo "🔧 使用yarn强制安装"
|
||||
yarn install --force
|
||||
yarn install --force ${INSTALL_ARGS}
|
||||
else
|
||||
echo "🔧 使用yarn安装"
|
||||
yarn install
|
||||
yarn install ${INSTALL_ARGS}
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
@@ -147,6 +280,16 @@ runs:
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# 可选清理:如启用并发现项目根存在残留的 .pnpm-store,且与目标目录不同,则清理
|
||||
if [[ "${{ inputs.package-manager }}" == "pnpm" && "${{ inputs.clean-project-store }}" == "true" ]]; then
|
||||
# 进一步在项目级设置覆盖一次,杜绝 .npmrc 相对路径带来的影响(仅对本 CI 工作目录生效)
|
||||
pnpm config set store-dir "${PNPM_STORE_DIR}" --location=project || true
|
||||
if [[ -d ".pnpm-store" && "${PNPM_STORE_DIR}" != "$PWD/.pnpm-store" ]]; then
|
||||
echo "🧹 清理项目根的残留 .pnpm-store(目标store为 ${PNPM_STORE_DIR})"
|
||||
rm -rf .pnpm-store || true
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "✅ 依赖安装完成"
|
||||
|
||||
@@ -169,3 +312,22 @@ runs:
|
||||
echo " - 强制安装: ${{ inputs.force-install }}"
|
||||
echo " - Git Stash: ${{ inputs.enable-git-stash }}"
|
||||
fi
|
||||
# 诊断工作目录是否存在 .pnpm-store 以及其 Git 状态
|
||||
echo "\n🧪 目录状态自检:"
|
||||
echo " - PNPM_STORE_DIR: ${PNPM_STORE_DIR:-<unset>}"
|
||||
if [[ -d ".pnpm-store" ]]; then
|
||||
echo " - 工作目录存在 .pnpm-store 目录"
|
||||
if git rev-parse --git-dir >/dev/null 2>&1; then
|
||||
if git ls-files --error-unmatch .pnpm-store >/dev/null 2>&1; then
|
||||
echo " - Git 状态: 已被跟踪 (tracked)"
|
||||
elif git check-ignore -q .pnpm-store; then
|
||||
echo " - Git 状态: 被忽略 (ignored)"
|
||||
else
|
||||
echo " - Git 状态: 未跟踪 (untracked)"
|
||||
fi
|
||||
else
|
||||
echo " - Git 仓库: 未检测到 (非 Git 工作目录)"
|
||||
fi
|
||||
else
|
||||
echo " - 工作目录未发现 .pnpm-store 目录 ✅"
|
||||
fi
|
||||
|
@@ -7,28 +7,35 @@
|
||||
- 🏷️ **标签触发检测**:自动识别版本标签(如 `v1.2.3`)并提取版本号
|
||||
- 🔄 **版本分支检测**:识别版本分支(如 `v1.2.x`)并提取版本信息
|
||||
- 🆕 **常规分支处理**:对于非版本分支提供基础信息
|
||||
- 📦 **最新版本获取**:始终获取仓库中的最新版本号,无论触发方式如何
|
||||
- 🎯 **灵活的版本前缀**:支持自定义版本前缀(默认为 `v`)
|
||||
- 🔍 **标签过滤功能**:支持通配符模式匹配和排除特定标签
|
||||
- 🔧 **版本格式转换**:自动生成横线格式的版本号(如 `v1.2.3` → `v1-2-3`)
|
||||
- 📤 **环境变量输出**:自动设置环境变量供后续步骤使用
|
||||
- 📊 **详细的输出信息**:提供完整的引用信息和触发状态
|
||||
|
||||
## 输入参数
|
||||
|
||||
| 参数名 | 描述 | 必需 | 默认值 |
|
||||
| ---------------- | -------------------------------- | ---- | ------ |
|
||||
| `version-prefix` | 版本前缀,用于匹配版本标签或分支 | 否 | `v` |
|
||||
| 参数名 | 描述 | 必需 | 默认值 |
|
||||
| -------------------- | ------------------------------------------------------------ | ---- | ------- |
|
||||
| `version-prefix` | 版本前缀,用于匹配版本标签或分支 | 否 | `v` |
|
||||
| `use-latest-version` | 在非版本触发时是否使用最新版本 | 否 | `false` |
|
||||
| `tag-match` | 标签匹配模式,支持通配符(如:`v*.*.*` 或 `v[0-9]*`),用于进一步过滤标签 | 否 | `""` |
|
||||
| `tag-exclude` | 标签排除模式,支持通配符(如:`*-alpha*` 或 `*-beta*`),匹配的标签将被排除 | 否 | `""` |
|
||||
|
||||
## 输出参数
|
||||
|
||||
| 参数名 | 描述 | 示例值 |
|
||||
| -------------------- | ------------------------ | ------------------------------- |
|
||||
| `ref-type` | 引用类型 | `tag` 或 `branch` |
|
||||
| `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` |
|
||||
| 参数名 | 描述 | 示例值 |
|
||||
| -------------------------- | -------------------------- | ------------------------------- |
|
||||
| `ref-type` | 引用类型 | `tag` 或 `branch` |
|
||||
| `ref-name` | 引用名称 | `v1.2.3`、`main`、`feature/xxx` |
|
||||
| `is-version-trigger` | 是否为版本触发 | `true` 或 `false` |
|
||||
| `trigger-version` | 触发的版本号(标准化格式) | `v1.2.3` |
|
||||
| `version-with-dash` | 版本号,点替换为横线 | `v1-2-3` |
|
||||
| `trigger-source` | 触发源 | `tag` 或 `branch` |
|
||||
| `full-ref` | 完整的 Git 引用 | `refs/tags/v1.2.3` |
|
||||
| `latest-version` | 仓库中的最新版本号 | `v1.2.3` |
|
||||
| `latest-version-with-dash` | 最新版本号,点替换为横线 | `v1-2-3` |
|
||||
|
||||
## 环境变量
|
||||
|
||||
@@ -56,17 +63,24 @@ jobs:
|
||||
outputs:
|
||||
is-version-trigger: ${{ steps.version-info.outputs.is-version-trigger }}
|
||||
trigger-version: ${{ steps.version-info.outputs.trigger-version }}
|
||||
latest-version: ${{ steps.version-info.outputs.latest-version }}
|
||||
version-with-dash: ${{ steps.version-info.outputs.version-with-dash }}
|
||||
trigger-source: ${{ steps.version-info.outputs.trigger-source }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # 必需:获取完整历史以获取所有标签
|
||||
|
||||
- name: 获取版本信息
|
||||
id: version-info
|
||||
uses: actions/xgj/trigger-version@v1
|
||||
uses: ./trigger-version
|
||||
|
||||
- name: 显示版本信息
|
||||
run: |
|
||||
echo "是否版本触发: ${{ steps.version-info.outputs.is-version-trigger }}"
|
||||
echo "版本号: ${{ steps.version-info.outputs.trigger-version }}"
|
||||
echo "触发版本: ${{ steps.version-info.outputs.trigger-version }}"
|
||||
echo "最新版本: ${{ steps.version-info.outputs.latest-version }}"
|
||||
echo "横线版本号: ${{ steps.version-info.outputs.version-with-dash }}"
|
||||
echo "触发源: ${{ steps.version-info.outputs.trigger-source }}"
|
||||
|
||||
@@ -81,6 +95,25 @@ jobs:
|
||||
echo "Docker标签: myapp:${{ needs.get-version-info.outputs.version-with-dash }}"
|
||||
```
|
||||
|
||||
### 使用最新版本功能
|
||||
|
||||
````yaml
|
||||
- name: 获取版本信息(启用最新版本)
|
||||
id: version-info
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
use-latest-version: true # 在非版本触发时使用最新版本
|
||||
|
||||
- name: 使用最新版本进行构建
|
||||
run: |
|
||||
if [[ -n "${{ steps.version-info.outputs.latest-version }}" ]]; then
|
||||
echo "构建镜像标签: myapp:${{ steps.version-info.outputs.latest-version-with-dash }}"
|
||||
# docker build -t myapp:${{ steps.version-info.outputs.latest-version-with-dash }} .
|
||||
else
|
||||
echo "未找到版本标签,使用默认标签"
|
||||
# docker build -t myapp:latest .
|
||||
fi
|
||||
|
||||
### 自定义版本前缀
|
||||
|
||||
```yaml
|
||||
@@ -91,6 +124,73 @@ jobs:
|
||||
version-prefix: "release-"
|
||||
```
|
||||
|
||||
### 标签过滤功能
|
||||
|
||||
#### 排除预发布版本
|
||||
|
||||
```yaml
|
||||
- name: 获取稳定版本(排除预发布)
|
||||
id: stable-version
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: "v"
|
||||
use-latest-version: true
|
||||
tag-exclude: "*-alpha*" # 排除包含 alpha 的版本
|
||||
|
||||
- name: 显示稳定版本
|
||||
run: |
|
||||
echo "最新稳定版本: ${{ steps.stable-version.outputs.latest-version }}"
|
||||
```
|
||||
|
||||
#### 匹配特定版本模式
|
||||
|
||||
```yaml
|
||||
- name: 获取标准语义版本
|
||||
id: semver
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: "v"
|
||||
use-latest-version: true
|
||||
tag-match: "v[0-9]*.[0-9]*.[0-9]*" # 只匹配 v1.2.3 格式
|
||||
|
||||
- name: 显示语义版本
|
||||
run: |
|
||||
echo "语义版本: ${{ steps.semver.outputs.latest-version }}"
|
||||
```
|
||||
|
||||
#### 复合过滤条件
|
||||
|
||||
```yaml
|
||||
- name: 获取 v2.x 稳定版本
|
||||
id: v2-stable
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: "v"
|
||||
use-latest-version: true
|
||||
tag-match: "v2.*.*" # 只匹配 v2.x.x 版本
|
||||
tag-exclude: "*-*" # 排除所有预发布版本(包含连字符)
|
||||
|
||||
- name: 显示 v2.x 稳定版本
|
||||
run: |
|
||||
echo "v2.x 最新稳定版本: ${{ steps.v2-stable.outputs.latest-version }}"
|
||||
```
|
||||
|
||||
#### 获取预发布版本
|
||||
|
||||
```yaml
|
||||
- name: 获取最新 beta 版本
|
||||
id: beta-version
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: "v"
|
||||
use-latest-version: true
|
||||
tag-match: "*-beta*" # 只匹配包含 beta 的版本
|
||||
|
||||
- name: 显示 beta 版本
|
||||
run: |
|
||||
echo "最新 beta 版本: ${{ steps.beta-version.outputs.latest-version }}"
|
||||
````
|
||||
|
||||
### 完整的 CI/CD 流程
|
||||
|
||||
```yaml
|
||||
@@ -150,6 +250,44 @@ jobs:
|
||||
echo "部署版本 ${{ needs.analyze.outputs.trigger-version }} 到生产环境"
|
||||
```
|
||||
|
||||
## 标签过滤功能详解
|
||||
|
||||
### 通配符模式支持
|
||||
|
||||
`tag-match` 和 `tag-exclude` 参数支持 bash 通配符模式:
|
||||
|
||||
- `*`:匹配任意字符序列
|
||||
- `?`:匹配单个字符
|
||||
- `[...]`:匹配括号内的任意字符
|
||||
- `[!...]`:匹配不在括号内的任意字符
|
||||
|
||||
### 常用过滤模式
|
||||
|
||||
| 模式 | 描述 | 示例匹配 |
|
||||
| ------------------- | ------------------------------ | --------------------------- |
|
||||
| `v*.*.*` | 匹配标准三段式版本号 | `v1.2.3`, `v2.0.1` |
|
||||
| `v[0-9]*.[0-9]*.*` | 匹配数字开头的版本号 | `v1.2.3`, `v10.0.1` |
|
||||
| `*-alpha*` | 匹配包含 alpha 的版本 | `v1.0.0-alpha1` |
|
||||
| `*-beta*` | 匹配包含 beta 的版本 | `v1.0.0-beta2` |
|
||||
| `*-rc*` | 匹配包含 rc 的版本 | `v1.0.0-rc1` |
|
||||
| `*-*` | 匹配所有包含连字符的版本 | `v1.0.0-alpha`, `v1.0.0-1` |
|
||||
| `v2.*` | 匹配 v2 开头的所有版本 | `v2.0.0`, `v2.1.5` |
|
||||
| `v[12].*.*` | 匹配 v1 或 v2 开头的版本 | `v1.0.0`, `v2.3.1` |
|
||||
|
||||
### 过滤优先级
|
||||
|
||||
1. 首先应用 `version-prefix` 过滤(获取匹配前缀的标签)
|
||||
2. 然后应用 `tag-match` 过滤(保留匹配模式的标签)
|
||||
3. 最后应用 `tag-exclude` 过滤(排除匹配模式的标签)
|
||||
4. 对剩余标签进行版本排序,选择最新版本
|
||||
|
||||
### 注意事项
|
||||
|
||||
- 标签过滤主要影响 `latest-version` 的获取,不影响当前触发版本的识别
|
||||
- 当通过标签触发时,`trigger-version` 始终是触发的标签,过滤只影响 `latest-version`
|
||||
- 如果过滤后没有匹配的标签,`latest-version` 将为空
|
||||
- 建议在使用过滤功能时设置 `fetch-depth: 0` 以获取完整的标签历史
|
||||
|
||||
## 触发场景
|
||||
|
||||
### 标签触发
|
||||
@@ -183,14 +321,19 @@ jobs:
|
||||
|
||||
1. **条件部署**:使用 `is-version-trigger` 来决定是否执行生产部署
|
||||
2. **版本标记**:在构建产物中使用 `trigger-version` 进行版本标记
|
||||
3. **Docker 标签**:使用 `version-with-dash` 作为 Docker 镜像标签(避免点号问题)
|
||||
4. **环境区分**:根据触发源选择不同的部署环境
|
||||
5. **日志记录**:记录详细的版本信息用于追踪和调试
|
||||
3. **最新版本获取**:使用 `latest-version` 输出来获取仓库的最新版本,适用于回滚或版本比较
|
||||
4. **Docker 标签**:使用 `version-with-dash` 作为 Docker 镜像标签(避免点号问题)
|
||||
5. **环境区分**:根据触发源选择不同的部署环境
|
||||
6. **完整历史获取**:在工作流中使用 `fetch-depth: 0` 确保能获取所有标签
|
||||
7. **日志记录**:记录详细的版本信息用于追踪和调试
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 版本前缀区分大小写
|
||||
- 空的版本号会被设置为空字符串
|
||||
- `latest-version` 输出始终获取仓库的最新版本,无论触发方式如何
|
||||
- 获取最新版本需要完整的 Git 历史,建议使用 `fetch-depth: 0`
|
||||
- 最新版本按语义化版本排序,确保标签格式符合版本规范
|
||||
- 确保工作流触发条件与你的版本策略一致
|
||||
- 在使用输出参数时注意布尔值的字符串比较(使用 `== 'true'`)
|
||||
|
||||
|
@@ -1,47 +1,148 @@
|
||||
name: 'Trigger Version Info'
|
||||
description: '获取触发版本信息,支持标签触发、版本分支触发和常规分支触发'
|
||||
author: 'Your Organization'
|
||||
name: "Trigger Version Info"
|
||||
description: "获取触发版本信息,支持标签触发、版本分支触发和常规分支触发"
|
||||
author: "Your Organization"
|
||||
|
||||
inputs:
|
||||
version-prefix:
|
||||
description: '版本前缀,用于匹配版本标签或分支(默认:v)'
|
||||
description: "版本前缀,用于匹配版本标签或分支(默认:v)"
|
||||
required: false
|
||||
default: 'v'
|
||||
default: "v"
|
||||
use-latest-version:
|
||||
description: '在非版本触发时是否使用当前分支最新的版本标签(默认:false)'
|
||||
description: "在非版本触发时是否使用当前分支最新的版本标签(默认:false)"
|
||||
required: false
|
||||
default: 'false'
|
||||
default: "false"
|
||||
tag-match:
|
||||
description: "标签匹配模式,支持通配符(如:v*.*.* 或 v[0-9]*),用于进一步过滤标签"
|
||||
required: false
|
||||
default: ""
|
||||
tag-exclude:
|
||||
description: "标签排除模式,支持通配符(如:*-alpha* 或 *-beta*),匹配的标签将被排除"
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
outputs:
|
||||
ref-type:
|
||||
description: '引用类型 (tag/branch)'
|
||||
description: "引用类型 (tag/branch)"
|
||||
value: ${{ steps.get-version-info.outputs.ref_type }}
|
||||
ref-name:
|
||||
description: '引用名称'
|
||||
description: "引用名称"
|
||||
value: ${{ steps.get-version-info.outputs.ref_name }}
|
||||
is-version-trigger:
|
||||
description: '是否为版本触发(true/false)'
|
||||
description: "是否为版本触发(true/false)"
|
||||
value: ${{ steps.get-version-info.outputs.is_version_trigger }}
|
||||
trigger-version:
|
||||
description: '触发的版本号(标准化为v开头的格式)'
|
||||
description: "触发的版本号(标准化为v开头的格式)"
|
||||
value: ${{ steps.get-version-info.outputs.trigger_version }}
|
||||
trigger-source:
|
||||
description: '触发源(tag/branch)'
|
||||
description: "触发源(tag/branch)"
|
||||
value: ${{ steps.get-version-info.outputs.trigger_source }}
|
||||
full-ref:
|
||||
description: '完整的 Git 引用'
|
||||
description: "完整的 Git 引用"
|
||||
value: ${{ steps.get-version-info.outputs.full_ref }}
|
||||
version-with-dash:
|
||||
description: '版本号,点替换为横线(例如:v1.2.3 -> v1-2-3)'
|
||||
description: "版本号,点替换为横线(例如:v1.2.3 -> v1-2-3)"
|
||||
value: ${{ steps.get-version-info.outputs.version_with_dash }}
|
||||
latest-version:
|
||||
description: "仓库中的最新版本号(始终获取,格式如:v1.2.3)"
|
||||
value: ${{ steps.get-version-info.outputs.latest_version }}
|
||||
latest-version-with-dash:
|
||||
description: "最新版本号,点替换为横线(例如:v1.2.3 -> v1-2-3)"
|
||||
value: ${{ steps.get-version-info.outputs.latest_version_with_dash }}
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: 获取触发版本信息
|
||||
id: get-version-info
|
||||
shell: bash
|
||||
run: |
|
||||
# 获取最新版本号的函数
|
||||
get_latest_version() {
|
||||
local prefix="$1"
|
||||
local tag_match="$2"
|
||||
local tag_exclude="$3"
|
||||
local latest_version=""
|
||||
local latest_version_with_dash=""
|
||||
|
||||
echo "🔍 开始获取最新版本号(前缀:${prefix})..."
|
||||
[[ -n "$tag_match" ]] && echo "🎯 标签匹配模式: $tag_match"
|
||||
[[ -n "$tag_exclude" ]] && echo "🚫 标签排除模式: $tag_exclude"
|
||||
|
||||
# 检查git仓库是否可用
|
||||
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo "✅ Git仓库可用,开始获取标签..."
|
||||
|
||||
# 确保获取所有标签信息(GitHub Actions 默认是浅克隆)
|
||||
echo "📥 获取远程标签信息..."
|
||||
git fetch --tags --quiet 2>/dev/null || echo "⚠️ 获取远程标签失败,继续使用本地标签"
|
||||
|
||||
# 获取所有匹配的标签
|
||||
echo "🏷️ 查找匹配前缀 '${prefix}' 的标签..."
|
||||
local all_tags=$(git tag --list "${prefix}*" 2>/dev/null)
|
||||
|
||||
if [[ -n "$all_tags" ]]; then
|
||||
# 应用标签匹配过滤
|
||||
if [[ -n "$tag_match" ]]; then
|
||||
echo "🔍 应用标签匹配过滤: $tag_match"
|
||||
local filtered_tags=""
|
||||
while IFS= read -r tag; do
|
||||
if [[ "$tag" == $tag_match ]]; then
|
||||
filtered_tags="$filtered_tags$tag\n"
|
||||
fi
|
||||
done <<< "$all_tags"
|
||||
all_tags=$(echo -e "$filtered_tags" | sed '/^$/d')
|
||||
echo "📋 匹配后的标签数量: $(echo "$all_tags" | wc -l | tr -d ' ')"
|
||||
fi
|
||||
|
||||
# 应用标签排除过滤
|
||||
if [[ -n "$tag_exclude" && -n "$all_tags" ]]; then
|
||||
echo "🚫 应用标签排除过滤: $tag_exclude"
|
||||
local filtered_tags=""
|
||||
while IFS= read -r tag; do
|
||||
if [[ "$tag" != $tag_exclude ]]; then
|
||||
filtered_tags="$filtered_tags$tag\n"
|
||||
fi
|
||||
done <<< "$all_tags"
|
||||
all_tags=$(echo -e "$filtered_tags" | sed '/^$/d')
|
||||
echo "📋 排除后的标签数量: $(echo "$all_tags" | wc -l | tr -d ' ')"
|
||||
fi
|
||||
|
||||
if [[ -n "$all_tags" ]]; then
|
||||
# echo "最终标签列表:"
|
||||
# echo "$all_tags"
|
||||
|
||||
# 获取最新的版本标签
|
||||
if command -v sort >/dev/null 2>&1; then
|
||||
# 使用 sort 命令进行版本排序
|
||||
latest_version=$(echo "$all_tags" | sort -V | tail -1)
|
||||
else
|
||||
# 如果没有 sort -V,使用简单的字典序排序
|
||||
latest_version=$(echo "$all_tags" | sort | tail -1)
|
||||
fi
|
||||
|
||||
if [[ -n "$latest_version" ]]; then
|
||||
# 生成带横线的版本号
|
||||
latest_version_with_dash=$(echo "$latest_version" | sed 's/\./-/g')
|
||||
echo "📦 找到最新版本: $latest_version"
|
||||
echo "📦 横线格式版本: $latest_version_with_dash"
|
||||
else
|
||||
echo "⚠️ 未能确定最新版本"
|
||||
fi
|
||||
else
|
||||
echo "⚠️ 过滤后没有找到匹配的版本标签"
|
||||
fi
|
||||
else
|
||||
echo "⚠️ 未找到匹配前缀 '${prefix}' 的版本标签"
|
||||
fi
|
||||
else
|
||||
echo "❌ Git仓库不可用"
|
||||
fi
|
||||
|
||||
# 设置全局变量
|
||||
LATEST_VERSION="$latest_version"
|
||||
LATEST_VERSION_WITH_DASH="$latest_version_with_dash"
|
||||
}
|
||||
|
||||
# 获取GitHub上下文信息
|
||||
echo "触发方式: ${{ github.event_name }}"
|
||||
echo "引用类型: ${{ github.ref_type }}"
|
||||
@@ -53,6 +154,11 @@ runs:
|
||||
FULL_REF="${{ github.ref }}"
|
||||
VERSION_PREFIX="${{ inputs.version-prefix }}"
|
||||
USE_LATEST_VERSION="${{ inputs.use-latest-version }}"
|
||||
TAG_MATCH="${{ inputs.tag-match }}"
|
||||
TAG_EXCLUDE="${{ inputs.tag-exclude }}"
|
||||
|
||||
# 获取最新版本号(无论触发方式如何都获取)
|
||||
get_latest_version "$VERSION_PREFIX" "$TAG_MATCH" "$TAG_EXCLUDE"
|
||||
|
||||
# 判断是否为标签触发
|
||||
if [[ "$REF_TYPE" == "tag" ]]; then
|
||||
@@ -84,31 +190,17 @@ runs:
|
||||
echo "🆕 常规分支触发: $REF_NAME"
|
||||
|
||||
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
|
||||
# 使用已获取的最新版本
|
||||
if [[ -n "$LATEST_VERSION" ]]; then
|
||||
TRIGGER_VERSION=$LATEST_VERSION
|
||||
VERSION_WITH_DASH=$LATEST_VERSION_WITH_DASH
|
||||
echo "📦 使用最新版本标签: $LATEST_VERSION"
|
||||
echo "标准化版本号: $TRIGGER_VERSION"
|
||||
echo "横线版本号: $VERSION_WITH_DASH"
|
||||
IS_VERSION_TRIGGER=true
|
||||
else
|
||||
# Git仓库不可用
|
||||
echo "⚠️ Git仓库不可用,使用空版本"
|
||||
# 没有找到版本标签
|
||||
echo "⚠️ 未找到匹配前缀 '${VERSION_PREFIX}' 的版本标签,使用空版本"
|
||||
IS_VERSION_TRIGGER=false
|
||||
TRIGGER_VERSION=""
|
||||
VERSION_WITH_DASH=""
|
||||
@@ -137,7 +229,17 @@ runs:
|
||||
echo "trigger_version=$TRIGGER_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "version_with_dash=$VERSION_WITH_DASH" >> $GITHUB_OUTPUT
|
||||
echo "trigger_source=$TRIGGER_SOURCE" >> $GITHUB_OUTPUT
|
||||
echo "latest_version=$LATEST_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "latest_version_with_dash=$LATEST_VERSION_WITH_DASH" >> $GITHUB_OUTPUT
|
||||
|
||||
# 输出摘要信息
|
||||
echo ""
|
||||
echo "=== 版本信息摘要 ==="
|
||||
echo "🔸 触发版本: $TRIGGER_VERSION"
|
||||
echo "🔸 最新版本: $LATEST_VERSION"
|
||||
echo "🔸 是否版本触发: $IS_VERSION_TRIGGER"
|
||||
echo "🔸 触发源: $TRIGGER_SOURCE"
|
||||
|
||||
branding:
|
||||
icon: 'git-branch'
|
||||
color: 'blue'
|
||||
icon: "git-branch"
|
||||
color: "blue"
|
||||
|
65
trigger-version/examples/latest-version-demo.yml
Normal file
65
trigger-version/examples/latest-version-demo.yml
Normal file
@@ -0,0 +1,65 @@
|
||||
name: Latest Version Demo
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
show-version-info:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # 获取完整历史,确保能获取所有标签
|
||||
|
||||
- name: Get Version Info
|
||||
id: version
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: "v"
|
||||
use-latest-version: true
|
||||
|
||||
- name: Display Version Information
|
||||
run: |
|
||||
echo "=== 版本信息详情 ==="
|
||||
echo "引用类型: ${{ steps.version.outputs.ref-type }}"
|
||||
echo "引用名称: ${{ steps.version.outputs.ref-name }}"
|
||||
echo "完整引用: ${{ steps.version.outputs.full-ref }}"
|
||||
echo ""
|
||||
echo "=== 触发版本信息 ==="
|
||||
echo "是否版本触发: ${{ steps.version.outputs.is-version-trigger }}"
|
||||
echo "触发版本: ${{ steps.version.outputs.trigger-version }}"
|
||||
echo "触发源: ${{ steps.version.outputs.trigger-source }}"
|
||||
echo "版本(横线格式): ${{ steps.version.outputs.version-with-dash }}"
|
||||
echo ""
|
||||
echo "=== 最新版本信息 ==="
|
||||
echo "最新版本: ${{ steps.version.outputs.latest-version }}"
|
||||
echo "最新版本(横线格式): ${{ steps.version.outputs.latest-version-with-dash }}"
|
||||
|
||||
- name: Use Latest Version in Deployment
|
||||
if: steps.version.outputs.latest-version != ''
|
||||
run: |
|
||||
echo "使用最新版本进行部署: ${{ steps.version.outputs.latest-version }}"
|
||||
echo "镜像标签: myapp:${{ steps.version.outputs.latest-version-with-dash }}"
|
||||
|
||||
# 示例:构建 Docker 镜像
|
||||
# docker build -t myapp:${{ steps.version.outputs.latest-version-with-dash }} .
|
||||
|
||||
# 示例:设置 Kubernetes 部署
|
||||
# kubectl set image deployment/myapp container=myapp:${{ steps.version.outputs.latest-version-with-dash }}
|
||||
|
||||
- name: Handle No Version Found
|
||||
if: steps.version.outputs.latest-version == ''
|
||||
run: |
|
||||
echo "⚠️ 未找到任何版本标签"
|
||||
echo "这可能是因为:"
|
||||
echo "1. 仓库中没有版本标签"
|
||||
echo "2. 版本标签不匹配指定的前缀"
|
||||
echo "3. Git 获取标签失败"
|
||||
echo ""
|
||||
echo "建议:"
|
||||
echo "1. 检查仓库是否有版本标签(如 v1.0.0)"
|
||||
echo "2. 确认版本前缀设置正确"
|
||||
echo "3. 确保 fetch-depth: 0 以获取完整历史"
|
137
trigger-version/examples/tag-filtering-demo.yml
Normal file
137
trigger-version/examples/tag-filtering-demo.yml
Normal file
@@ -0,0 +1,137 @@
|
||||
name: Tag Filtering Demo
|
||||
|
||||
# 演示如何使用 tagMatch 和 tagExclude 功能来过滤版本标签
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
# 示例1:只匹配稳定版本(排除预发布版本)
|
||||
stable-versions-only:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # 获取完整的 git 历史
|
||||
|
||||
- name: Get stable version (exclude alpha/beta/rc)
|
||||
id: stable-version
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: 'v'
|
||||
use-latest-version: 'true'
|
||||
tag-exclude: '*-alpha*|*-beta*|*-rc*'
|
||||
|
||||
- name: Display stable version info
|
||||
run: |
|
||||
echo "Latest stable version: ${{ steps.stable-version.outputs.latest-version }}"
|
||||
echo "Version with dash: ${{ steps.stable-version.outputs.latest-version-with-dash }}"
|
||||
|
||||
# 示例2:只匹配特定模式的版本
|
||||
specific-pattern-match:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get version matching specific pattern
|
||||
id: pattern-version
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: 'v'
|
||||
use-latest-version: 'true'
|
||||
tag-match: 'v[0-9]*.[0-9]*.[0-9]*' # 只匹配标准的语义版本格式
|
||||
|
||||
- name: Display pattern matched version
|
||||
run: |
|
||||
echo "Pattern matched version: ${{ steps.pattern-version.outputs.latest-version }}"
|
||||
|
||||
# 示例3:复杂过滤 - 匹配主版本号并排除预发布
|
||||
complex-filtering:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get v2.x versions excluding pre-releases
|
||||
id: v2-stable
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: 'v'
|
||||
use-latest-version: 'true'
|
||||
tag-match: 'v2.*.*' # 只匹配 v2.x.x 版本
|
||||
tag-exclude: '*-*' # 排除所有包含连字符的版本(预发布版本)
|
||||
|
||||
- name: Display filtered version
|
||||
run: |
|
||||
echo "Latest v2.x stable version: ${{ steps.v2-stable.outputs.latest-version }}"
|
||||
|
||||
# 示例4:获取预发布版本
|
||||
prerelease-versions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get latest beta version
|
||||
id: beta-version
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: 'v'
|
||||
use-latest-version: 'true'
|
||||
tag-match: '*-beta*' # 只匹配包含 beta 的版本
|
||||
|
||||
- name: Display beta version
|
||||
run: |
|
||||
echo "Latest beta version: ${{ steps.beta-version.outputs.latest-version }}"
|
||||
|
||||
# 示例5:多条件排除
|
||||
multi-exclude:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get version excluding multiple patterns
|
||||
id: multi-exclude
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: 'v'
|
||||
use-latest-version: 'true'
|
||||
# 注意:多个排除模式需要在 shell 脚本中处理,这里展示单个模式
|
||||
tag-exclude: '*-alpha*' # 排除 alpha 版本
|
||||
|
||||
- name: Display filtered version
|
||||
run: |
|
||||
echo "Version (excluding alpha): ${{ steps.multi-exclude.outputs.latest-version }}"
|
||||
|
||||
# 示例6:在版本触发时的行为
|
||||
version-trigger-behavior:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref_type == 'tag'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Process version trigger
|
||||
id: version-trigger
|
||||
uses: ./trigger-version
|
||||
with:
|
||||
version-prefix: 'v'
|
||||
# 注意:当通过标签触发时,tag-match 和 tag-exclude 主要影响 latest-version 的获取
|
||||
# 而不影响当前触发的版本
|
||||
tag-exclude: '*-alpha*'
|
||||
|
||||
- name: Display trigger info
|
||||
run: |
|
||||
echo "Triggered by tag: ${{ steps.version-trigger.outputs.trigger-version }}"
|
||||
echo "Latest stable version: ${{ steps.version-trigger.outputs.latest-version }}"
|
||||
echo "Is version trigger: ${{ steps.version-trigger.outputs.is-version-trigger }}"
|
Reference in New Issue
Block a user