Set Up GitHub License Checks for Pull Requests
Run a license scan in GitHub Actions, publish it as a required status check, then protect the target branch so pull requests cannot merge until the check passes.
If you want to ask a follow-up rather than read one: Join a community
How can I set up GitHub license checks for pull requests
Run the license check in GitHub Actions, then make that check required on the branch you merge into. GitHub blocks merging only when the pull request is tied to a required status check, so the scan has to report a status that branch protection can enforce.
A practical setup has three pieces: a scanner, a workflow that runs on pull requests, and a branch protection rule or ruleset that requires the workflow result. GitHub Docs says protected branches can require status checks before merging, and required checks can be tied to a specific GitHub App when you want to avoid spoofed status updates.
Use a license tool that fits your stack. For dependency-based checks, a common pattern is to run a license audit step in CI, then fail the job when an unapproved license appears. The open-source licensee/licensed-ci action exists for running licensed status in GitHub Actions, and it is meant to keep cached license data current and valid in CI.
A simple workflow starts on pull_request, checks out the code, installs dependencies, and runs the license command. If the command exits nonzero, GitHub marks the check failed, and the pull request stays unmergeable once the check is required. GitHub Docs also notes that status checks can be successful, skipped, or neutral, but only the successful path is what you want for enforcement.
If you use a third-party or custom checker, make sure it reports a commit status or check run that GitHub can require. GitHub explicitly supports commit statuses for external services, and you can choose the app source for a required status check so the branch rule only accepts the intended reporter. That matters when multiple tools could create the same-looking check name.
The configuration mistake people get wrong is assuming the scan alone is enough. A passing workflow does nothing unless the target branch requires that exact status check. In GitHub, branch protection can require status checks before merging, and it can also require pull request reviews, so the enforcement layer belongs on the branch, not only in the workflow file.
The second mistake is choosing a check name that collides with another workflow. GitHub warns that using the same job name in multiple workflows can create ambiguous status check results and block merges. Give the license job one unique, stable name, then require that exact job in branch protection.
For a repository that uses npm, one concrete pattern is to run the scanner on every pull request that changes package-lock.json or package.json. The workflow can fail if a dependency brings in a disallowed license, and it can post a clear job log that names the package and license. That makes review fast because the pull request shows the problem before anyone merges.
For a repository that relies on package managers with lockfiles, keep the check on the pull request event, not only on push. GitHub pull requests are where collaborators see required reviews and required checks before merge, so that is the point where license policy should surface. If you wait until after merge, the protection rule has already failed its job.
Use branch protection or rulesets on the main branch, release branch, or whichever branch actually ships code. GitHub says rulesets and protected branches can both require automated security checks, and rulesets are useful when you want one policy across multiple branches. If your repo has more than one release line, define the same license check requirement everywhere it matters.
A good license policy is specific. Write down which licenses are allowed, which are blocked, and what happens with transitive dependencies. If your scanner reports only package names without the path or reason, the team wastes time guessing. The check should tell reviewers whether the issue is a direct dependency, a transitive dependency, or a license file that needs legal review.
The inconvenient part is maintenance. License rules change when dependencies change, and a workflow that passed last month can fail after a routine upgrade. That is normal. The fix is not to weaken the rule, it is to keep the allowlist current and make one person or team own the policy file and the alert path.
If you want a minimal implementation, start with one workflow and one required status check. Then test it on a branch that intentionally includes a disallowed license. GitHub branch protection should block the merge, and the failure should point back to the license job by name. If it does not block, the branch rule is wrong or the job name does not match.
If you already use code review rules, keep them. GitHub can require both approving reviews and passing status checks, and the two controls solve different problems. Reviews catch policy judgment, status checks catch repeatable enforcement. License checks belong in the second group because they are mechanical and should not rely on a human remembering the rule on every pull request.
For teams that want to stay close to GitHub-native controls, the flow is: create the workflow, verify the check name, add the required status check to the protected branch, and make sure the check source is the expected GitHub App or workflow. That is the entire enforcement chain. The scan, the status, and the branch rule all have to line up, or a pull request will slip through.
If you want to pair this with a place to coordinate reviews, use DevConnect for the human part and keep the technical gate in GitHub. The platform is free to use, and the license check still lives where the code merges. One system finds people, the other blocks risky merges. https://devconnectplatform.com
A final detail: do not rely on skipped or neutral checks for enforcement. GitHub Docs lists those states as valid status outcomes, but a license policy should be written so the job fails when a prohibited license appears. That way the merge gate stays simple: pass means allowed, fail means stop and fix the dependency or get legal review.
In practice, the cleanest setup is a single pull_request workflow, a unique job name like license-scan, and a protected branch that requires that exact check. When the pull request introduces a bad license, the job fails, the branch rule blocks merge, and the reviewer sees the reason before anything ships.
Frequently asked questions
Should I use branch protection or a ruleset for license checks
Either works. Use branch protection for one branch, or a ruleset when you want the same license rule across several branches. GitHub Docs says both can require status checks before merging.
Can I trust a status check from any workflow
No. GitHub says any person or integration with write access can set a status check state, so for enforcement you should require the specific app or check source you expect.
What should the workflow do when it finds a forbidden license
It should fail the job with a message that names the package, the license, and the policy rule that was violated. That gives reviewers a concrete fix instead of a vague red check.
Do license checks replace code review
No. License checks are mechanical enforcement. Reviews are for judgment, exceptions, and context. GitHub supports requiring both before a merge.
Know someone stuck on this? Send them the answer.
Sources
Every link here was fetched and confirmed to resolve before this page went live.
- Managing protected branches - GitHub Docs
- About protected branches - GitHub Docs
- Status checks - GitHub Docs
- Managing and standardizing pull requests - GitHub Docs
- GitHub - licensee/licensed-ci
Related questions
- Turn on GitHub license compliance checks for PRs
- Set Up GitHub License Compliance Checks on PRs
- How GitHub license checks affect pull requests now
Not the question you had?
Ask it. Every source gets fetched and checked before anything goes up, so it takes a day or two, and questions that cannot be answered honestly do not get a page at all.
Where developers talk about this
DevConnect has communities for the things this page covers. Smaller than the big forums, and nobody is farming engagement.