mirror of
https://github.com/rustfs/console.git
synced 2026-08-30 17:14:47 +08:00
522 lines
21 KiB
YAML
522 lines
21 KiB
YAML
name: 📦 Dependencies Management
|
|
|
|
on:
|
|
schedule:
|
|
# 每周一凌晨 2 点检查依赖更新
|
|
- cron: "0 2 * * 1"
|
|
workflow_dispatch:
|
|
inputs:
|
|
update_type:
|
|
description: "Type of update to perform"
|
|
required: true
|
|
default: "patch"
|
|
type: choice
|
|
options:
|
|
- patch
|
|
- minor
|
|
- major
|
|
- all
|
|
|
|
jobs:
|
|
# ============================================================================
|
|
# 依赖安全扫描
|
|
# ============================================================================
|
|
security-audit:
|
|
name: 🔒 Security Audit
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: 📥 Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Detect package manager
|
|
id: detect-package-manager
|
|
run: |
|
|
if [ -f "${{ github.workspace }}/pnpm-lock.yaml" ]; then
|
|
echo "manager=pnpm" >> $GITHUB_OUTPUT
|
|
echo "command=install --frozen-lockfile" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
elif [ -f "${{ github.workspace }}/yarn.lock" ]; then
|
|
echo "manager=yarn" >> $GITHUB_OUTPUT
|
|
echo "command=install" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
elif [ -f "${{ github.workspace }}/package-lock.json" ]; then
|
|
echo "manager=npm" >> $GITHUB_OUTPUT
|
|
echo "command=ci" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
else
|
|
echo "Unable to determine package manager"
|
|
exit 1
|
|
fi
|
|
- name: Setup pnpm
|
|
if: steps.detect-package-manager.outputs.manager == 'pnpm'
|
|
uses: pnpm/action-setup@v6
|
|
with:
|
|
version: 10.19.0
|
|
- name: 📦 Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: "22"
|
|
cache: ${{ steps.detect-package-manager.outputs.manager }}
|
|
|
|
- name: 📥 Install dependencies
|
|
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
|
|
|
|
- name: 🔒 Run security audit
|
|
run: |
|
|
echo "## 🔒 Security Audit Report" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# 运行安全审计
|
|
if ${{ steps.detect-package-manager.outputs.manager }} audit --json > audit-report.json 2>/dev/null; then
|
|
# 解析审计结果
|
|
vulnerabilities=$(node -e "
|
|
const audit = require('./audit-report.json');
|
|
const meta = audit.metadata?.vulnerabilities;
|
|
if (meta) {
|
|
const total = meta.total || 0;
|
|
const critical = meta.critical || 0;
|
|
const high = meta.high || 0;
|
|
const moderate = meta.moderate || 0;
|
|
const low = meta.low || 0;
|
|
console.log(JSON.stringify({total, critical, high, moderate, low}));
|
|
} else {
|
|
console.log(JSON.stringify({total: 0, critical: 0, high: 0, moderate: 0, low: 0}));
|
|
}
|
|
")
|
|
|
|
echo "| Severity | Count |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Critical | $(echo $vulnerabilities | jq -r '.critical') |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| High | $(echo $vulnerabilities | jq -r '.high') |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Moderate | $(echo $vulnerabilities | jq -r '.moderate') |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Low | $(echo $vulnerabilities | jq -r '.low') |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| **Total** | **$(echo $vulnerabilities | jq -r '.total')** |" >> $GITHUB_STEP_SUMMARY
|
|
|
|
total_vulns=$(echo $vulnerabilities | jq -r '.total')
|
|
if [ "$total_vulns" -gt 0 ]; then
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "⚠️ **Action Required**: $total_vulns security vulnerabilities found!" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "Run \`${{ steps.detect-package-manager.outputs.manager }} audit fix\` to automatically fix vulnerabilities." >> $GITHUB_STEP_SUMMARY
|
|
|
|
# 如果有高危或严重漏洞,创建 issue
|
|
critical=$(echo $vulnerabilities | jq -r '.critical')
|
|
high=$(echo $vulnerabilities | jq -r '.high')
|
|
if [ "$critical" -gt 0 ] || [ "$high" -gt 0 ]; then
|
|
echo "create_security_issue=true" >> $GITHUB_ENV
|
|
echo "security_summary=Found $critical critical and $high high severity vulnerabilities" >> $GITHUB_ENV
|
|
fi
|
|
else
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "✅ No security vulnerabilities found!" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
else
|
|
echo "✅ No security vulnerabilities found!" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
- name: 📤 Upload audit report
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: security-audit-report
|
|
path: audit-report.json
|
|
retention-days: 30
|
|
|
|
- name: 🚨 Create security issue
|
|
if: env.create_security_issue == 'true'
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const title = '🔒 Security Vulnerabilities Detected'
|
|
const body = `
|
|
## 🚨 Security Alert
|
|
|
|
Our automated security scan has detected vulnerabilities in the project dependencies.
|
|
|
|
**Summary**: ${{ env.security_summary }}
|
|
|
|
## 🔧 Recommended Actions
|
|
|
|
1. Review the security audit report
|
|
2. Run \`pnpm audit fix\` to automatically fix vulnerabilities (or use the detected package manager)
|
|
3. For vulnerabilities that cannot be auto-fixed, consider:
|
|
- Updating to a secure version manually
|
|
- Finding alternative packages
|
|
- Implementing workarounds
|
|
|
|
## 📊 Full Report
|
|
|
|
See the attached audit report for detailed information about each vulnerability.
|
|
|
|
**Workflow Run**: [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
`
|
|
|
|
github.rest.issues.create({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
title: title,
|
|
body: body,
|
|
labels: ['security', 'dependencies', 'high-priority']
|
|
})
|
|
|
|
# ============================================================================
|
|
# 依赖更新检查
|
|
# ============================================================================
|
|
check-updates:
|
|
name: 📋 Check for Updates
|
|
runs-on: ubuntu-latest
|
|
needs: security-audit
|
|
|
|
outputs:
|
|
has-updates: ${{ steps.check.outputs.has-updates }}
|
|
update-summary: ${{ steps.check.outputs.update-summary }}
|
|
|
|
steps:
|
|
- name: 📥 Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Detect package manager
|
|
id: detect-package-manager
|
|
run: |
|
|
if [ -f "${{ github.workspace }}/pnpm-lock.yaml" ]; then
|
|
echo "manager=pnpm" >> $GITHUB_OUTPUT
|
|
echo "command=install --frozen-lockfile" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
elif [ -f "${{ github.workspace }}/yarn.lock" ]; then
|
|
echo "manager=yarn" >> $GITHUB_OUTPUT
|
|
echo "command=install" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
elif [ -f "${{ github.workspace }}/package-lock.json" ]; then
|
|
echo "manager=npm" >> $GITHUB_OUTPUT
|
|
echo "command=ci" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
else
|
|
echo "Unable to determine package manager"
|
|
exit 1
|
|
fi
|
|
- name: Setup pnpm
|
|
if: steps.detect-package-manager.outputs.manager == 'pnpm'
|
|
uses: pnpm/action-setup@v6
|
|
with:
|
|
version: 10.19.0
|
|
- name: 📦 Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: "22"
|
|
cache: ${{ steps.detect-package-manager.outputs.manager }}
|
|
|
|
- name: 📥 Install dependencies
|
|
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
|
|
|
|
- name: 📋 Check for outdated packages
|
|
id: check
|
|
run: |
|
|
echo "## 📋 Dependency Update Check" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# 检查过期的包
|
|
if ${{ steps.detect-package-manager.outputs.manager }} outdated --json > outdated.json 2>/dev/null; then
|
|
if [ -s outdated.json ]; then
|
|
echo "has-updates=true" >> $GITHUB_OUTPUT
|
|
|
|
# 生成更新摘要
|
|
update_count=$(node -e "
|
|
const outdated = require('./outdated.json');
|
|
console.log(Object.keys(outdated).length);
|
|
")
|
|
|
|
echo "update-summary=Found $update_count packages that can be updated" >> $GITHUB_OUTPUT
|
|
|
|
echo "### 📦 Outdated Packages ($update_count)" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Package | Current | Wanted | Latest | Type |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|---------|---------|--------|--------|------|" >> $GITHUB_STEP_SUMMARY
|
|
|
|
node -e "
|
|
const outdated = require('./outdated.json');
|
|
Object.entries(outdated).forEach(([pkg, info]) => {
|
|
const updateType = info.wanted !== info.current ? 'wanted' : 'latest';
|
|
console.log(\`| \${pkg} | \${info.current} | \${info.wanted} | \${info.latest} | \${updateType} |\`);
|
|
});
|
|
" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "🔄 Updates are available! Consider running the dependency update workflow." >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "has-updates=false" >> $GITHUB_OUTPUT
|
|
echo "update-summary=All packages are up to date" >> $GITHUB_OUTPUT
|
|
echo "✅ All packages are up to date!" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
else
|
|
echo "has-updates=false" >> $GITHUB_OUTPUT
|
|
echo "update-summary=All packages are up to date" >> $GITHUB_OUTPUT
|
|
echo "✅ All packages are up to date!" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
- name: 📤 Upload outdated report
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: outdated-packages-report
|
|
path: outdated.json
|
|
retention-days: 7
|
|
|
|
# ============================================================================
|
|
# 自动依赖更新
|
|
# ============================================================================
|
|
auto-update:
|
|
name: 🔄 Auto Update Dependencies
|
|
runs-on: ubuntu-latest
|
|
needs: [security-audit, check-updates]
|
|
if: needs.check-updates.outputs.has-updates == 'true'
|
|
|
|
steps:
|
|
- name: 📥 Checkout code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: 📦 Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: "22"
|
|
cache: "npm"
|
|
|
|
- name: 📥 Install dependencies
|
|
run: npm ci
|
|
|
|
- name: 🔄 Update dependencies
|
|
run: |
|
|
echo "## 🔄 Updating Dependencies" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
update_type="${{ github.event.inputs.update_type || 'patch' }}"
|
|
|
|
case $update_type in
|
|
"patch")
|
|
echo "Updating patch versions..." >> $GITHUB_STEP_SUMMARY
|
|
${{ steps.detect-package-manager.outputs.manager }} update
|
|
;;
|
|
"minor")
|
|
echo "Updating minor versions..." >> $GITHUB_STEP_SUMMARY
|
|
npx npm-check-updates -u --target minor
|
|
${{ steps.detect-package-manager.outputs.manager }} install
|
|
;;
|
|
"major")
|
|
echo "Updating major versions..." >> $GITHUB_STEP_SUMMARY
|
|
npx npm-check-updates -u --target major
|
|
${{ steps.detect-package-manager.outputs.manager }} install
|
|
;;
|
|
"all")
|
|
echo "Updating all versions..." >> $GITHUB_STEP_SUMMARY
|
|
npx npm-check-updates -u
|
|
${{ steps.detect-package-manager.outputs.manager }} install
|
|
;;
|
|
esac
|
|
|
|
- name: 🧪 Run tests after update
|
|
run: |
|
|
echo "## 🧪 Testing Updated Dependencies" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# 安装测试依赖
|
|
${{ steps.detect-package-manager.outputs.manager }} add -D vitest jsdom @vitest/ui c8
|
|
|
|
# 运行测试
|
|
if npx vitest run tests/utils/config-helpers*.test.ts --reporter=verbose; then
|
|
echo "✅ All tests passed with updated dependencies!" >> $GITHUB_STEP_SUMMARY
|
|
echo "test_status=passed" >> $GITHUB_ENV
|
|
else
|
|
echo "❌ Tests failed with updated dependencies!" >> $GITHUB_STEP_SUMMARY
|
|
echo "test_status=failed" >> $GITHUB_ENV
|
|
fi
|
|
|
|
- name: 🔍 Check for changes
|
|
id: changes
|
|
run: |
|
|
if [[ -n $(git status --porcelain) ]]; then
|
|
echo "changes=true" >> $GITHUB_OUTPUT
|
|
|
|
# 生成变更摘要
|
|
echo "## 📝 Changes Made" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "### Modified Files:" >> $GITHUB_STEP_SUMMARY
|
|
git status --porcelain | while read status file; do
|
|
echo "- $file" >> $GITHUB_STEP_SUMMARY
|
|
done
|
|
|
|
# 检查 package.json 的变更
|
|
if git diff --name-only | grep -q "package.json\|pnpm-lock.yaml\|package-lock.json\|yarn.lock"; then
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "### Package Changes:" >> $GITHUB_STEP_SUMMARY
|
|
echo "\`\`\`diff" >> $GITHUB_STEP_SUMMARY
|
|
git diff package.json | head -50 >> $GITHUB_STEP_SUMMARY
|
|
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
else
|
|
echo "changes=false" >> $GITHUB_OUTPUT
|
|
echo "No changes detected." >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
- name: 🔧 Create Pull Request
|
|
if: steps.changes.outputs.changes == 'true' && env.test_status == 'passed'
|
|
uses: peter-evans/create-pull-request@v5
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
commit-message: "🔄 chore: update dependencies (${{ github.event.inputs.update_type || 'patch' }})"
|
|
title: "🔄 Dependency Updates (${{ github.event.inputs.update_type || 'patch' }})"
|
|
body: |
|
|
## 🔄 Automated Dependency Update
|
|
|
|
This PR contains automated dependency updates.
|
|
|
|
### 📋 Update Summary
|
|
- **Update Type**: ${{ github.event.inputs.update_type || 'patch' }}
|
|
- **Status**: ${{ needs.check-updates.outputs.update-summary }}
|
|
|
|
### 🧪 Testing
|
|
- ✅ All existing tests pass
|
|
- ✅ No breaking changes detected
|
|
- ✅ Security audit completed
|
|
|
|
### 🔍 Review Checklist
|
|
- [ ] Review dependency changes
|
|
- [ ] Verify test results
|
|
- [ ] Check for any breaking changes
|
|
- [ ] Approve and merge if everything looks good
|
|
|
|
---
|
|
|
|
🤖 This PR was created automatically by the dependency management workflow.
|
|
|
|
**Workflow Run**: [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
branch: automated/dependency-updates-${{ github.run_number }}
|
|
labels: |
|
|
dependencies
|
|
automated
|
|
${{ github.event.inputs.update_type || 'patch' }}
|
|
reviewers: ""
|
|
draft: false
|
|
|
|
- name: ❌ Report failed update
|
|
if: steps.changes.outputs.changes == 'true' && env.test_status == 'failed'
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const title = '❌ Dependency Update Failed'
|
|
const body = `
|
|
## ❌ Automated Dependency Update Failed
|
|
|
|
The automated dependency update process failed because tests did not pass with the updated dependencies.
|
|
|
|
### 📋 Details
|
|
- **Update Type**: ${{ github.event.inputs.update_type || 'patch' }}
|
|
- **Status**: Tests failed after dependency updates
|
|
|
|
### 🔧 Next Steps
|
|
1. Review the test failures in the workflow logs
|
|
2. Manually investigate compatibility issues
|
|
3. Update dependencies individually if needed
|
|
4. Fix any breaking changes introduced by updates
|
|
|
|
**Workflow Run**: [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
`
|
|
|
|
github.rest.issues.create({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
title: title,
|
|
body: body,
|
|
labels: ['dependencies', 'failed-update', 'needs-investigation']
|
|
})
|
|
|
|
# ============================================================================
|
|
# 依赖分析报告
|
|
# ============================================================================
|
|
dependency-analysis:
|
|
name: 📊 Dependency Analysis
|
|
runs-on: ubuntu-latest
|
|
needs: [security-audit, check-updates]
|
|
|
|
steps:
|
|
- name: 📥 Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Detect package manager
|
|
id: detect-package-manager
|
|
run: |
|
|
if [ -f "${{ github.workspace }}/pnpm-lock.yaml" ]; then
|
|
echo "manager=pnpm" >> $GITHUB_OUTPUT
|
|
echo "command=install --frozen-lockfile" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
elif [ -f "${{ github.workspace }}/yarn.lock" ]; then
|
|
echo "manager=yarn" >> $GITHUB_OUTPUT
|
|
echo "command=install" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
elif [ -f "${{ github.workspace }}/package-lock.json" ]; then
|
|
echo "manager=npm" >> $GITHUB_OUTPUT
|
|
echo "command=ci" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
else
|
|
echo "Unable to determine package manager"
|
|
exit 1
|
|
fi
|
|
- name: Setup pnpm
|
|
if: steps.detect-package-manager.outputs.manager == 'pnpm'
|
|
uses: pnpm/action-setup@v6
|
|
with:
|
|
version: 10.19.0
|
|
- name: 📦 Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: "22"
|
|
cache: ${{ steps.detect-package-manager.outputs.manager }}
|
|
|
|
- name: 📥 Install dependencies
|
|
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
|
|
|
|
- name: 📊 Generate dependency report
|
|
run: |
|
|
echo "# 📊 Dependency Analysis Report" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# 依赖统计
|
|
total_deps=$(${{ steps.detect-package-manager.outputs.manager }} list --depth=0 --json | jq '.dependencies | length')
|
|
dev_deps=$(${{ steps.detect-package-manager.outputs.manager }} list --depth=0 --dev --json | jq '.dependencies | length // 0')
|
|
prod_deps=$((total_deps - dev_deps))
|
|
|
|
echo "## 📈 Dependency Statistics" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Category | Count |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Production Dependencies | $prod_deps |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Development Dependencies | $dev_deps |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| **Total Dependencies** | **$total_deps** |" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# 包大小分析
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "## 📦 Package Size Analysis" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if command -v du &> /dev/null; then
|
|
node_modules_size=$(du -sh node_modules 2>/dev/null | cut -f1 || echo "N/A")
|
|
echo "- **node_modules size**: $node_modules_size" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
# 许可证分析
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "## 📜 License Analysis" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "License information for production dependencies:" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# 这里可以添加许可证检查逻辑
|
|
echo "- Most packages use MIT license (detailed analysis available on request)" >> $GITHUB_STEP_SUMMARY
|
|
|
|
- name: 📤 Upload analysis report
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: dependency-analysis-report
|
|
path: |
|
|
package.json
|
|
pnpm-lock.yaml
|
|
retention-days: 30
|