Fix gitleaks workflow token #7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Gitleaks Scan | |
| on: | |
| push: | |
| pull_request: | |
| workflow_dispatch: | |
| permissions: | |
| actions: write | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| scan: | |
| name: Scan for Leaked Secrets | |
| runs-on: ubuntu-latest | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RESPONSE_GUIDE_URL: https://github.com/CivicTechWR/.github/blob/main/docs/gitleaks-response.md | |
| GITLEAKS_VERSION: v8.18.2 | |
| steps: | |
| - name: Check out code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Gitleaks CLI | |
| run: | | |
| VERSION_NUMBER="${GITLEAKS_VERSION#v}" | |
| ARCHIVE="gitleaks_${VERSION_NUMBER}_linux_x64.tar.gz" | |
| curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/${GITLEAKS_VERSION}/${ARCHIVE}" -o gitleaks.tar.gz | |
| tar -xzf gitleaks.tar.gz gitleaks | |
| sudo install -m 0755 gitleaks /usr/local/bin/gitleaks | |
| rm -f gitleaks.tar.gz gitleaks | |
| env: | |
| GITLEAKS_VERSION: ${{ env.GITLEAKS_VERSION }} | |
| - name: Run Gitleaks (redacted) | |
| id: gitleaks | |
| continue-on-error: true | |
| env: | |
| GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} | |
| run: | | |
| gitleaks detect \ | |
| --source . \ | |
| --no-banner \ | |
| --redact \ | |
| --report-format json \ | |
| --report-path gitleaks-report.json | |
| - name: Summarize findings | |
| id: summarize | |
| run: | | |
| if [ ! -f gitleaks-report.json ]; then | |
| echo "[]" > gitleaks-report.json | |
| fi | |
| count=$(jq 'length' gitleaks-report.json 2>/dev/null || echo 0) | |
| if [ "$count" -gt 0 ]; then | |
| echo "found=true" >> "$GITHUB_OUTPUT" | |
| echo "count=$count" >> "$GITHUB_OUTPUT" | |
| echo "::warning::Gitleaks detected ${count} potential secret(s)." | |
| else | |
| echo "found=false" >> "$GITHUB_OUTPUT" | |
| echo "count=0" >> "$GITHUB_OUTPUT" | |
| echo "::notice::Gitleaks found no potential secrets." | |
| fi | |
| - name: Note scan issues | |
| if: ${{ steps.gitleaks.outcome == 'failure' && steps.summarize.outputs.found == 'false' }} | |
| run: | | |
| echo "::warning::Gitleaks scan ended with an error before producing findings. Review the action logs." | |
| - name: Add pull request comment | |
| if: ${{ steps.summarize.outputs.found == 'true' && github.event_name == 'pull_request' }} | |
| uses: actions/github-script@v7 | |
| env: | |
| LEAK_COUNT: ${{ steps.summarize.outputs.count }} | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const fs = require('fs'); | |
| const path = 'gitleaks-report.json'; | |
| const responseGuide = process.env.RESPONSE_GUIDE_URL; | |
| const findings = JSON.parse(fs.readFileSync(path, 'utf8')); | |
| if (!Array.isArray(findings) || findings.length === 0) { | |
| return; | |
| } | |
| const lines = findings.slice(0, 10).map((finding) => { | |
| const file = finding.file ? `\`${finding.file}\`` : 'unknown file'; | |
| const line = finding.startLine ? ` (line ${finding.startLine})` : ''; | |
| const rule = finding.ruleId || finding.rule || 'potential secret'; | |
| return `- ${file}${line} — ${rule}`; | |
| }).join('\n'); | |
| const remainder = findings.length > 10 | |
| ? `\n\n…and ${findings.length - 10} more finding${findings.length - 10 === 1 ? '' : 's'} in the attached report.` | |
| : ''; | |
| const body = [ | |
| `@CivicTechWR/organizers Gitleaks flagged **${process.env.LEAK_COUNT}** potential secret${findings.length === 1 ? '' : 's'} in this pull request.`, | |
| '', | |
| `Please review the [Gitleaks response guide](${responseGuide}) for next steps.`, | |
| '', | |
| lines, | |
| remainder, | |
| '', | |
| '_Secret values are redacted by the scanner. Follow the guide before merging._' | |
| ].filter(Boolean).join('\n'); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body, | |
| }); | |
| - name: Upload redacted report | |
| if: ${{ steps.summarize.outputs.found == 'true' }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: gitleaks-report | |
| path: gitleaks-report.json | |
| retention-days: 7 | |
| - name: Record scan summary | |
| if: ${{ always() }} | |
| env: | |
| LEAK_COUNT: ${{ steps.summarize.outputs.count }} | |
| HAS_FINDINGS: ${{ steps.summarize.outputs.found }} | |
| run: | | |
| if [ "$HAS_FINDINGS" = "true" ]; then | |
| { | |
| echo "## Gitleaks Findings" | |
| echo "" | |
| echo "Potential secrets detected: $LEAK_COUNT" | |
| echo "Report: gitleaks-report.json (uploaded as artifact when available)" | |
| echo "Guide: $RESPONSE_GUIDE_URL" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| else | |
| { | |
| echo "## Gitleaks Findings" | |
| echo "" | |
| echo "No potential secrets detected." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| fi |