Skip to content

mathieurivierre/github-sonar-checker

Repository files navigation

Sonar Status Checker

This directory contains a standalone script that:

  1. Lists the repositories assigned to a GitHub team.
  2. Lists the projects available in Sonar.
  3. Reports whether each GitHub repository appears to exist in Sonar.
  4. Marks repositories as excluded when they have neither a root pom.xml nor a root package.json.

Requirements

  • Python 3.9+
  • Node.js on PATH for Excel export
  • Either:
    • a GitHub token with access to read the target organization/team
    • or GitHub CLI (gh) installed and authenticated with gh auth login
  • A Sonar token with permission to browse projects

Configuration

The script reads its credentials from CLI flags or environment variables. For GitHub auth it uses this order:

  1. --github-token
  2. GITHUB_TOKEN
  3. gh auth token

It also auto-loads a local .env file from the current directory before reading environment variables.

For teammates, start from .env.example and create a local .env with your own credentials and exclusions.

If you want to rely on GitHub CLI instead of exporting GITHUB_TOKEN, log in once:

gh auth login

To create a Sonar token:

  1. Log in to your Sonar instance
  2. Open your profile menu
  3. Go to My Account
  4. Open Security
  5. Generate a new token
  6. Copy it immediately, because Sonar only shows it once

Then set the rest:

export GITHUB_ORG="your-org"
export GITHUB_TEAM_SLUG="your-team-slug"
export SONAR_URL="https://sonar.example.com"
export SONAR_TOKEN="sonar_token"

Or copy .env.example to .env and fill in your own values.

Optional:

export GITHUB_API_URL="https://api.github.com"
export GITHUB_REPO_PREFIXES="analytics-,shared-"
export GITHUB_REPO_IGNORE_LIST="analytics-wrong-match"
export GITHUB_REPO_OBSOLETE_LIST="analytics-sunset-service"
export GITHUB_REPO_NO_PRODUCTIVE_CODE_LIST="shared-docs-only"
export GITHUB_REPO_FORKED_LIBRARIES_LIST="analytics-forked-lib"
export XLSX_OUTPUT_PATH=""

GITHUB_REPO_PREFIXES is a comma-separated allowlist on GitHub repository names. Only repositories whose names start with one of those prefixes are included in the report. Set it to an empty string to disable prefix filtering.

The exclusion lists are comma-separated and each entry can be either a repo name such as analytics-legacy or a full repo name such as mapp-digital/analytics-legacy.

For JavaScript submodules under packages/, exclusions can also target the submodule using one of these forms:

  • submodule-name
  • packages/submodule-name
  • repo-name/packages/submodule-name
  • org/repo-name/packages/submodule-name

Use the most specific form when possible. org/repo-name/packages/submodule-name is the safest choice.

  • GITHUB_REPO_IGNORE_LIST: wrong match, completely omitted from the script output
  • GITHUB_REPO_OBSOLETE_LIST: sunset projects not being integrated to Sonar
  • GITHUB_REPO_NO_PRODUCTIVE_CODE_LIST: projects that do not make sense in Sonar
  • GITHUB_REPO_FORKED_LIBRARIES_LIST: forked libraries that should be excluded from Sonar tracking

XLSX_OUTPUT_PATH controls where the script writes the Excel workbook. If unset or empty, the script generates a timestamped filename in outputs/ so each run creates a new workbook. Set it to an empty string only if you want the default timestamped behavior. If node is not on PATH, you can override the binary with NODE_BINARY=/absolute/path/to/node.

Usage

Default table output:

python3 check_team_repos_against_sonar.py

The script writes progress logs to stderr while it runs, so long GitHub and Sonar scans stay visible without changing the table/JSON output on stdout. It also writes an Excel workbook to a timestamped file in outputs/ by default.

Only list repositories missing from Sonar:

python3 check_team_repos_against_sonar.py --only-missing

--only-missing excludes repositories that were marked as excluded.

JSON output:

python3 check_team_repos_against_sonar.py --format json

Strict mode only accepts exact matches against Sonar project key:

python3 check_team_repos_against_sonar.py --strict-exact

Override any setting from the command line:

python3 check_team_repos_against_sonar.py \
  --github-org your-org \
  --github-team your-team-slug \
  --github-repo-prefixes "analytics-,shared-" \
  --github-repo-ignore-list "analytics-wrong-match" \
  --github-repo-obsolete-list "analytics-sunset-service" \
  --github-repo-no-productive-code-list "shared-docs-only" \
  --github-repo-forked-libraries-list "analytics-forked-lib" \
  --xlsx-output "outputs/sonar_status_report_20260421_113500.xlsx" \
  --sonar-url "https://sonar.example.com" \
  --sonar-token "$SONAR_TOKEN"

Matching behavior

By default the script tries these checks in order:

  1. If a repository has a root pom.xml, the script reads it from GitHub and tries to derive a Maven-style Sonar key as groupId:artifactId
  2. If a repository has a root package.json, the script reads it from GitHub and, for JavaScript matching, treats the repository folder name as the expected Sonar key and the package name as the expected Sonar name
  3. Exact match against Sonar project key using the derived Maven key, or the JavaScript key/name pair
  4. Exact match against Sonar project key using deterministic repository-based fallbacks such as full_name, name, and the prefix-stripped name like analytics-foo -> foo
  5. For JavaScript repositories with a root package.json, if the repository is still missing, the script inspects packages/*/package.json and checks each subpackage with subpackage folder -> Sonar key and package.json name -> Sonar name. If every subpackage is present, the parent repository is marked as present and sonar_name contains a comma-separated list of the matched submodules.
  6. Normalized versions of the same candidates are used as a fallback, unless --strict-exact is enabled

Outside the JavaScript key/name pair checks, the script does not use Sonar project name as a standalone match target.

If the normalized key lookup matches more than one Sonar project, the script reports the repository as ambiguous instead of guessing.

Before matching, the script filters GitHub repositories by name prefix. By default it includes only repositories whose names start with analytics- or shared-, and this can be changed with GITHUB_REPO_PREFIXES or --github-repo-prefixes.

After prefix filtering, repositories can be marked Excluded for one of these reasons:

  • Obsolete
  • No Productive Code
  • Forked Libraries

Repositories with neither a root pom.xml nor a root package.json automatically get the reason No Productive Code.

Repositories in GITHUB_REPO_IGNORE_LIST are not shown at all in the results table or summary.

Excluded repositories stay in the main results table, the present_in_sonar column shows Yes, Missing, or Excluded, and the reason column is filled when a repository is excluded.

About

GitHub Sonar Checker compares the repositories owned by a GitHub team with the projects available in Sonar, applies repository and submodule-aware matching rules, and produces a report in both terminal and Excel formats.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors