name: Dependency Updates on: schedule: # Run every Monday at 06:00 UTC - cron: '0 6 * * 1' workflow_dispatch: env: NODE_VERSION: '20' PNPM_VERSION: '9.15.0' jobs: # Check for outdated dependencies check-outdated: name: Check Outdated Dependencies runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Check for outdated dependencies run: pnpm outdated --format json > outdated.json || true - name: Generate outdated report run: | echo "## Outdated Dependencies Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "Generated on: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [ -f outdated.json ] && [ -s outdated.json ]; then echo "### Packages to Update" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY cat outdated.json | jq -r 'to_entries[] | "- **\(.key)**: \(.value.current) → \(.value.latest)"' >> $GITHUB_STEP_SUMMARY || echo "No outdated packages found" >> $GITHUB_STEP_SUMMARY else echo "✅ All dependencies are up to date!" >> $GITHUB_STEP_SUMMARY fi - name: Upload outdated report uses: actions/upload-artifact@v4 with: name: outdated-dependencies path: outdated.json retention-days: 30 if: always() # Security audit security-audit: name: Security Audit runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Run security audit run: | pnpm audit --json > audit-report.json || true pnpm audit --audit-level=moderate || echo "Security vulnerabilities found" - name: Generate security report run: | echo "## Security Audit Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "Generated on: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [ -f audit-report.json ]; then # Parse audit report CRITICAL=$(jq -r '.metadata.vulnerabilities.critical // 0' audit-report.json) HIGH=$(jq -r '.metadata.vulnerabilities.high // 0' audit-report.json) MODERATE=$(jq -r '.metadata.vulnerabilities.moderate // 0' audit-report.json) LOW=$(jq -r '.metadata.vulnerabilities.low // 0' audit-report.json) echo "| Severity | Count |" >> $GITHUB_STEP_SUMMARY echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY echo "| Critical | $CRITICAL |" >> $GITHUB_STEP_SUMMARY echo "| High | $HIGH |" >> $GITHUB_STEP_SUMMARY echo "| Moderate | $MODERATE |" >> $GITHUB_STEP_SUMMARY echo "| Low | $LOW |" >> $GITHUB_STEP_SUMMARY if [ "$CRITICAL" -gt 0 ] || [ "$HIGH" -gt 0 ]; then echo "" >> $GITHUB_STEP_SUMMARY echo "⚠️ **Action Required**: Critical or high severity vulnerabilities detected!" >> $GITHUB_STEP_SUMMARY fi fi - name: Upload security audit uses: actions/upload-artifact@v4 with: name: security-audit path: audit-report.json retention-days: 90 if: always() - name: Create issue for critical vulnerabilities if: always() uses: actions/github-script@v7 with: script: | const fs = require('fs'); if (!fs.existsSync('audit-report.json')) { console.log('No audit report found'); return; } const auditData = JSON.parse(fs.readFileSync('audit-report.json', 'utf8')); const critical = auditData.metadata?.vulnerabilities?.critical || 0; const high = auditData.metadata?.vulnerabilities?.high || 0; if (critical > 0 || high > 0) { const issueTitle = `🚨 Security Alert: ${critical} Critical, ${high} High Severity Vulnerabilities`; const issueBody = ` ## Security Vulnerability Report **Date**: ${new Date().toISOString()} **Workflow Run**: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} ### Summary - Critical: ${critical} - High: ${high} - Moderate: ${auditData.metadata?.vulnerabilities?.moderate || 0} - Low: ${auditData.metadata?.vulnerabilities?.low || 0} ### Action Required Please review the security audit report and update affected dependencies. \`\`\`bash pnpm audit pnpm audit fix \`\`\` **Note**: This issue was automatically created by the dependency update workflow. `; // Check if similar issue exists const { data: existingIssues } = await github.rest.issues.listForRepo({ owner: context.repo.owner, repo: context.repo.repo, state: 'open', labels: 'security,automated' }); const hasExistingIssue = existingIssues.some(issue => issue.title.includes('Security Alert') ); if (!hasExistingIssue) { await github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, title: issueTitle, body: issueBody, labels: ['security', 'automated', 'high-priority'] }); } } # Update lock file update-lockfile: name: Update Lock File runs-on: ubuntu-latest needs: [check-outdated, security-audit] steps: - name: Checkout code uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Update lock file run: | # Update lock file without changing package.json versions pnpm install --no-frozen-lockfile - name: Check for changes id: changes run: | if git diff --quiet pnpm-lock.yaml; then echo "has-changes=false" >> $GITHUB_OUTPUT else echo "has-changes=true" >> $GITHUB_OUTPUT fi - name: Create Pull Request if: steps.changes.outputs.has-changes == 'true' uses: peter-evans/create-pull-request@v6 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "chore: update pnpm-lock.yaml" title: "chore: Update dependency lock file" body: | ## Dependency Lock File Update This PR updates the `pnpm-lock.yaml` file to reflect the latest compatible versions. ### Changes - Updated lock file to latest compatible versions - No breaking changes to package.json ### Testing - [ ] All CI checks pass - [ ] Manual testing completed **Note**: This PR was automatically created by the dependency update workflow. branch: chore/update-lockfile labels: | dependencies automated assignees: wuesteon