Compare commits

...

26 Commits

Author SHA1 Message Date
Lyda
ca7e4be804 refactor: 合并多个校验选项为单一的enable-validation开关 2025-10-11 18:56:51 +08:00
Lyda
a26f91ab25 refactor: 将多个环境校验开关合并为单一的enable-validation配置项 2025-10-11 18:55:22 +08:00
Lyda
55e66894bd feat: 添加跳过pnpm-setup选项以支持自定义pnpm安装 2025-10-11 18:42:28 +08:00
Lyda
4473ed9c52 fix: 优化 kubectl 版本检测以支持新旧版本格式 2025-10-11 18:38:07 +08:00
Lyda
425b35a08a fix: 在 GitHub Action 中显式指定 bash 执行脚本 2025-10-11 18:36:06 +08:00
Lyda
5c74c75f48 feat: 添加Docker私有仓库登录支持及相关配置参数 2025-10-11 18:29:10 +08:00
Lyda
f618608667 feat: 新增配置构建环境的 GitHub Action,支持 Git 和 kubectl 配置验证 2025-10-11 18:21:10 +08:00
Lyda
2fe7c6809c feat: 添加.pnpm-store目录状态和Git跟踪诊断功能 2025-09-18 18:35:14 +08:00
Lyda
06298f9e15 fix: 增强 pnpm store 路径配置以防止相对路径解析问题 2025-09-18 18:33:56 +08:00
Lyda
d35b42c064 feat: 增加清理项目根 .pnpm-store 残留的选项并优化 store 目录配置 2025-09-18 18:22:54 +08:00
Lyda
af648e65f2 fix: 将 pnpm store 路径固定到临时目录以避免在项目根创建缓存 2025-09-18 18:06:08 +08:00
Lyda
c3e927c596 chore: 移除 pnpm 二进制的缓存步骤,简化工作流程 2025-09-18 11:59:41 +08:00
Lyda
9e3ffa7ea2 feat: 为pnpm添加自动离线安装优化参数以提升缓存命中时的安装性能 2025-09-18 11:51:30 +08:00
Lyda
64403850ee refactor: 优化pnpm安装流程并合并重复的pnpm设置步骤 2025-09-18 11:43:21 +08:00
Lyda
86d6bb988f fix: 移除重复和无效的 Corepack 缓存路径配置 2025-09-18 11:12:32 +08:00
Lyda
7366d46959 feat: 添加pnpm二进制缓存以优化封闭网络环境下的安装性能 2025-09-18 11:11:44 +08:00
Lyda
8a16a8bec5 chore: 将默认包管理器从 npm 改为 pnpm 2025-09-18 10:49:01 +08:00
Lyda
5c47db3ee2 feat: 添加pnpm自动安装和store缓存模式支持 2025-09-18 10:46:31 +08:00
Lyda
6fff7a90e1 feat(trigger-version): 添加标签过滤功能支持通配符匹配和排除
新增 `tag-match` 和 `tag-exclude` 输入参数,支持通过通配符模式匹配和排除特定标签
更新 README 文档并添加示例配置文件展示标签过滤功能的使用场景
2025-08-22 13:22:31 +08:00
Lyda
b53d899f41 feat: 注释掉获取标签的输出信息,以减少日志噪声并提高可读性 2025-08-21 19:32:11 +08:00
Lyda
1949a48d96 fix: 规范化示例文件和文档中的格式,优化参数描述,提升可读性 2025-08-21 18:19:02 +08:00
Lyda
d17dea4ca0 feat: 添加最新版本获取功能,更新文档示例以展示如何使用最新版本进行部署 2025-08-21 18:18:15 +08:00
Lyda
ee024ce50d feat: 注释掉获取标签的输出信息,以减少日志噪声并提高可读性 2025-08-21 15:02:11 +08:00
Lyda
77dcc1bed2 feat: 更新 action.yml 文件,统一引号格式,增强 Git 标签获取逻辑,确保在 GitHub Actions 中正确处理标签信息 2025-08-21 14:58:56 +08:00
Lyda
1299feac14 feat: 注释掉 test-cache-state.yml 中的过期测试部分,以便于后续功能调整和优化,保持代码整洁性。 2025-08-21 13:36:42 +08:00
Lyda
210d257b44 fix: 更新 cache-state 示例文件,修正 GitHub Action 使用路径,从 .actions/xgj/cache-state@v1 修改为 actions/xgj/cache-state@v1,以确保正确引用和执行缓存状态管理功能。 2025-08-21 13:17:19 +08:00
19 changed files with 1494 additions and 323 deletions

View File

@@ -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:

View File

@@ -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 }}

