Browse Source

Updated CI

maziggy 3 months ago
parent
commit
5d48ab88f0
1 changed files with 118 additions and 29 deletions
  1. 118 29
      .github/workflows/security.yml

+ 118 - 29
.github/workflows/security.yml

@@ -141,13 +141,49 @@ jobs:
           path: pip-audit-results.json
           retention-days: 30
 
-      - name: Create issue on vulnerability
-        if: steps.pip-audit.outputs.vulnerabilities_found == 'true'
+      - name: Create or close pip security issue
+        if: always()
         uses: actions/github-script@v7
         with:
           script: |
             const fs = require('fs');
-            const results = JSON.parse(fs.readFileSync('pip-audit-results.json', 'utf8'));
+
+            // Check for existing open issue
+            const existingIssues = await github.rest.issues.listForRepo({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              state: 'open',
+              labels: 'security,automated'
+            });
+            const existingIssue = existingIssues.data.find(i => i.title.startsWith('Security Alert:') && i.title.includes('Python'));
+
+            // If no vulnerabilities found, auto-close any stale issue
+            if ('${{ steps.pip-audit.outputs.vulnerabilities_found }}' !== 'true') {
+              if (existingIssue) {
+                await github.rest.issues.createComment({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: existingIssue.number,
+                  body: 'All Python vulnerabilities have been resolved. Closing automatically.'
+                });
+                await github.rest.issues.update({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: existingIssue.number,
+                  state: 'closed'
+                });
+                console.log(`Auto-closed resolved issue #${existingIssue.number}`);
+              }
+              return;
+            }
+
+            let results;
+            try {
+              results = JSON.parse(fs.readFileSync('pip-audit-results.json', 'utf8'));
+            } catch {
+              console.log('Could not read audit results');
+              return;
+            }
 
             // Build vulnerability table
             let table = '| Package | Version | Vulnerability | Fix Version |\n';
@@ -159,17 +195,29 @@ jobs:
               }
             }
 
-            const title = `Security Alert: ${results.dependencies?.reduce((acc, d) => acc + (d.vulns?.length || 0), 0) || 0} Python vulnerabilities found`;
+            const vulnCount = results.dependencies?.reduce((acc, d) => acc + (d.vulns?.length || 0), 0) || 0;
 
-            // Check for existing open issue
-            const existingIssues = await github.rest.issues.listForRepo({
-              owner: context.repo.owner,
-              repo: context.repo.repo,
-              state: 'open',
-              labels: 'security,automated'
-            });
+            if (vulnCount === 0) {
+              console.log('No vulnerabilities to report');
+              if (existingIssue) {
+                await github.rest.issues.createComment({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: existingIssue.number,
+                  body: 'All Python vulnerabilities have been resolved. Closing automatically.'
+                });
+                await github.rest.issues.update({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: existingIssue.number,
+                  state: 'closed'
+                });
+                console.log(`Auto-closed resolved issue #${existingIssue.number}`);
+              }
+              return;
+            }
 
-            const existingIssue = existingIssues.data.find(i => i.title.startsWith('Security Alert:') && i.title.includes('Python'));
+            const title = `Security Alert: ${vulnCount} Python vulnerabilities found`;
 
             const body = `## Automated Security Audit Results
 
@@ -182,7 +230,6 @@ jobs:
             1. Review each vulnerability
             2. Update affected packages: \`pip install --upgrade <package>\`
             3. Run \`pip-audit\` locally to verify fixes
-            4. Close this issue when resolved
 
             ---
             *This issue was automatically created by the security audit workflow.*`;
@@ -230,12 +277,14 @@ jobs:
         id: npm-audit
         working-directory: frontend
         run: |
-          npm audit --omit=dev --json > npm-audit-raw.json 2>&1 || true
+          npm audit --omit=dev --json > npm-audit-raw.json 2>/dev/null || true
           # Filter audit results to only include actual project dependencies
           # (npm audit sometimes reports vulnerabilities in the npm CLI itself)
           node -e "
             const fs = require('fs');
-            const results = JSON.parse(fs.readFileSync('npm-audit-raw.json', 'utf8'));
+            const raw = fs.readFileSync('npm-audit-raw.json', 'utf8');
+            let results;
+            try { results = JSON.parse(raw); } catch { results = { vulnerabilities: {} }; }
             const depTree = JSON.parse(require('child_process').execSync(
               'npm ls --omit=dev --all --json 2>/dev/null', { encoding: 'utf8' }
             ));
@@ -269,19 +318,70 @@ jobs:
           path: frontend/npm-audit-results.json
           retention-days: 30
 
-      - name: Create issue on vulnerability
-        if: steps.npm-audit.outputs.vulnerabilities_found == 'true'
+      - name: Create or close npm security issue
+        if: always()
         uses: actions/github-script@v7
         with:
           script: |
             const fs = require('fs');
-            const results = JSON.parse(fs.readFileSync('frontend/npm-audit-results.json', 'utf8'));
+
+            // Check for existing open issue
+            const existingIssues = await github.rest.issues.listForRepo({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              state: 'open',
+              labels: 'security,automated'
+            });
+            const existingIssue = existingIssues.data.find(i => i.title.startsWith('Security Alert:') && i.title.includes('npm'));
+
+            // If filter didn't flag vulnerabilities, auto-close any stale issue
+            if ('${{ steps.npm-audit.outputs.vulnerabilities_found }}' !== 'true') {
+              if (existingIssue) {
+                await github.rest.issues.createComment({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: existingIssue.number,
+                  body: 'All npm production vulnerabilities have been resolved. Closing automatically.'
+                });
+                await github.rest.issues.update({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: existingIssue.number,
+                  state: 'closed'
+                });
+                console.log(`Auto-closed resolved issue #${existingIssue.number}`);
+              }
+              return;
+            }
+
+            let results;
+            try {
+              results = JSON.parse(fs.readFileSync('frontend/npm-audit-results.json', 'utf8'));
+            } catch {
+              console.log('Could not read filtered audit results');
+              return;
+            }
 
             const vulns = results.vulnerabilities || {};
             const vulnCount = Object.keys(vulns).length;
 
             if (vulnCount === 0) {
               console.log('No vulnerabilities to report');
+              if (existingIssue) {
+                await github.rest.issues.createComment({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: existingIssue.number,
+                  body: 'All npm production vulnerabilities have been resolved. Closing automatically.'
+                });
+                await github.rest.issues.update({
+                  owner: context.repo.owner,
+                  repo: context.repo.repo,
+                  issue_number: existingIssue.number,
+                  state: 'closed'
+                });
+                console.log(`Auto-closed resolved issue #${existingIssue.number}`);
+              }
               return;
             }
 
@@ -296,16 +396,6 @@ jobs:
 
             const title = `Security Alert: ${vulnCount} npm vulnerabilities found`;
 
-            // Check for existing open issue
-            const existingIssues = await github.rest.issues.listForRepo({
-              owner: context.repo.owner,
-              repo: context.repo.repo,
-              state: 'open',
-              labels: 'security,automated'
-            });
-
-            const existingIssue = existingIssues.data.find(i => i.title.startsWith('Security Alert:') && i.title.includes('npm'));
-
             const body = `## Automated Security Audit Results
 
             The weekly security audit found vulnerabilities in npm dependencies.
@@ -317,7 +407,6 @@ jobs:
             1. Review each vulnerability: \`npm audit\`
             2. Auto-fix if possible: \`npm audit fix\`
             3. Manual fix for breaking changes: \`npm audit fix --force\` (review changes!)
-            4. Close this issue when resolved
 
             ---
             *This issue was automatically created by the security audit workflow.*`;