fscan/.github/workflows/test-build.yml
2025-07-17 21:23:29 +08:00

457 lines
20 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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

name: 测试构建
on:
push:
branches:
- dev
- develop
- feature/*
pull_request:
branches:
- main
- master
- dev
workflow_dispatch:
inputs:
branch:
description: '测试分支'
required: false
default: 'dev'
skip_tests:
description: '跳过测试'
type: boolean
default: false
enable_benchmark:
description: '启用性能测试'
type: boolean
default: false
permissions:
contents: read
jobs:
test-build:
name: 测试构建
runs-on: ubuntu-latest
timeout-minutes: 45
# 设置作业级别的环境变量
env:
GITHUB_OWNER: ${{ github.repository_owner }}
GITHUB_REPO: ${{ github.event.repository.name }}
PROJECT_NAME: ${{ github.event.repository.name }}
BUILD_START_TIME: ${{ github.run_number }}
steps:
- name: 📥 检出代码
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.inputs.branch || github.ref }}
- name: 🔍 获取项目信息
id: project
run: |
echo "owner=${GITHUB_REPOSITORY_OWNER}" >> $GITHUB_OUTPUT
echo "repo=${GITHUB_REPOSITORY#*/}" >> $GITHUB_OUTPUT
echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
echo "short_sha=${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT
echo "full_sha=${GITHUB_SHA}" >> $GITHUB_OUTPUT
echo "build_number=${GITHUB_RUN_NUMBER}" >> $GITHUB_OUTPUT
echo "build_start=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_OUTPUT
# 获取Git提交信息
echo "commit_message=$(git log -1 --pretty=format:'%s')" >> $GITHUB_OUTPUT
echo "commit_author=$(git log -1 --pretty=format:'%an')" >> $GITHUB_OUTPUT
echo "commit_date=$(git log -1 --pretty=format:'%ci')" >> $GITHUB_OUTPUT
- name: 🐹 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.21'
cache: true
- name: 📦 下载依赖
run: |
echo "build_deps_start=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
go mod download
go mod verify
echo "build_deps_end=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
- name: 🗜️ 安装 UPX 压缩工具
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
- name: 🔧 安装额外工具
run: |
# 安装用于生成更详细报告的工具
go install github.com/securecodewarrior/gosec/v2/cmd/gosec@latest
go install honnef.co/go/tools/cmd/staticcheck@latest
- name: 显示构建环境信息
run: |
echo "Go 版本: $(go version)"
echo "UPX 版本: $(upx --version)"
echo "分支: ${{ steps.project.outputs.branch }}"
echo "提交: ${{ steps.project.outputs.short_sha }}"
echo "仓库: ${{ steps.project.outputs.owner }}/${{ steps.project.outputs.repo }}"
echo "环境变量:"
echo "- GITHUB_OWNER: $GITHUB_OWNER"
echo "- GITHUB_REPO: $GITHUB_REPO"
echo "- PROJECT_NAME: $PROJECT_NAME"
- name: 🧪 运行测试
if: ${{ !inputs.skip_tests }}
run: |
echo "test_start=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
# 运行测试并生成覆盖率报告
go test -v -coverprofile=coverage.out -covermode=atomic ./... > test_results.txt 2>&1
# 生成覆盖率HTML报告
go tool cover -html=coverage.out -o coverage.html
# 获取覆盖率百分比
coverage_percent=$(go tool cover -func=coverage.out | grep total | awk '{print $3}')
echo "test_coverage=$coverage_percent" >> $GITHUB_ENV
echo "test_end=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
- name: 🏃 运行性能测试
if: ${{ inputs.enable_benchmark }}
run: |
echo "benchmark_start=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
go test -bench=. -benchmem ./... > benchmark_results.txt 2>&1
echo "benchmark_end=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
- name: 🔒 安全扫描
run: |
echo "security_start=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
gosec -fmt json -out gosec_results.json ./... || true
staticcheck ./... > staticcheck_results.txt 2>&1 || true
echo "security_end=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
- name: 📊 依赖分析
run: |
# 分析依赖信息
go list -m all > dependencies.txt
go mod why -m all > dependency_why.txt 2>&1 || true
# 统计依赖数量
dep_count=$(go list -m all | wc -l)
echo "dependency_count=$dep_count" >> $GITHUB_ENV
- name: 🔍 验证 GoReleaser 配置
run: |
echo "config_check_start=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
goreleaser check -f .github/conf/.goreleaser.yml
echo "config_check_end=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
- name: 🚀 测试构建 (Snapshot 模式)
uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser
version: latest
args: release --snapshot --clean -f .github/conf/.goreleaser.yml
workdir: .
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: 📋 上传测试产物
uses: actions/upload-artifact@v4
with:
name: 测试构建-${{ steps.project.outputs.branch }}-${{ steps.project.outputs.short_sha }}
path: |
dist/
coverage.html
test_results.txt
benchmark_results.txt
gosec_results.json
staticcheck_results.txt
dependencies.txt
retention-days: 7
- name: 🧪 测试生成的二进制文件
run: |
echo "binary_test_start=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
# 创建测试结果文件
mkdir -p test_reports
echo "## 🧪 二进制文件测试结果" > test_reports/binary_test.md
echo "" >> test_reports/binary_test.md
tested_count=0
passed_count=0
for binary in dist/*; do
if [[ -f "$binary" && -x "$binary" ]]; then
tested_count=$((tested_count + 1))
echo "### 测试文件: $(basename "$binary")" >> test_reports/binary_test.md
# 获取文件信息
file_info=$(file "$binary")
file_size=$(stat -c%s "$binary" | numfmt --to=iec)
echo "- **文件路径**: $binary" >> test_reports/binary_test.md
echo "- **文件大小**: $file_size" >> test_reports/binary_test.md
echo "- **文件类型**: $file_info" >> test_reports/binary_test.md
# 计算SHA256
sha256_hash=$(sha256sum "$binary" | cut -d' ' -f1)
echo "- **SHA256**: $sha256_hash" >> test_reports/binary_test.md
# 测试运行
if timeout 10s "$binary" --help > /dev/null 2>&1; then
echo "- **运行测试**: ✅ 通过" >> test_reports/binary_test.md
passed_count=$((passed_count + 1))
else
echo "- **运行测试**: ❌ 失败" >> test_reports/binary_test.md
fi
# 测试版本信息
if timeout 5s "$binary" --version > version_output.txt 2>&1; then
version_info=$(cat version_output.txt)
echo "- **版本信息**: $version_info" >> test_reports/binary_test.md
else
echo "- **版本信息**: 无法获取" >> test_reports/binary_test.md
fi
echo "" >> test_reports/binary_test.md
fi
done
echo "binary_tested_count=$tested_count" >> $GITHUB_ENV
echo "binary_passed_count=$passed_count" >> $GITHUB_ENV
echo "binary_test_end=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
- name: 📊 生成详细测试报告
if: always()
run: |
echo "report_start=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
# 计算构建时间
build_end=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# 创建详细报告
echo "# 🎯 详细测试构建报告" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 基本信息部分
echo "## 📋 基本信息" >> $GITHUB_STEP_SUMMARY
echo "| 项目 | 值 |" >> $GITHUB_STEP_SUMMARY
echo "|------|-----|" >> $GITHUB_STEP_SUMMARY
echo "| **仓库** | ${{ steps.project.outputs.owner }}/${{ steps.project.outputs.repo }} |" >> $GITHUB_STEP_SUMMARY
echo "| **分支** | ${{ steps.project.outputs.branch }} |" >> $GITHUB_STEP_SUMMARY
echo "| **提交** | ${{ steps.project.outputs.short_sha }} |" >> $GITHUB_STEP_SUMMARY
echo "| **构建号** | ${{ steps.project.outputs.build_number }} |" >> $GITHUB_STEP_SUMMARY
echo "| **提交消息** | ${{ steps.project.outputs.commit_message }} |" >> $GITHUB_STEP_SUMMARY
echo "| **提交作者** | ${{ steps.project.outputs.commit_author }} |" >> $GITHUB_STEP_SUMMARY
echo "| **构建时间** | $build_end |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 构建状态部分
echo "## 📈 构建状态" >> $GITHUB_STEP_SUMMARY
# 检查各个步骤的状态
if [ "${{ job.status }}" == "success" ]; then
echo "🟢 **总体状态**: 成功" >> $GITHUB_STEP_SUMMARY
elif [ "${{ job.status }}" == "failure" ]; then
echo "🔴 **总体状态**: 失败" >> $GITHUB_STEP_SUMMARY
else
echo "🟡 **总体状态**: 进行中" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
# 测试结果部分
if [ "${{ !inputs.skip_tests }}" == "true" ]; then
echo "## 🧪 测试结果" >> $GITHUB_STEP_SUMMARY
if [ -f "test_results.txt" ]; then
# 统计测试结果
total_tests=$(grep -c "=== RUN" test_results.txt || echo "0")
passed_tests=$(grep -c "--- PASS:" test_results.txt || echo "0")
failed_tests=$(grep -c "--- FAIL:" test_results.txt || echo "0")
echo "| 指标 | 值 |" >> $GITHUB_STEP_SUMMARY
echo "|------|-----|" >> $GITHUB_STEP_SUMMARY
echo "| **总测试数** | $total_tests |" >> $GITHUB_STEP_SUMMARY
echo "| **通过** | $passed_tests |" >> $GITHUB_STEP_SUMMARY
echo "| **失败** | $failed_tests |" >> $GITHUB_STEP_SUMMARY
echo "| **覆盖率** | ${test_coverage:-N/A} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 如果有失败的测试,显示详情
if [ "$failed_tests" -gt 0 ]; then
echo "### ❌ 失败的测试" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
grep -A 5 "--- FAIL:" test_results.txt | head -20 >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
fi
fi
else
echo "## 🧪 测试结果" >> $GITHUB_STEP_SUMMARY
echo "⏭️ **测试已跳过**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
# 性能测试结果
if [ "${{ inputs.enable_benchmark }}" == "true" ] && [ -f "benchmark_results.txt" ]; then
echo "## 🏃 性能测试结果" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
grep "Benchmark" benchmark_results.txt | head -10 >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
# 安全扫描结果
echo "## 🔒 安全扫描结果" >> $GITHUB_STEP_SUMMARY
# GoSec结果
if [ -f "gosec_results.json" ]; then
issues_count=$(jq '.Issues | length' gosec_results.json 2>/dev/null || echo "0")
echo "- **GoSec扫描**: $issues_count 个问题发现" >> $GITHUB_STEP_SUMMARY
fi
# StaticCheck结果
if [ -f "staticcheck_results.txt" ]; then
staticcheck_issues=$(wc -l < staticcheck_results.txt || echo "0")
echo "- **StaticCheck扫描**: $staticcheck_issues 个问题发现" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
# 依赖信息
echo "## 📦 依赖信息" >> $GITHUB_STEP_SUMMARY
echo "- **依赖总数**: ${dependency_count:-N/A}" >> $GITHUB_STEP_SUMMARY
echo "- **Go版本**: $(go version | cut -d' ' -f3)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 二进制文件测试结果
echo "## 🧪 二进制文件测试" >> $GITHUB_STEP_SUMMARY
echo "- **测试文件数**: ${binary_tested_count:-0}" >> $GITHUB_STEP_SUMMARY
echo "- **通过数**: ${binary_passed_count:-0}" >> $GITHUB_STEP_SUMMARY
if [ "${binary_tested_count:-0}" -gt 0 ]; then
success_rate=$((binary_passed_count * 100 / binary_tested_count))
echo "- **成功率**: ${success_rate}%" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
# 构建产物统计
if [ -d "dist" ]; then
echo "## 📦 构建产物统计" >> $GITHUB_STEP_SUMMARY
# 文件数量统计
total_files=$(find dist -type f | wc -l)
echo "- **总文件数**: $total_files" >> $GITHUB_STEP_SUMMARY
# 总大小统计
total_size=$(du -sh dist/ | cut -f1)
echo "- **总大小**: $total_size" >> $GITHUB_STEP_SUMMARY
# 按类型分类
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📊 文件类型分布" >> $GITHUB_STEP_SUMMARY
echo "| 类型 | 数量 | 大小 |" >> $GITHUB_STEP_SUMMARY
echo "|------|------|------|" >> $GITHUB_STEP_SUMMARY
# 统计不同类型的文件
for ext in "tar.gz" "zip" "deb" "rpm" "apk" ""; do
if [ -z "$ext" ]; then
# 统计无扩展名的文件(通常是二进制文件)
count=$(find dist -type f -executable | wc -l)
size=$(find dist -type f -executable -exec du -ch {} + 2>/dev/null | tail -1 | cut -f1 || echo "0")
[ "$count" -gt 0 ] && echo "| 二进制文件 | $count | $size |" >> $GITHUB_STEP_SUMMARY
else
count=$(find dist -name "*.$ext" | wc -l)
if [ "$count" -gt 0 ]; then
size=$(find dist -name "*.$ext" -exec du -ch {} + 2>/dev/null | tail -1 | cut -f1 || echo "0")
echo "| .$ext | $count | $size |" >> $GITHUB_STEP_SUMMARY
fi
fi
done
echo "" >> $GITHUB_STEP_SUMMARY
# 最大文件Top 5
echo "### 📏 最大文件 Top 5" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
find dist -type f -exec du -h {} + | sort -rh | head -5 >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 架构分布
echo "### 🏗️ 架构分布" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
find dist -type f -name "*" | grep -E "(amd64|arm64|386|arm)" | cut -d'_' -f2- | cut -d'.' -f1 | sort | uniq -c | sort -nr >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
fi
# 构建时间分析
echo "## ⏱️ 构建时间分析" >> $GITHUB_STEP_SUMMARY
echo "| 阶段 | 开始时间 | 结束时间 |" >> $GITHUB_STEP_SUMMARY
echo "|------|----------|----------|" >> $GITHUB_STEP_SUMMARY
echo "| **依赖下载** | ${build_deps_start:-N/A} | ${build_deps_end:-N/A} |" >> $GITHUB_STEP_SUMMARY
echo "| **测试执行** | ${test_start:-N/A} | ${test_end:-N/A} |" >> $GITHUB_STEP_SUMMARY
echo "| **安全扫描** | ${security_start:-N/A} | ${security_end:-N/A} |" >> $GITHUB_STEP_SUMMARY
echo "| **二进制测试** | ${binary_test_start:-N/A} | ${binary_test_end:-N/A} |" >> $GITHUB_STEP_SUMMARY
echo "| **报告生成** | ${report_start:-N/A} | $build_end |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 环境信息
echo "## 🔧 环境信息" >> $GITHUB_STEP_SUMMARY
echo "- **Runner OS**: $(uname -s)" >> $GITHUB_STEP_SUMMARY
echo "- **Runner Architecture**: $(uname -m)" >> $GITHUB_STEP_SUMMARY
echo "- **Go Version**: $(go version)" >> $GITHUB_STEP_SUMMARY
echo "- **UPX Version**: $(upx --version 2>/dev/null | head -1 || echo 'N/A')" >> $GITHUB_STEP_SUMMARY
echo "- **GoReleaser Version**: $(goreleaser --version 2>/dev/null | head -1 || echo 'N/A')" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 添加二进制文件详细测试结果
if [ -f "test_reports/binary_test.md" ]; then
echo "## 🔍 二进制文件详细测试" >> $GITHUB_STEP_SUMMARY
echo "<details><summary>点击查看详细测试结果</summary>" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
cat test_reports/binary_test.md >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "</details>" >> $GITHUB_STEP_SUMMARY
fi
# 构建建议
echo "## 💡 构建建议" >> $GITHUB_STEP_SUMMARY
# 根据测试结果给出建议
if [ "${test_coverage%.*}" -lt 80 ] 2>/dev/null; then
echo "⚠️ 建议提高测试覆盖率到80%以上" >> $GITHUB_STEP_SUMMARY
fi
if [ "${binary_passed_count:-0}" -lt "${binary_tested_count:-0}" ]; then
echo "⚠️ 部分二进制文件测试失败,请检查构建配置" >> $GITHUB_STEP_SUMMARY
fi
if [ "${dependency_count:-0}" -gt 50 ]; then
echo "💡 依赖较多,建议定期审查和清理不必要的依赖" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "📊 报告生成时间: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_STEP_SUMMARY
echo "🔗 构建URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY
- name: 📎 上传详细报告
if: always()
uses: actions/upload-artifact@v4
with:
name: 详细测试报告-${{ steps.project.outputs.branch }}-${{ steps.project.outputs.short_sha }}
path: |
test_reports/
coverage.html
test_results.txt
benchmark_results.txt
gosec_results.json
staticcheck_results.txt
dependencies.txt
dependency_why.txt
retention-days: 14