View File

@@ -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'

View File

@@ -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'

View File

@@ -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 }}'

View File

@@ -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: ''

82
config-env/README.md Normal file
View File

@@ -0,0 +1,82 @@
# Configure Build Environment Action
该 GitHub Action 用于在已有环境中执行验证与配置操作,确保必要工具可用并完成 Git 与 kubectl 配置,适用于已预装所有依赖的构建机场景。
## 🚦 能力概览
- ✅ 配置 Git 用户信息
- 🔍 校验 `docker``kubectl` 可用性及版本
- ☸️ 可选写入 Base64 编码的 kubeconfig并验证集群连通性
- 🐳 可选登录私有 Docker 仓库
- ⚠️ **不进行任何软件安装**,适用于受控环境
## 📥 输入参数
| 参数名 | 描述 | 必填 | 默认值 |
| --- | --- | --- | --- |
| `git-user-name` | Git 用户名 | ❌ | `GiteaActions` |
| `git-user-email` | Git 用户邮箱 | ❌ | `actions@gitea.com` |
| `kube-config` | Base64 编码的 kubeconfig | ❌ | `''` |
| `enable-validation` | 是否执行环境校验 (`true`/`false`) | ❌ | `true` |
| `docker-registry` | Docker 私有仓库地址 | ❌ | `docker-registry.bjxgj.com` |
| `docker-username` | Docker 仓库用户名 | ❌ | `ci-action` |
| `docker-password` | Docker 仓库密码(当未跳过登录时必填) | ❌ | `''` |
| `skip-docker-login` | 是否跳过 Docker 登录 (`true`/`false`) | ❌ | `false` |
## 📤 输出参数
| 参数名 | 描述 |
| --- | --- |
| `docker-version` | 检测到的 Docker 版本或状态 |
| `kubectl-version` | 检测到的 kubectl 版本或状态 |
| `kubectl-context` | 集群验证成功时的当前 context |
## 🚀 基本用法
```yaml
- name: 校验并配置环境
uses: actions/xgj/config-env@v1
with:
git-user-name: "CI Bot"
git-user-email: "ci@example.com"
kube-config: ${{ secrets.KUBE_CONFIG }}
docker-password: ${{ secrets.DOCKER_PASSWORD }}
```
## 🎯 自定义校验
禁用所有校验,仅进行 Git 配置(若提供)及 kubeconfig 写入:
```yaml
- name: 跳过环境校验
uses: actions/xgj/config-env@v1
with:
enable-validation: "false"
```
## 🚀 Docker 登录配置
```yaml
- name: 验证 kubectl 集群
uses: actions/xgj/config-env@v1
with:
enable-validation: "true"
kube-config: ${{ secrets.KUBE_CONFIG }}
docker-registry: "registry.example.com"
docker-username: "ci-bot"
docker-password: ${{ secrets.DOCKER_PASSWORD }}
```
## 🔒 注意事项
- 请确保运行环境已安装 `docker``kubectl`(若开启对应校验)。
- kubeconfig 建议通过 GitHub Secrets 以 Base64 编码方式提供。
- Action 执行失败会立即终止后续步骤,便于快速发现环境问题。
## 🧪 示例工作流
详见 `examples/basic-usage.yml`,展示了与 CI 构建流程结合的典型用法。
## 🤝 贡献
欢迎提 Issue 或提交 PR

102
config-env/action.yml Normal file
View File

