|
35 | 35 | - name: Checkout (PR-fast / Main-full) |
36 | 36 | uses: actions/checkout@v4 |
37 | 37 | with: |
| 38 | + # PR: shallow checkout for speed. Push to main: full history for maximum coverage. |
38 | 39 | fetch-depth: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && 0 || 2 }} |
39 | 40 |
|
40 | 41 | - name: Ensure output folder exists + baselines |
|
78 | 79 | if: always() |
79 | 80 | shell: bash |
80 | 81 | run: | |
| 82 | + # Report-only: never fail the job |
81 | 83 | set +e |
82 | 84 |
|
83 | 85 | CFG=() |
@@ -110,12 +112,12 @@ jobs: |
110 | 112 | python3 - << 'PY' |
111 | 113 | import json, os, re |
112 | 114 |
|
113 | | - out_dir = os.environ["OUT_DIR"] |
114 | | - json_path = os.path.join(out_dir, os.environ["OUT_JSON"]) |
115 | | - sarif_path= os.path.join(out_dir, os.environ["OUT_SARIF"]) |
116 | | - log_path = os.path.join(out_dir, os.environ["OUT_LOG"]) |
117 | | - md_path = os.path.join(out_dir, os.environ["OUT_MD"]) |
118 | | - ver = os.environ.get("GITLEAKS_VERSION","0") |
| 115 | + out_dir = os.environ["OUT_DIR"] |
| 116 | + json_path = os.path.join(out_dir, os.environ["OUT_JSON"]) |
| 117 | + sarif_path = os.path.join(out_dir, os.environ["OUT_SARIF"]) |
| 118 | + log_path = os.path.join(out_dir, os.environ["OUT_LOG"]) |
| 119 | + md_path = os.path.join(out_dir, os.environ["OUT_MD"]) |
| 120 | + ver = os.environ.get("GITLEAKS_VERSION","0") |
119 | 121 |
|
120 | 122 | # Read log (for error context) |
121 | 123 | log_text = "" |
@@ -179,35 +181,71 @@ jobs: |
179 | 181 |
|
180 | 182 | # --- Markdown report --- |
181 | 183 | status = "OK" |
182 | | - # Detect config failure or fatal error in log |
183 | 184 | if re.search(r"\bFTL\b|\bFailed to load config\b", log_text, re.IGNORECASE): |
184 | 185 | status = "ERROR (see log)" |
185 | 186 |
|
| 187 | + mode = "Main (full history)" |
| 188 | + if os.environ.get("GITHUB_EVENT_NAME","") == "pull_request": |
| 189 | + mode = "PR-fast (working tree only)" |
| 190 | +
|
186 | 191 | md = [] |
187 | 192 | md.append("# Gitleaks Secret Scan (Report-Only)") |
188 | 193 | md.append("") |
189 | 194 | md.append(f"**Status:** {status}") |
190 | | - md.append(f"**Mode:** {'PR-fast (working tree only)' if os.environ.get('GITHUB_EVENT_NAME','')=='pull_request' else 'Main (full history)'}") |
| 195 | + md.append(f"**Mode:** {mode}") |
191 | 196 | md.append(f"**Findings:** {len(findings)}") |
192 | 197 | md.append("") |
193 | 198 | if len(findings) == 0: |
194 | 199 | md.append("No secrets detected (or scan produced no findings).") |
195 | 200 | else: |
196 | | - # Top rule counts |
197 | 201 | counts = {} |
198 | 202 | for x in findings: |
199 | 203 | rid = pick(x, "RuleID", "ruleID", "Rule", "rule", default="gitleaks") |
200 | 204 | counts[rid] = counts.get(rid, 0) + 1 |
| 205 | +
|
201 | 206 | md.append("## Top Rules") |
202 | 207 | for rid, c in sorted(counts.items(), key=lambda kv: kv[1], reverse=True)[:15]: |
203 | 208 | md.append(f"- `{rid}`: {c}") |
| 209 | +
|
204 | 210 | md.append("") |
205 | | - md.append("> Artifacts: `gitleaks.json`, `gitleaks.sarif`, `gitleaks.log`") |
| 211 | + md.append("> Artifacts: `gitleaks.json`, `gitleaks.sarif`, `gitleaks.log`, `gitleaks-report.md`") |
206 | 212 |
|
207 | 213 | with open(md_path, "w", encoding="utf-8") as f: |
208 | 214 | f.write("\n".join(md) + "\n") |
209 | 215 | PY |
210 | 216 |
|
| 217 | + - name: Publish report to Run Summary (View Runs) |
| 218 | + if: always() |
| 219 | + shell: bash |
| 220 | + run: | |
| 221 | + set -euo pipefail |
| 222 | +
|
| 223 | + COUNT="$(python3 -c 'import json; import sys; print(len(json.load(open(sys.argv[1]))))' "${OUT_DIR}/${OUT_JSON}" 2>/dev/null || echo 0)" |
| 224 | +
|
| 225 | + { |
| 226 | + echo "## 🔐 Gitleaks Secret Scan (Report-Only)" |
| 227 | + echo "" |
| 228 | + echo "**Workflow:** PR-fast / Main-full" |
| 229 | + echo "**Event:** \`${{ github.event_name }}\`" |
| 230 | + echo "**Ref:** \`${{ github.ref }}\`" |
| 231 | + echo "**Findings:** ${COUNT}" |
| 232 | + echo "" |
| 233 | + echo "### Report" |
| 234 | + echo "" |
| 235 | + if [ -f "${OUT_DIR}/${OUT_MD}" ]; then |
| 236 | + cat "${OUT_DIR}/${OUT_MD}" |
| 237 | + else |
| 238 | + echo "_No markdown report file found:_ \`${OUT_DIR}/${OUT_MD}\`" |
| 239 | + fi |
| 240 | + echo "" |
| 241 | + echo "### Artifacts" |
| 242 | + echo "" |
| 243 | + echo "- \`${OUT_DIR}/${OUT_JSON}\`" |
| 244 | + echo "- \`${OUT_DIR}/${OUT_SARIF}\`" |
| 245 | + echo "- \`${OUT_DIR}/${OUT_LOG}\`" |
| 246 | + echo "- \`${OUT_DIR}/${OUT_MD}\`" |
| 247 | + } >> "$GITHUB_STEP_SUMMARY" |
| 248 | +
|
211 | 249 | - name: Upload artifacts (reports) |
212 | 250 | if: always() |
213 | 251 | uses: actions/upload-artifact@v4 |
|
0 commit comments