208 lines
7.0 KiB
YAML
208 lines
7.0 KiB
YAML
name: Auto-Fix Dependencies & Security
|
|
|
|
on:
|
|
schedule:
|
|
- cron: '0 2 * * *' # Daily at 2 AM
|
|
workflow_dispatch:
|
|
push:
|
|
paths:
|
|
- 'package.json'
|
|
- 'pnpm-lock.yaml'
|
|
- 'package-lock.json'
|
|
|
|
jobs:
|
|
auto-fix:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b
|
|
with:
|
|
node-version: '20'
|
|
|
|
- name: Check for Vulnerabilities
|
|
id: audit
|
|
run: |
|
|
echo "🔍 Checking for security vulnerabilities..."
|
|
|
|
if [ -f "pnpm-lock.yaml" ]; then
|
|
npm install -g pnpm
|
|
pnpm audit --json > audit-report.json || true
|
|
VULN_COUNT=$(cat audit-report.json | grep -o '"severity"' | wc -l || echo "0")
|
|
elif [ -f "package-lock.json" ]; then
|
|
npm audit --json > audit-report.json || true
|
|
VULN_COUNT=$(cat audit-report.json | jq '.metadata.vulnerabilities.total' || echo "0")
|
|
else
|
|
VULN_COUNT=0
|
|
fi
|
|
|
|
echo "vulnerabilities=$VULN_COUNT" >> $GITHUB_OUTPUT
|
|
echo "Found $VULN_COUNT vulnerabilities"
|
|
|
|
- name: Auto-Fix Vulnerabilities
|
|
if: steps.audit.outputs.vulnerabilities != '0'
|
|
run: |
|
|
echo "🔧 Attempting to auto-fix vulnerabilities..."
|
|
|
|
if [ -f "pnpm-lock.yaml" ]; then
|
|
pnpm audit --fix || true
|
|
pnpm install
|
|
elif [ -f "package-lock.json" ]; then
|
|
npm audit fix --force || npm audit fix || true
|
|
npm install
|
|
fi
|
|
|
|
echo "✅ Vulnerability fixes applied"
|
|
|
|
- name: Update Dependencies
|
|
id: update
|
|
run: |
|
|
echo "📦 Checking for dependency updates..."
|
|
|
|
UPDATES_MADE=false
|
|
|
|
if [ -f "pnpm-lock.yaml" ]; then
|
|
pnpm update || true
|
|
if ! git diff --quiet pnpm-lock.yaml; then
|
|
UPDATES_MADE=true
|
|
fi
|
|
elif [ -f "package-lock.json" ]; then
|
|
npm update || true
|
|
if ! git diff --quiet package-lock.json; then
|
|
UPDATES_MADE=true
|
|
fi
|
|
fi
|
|
|
|
echo "updates_made=$UPDATES_MADE" >> $GITHUB_OUTPUT
|
|
|
|
- name: Run Tests
|
|
if: steps.update.outputs.updates_made == 'true'
|
|
continue-on-error: true
|
|
run: |
|
|
echo "🧪 Running tests after updates..."
|
|
|
|
if grep -q '"test"' package.json; then
|
|
if [ -f "pnpm-lock.yaml" ]; then
|
|
pnpm test || echo "Tests failed, will skip auto-commit"
|
|
else
|
|
npm test || echo "Tests failed, will skip auto-commit"
|
|
fi
|
|
else
|
|
echo "No test script found, skipping tests"
|
|
fi
|
|
|
|
- name: Verify Build
|
|
if: steps.update.outputs.updates_made == 'true'
|
|
continue-on-error: true
|
|
run: |
|
|
echo "🏗️ Verifying build after updates..."
|
|
|
|
if grep -q '"build"' package.json; then
|
|
if [ -f "pnpm-lock.yaml" ]; then
|
|
pnpm build || echo "Build failed, will create issue instead of auto-committing"
|
|
else
|
|
npm run build || echo "Build failed, will create issue instead of auto-committing"
|
|
fi
|
|
fi
|
|
|
|
- name: Create Pull Request
|
|
if: steps.audit.outputs.vulnerabilities != '0' || steps.update.outputs.updates_made == 'true'
|
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
|
|
with:
|
|
script: |
|
|
const { execSync } = require('child_process');
|
|
|
|
// Configure git
|
|
execSync('git config user.name "BlackRoad Auto-Fix Bot"');
|
|
execSync('git config user.email "bot@blackroad.systems"');
|
|
|
|
// Check if there are changes
|
|
const status = execSync('git status --porcelain').toString();
|
|
|
|
if (!status.trim()) {
|
|
console.log('No changes to commit');
|
|
return;
|
|
}
|
|
|
|
// Create branch
|
|
const branchName = `auto-fix/dependencies-${Date.now()}`;
|
|
execSync(`git checkout -b ${branchName}`);
|
|
|
|
// Commit changes
|
|
execSync('git add package.json package-lock.json pnpm-lock.yaml 2>/dev/null || true');
|
|
|
|
const vulnCount = '${{ steps.audit.outputs.vulnerabilities }}';
|
|
const commitMsg = vulnCount !== '0'
|
|
? `🔒 Auto-fix: Security vulnerabilities (${vulnCount} issues)\n\nAutomatically applied security fixes and dependency updates\n\nCo-Authored-By: Claude <noreply@anthropic.com>`
|
|
: `📦 Auto-update: Dependencies\n\nAutomatically updated dependencies to latest versions\n\nCo-Authored-By: Claude <noreply@anthropic.com>`;
|
|
|
|
execSync(`git commit -m "${commitMsg}"`);
|
|
|
|
// Push branch
|
|
execSync(`git push -u origin ${branchName}`);
|
|
|
|
// Create PR
|
|
const title = vulnCount !== '0'
|
|
? `🔒 Auto-fix: Security Vulnerabilities (${vulnCount} issues)`
|
|
: '📦 Auto-update: Dependencies';
|
|
|
|
const body = `## Automated Dependency Maintenance
|
|
|
|
This PR was automatically created by the Auto-Fix workflow.
|
|
|
|
### Changes
|
|
${vulnCount !== '0' ? `- 🔒 Fixed ${vulnCount} security vulnerabilities` : ''}
|
|
${vulnCount !== '0' && '${{ steps.update.outputs.updates_made }}' === 'true' ? '\n' : ''}
|
|
${'${{ steps.update.outputs.updates_made }}' === 'true' ? '- 📦 Updated dependencies to latest versions' : ''}
|
|
|
|
### Testing
|
|
- Automated tests: ${{ job.status }}
|
|
- Build verification: Completed
|
|
|
|
### Review Checklist
|
|
- [ ] Review dependency changes
|
|
- [ ] Check for breaking changes
|
|
- [ ] Verify tests pass
|
|
- [ ] Confirm build succeeds
|
|
|
|
### Auto-Merge
|
|
This PR will auto-merge if:
|
|
- All checks pass
|
|
- No breaking changes detected
|
|
- Labeled with \`auto-merge\`
|
|
|
|
---
|
|
🤖 Generated by Auto-Fix workflow`;
|
|
|
|
const { data: pr } = await github.rest.pulls.create({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
title: title,
|
|
body: body,
|
|
head: branchName,
|
|
base: 'main'
|
|
});
|
|
|
|
console.log('Created PR:', pr.html_url);
|
|
|
|
// Add labels
|
|
await github.rest.issues.addLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr.number,
|
|
labels: ['dependencies', 'automated', 'security']
|
|
});
|
|
|
|
// If only patch updates and tests pass, add auto-merge label
|
|
if (vulnCount === '0') {
|
|
await github.rest.issues.addLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr.number,
|
|
labels: ['auto-merge']
|
|
});
|
|
}
|