This is mainly for me, but it's a way of going through the Github repositories that you have access to, to check all the things you'd usually expect.
Because I've got like ~100 repos and keep changing how I do things, and it annoys me to work on an old one and hit all the weird edge cases I've fixed elsewhere.
Install using uv (recommended) or pip:
# Or install from source
git clone https://github.com/yaleman/github_linter.git
cd github_linter
uv syncCreate a configuration file at ~/.config/github_linter.json or in your project directory:
{
"github": {
"token": "ghp_your_personal_access_token_here"
},
"linter": {
"owner_list": ["your_github_username"]
}
}Generating a Personal Access Token (PAT):
- Go to GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)
- Click "Generate new token" > "Generate new token (classic)"
- Select scopes:
repo(for full repo access) andread:user(for user info) - Copy the token and save it in your config file
List repositories you have access to:
uv run github-linter --list-reposRun all checks on your repositories:
uv run github-linterRun checks for a specific module:
uv run github-linter --module pyproject
uv run github-linter --module dependabotApply automated fixes (requires --fix flag):
uv run github-linter --fixFilter by repository or owner:
uv run github-linter --repo my-project
uv run github-linter --owner my-orgIf you see authentication errors:
- Verify your PAT is correct and has the required scopes (
repo,read:user) - Ensure the token is saved in your config file without extra quotes or whitespace
- Test your token:
curl -H "Authorization: token ghp_your_token" https://api.github.com/user
- The token must have appropriate permissions for the repositories you're checking
- For organization repos, you need to be a member with at least read access
- Check the module name matches one of the available modules:
branch_protection,codeowners,dependabot,generic,github_actions,issues,mkdocs,pyproject,security_md,terraform - Run
uv run github-linter --helpto see all available options
If you hit GitHub API rate limits:
- Use a PAT instead of unauthenticated requests
- Reduce the number of repositories checked at once using
--repoor--ownerfilters
- Checks for a (valid-ish) config
- Files you want gone
CODEOWNERSgeneration- generation of
.github/FUNDING.yml
- Checks for github actions tests and stuff
- Checks for open Issues
- Checks for open Pull Requests
Only runs if you've got Python.
- Checks authors based on a list.
- Check module name matches repo
- TODO: Check for imports, maybe?
- Checks it exists
- Checks for max line length configuration
- TODO: Checks for other things (typically I disable TODO's, IE W0501)
- TODO: flesh this out
- Checks for provider versions
- Checks you have provider config for all your required providers.
- Doesn't check for much - have moved this to github_actions
- checks if you've got mkdocs-looking things and then makes sure you've got a github actions thing to run them
The config file is called github_linter.json - you can put it in the local dir or ~/.config/github_linter.json - I've included my configuration in the repository.
Each test module has its defaults, in the DEFAULT_CONFIG attribute.
For an example:
>>> import github_linter.tests.pyproject
>>> print(github_linter.tests.pyproject.DEFAULT_CONFIG)
{'build-system': ['flit_core.buildapi', 'poetry.core.masonry.api'], 'readme': 'README.md'}"github" : {
"token" : "<pat>"
}"github" : {
"username" : "<your_username>",
"password" : "<your_password>"
}"github" : {
"ignore_auth" : true
}- Add a module under
github_linter/tests/ - Set
CATEGORY: str = "nameofmodule"to a name which will go in the reports. - Set
LANGUAGES: List[str] = []to a list of lower case languages, eg: python / javascript / rust / shell / "all" which matches all. This is based on GitHub's auto-detection. - Call check functions
check_<something> - Call fix functions
fix_<something> - Import the module in
tests/__init__.pyas part of the bigfrom . import ()block. - Eat cake.
The container runs an entrypoint of /bin/bash which puts you in an environment where the package and non-dev deps are installed.
The container name to pull is ghcr.io/yaleman/github_linter:latest.
This should auto-build with github actions (soon!) but here's a handy command:
docker build -t 'ghcr.io/yaleman/github_linter' .Running the web server.
docker run --rm -it \
* e "GITHUB_TOKEN=${GITHUB_TOKEN}" \
* v "$(pwd)/github_linter.json:/home/useruser/github_linter.json" \
* p '8000:8000' \
ghcr.io/yaleman/github_linter:latest \
python -m github_linter.web