The project is in a healthy, maintained state
Packages baseline RuboCop and erb_lint configs with runtime dependencies for consumer Ruby projects.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

 Project Readme

Baseline

Baseline simplifies managing repositories across multiple organizations and programming language stacks. It provides a homogeneous development environment for language-agnostic developers and a centrally managed baseline for repository owners.

Connect a workflow and Baseline supplies the policy, configuration, runtimes, and implementation. Consumer repositories only declare which capabilities they want and, when necessary, explicit exceptions.

The examples use the latest Baseline release and are updated automatically with every release. Dependabot keeps the pin current in consumer repositories.

Lint automatically

Create .github/workflows/lint.yml:

name: Lint
on:
  push:
    branches: ["main"]
  pull_request:
jobs:
  lint:
    uses: rubykatzen/baseline/.github/workflows/lint-shared.yml@v0.12.0 # x-release-please-version

That is enough to get CI linting. Baseline inspects the tracked files, selects every applicable linter, installs its runtime, and runs it with the canonical configuration. Adding a new supported file type automatically enables its linter on the next run.

When the repository contains .pre-commit-config.yaml, Baseline also checks that its local hooks match the automatically selected CI linters.

Check GitHub configuration

Create .github/workflows/github.yml:

name: GitHub
on:
  push:
    branches: ["main"]
  pull_request:
jobs:
  github:
    uses: rubykatzen/baseline/.github/workflows/github-shared.yml@v0.12.0 # x-release-please-version

Baseline checks the repository settings and labels against config/github.yml. This includes squash-only merging, automatic branch deletion, auto-merge, and the canonical label set and colors. Release Please labels are allowed but optional.

Check shared repository files

Create .github/workflows/embedder.yml:

name: Embedder
on:
  push:
    branches: ["main"]
  pull_request:
jobs:
  embedder:
    uses: rubykatzen/baseline/.github/workflows/embedder-shared.yml@v0.12.0 # x-release-please-version

Baseline checks that the repository contains every fragment declared in config/embedder.yml, including the shared Dependabot configuration and agent instructions. A failure reports all differences, not only the first missing fragment.

Notify Telegram about pull requests

Create .github/workflows/notify-telegram-pr.yml:

name: Notify Telegram PR
on:
  pull_request_target:
    types: [opened, ready_for_review, reopened, closed]
  schedule:
    - cron: "0 10 * * *"
  workflow_dispatch:
jobs:
  notify:
    uses: rubykatzen/baseline/.github/workflows/notify-telegram-pr-shared.yml@v0.12.0 # x-release-please-version
    secrets:
      TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
      TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}

Baseline sends notifications for opened, reopened, ready, and merged pull requests, plus a daily digest of up to ten open non-draft pull requests. Empty digests do not send a message.

pull_request_target keeps Telegram secrets available while loading trusted workflow code from the default branch. The shared workflow does not check out or execute pull request code. Pass the two secrets explicitly rather than using secrets: inherit.

Notify Telegram about closed issues

Issue notifications are optional and can use a different Telegram channel from pull request notifications. Create .github/workflows/notify-telegram-issue.yml:

name: Notify Telegram issue
on:
  issues:
    types: [closed]
jobs:
  notify:
    if: contains(github.event.issue.labels.*.name, 'notify')
    uses: rubykatzen/baseline/.github/workflows/notify-telegram-issue-shared.yml@v0.12.0 # x-release-please-version
    secrets:
      TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
      TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_ISSUE_CHAT_ID }}

The caller decides which closed issues should produce a notification. Change or remove the if condition to match the repository's policy. Baseline only formats and sends the message; it does not modify the issue or its labels.

Explicit exceptions

Automatic policy is the default. When a repository intentionally differs, pass a JSON array through skip:

jobs:
  lint:
    uses: rubykatzen/baseline/.github/workflows/lint-shared.yml@v0.12.0 # x-release-please-version
    with:
      skip: '["rubocop", "herb"]'

The GitHub and Embedder workflows use the same convention:

with:
  skip: '["labels"]'
with:
  skip: '["message-prefix"]'

Unknown names fail the workflow. A skipped linter must also be absent from the Baseline entry in .pre-commit-config.yaml, keeping local and CI linting equal.

Local linting

CI runtime installation is automatic. For local pre-commit use, copy .pre-commit-config.yaml.example and keep only the hooks relevant to the repository:

repos:
  - repo: https://github.com/rubykatzen/baseline
    rev: v0.12.0 # x-release-please-version
    hooks:
      - id: yamllint
      - id: pymarkdown
      - id: ruff
      - id: tombi
      - id: shellcheck
      - id: actionlint
      - id: rubocop
      - id: erb-lint

Pre-commit hooks are thin wrappers and expect their tools on PATH. Install the Python and standalone tools used by the repository:

python -m pip install yamllint pymarkdownlnt ruff tombi
brew install shellcheck actionlint

Ruby projects

Ruby projects get RuboCop and erb_lint, with Baseline's configuration, from one gem:

group :development, :test do
  gem "rubykatzen-baseline", require: false
end

After bundle install, create the project config stubs:

bundle exec baseline-install

The generated .rubocop.yml and .erb_lint.yml inherit the configs shipped in the gem. Project-specific existing violations can remain in .rubocop_todo.yml or .erb_lint_todo.yml; Baseline continues to catch new violations.

Keep Baseline current

Add GitHub Actions and pre-commit ecosystems to .github/dependabot.yml so Dependabot updates every Baseline pin:

version: 2
updates:
  - package-ecosystem: github-actions
    directory: /
    labels: [dependencies]
    commit-message:
      prefix: chore
      include: scope
    schedule:
      interval: daily
      time: "10:00"
      timezone: "Europe/Berlin"
  - package-ecosystem: pre-commit
    directory: /
    labels: [dependencies]
    commit-message:
      prefix: chore
      include: scope
    schedule:
      interval: daily
      time: "10:00"
      timezone: "Europe/Berlin"

Dependabot opens chore(deps): pull requests, which do not request a release by default. Rename a release-worthy dependency update to fix(deps): to request a patch release.

Supported linters

Key Files Configuration
yamllint *.yml, *.yaml config/yamllint.yml
pymarkdown *.md config/pymarkdown.json
ruff *.py config/ruff.toml
tombi *.toml consumer config or Tombi defaults
shellcheck *.sh config/shellcheck.rc
actionlint .github/workflows/*.yml actionlint defaults
rubocop *.rb config/rubocop.yml
erb-lint *.erb config/erb_lint.yml
herb HTML and Rails template variants Herb defaults

See LINTERS-DEFAULTS-OVERRIDES.md for deliberate deviations from upstream linter defaults.

Releasing Baseline

Release Please maintains a release pull request from Conventional Commits on main. Merging it creates the version tag and GitHub Release, publishes the Ruby gem, and updates the floating major and minor tags used by consumers.