|
14 | 14 | env: |
15 | 15 | JAVA_VERSION: '25' |
16 | 16 | JAVA_DISTRO: 'zulu' |
17 | | - GRAAL_VERSION: '25.0.1' |
18 | | - GRAAL_DISTRIBUTION: 'graalvm-community' |
| 17 | + |
| 18 | +permissions: |
| 19 | + contents: read |
| 20 | + security-events: write |
| 21 | + pull-requests: write |
| 22 | + |
19 | 23 | jobs: |
20 | 24 | build: |
21 | 25 | name: Build and analyze |
22 | 26 | runs-on: ubuntu-latest |
| 27 | + timeout-minutes: 30 |
23 | 28 | steps: |
24 | | - - uses: actions/checkout@v4 |
| 29 | + - name: 'Checkout code' |
| 30 | + uses: actions/checkout@v4 |
25 | 31 |
|
26 | 32 | - name: 'Set up JDK' |
27 | 33 | uses: actions/setup-java@v5 |
|
41 | 47 | - name: Grant execute permission to MVN Wrapper |
42 | 48 | run: chmod +x ./mvnw |
43 | 49 |
|
44 | | - - name: Build and analyze |
| 50 | + - name: Build with Maven |
| 51 | + run: ./mvnw -ntp -B verify |
| 52 | + |
| 53 | + - name: Analyze with SonarCloud |
45 | 54 | env: |
46 | | - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any |
| 55 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
47 | 56 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} |
48 | | - SONAR_SKIP: ${{ secrets.SONAR_TOKEN && 'false' || 'true' }} # skip analysis if token is missing |
49 | | - run: ./mvnw -ntp -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=streamthoughts_jikkou |
| 57 | + run: | |
| 58 | + if [ -n "$SONAR_TOKEN" ]; then |
| 59 | + ./mvnw -ntp -B org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=streamthoughts_jikkou |
| 60 | + else |
| 61 | + echo "Skipping SonarCloud analysis (SONAR_TOKEN not set)" |
| 62 | + fi |
| 63 | +
|
| 64 | + - name: Run Trivy vulnerability scanner (SARIF) |
| 65 | + if: github.event_name == 'push' |
| 66 | + uses: aquasecurity/trivy-action@0.28.0 |
| 67 | + with: |
| 68 | + scan-type: 'fs' |
| 69 | + scan-ref: '.' |
| 70 | + ignore-unfixed: true |
| 71 | + format: 'sarif' |
| 72 | + output: 'trivy-results.sarif' |
| 73 | + severity: 'CRITICAL,HIGH' |
| 74 | + |
| 75 | + - name: Upload Trivy scan results to GitHub Security tab |
| 76 | + if: github.event_name == 'push' |
| 77 | + uses: github/codeql-action/upload-sarif@v3 |
| 78 | + with: |
| 79 | + sarif_file: 'trivy-results.sarif' |
| 80 | + |
| 81 | + - name: Run Trivy vulnerability scanner (Table) |
| 82 | + if: github.event_name == 'pull_request' |
| 83 | + uses: aquasecurity/trivy-action@0.28.0 |
| 84 | + with: |
| 85 | + scan-type: 'fs' |
| 86 | + scan-ref: '.' |
| 87 | + ignore-unfixed: true |
| 88 | + format: 'table' |
| 89 | + output: 'trivy-results.txt' |
| 90 | + severity: 'CRITICAL,HIGH' |
| 91 | + |
| 92 | + - name: Add vulnerability report to PR |
| 93 | + if: github.event_name == 'pull_request' |
| 94 | + uses: actions/github-script@v7 |
| 95 | + with: |
| 96 | + script: | |
| 97 | + const fs = require('fs'); |
| 98 | + const trivyResults = fs.readFileSync('trivy-results.txt', 'utf8'); |
| 99 | +
|
| 100 | + let body = '## Security Scan Results\n\n'; |
| 101 | +
|
| 102 | + if (trivyResults.trim().length === 0) { |
| 103 | + body += 'No vulnerabilities found with CRITICAL or HIGH severity.\n'; |
| 104 | + } else { |
| 105 | + body += 'Vulnerabilities detected:\n\n'; |
| 106 | + body += '```\n' + trivyResults + '\n```\n'; |
| 107 | + } |
| 108 | +
|
| 109 | + body += '\n\n<sub>Scanned by [Trivy](https://github.com/aquasecurity/trivy)</sub>'; |
| 110 | +
|
| 111 | + const { data: comments } = await github.rest.issues.listComments({ |
| 112 | + owner: context.repo.owner, |
| 113 | + repo: context.repo.repo, |
| 114 | + issue_number: context.issue.number, |
| 115 | + }); |
| 116 | +
|
| 117 | + const botComment = comments.find(comment => |
| 118 | + comment.user.type === 'Bot' && |
| 119 | + comment.body.includes('Security Scan Results') |
| 120 | + ); |
| 121 | +
|
| 122 | + if (botComment) { |
| 123 | + await github.rest.issues.updateComment({ |
| 124 | + owner: context.repo.owner, |
| 125 | + repo: context.repo.repo, |
| 126 | + comment_id: botComment.id, |
| 127 | + body: body |
| 128 | + }); |
| 129 | + } else { |
| 130 | + await github.rest.issues.createComment({ |
| 131 | + owner: context.repo.owner, |
| 132 | + repo: context.repo.repo, |
| 133 | + issue_number: context.issue.number, |
| 134 | + body: body |
| 135 | + }); |
| 136 | + } |
0 commit comments