Finally got tired of waiting 45 minutes for FOSSA to scan the entire monorepo on every PR. It's a compliance checkbox, not a deep philosophical inquiry. Built something that actually makes sense.
The gist: use `git diff` to find changed directories, then run FOSSA's `--only-unpack` flag on those specific paths. Slapped it into a GitHub Action. The core logic is just a shell script.
```bash
# Get unique top-level directories containing changed files
DIRS=$(git diff --name-only HEAD~1 | xargs -I {} dirname {} | cut -d'/' -f1 | sort | uniq)
for DIR in $DIRS; do
if [ -f "$DIR/package.json" ] || [ -f "$DIR/go.mod" ] || [ -f "$DIR/pom.xml" ]; then
echo "Scanning $DIR"
fossa analyze --only-unpack "$DIR" --debug
fi
done
```
Now it finishes in under 15 minutes. Shocking what happens when you think for two seconds instead of just running the brute-force default command.
If it ain't broke, don't 'upgrade' it.
Nice! That's the kind of pragmatic fix I live for. It reminds me of the time we had a similar "checkbox" scan that ran on the whole codebase every night at midnight... and also woke up the entire on-call rotation when it inevitably OOM'd on the biggest service. A targeted approach saves more than just time.
One little caveat I'd add: watch out for deleted directories. Your `-f` check might skip them, but if someone removes a whole module, you might still want to flag that for the compliance folks. Might need a `git log --diff-filter=D` pass as well.
Cutting from 45 to 15 minutes is huge. That's the difference between "annoying gate" and "actually usable step." Good stuff
it worked on my machine
That's such a clean solution. It always amazes me how a simple shell script can replace what teams sometimes build as an entire microservice.
I've seen teams get tripped up by one edge case though: when a PR changes a shared library or a root-level config file, your diff might not catch a directory that *indirectly* needs a scan. Like if `shared-lib/package.json` gets a version bump, every service that depends on it should technically be re-evaluated. Your script would miss that, but honestly? For a compliance checkbox, scanning just the directly changed dirs is probably the right trade-off.
Keep it civil, keep it real.
Exactly. If you're chasing every indirect dependency, you're not building a pipeline, you're building a PhD dissertation. FOSSA's own manifest files already map those transitive dependencies. The scan on the shared lib will catch the version bump, and that's what gets reported. Running it on every consumer is just burning cycles to feel thorough.
The whole point of a tool like this is to be a canary, not a blood test. If a change in a core library introduces a new license issue, it'll be flagged in that library's scan. The consumers will pick it up on their next actual change.
Teams overcomplicate this stuff because they're scared of missing something. But a fast, simple check that runs every time beats a "comprehensive" one that's so slow people bypass it.
SQL is enough
Ha, the midnight OOM special. Been there. Nothing like getting paged because a compliance scan decided to hoover up 32GB on the monolith.
> watch out for deleted directories
Good shout. The `-f` check will definitely fail on a deleted dir. Could adjust it to check if the path *was* a directory in the previous commit. Something like:
```bash
git ls-tree --name-only HEAD~1 "$DIR" 2>/dev/null | grep -q . && WAS_DIR=true
```
But honestly? If someone deletes an entire module, the compliance concern kinda vanishes with it. The real headache is when they delete a single manifest file but leave the rest of the code, because then you're scanning orphaned source. That's where the `--diff-filter=D` trick pays off.
NightOps
That git ls-tree approach is clever, but it introduces a race condition if the directory existed in HEAD~1 but its manifest file didn't. You'd still try to scan a directory without a valid manifest.
The deeper issue is you're now scanning based on the *presence* of a directory, not the *change* to a relevant file. It's more accurate to invert the logic: use `git diff` to find changed manifest files directly, then derive the target directory from that. That handles deletions implicitly.
```bash
git diff --name-only HEAD~1 -- '*/package.json' '*/go.mod' '*/pom.xml' | xargs -I {} dirname {} | sort | uniq
```
This yields directories where a manifest actually changed, which is the precise set `--only-unpack` needs. Deletions are included because the file path is in the diff.
-- bb42
This is the way. The brute-force default scan is a lazy vendor default, not a production-ready step.
Your manifest check is smart, but it's a bit redundant. If you filter for manifest files in the git diff itself, you get the target list directly. You also automatically capture deletions, which your -f check would skip.
The real ROI isn't the 70% time save. It's that the team won't disable the check because it's fast. A slow "perfect" scan is worse than a fast "good enough" one that actually runs.