@@ -0,0 +1,102 @@
name: 'Configure Build Environment'
description: '验证已有环境并配置 Git 与 kubectl不执行软件安装'
author: 'Your Organization'
branding:
icon: 'settings'
color: 'green'
inputs:
git-user-name:
description: 'Git 用户名'
required: false
default: 'GiteaActions'
git-user-email:
description: 'Git 用户邮箱'
required: false
default: 'actions@gitea.com'
kube-config:
description: 'Base64 编码的 kubectl 配置文件'
required: false
default: ''
enable-validation:
description: '是否执行环境校验 (true/false)'
required: false
default: 'true'
docker-registry:
description: 'Docker 私有仓库地址'
required: false
default: 'docker-registry.bjxgj.com'
docker-username:
description: 'Docker 仓库用户名'
required: false
default: 'ci-action'
docker-password:
description: 'Docker 仓库密码(开启登录时必填)'
required: false
default: ''
skip-docker-login:
description: '是否跳过 Docker 登录 (true/false)'
required: false
default: 'false'
outputs:
docker-version:
description: '检测到的 Docker 版本'
value: ${{ steps.validate-tools.outputs.docker-version }}
kubectl-version:
description: '检测到的 kubectl 版本'
value: ${{ steps.validate-tools.outputs.kubectl-version }}
kubectl-context:
description: '验证通过时的当前 kubectl 上下文'
value: ${{ steps.verify-kubectl.outputs.current-context }}
runs:
using: 'composite'
steps:
- name: 配置 Git
shell: bash
run: bash ${{ github.action_path }}/scripts/configure-git.sh
env:
GIT_USER_NAME: ${{ inputs.git-user-name }}
GIT_USER_EMAIL: ${{ inputs.git-user-email }}
- name: 校验工具可用性
id: validate-tools
shell: bash
run: bash ${{ github.action_path }}/scripts/validate-tools.sh
env:
ENABLE_VALIDATION: ${{ inputs.enable-validation }}
- name: 配置 kubectl
if: ${{ inputs.kube-config != '' }}
shell: bash
run: bash ${{ github.action_path }}/scripts/configure-kubectl.sh
env:
KUBE_CONFIG_BASE64: ${{ inputs.kube-config }}
- name: 验证 kubectl 连通性
id: verify-kubectl
if: ${{ inputs.kube-config != '' && inputs.enable-validation != 'false' }}
shell: bash
run: bash ${{ github.action_path }}/scripts/verify-kubectl.sh
- name: 登录私有 Docker 仓库
if: ${{ inputs.skip-docker-login != 'true' }}
uses: docker/login-action@v3
with:
registry: ${{ inputs.docker-registry }}
username: ${{ inputs.docker-username }}
password: ${{ inputs.docker-password }}
- name: 环境校验完成
shell: bash
run: |
echo '🎉 环境校验与配置步骤完成'
if [[ "${{ inputs.enable-validation }}" != 'false' ]]; then
echo " - Docker: ${{ steps.validate-tools.outputs.docker-version }}"
echo " - kubectl: ${{ steps.validate-tools.outputs.kubectl-version }}"
fi
if [[ "${{ inputs.kube-config }}" != '' && "${{ inputs.enable-validation }}" != 'false' ]]; then
echo " - 当前上下文: ${{ steps.verify-kubectl.outputs.current-context }}"
fi

View File

@@ -0,0 +1,29 @@
name: Config Env Example
on:
push:
branches:
- main
jobs:
validate-environment:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 校验环境并配置 Git
id: config-env
uses: actions/xgj/config-env@v1
with:
git-user-name: "CI Bot"
git-user-email: "ci@example.com"
require-docker: "true"
require-kubectl: "true"
verify-kubectl-cluster: "true"
kube-config: ${{ secrets.KUBE_CONFIG }}
- name: 输出工具信息
run: |
echo "Docker 版本: ${{ steps.config-env.outputs.docker-version }}"
echo "kubectl 版本: ${{ steps.config-env.outputs.kubectl-version }}"
echo "kubectl 上下文: ${{ steps.config-env.outputs.kubectl-context }}"

View File

@@ -0,0 +1,59 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() {
echo -e "${BLUE} $1${NC}"
}
log_success() {
echo -e "${GREEN}$1${NC}"
}
log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
log_error() {
echo -e "${RED}$1${NC}"
}
main() {
if ! command -v git >/dev/null 2>&1; then
log_error "未检测到 git 命令"
exit 1
else
log_info "已检测到 git: $(git --version)"
fi
local name="${GIT_USER_NAME:-}"
local email="${GIT_USER_EMAIL:-}"
if [[ -z "$name" && -z "$email" ]]; then
log_warning "未提供 Git 用户名和邮箱,跳过配置"
return 0
fi
if [[ -n "$name" ]]; then
git config --global user.name "$name"
log_success "已配置 Git 用户名: $name"
else
log_warning "未提供 Git 用户名"
fi
if [[ -n "$email" ]]; then
git config --global user.email "$email"
log_success "已配置 Git 邮箱: $email"
else
log_warning "未提供 Git 邮箱"
fi
}
trap 'log_error "Git 配置失败,退出码: $?"' ERR
main "$@"

View File

