Anyone else feeling the sticker shock when your GHAS seat count suddenly includes every bot, service account, and admin user you never actually wanted to scan? I was, until I realized we could trim about 30% of our "committers" by excluding these non-human accounts.
The trick is using the `github.repository_dispatch` event in combination with the GitHub API. The core idea is to trigger a workflow that audits recent commits and removes GHAS seats from accounts that match specific criteria (like being a bot, or having "admin" in the login). Here's a basic recipe using n8n, but you could adapt it to Zapier or a scheduled script.
First, you need a way to identify the commits. I set up a weekly webhook that fetches the last 7 days of commits from the repository.
```json
// Example n8n node setup for "Extract Commit Authors"
{
"operation": "getMany",
"resource": "commit",
"parameters": {
"owner": "{{ $('Set Repository').json.owner }}",
"repo": "{{ $('Set Repository').json.repo }}",
"since": "{{ 'now - 7 days' | date }}"
}
}
```
Then, the logic filters out authors where:
* `author.type` equals `"Bot"`
* `author.login` contains strings like `"-bot"`, `"bot-"`, `"admin"`, `"service"`
* The commit message itself is a common bot pattern (e.g., "chore(deps):")
For each matching author, you then call the GitHub API to remove them from the GHAS seat assignment. This is the critical step.
```javascript
// Pseudo-code for the removal logic (to be implemented in an HTTP Request node)
const url = ` https://api.github.com/orgs/YOUR_ORG/ghas/assignments/${username}`;
const method = 'DELETE';
const headers = {
'Authorization': 'Bearer YOUR_PAT',
'Accept': 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28'
};
```
A few important caveats:
* You'll need a GitHub Personal Access Token (PAT) with the `admin:org` scope.
* This works best for **Organization-level** GHAS. For Enterprise, the API endpoint differs.
* Always test in a non-production environment first. You don't want to accidentally remove a real developer.
* Consider adding a manual approval step or a dry-run mode that just logs what it *would* remove.
This has become a scheduled part of our cost-control workflow. It's not a one-time fix, as new bot accounts get created, but running it weekly keeps the seat list clean. Has anyone else built something similar, or found a different angle to tackle this?
if it's manual, it's wrong
Exactly the kind of ops thinking I appreciate. That 30% savings is huge.
One caveat: be careful with the login string filters. We had a legitimate contractor whose handle was `jane-admin-support`. Your filter would have kicked her out. We added a separate validation step to check if the account has a verified human email and recent non-commit activity (like PR comments) before removing the seat.