Skip to content

ydah/nomos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nomos header logo Bring harmony to your pull requests.

Ruby Version License Gem Version CI Status

Features · Installation · Quick Start · Configuration · Rules · Reporters · How It Works


Nomos evaluates PR metadata and diffs, then reports findings as message, warn, or fail. It is designed for fast startup, minimal API calls, and clear configuration.

Features

  • Diff-driven by default with optional lazy diff fetching
  • Built-in cache to avoid redundant GitHub API calls
  • Parallel rule execution
  • Built-in rules plus Ruby DSL for custom checks
  • Multiple reporters: GitHub comment, console, JSON
  • Strict mode for CI gating

Installation

Add to your Gemfile:

gem "nomos"

Then install:

bundle install

Quick Start

Run in CI or locally:

nomos run

Required ENV

  • GITHUB_TOKEN (GitHub API token)
  • GITHUB_REPOSITORY (e.g. owner/repo)
  • GITHUB_EVENT_PATH (path to GitHub event JSON)

Local override:

  • NOMOS_REPOSITORY and NOMOS_PR_NUMBER if GITHUB_EVENT_PATH is not available

GitHub Actions

- name: Nomos
  run: nomos run
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Configuration

Create nomos.yml:

version: 1

reporter:
  github: true
  console: true

performance:
  concurrency: 4
  cache: true
  lazy_diff: true
  timing: false

rules:
  - name: no_large_pr
    type: builtin.no_large_pr
    params:
      max_changed_lines: 800

  - name: require_changelog
    type: builtin.require_file_change
    params:
      patterns:
        - CHANGELOG.md

  - name: custom_rules
    type: ruby.file
    params:
      path: .nomos/rules.rb

Performance notes:

  • Cache file defaults to .nomos/cache.json (override with performance.cache_path)
  • Use --no-cache to disable cache and lazy diff for a single run

CLI

nomos run [--config PATH] [--strict] [--debug] [--no-cache] [--reporter github,console,json]
nomos init
nomos doctor

Rules

Built-in rules

  • builtin.no_large_pr
  • builtin.require_file_change
  • builtin.forbid_paths
  • builtin.require_labels
  • builtin.todo_guard

Ruby DSL (.nomos/rules.rb)

rule "no_debugger" do
  changed_files.grep(/\.rb$/).each do |file|
    if diff(file).include?("binding.pry")
      fail "binding.pry detected", file: file
    end
  end
end

Available DSL API:

changed_files

Array of changed file paths.

rule "example_changed_files" do
  changed_files.grep(/\.md$/).each do |file|
    message "Docs updated", file: file
  end
end

diff(file)

Unified diff for a file (string; empty if unavailable).

rule "example_diff" do
  if diff("lib/app.rb").include?("binding.pry")
    fail "Debug hook found", file: "lib/app.rb"
  end
end

pr_title

PR title string.

rule "example_pr_title" do
  warn "Title should start with [chore]", file: "PR" unless pr_title.start_with?("[chore]")
end

pr_body

PR body string.

rule "example_pr_body" do
  fail "PR body must include a checklist", file: "PR" unless pr_body.to_s.include?("- [ ]")
end

pr_number

PR number.

rule "example_pr_number" do
  message "Reviewing PR ##{pr_number}"
end

pr_author

PR author login.

rule "example_pr_author" do
  warn "First-time contributor", file: "PR" if pr_author == "new-contributor"
end

pr_labels

Array of label names.

rule "example_pr_labels" do
  fail "Missing security label", file: "PR" unless pr_labels.include?("security")
end

repo

Repository identifier (owner/repo).

rule "example_repo" do
  message "Running in #{repo}"
end

base_branch

Base branch name.

rule "example_base_branch" do
  warn "Target branch should be main", file: "PR" unless base_branch == "main"
end

ci

CI context hash.

rule "example_ci" do
  fail "Missing CI provider info", file: "CI" unless ci["provider"]
end

message(text, **opts)

Add informational finding.

rule "example_message" do
  message "Heads up", file: "README.md", line: 1, code: "docs"
end

warn(text, **opts)

Add warning finding.

rule "example_warn" do
  warn "Large change set", file: "PR", code: "size"
end

fail(text, **opts)

Add failure finding.

rule "example_fail" do
  fail "Missing CHANGELOG entry", file: "CHANGELOG.md", code: "changelog"
end

Adding custom rules

  1. Create .nomos/rules.rb and define one or more rule "name" blocks.
  2. Register the file in nomos.yml under rules with type: ruby.file and params.path: .nomos/rules.rb.
  3. Run nomos run (or your CI job) to verify the rule executes.

Example:

# .nomos/rules.rb
rule "require_docs_change" do
  unless changed_files.any? { |file| file.start_with?("docs/") }
    fail "Docs must be updated for this change", file: "docs/"
  end
end
# nomos.yml
rules:
  - name: require_docs_change
    type: ruby.file
    params:
      path: .nomos/rules.rb

Reporters

  • GitHub comment reporter
  • Console reporter
  • JSON reporter (for post-processing)

How It Works

  1. Load PR context from GitHub API or event payload
  2. Fetch changed files and patches (lazy diff optional)
  3. Run rules in parallel where safe
  4. Report findings to configured outputs
  5. Exit with CI-friendly status

Development

bundle exec rspec

License

MIT License. See LICENSE file for details.