@@ -0,0 +1,65 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() {
echo -e "${BLUE} $1${NC}"
}
log_success() {
echo -e "${GREEN}$1${NC}"
}
log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
log_error() {
echo -e "${RED}$1${NC}"
}
ensure_kubectl_available() {
if ! command -v kubectl >/dev/null 2>&1; then
log_error "kubectl 未安装或不可用"
exit 1
fi
log_info "kubectl 版本: $(kubectl version --client --short 2>/dev/null || kubectl version --client)"
}
write_kube_config() {
local encoded="${KUBE_CONFIG_BASE64:-}"
if [[ -z "$encoded" ]]; then
log_error "KUBE_CONFIG_BASE64 环境变量为空"
exit 1
fi
mkdir -p "$HOME/.kube"
local config_path="$HOME/.kube/config"
echo "$encoded" | base64 -d > "$config_path"
chmod 600 "$config_path"
log_success "已写入 kubectl 配置: $config_path"
}
validate_kube_config() {
if ! kubectl config view --minify >/dev/null 2>&1; then
log_error "kubectl 配置文件无效或权限不足"
exit 1
fi
log_success "kubectl 配置文件格式验证通过"
}
trap 'log_error "kubectl 配置失败,退出码: $?"' ERR
main() {
ensure_kubectl_available
write_kube_config
validate_kube_config
}
main "$@"

View File

@@ -0,0 +1,76 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() {
echo -e "${BLUE} $1${NC}"
}
log_success() {
echo -e "${GREEN}$1${NC}"
}
log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
log_error() {
echo -e "${RED}$1${NC}"
}
validate_binary() {
local name="$1"
local required="$2"
local version_cmd="$3"
local output_var="$4"
local version_output=""
if command -v "$name" >/dev/null 2>&1; then
if [[ "$name" == "kubectl" ]]; then
if version_output=$(kubectl version --client --short 2>/dev/null | head -n 1); then
:
else
version_output=$(kubectl version --client 2>/dev/null | head -n 1)
fi
else
version_output=$(bash -c "$version_cmd")
fi
log_success "检测到 $name: $version_output"
printf '%s=%s\n' "$output_var" "$version_output" >> "$GITHUB_OUTPUT"
return 0
fi
if [[ "$required" == "true" ]]; then
log_error "未检测到必需的命令: $name"
exit 1
else
log_warning "未检测到可选命令: $name"
printf '%s=%s\n' "$output_var" "not-found" >> "$GITHUB_OUTPUT"
fi
}
main() {
: "${GITHUB_OUTPUT:?GITHUB_OUTPUT 未设置}" >/dev/null
local enable_validation="${ENABLE_VALIDATION:-true}"
if [[ "$enable_validation" != "true" ]]; then
log_info "已通过统一开关禁用环境校验"
printf 'docker-version=%s\n' "skipped" >> "$GITHUB_OUTPUT"
printf 'kubectl-version=%s\n' "skipped" >> "$GITHUB_OUTPUT"
return 0
fi
validate_binary "docker" "true" "docker --version" "docker-version"
validate_binary "kubectl" "true" "kubectl version --client --short 2>/dev/null || kubectl version --client" "kubectl-version"
}
trap 'log_error "工具校验失败,退出码: $?"' ERR
main "$@"

View File

@@ -0,0 +1,60 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() {
echo -e "${BLUE} $1${NC}"
}
log_success() {
echo -e "${GREEN}$1${NC}"
}
log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
log_error() {
echo -e "${RED}$1${NC}"
}
: "${GITHUB_OUTPUT:?GITHUB_OUTPUT 未设置}" >/dev/null
verify_cluster() {
local timeout=30
if timeout "$timeout" kubectl cluster-info >/dev/null 2>&1; then
log_success "kubectl 集群连接验证通过"
log_info "集群信息:"
kubectl cluster-info
log_info "尝试获取节点信息"
if kubectl get nodes >/dev/null 2>&1; then
kubectl get nodes
else
log_warning "无法获取节点信息(可能权限不足)"
fi
local current_context
current_context=$(kubectl config current-context 2>/dev/null || echo "unknown")
log_info "当前上下文: $current_context"
printf 'current-context=%s\n' "$current_context" >> "$GITHUB_OUTPUT"
else
log_error "kubectl 集群连接验证失败"
kubectl cluster-info || true
exit 1
fi
}
trap 'log_error "kubectl 验证失败,退出码: $?"' ERR
main() {
verify_cluster
}
main "$@"

View File

@@ -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`
### 安装失败

View File

@@ -8,9 +8,28 @@ inputs:
package-manager:
description: '包管理器类型 (npm, pnpm, yarn)'
required: false
default: 'npm'
default: 'pnpm'
pnpm-version:
description: 'pnpm 版本(当 package-manager=pnpm 时生效)'
required: false
default: '10'
skip-pnpm-setup:
description: '当 package-manager=pnpm 时是否跳过 pnpm/action-setup (true/false)'
required: false
default: 'false'
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 +54,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 +79,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 +113,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' && inputs.skip-pnpm-setup != 'true'
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_modulespnpm 也会使用 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 +285,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 +317,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

View File

@@ -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'`

View File

@@ -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"

View 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 以获取完整历史"

View 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 }}"