Codatus scans every repository in a GitHub organization against a set of engineering standards and produces a Markdown compliance report.
It answers one question: does each repo in your org meet the baseline you care about?
This repository is a Go library and a CLI. Posting the report (e.g., as a GitHub Issue) is the caller's responsibility - the scanner returns structured results and Markdown, nothing more.
- Codatus receives a GitHub org to scan.
- It lists all non-archived repositories in the org.
- For each repo, it runs 11 rule checks (see below).
- It produces a single Markdown report summarizing pass/fail per repo per rule.
The CLI prints the Markdown to stdout. Callers using the library get both the structured []RepoResult and can generate the Markdown via GenerateReport.
Each rule produces a pass or fail result per repository. There are no scores, weights, or severity levels - just pass/fail.
Check: the GitHub repository description field is not blank.
Pass: description is set and non-empty. Fail: description is blank or not set.
Check: a .gitignore file exists in the repo root.
Pass: file found. Fail: file not found.
Check: a README.md file exists in the repo root and is larger than 2048 bytes.
Pass: README.md exists and is >2048 bytes.
Fail: README.md is missing, or exists but is ≤2048 bytes.
Check: a LICENSE or LICENSE.md file exists in the repo root.
Pass: file found. Fail: file not found.
Check: a SECURITY.md file exists in the repo root or .github/SECURITY.md.
Pass: file found in either location. Fail: file not found.
Check: at least one file exists under .github/workflows/ with a .yml or .yaml extension.
Pass: one or more workflow files found.
Fail: .github/workflows/ is missing or empty.
Check: a directory exists at the repo root level whose name indicates tests. Recognized names: test, tests, __tests__, spec, specs.
Pass: at least one matching directory found. Fail: none found.
Check: a CODEOWNERS file exists in one of the three standard locations: root (/CODEOWNERS), docs/CODEOWNERS, or .github/CODEOWNERS.
Pass: file found in any of the three locations. Fail: file not found in any location.
Check: the default branch has branch protection rules enabled (via the GitHub API's branch protection endpoint).
Pass: branch protection is enabled on the default branch. Fail: branch protection is not enabled, or the API returns 404 (no protection configured).
Check: the default branch's branch protection rules require at least one approving review before merging (via the GitHub API - required_pull_request_reviews.required_approving_review_count >= 1).
Pass: required reviewers is set to 1 or more. Fail: required reviewers is not configured, or set to 0, or branch protection is not enabled.
Check: the default branch's branch protection rules require at least one status check to pass before merging (via the GitHub API - required_status_checks is configured with one or more contexts).
Pass: at least one required status check is configured. Fail: required status checks are not configured, or the list of required contexts is empty, or branch protection is not enabled.
The report is a single Markdown document. Structure:
# Codatus - Org Compliance Report
**Org:** {org_name}
**Scanned:** {timestamp}
**Repos scanned:** {count}
**Compliant:** {n}/{total} ({percent}%)
**Skipped:** {count} <-- only if any repos were skipped
## Summary
| Rule | Passing | Failing | Pass rate |
|------|---------|---------|----------|
| Has branch protection | 1 | 3 | 25% |
| Has required reviewers | 1 | 3 | 25% |
| ... | ... | ... | ... |
## ✅ Fully compliant ({n} repos)
<details>
<summary>All rules passing</summary>
[repo-a](https://github.com/{org}/repo-a)
[repo-b](https://github.com/{org}/repo-b)
</details>
## ❌ Non-compliant ({n} repos)
<details>
<summary><a href="https://github.com/{org}/repo-c">repo-c</a> - {n} failing</summary>
- Has branch protection
- Has required reviewers
</details>
## ⚠️ Skipped ({n} repos) <-- only if any repos were skipped
- [empty-repo](https://github.com/{org}/empty-repo) - repository is empty
- [huge-repo](https://github.com/{org}/huge-repo) - file tree too large (truncated by GitHub API)
The summary table is sorted by pass rate ascending (worst compliance first). Sections are omitted when empty (e.g., no "Fully compliant" section if all repos have failures). Skipped repos are those that could not be scanned (empty repos, truncated file trees, API errors) - they are excluded from the compliance count.
The scanner module accepts a Config struct with the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
Org |
string |
Yes | GitHub organization name to scan |
Token |
string |
Yes | GitHub token (PAT or GitHub App installation token) |
Scan also accepts functional options:
| Option | Description |
|---|---|
WithBaseURL(url string) |
Override the GitHub API base URL. Defaults to the public GitHub API. Useful for testing against a mock server or targeting GitHub Enterprise. |
The token must have the following permissions across the org:
repo(read access to repo contents and branch protection)admin:org(read access to list org repos)
How these values are sourced (env vars, CLI flags, config file) is the responsibility of the caller, not the scanner module.
The codatus binary reads CODATUS_ORG and CODATUS_TOKEN from the environment, runs a scan, and prints the Markdown report to stdout. Log output (scan summary, errors) goes to stderr so stdout stays clean for piping.
CODATUS_ORG=myorg CODATUS_TOKEN=ghp_... codatus > report.md- Not a velocity/DORA metrics tool. It does not measure cycle time, deployment frequency, or review speed. That's a different product category.
- Not a security scanner. It checks whether
SECURITY.mdexists and whether branch protection is on, but it does not scan code for vulnerabilities. - Not a developer portal. There is no service catalog, no scaffolding, no self-service actions. Just standards compliance.