1818 - ' true'
1919 - ' false'
2020
21+ permissions :
22+ contents : read
23+ pull-requests : write
24+
2125jobs :
2226 security-scan :
2327 if : github.event.pull_request.draft == false || github.event_name == 'workflow_dispatch'
2933 with :
3034 fetch-depth : 0
3135
36+ - name : Resolve PR number
37+ id : pr
38+ run : |
39+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
40+ echo "number=${{ inputs.pr_number }}" >> "$GITHUB_OUTPUT"
41+ else
42+ echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
43+ fi
44+
3245 - name : Set up uv
3346 uses : astral-sh/setup-uv@v7
3447 with :
@@ -42,20 +55,13 @@ jobs:
4255 - name : Install skill-scanner
4356 run : uv pip install --system 'cisco-ai-skill-scanner[google]'
4457
45- - name : Make scripts executable
46- run : chmod +x scripts/detect-changed-packs.sh
47-
4858 - name : Detect changed packs
4959 id : detect
50- env :
51- GITHUB_EVENT_NAME : ${{ github.event_name }}
52- GITHUB_BASE_REF : ${{ github.base_ref }}
53- GITHUB_EVENT_BEFORE : ${{ github.event.before }}
5460 run : |
5561 if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ github.event.inputs.scan_all }}" = "true" ]; then
5662 PACKS=$(find . -maxdepth 2 -name skills -type d | sed 's|^\./||;s|/skills$||' | sort)
5763 else
58- PACKS=$(./ scripts/detect-changed-packs.sh || true)
64+ PACKS=$(bash scripts/detect-changed-packs.sh || true)
5965 fi
6066
6167 if [ -z "$PACKS" ]; then
@@ -106,41 +112,53 @@ jobs:
106112 fi
107113
108114 - name : Upload security reports
115+ id : upload
109116 if : steps.detect.outputs.changed == 'true' && always()
110117 uses : actions/upload-artifact@v4
111118 with :
112119 name : security-reports
113120 path : security-reports/
114121 retention-days : 30
122+ if-no-files-found : ignore
115123
116124 - name : Post scan summary
117- if : steps.detect.outputs.changed == 'true' && github.event_name == 'pull_request' && always()
125+ if : steps.detect.outputs.changed == 'true' && always()
118126 uses : actions/github-script@v7
119127 with :
120128 script : |
121129 const fs = require('fs');
122- const reports = fs.readdirSync('security-reports').filter(f => f.endsWith('.md')) ;
130+ const prNumber = ${{ steps.pr.outputs.number }} ;
123131 const scanResult = '${{ steps.scan.outputs.scan_result }}';
124132 const icon = scanResult === 'passed' ? '✅' : '❌';
125133
126134 let body = `## ${icon} Skill Security Scan\n\n`;
127135
128- if (reports.length === 0) {
129- body += 'No reports generated.\n';
130- } else {
131- for (const report of reports) {
132- const pack = report.replace('security-report-', '').replace('.md', '');
133- const content = fs.readFileSync(`security-reports/${report}`, 'utf8');
134- body += `<details>\n<summary>📋 ${pack}</summary>\n\n${content}\n\n</details>\n\n`;
136+ if (fs.existsSync('security-reports')) {
137+ const reports = fs.readdirSync('security-reports').filter(f => f.endsWith('.md'));
138+ if (reports.length === 0) {
139+ body += 'No reports generated.\n';
140+ } else {
141+ for (const report of reports) {
142+ const pack = report.replace('security-report-', '').replace('.md', '');
143+ const content = fs.readFileSync(`security-reports/${report}`, 'utf8');
144+ body += `<details>\n<summary>📋 ${pack}</summary>\n\n${content}\n\n</details>\n\n`;
145+ }
135146 }
147+ } else {
148+ body += 'No reports generated.\n';
136149 }
137150
138- body += `\n\n> Reports are also available as [workflow artifacts](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}).`;
151+ const artifactUrl = '${{ steps.upload.outputs.artifact-url }}';
152+ if (artifactUrl) {
153+ body += `\n\n> 📦 [Download security reports](${artifactUrl}) | [Workflow run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`;
154+ } else {
155+ body += `\n\n> [Workflow run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`;
156+ }
139157
140158 const { data: comments } = await github.rest.issues.listComments({
141159 owner: context.repo.owner,
142160 repo: context.repo.repo,
143- issue_number: context.issue.number ,
161+ issue_number: prNumber ,
144162 });
145163
146164 const existing = comments.find(c =>
@@ -158,7 +176,7 @@ jobs:
158176 await github.rest.issues.createComment({
159177 owner: context.repo.owner,
160178 repo: context.repo.repo,
161- issue_number: context.issue.number ,
179+ issue_number: prNumber ,
162180 body,
163181 });
164182 }
0 commit comments