Hey everyone! I've been diving deep into Semgrep's CI integrations, but I wanted a way to get a regular, high-level overview of findings across all our repos without having to dig through every pipeline log. Scheduled scans with email reports were the obvious answer, and setting it up was smoother than I expected. Here's how I pieced it together.
First, I set up a dedicated "monitoring" runner. The goal was to have a simple cron job that would:
* Pull the latest code for our key repositories.
* Run a standard Semgrep scan with our centralized rule set.
* Format the results cleanly.
* Email the report to the engineering leads.
I used a simple shell script as the core, triggered by a systemd timer (cron works fine too). The magic for the email was using `semgrep scan --json` and piping the output to `jq` to create a readable HTML summary. I found using `mjml` for the HTML template made it look professional with minimal effort.
The key parts of the setup are:
**1. The Scan Script (`/usr/local/bin/semgrep-scheduled-scan.sh`):**
```bash
#!/bin/bash
# Clone or pull repos, run semgrep, generate report, send mail
REPO_DIR="/opt/scans/repos"
RULES_FILE="/opt/scans/semgrep-rules.yaml"
OUTPUT_JSON="/opt/scans/results-$(date +%Y%m%d).json"
# ... repo sync logic ...
semgrep scan --config $RULES_FILE --json > $OUTPUT_JSON
# Use a Python script with jinja2 to transform the JSON to an HTML email body
python3 /opt/scans/generate_report.py $OUTPUT_JSON | mailx -s "$(date) Semgrep Scan Report" -a "Content-Type: text/html" team@example.com
```
**2. The Report Generator:** This is a small Python script that loads the JSON, extracts critical and high-confidence findings, counts them per repo, and renders a simple HTML table using a template.
**3. Scheduling:** I used a systemd timer unit for more control over logging, but a cron entry like `0 8 * * 1` (every Monday at 8 AM) works perfectly.
The biggest "aha" was configuring the email to group findings by rule and repository – it makes the report instantly actionable. The whole setup runs in a container on a small VM, keeping it isolated and easy to manage.
Has anyone else built something similar? I'm curious if you're integrating findings directly into a dashboard (like Grafana) instead of, or in addition to, email. Also, any tips for managing false positives in these automated reports? They can sometimes clutter the summary.
Ship fast, measure faster.