@@ -2,25 +2,132 @@ name: Security Scan
22
33on :
44 push :
5- branches : [ main ]
5+ branches : [ main, develop ]
66 pull_request :
7+ branches : [ main, develop ]
8+ workflow_dispatch :
9+
10+ permissions :
11+ contents : read
12+ security-events : write
13+ pull-requests : write
14+ checks : write
715
816jobs :
917 security-scan :
18+ name : Security Scan
1019 runs-on : ubuntu-latest
11-
20+
1221 steps :
13- - name : Checkout repository
14- uses : actions/checkout@v4
15-
16- - name : Make scan script executable
17- run : chmod +x ./scan.sh
18-
19- - name : Run security scan
20- run : ./scan.sh
22+ - name : Checkout code
23+ uses : actions/checkout@v4
24+
25+ - name : Set up Go
26+ uses : actions/setup-go@v5
27+ with :
28+ go-version : ' 1.21'
29+ cache : true
30+
31+ - name : Install dependencies
32+ run : |
33+ sudo apt-get update
34+ sudo apt-get install -y jq
35+
36+ - name : Make script executable
37+ run : chmod +x ./scan.sh
38+
39+ - name : Run security scan
40+ id : scan
41+ continue-on-error : true
42+ run : |
43+ if ./scan.sh; then
44+ echo "scan_status=success" >> $GITHUB_OUTPUT
45+ echo "scan_result=✅ PASSED" >> $GITHUB_OUTPUT
46+ else
47+ echo "scan_status=failure" >> $GITHUB_OUTPUT
48+ echo "scan_result=❌ FAILED" >> $GITHUB_OUTPUT
49+ fi
50+
51+ - name : Upload HTML Report
52+ if : always()
53+ uses : actions/upload-artifact@v4
54+ with :
55+ name : security-reports
56+ path : security-reports/
57+ retention-days : 30
58+
59+ - name : Upload SARIF to GitHub Security
60+ if : always()
61+ uses : github/codeql-action/upload-sarif@v3
62+ with :
63+ sarif_file : security-reports/gosec-*.sarif
64+ category : gosec
65+ continue-on-error : true
66+
67+ - name : Comment on PR
68+ if : github.event_name == 'pull_request' && always()
69+ uses : actions/github-script@v7
70+ with :
71+ github-token : ${{secrets.GITHUB_TOKEN}}
72+ script : |
73+ const fs = require('fs');
74+ const path = require('path');
75+
76+ // Find the summary file
77+ const reportsDir = 'security-reports';
78+ const files = fs.readdirSync(reportsDir);
79+ const summaryFile = files.find(f => f === 'SECURITY-SUMMARY.md');
80+
81+ if (summaryFile) {
82+ const summaryPath = path.join(reportsDir, summaryFile);
83+ const summary = fs.readFileSync(summaryPath, 'utf8');
84+
85+ // Find existing comment
86+ const { data: comments } = await github.rest.issues.listComments({
87+ owner: context.repo.owner,
88+ repo: context.repo.repo,
89+ issue_number: context.issue.number,
90+ });
91+
92+ const botComment = comments.find(comment =>
93+ comment.user.type === 'Bot' &&
94+ comment.body.includes('Security Scan Report')
95+ );
96+
97+ const commentBody = `${summary}
2198
22- - name : Upload scan report
23- uses : actions/upload-artifact@v4
24- with :
25- name : security-report
26- path : ./report/
99+ ---
100+ 📥 [Download detailed reports](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`;
101+
102+ if (botComment) {
103+ // Update existing comment
104+ await github.rest.issues.updateComment({
105+ owner : context.repo.owner,
106+ repo : context.repo.repo,
107+ comment_id : botComment.id,
108+ body : commentBody
109+ });
110+ } else {
111+ // Create new comment
112+ await github.rest.issues.createComment({
113+ owner : context.repo.owner,
114+ repo : context.repo.repo,
115+ issue_number : context.issue.number,
116+ body : commentBody
117+ });
118+ }
119+ }
120+
121+ - name : Set job summary
122+ if : always()
123+ run : |
124+ if [ -f "security-reports/SECURITY-SUMMARY.md" ]; then
125+ cat security-reports/SECURITY-SUMMARY.md >> $GITHUB_STEP_SUMMARY
126+ fi
127+
128+ - name : Fail if security issues found
129+ if : steps.scan.outputs.scan_status == 'failure'
130+ run : |
131+ echo "::error::❌ Security scan failed - critical issues detected"
132+ echo "::error::View the Security tab or download artifacts for details"
133+ exit 1
0 commit comments