{"id":13721525,"url":"https://github.com/enkessler/cuke_linter","last_synced_at":"2026-03-10T04:03:13.733Z","repository":{"id":34110081,"uuid":"160596845","full_name":"enkessler/cuke_linter","owner":"enkessler","description":"A linting tool for Cucumber","archived":false,"fork":false,"pushed_at":"2026-01-18T10:42:55.000Z","size":518,"stargazers_count":32,"open_issues_count":7,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-02-12T21:54:52.233Z","etag":null,"topics":["cucumber","gherkin","hacktoberfest","lint","linter","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/enkessler.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-12-06T00:39:26.000Z","updated_at":"2026-01-18T10:42:48.000Z","dependencies_parsed_at":"2025-01-17T23:45:18.708Z","dependency_job_id":"b8fcb419-dd56-4b2d-9782-992c6a02b369","html_url":"https://github.com/enkessler/cuke_linter","commit_stats":{"total_commits":351,"total_committers":8,"mean_commits":43.875,"dds":0.09686609686609682,"last_synced_commit":"3916466aecaf30d090d23a87caac9e41c3ce2543"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/enkessler/cuke_linter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enkessler%2Fcuke_linter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enkessler%2Fcuke_linter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enkessler%2Fcuke_linter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enkessler%2Fcuke_linter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enkessler","download_url":"https://codeload.github.com/enkessler/cuke_linter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enkessler%2Fcuke_linter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29450638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T15:52:44.973Z","status":"ssl_error","status_checked_at":"2026-02-14T15:52:11.208Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cucumber","gherkin","hacktoberfest","lint","linter","ruby"],"created_at":"2024-08-03T01:01:18.196Z","updated_at":"2026-03-10T04:03:13.705Z","avatar_url":"https://github.com/enkessler.png","language":"Ruby","readme":"Basic stuff:\n[![Gem Version](https://badge.fury.io/rb/cuke_linter.svg)](https://rubygems.org/gems/cuke_linter)\n[![Project License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/mit-license.php)\n[![Downloads](https://img.shields.io/gem/dt/cuke_linter.svg)](https://rubygems.org/gems/cuke_linter)\n\nUser stuff:\n[![Cucumber Docs](http://img.shields.io/badge/Documentation-Features-green.svg)](https://github.com/enkessler/cuke_linter/tree/master/testing/cucumber/features)\n[![Yard Docs](http://img.shields.io/badge/Documentation-API-blue.svg)](https://www.rubydoc.info/gems/cuke_linter)\n\nDeveloper stuff:\n[![Build Status](https://github.com/enkessler/cuke_linter/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/enkessler/cuke_linter/actions/workflows/ci.yml)\n[![Coverage Status](https://coveralls.io/repos/github/enkessler/cuke_linter/badge.svg?branch=master)](https://coveralls.io/github/enkessler/cuke_linter?branch=master)\n[![Maintainability](https://api.codeclimate.com/v1/badges/d1b86760e59a457c8e73/maintainability)](https://codeclimate.com/github/enkessler/cuke_linter/maintainability)\n[![Inline docs](http://inch-ci.org/github/enkessler/cuke_linter.svg?branch=master)](https://inch-ci.org/github/enkessler/cuke_linter?branch=master)\n\n---\n\n# CukeLinter\n\nSo you have started to use Cucumber to describe your system in the abstract, natural language style of Gherkin. But wait! All of your feature files are themselves code and that means that they may need the same protection from anti-patterns as the lower level source code of your system. Enter `cuke_linter`.\n\nThis gem provides linting functionality for `.feature` files by building upon the modeling capabilities of the [cuke_modeler](https://github.com/enkessler/cuke_modeler) gem. By passing models through a set of linters, reports can be generated that will inform you of potential bugs, style violations, or anything else that you can define as a problem  via custom linters! \n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'cuke_linter'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install cuke_linter\n\n## Usage\n\n#### From the command line\n\nThe easiest way to use the gem is to use all of the defaults by invoking it from the command line directly.\n\n```\n$ cuke_linter\n```\n\nAdditional command line options can be provided that can adjust the default behavior. See [documentation](#documentation) for specifics.\n\n#### From a Ruby script\n\nThe linter can also be used inside of a Ruby script, like so:\n\n```\nrequire 'cuke_linter'\n\nCukeLinter.lint\n```\n\nThe linting will happen against a tree of `CukeModeler` models that is generated based on the current directory. You can generate your own model trees and use them instead, if desired, or even provide specific file paths that will be modeled and linted.\n\n`cuke_linter` comes with a set of pre-made linters and will use them by default but custom linters can be used instead. Custom linters can be any object that responds to `#lint` and returns a detected issue (or `nil`) in the format of\n\n```\n{ problem: 'some linting issue',\n  location: 'path/to/file:line_number' }\n```\n\nNote that a linter will receive, in turn, *every model* in a model tree in order for it to have the chance to detect problems with it. Checking the model's class before attempting to lint it is recommended.\n\n**In order to simplify the process of creating custom linters a base class is provided (see [documentation](#documentation)).**\n\n`cuke_linter` comes with a set of pre-made formatters and will use them by default but custom formatters can be used instead. Custom formatters can be any object that responds to `#format` and takes input data in the following format:\n\n```\n[\n { linter: 'some linter name',\n   problem: 'some linting issue',\n   location: 'path/to/file:line_number' },\n { linter: 'some linter name',\n   problem: 'some linting issue',\n   location: 'path/to/file:line_number' },\n   # etc.\n]\n```\n\nAll formatted data will be output to STDOUT unless a file location is provided as an alternative.\n\nBelow is an example of using non-default linting options.\n\n```\nrequire 'cuke_linter'\n\nclass MyCustomLinter\n\n  def name\n    'MyCustomLinter'\n  end\n\n  def lint(model)\n    return nil unless model.is_a?(CukeModeler::Scenario)\n\n    if model.name.empty?\n      { problem: 'Scenario has no name', \n        location: \"#{model.get_ancestor(:feature_file).path}:#{model.source_line}\" }\n    else\n      nil\n    end\n  end\n\nend\n\nclass MyCustomFormatter\n\n  def format(linting_data)\n    formatted_data = ''\n\n    linting_data.each do |lint_item|\n      formatted_data \u003c\u003c \"#{lint_item[:linter]}\\n\"\n      formatted_data \u003c\u003c \"  #{lint_item[:problem]}\\n\"\n      formatted_data \u003c\u003c \"    #{lint_item[:location]}\\n\"\n    end\n\n    formatted_data\n  end\n\nend\n\nlinter               = MyCustomLinter.new\nformatter            = MyCustomFormatter.new\noutput_path          = \"#{__dir__}/my_report.txt\"\nmodel_tree_root      = CukeModeler::Directory.new(Dir.pwd)\nadditional_file_path = 'path/to/some.feature'\n\n# Providing the formatter twice so that output also is printed to the console\nCukeLinter.lint(linters: [linter],\n                formatters: [[formatter], [formatter, output_path]],\n                model_trees: [model_tree_root],\n                file_paths: [additional_file_path])\n```\n\n### Configuration\n\nRather than using the default linters or providing a custom set of of modified linters every time linting occurs, which linters to use and any linter specific modifications (such as choosing a non-default dialect) can be configured in a more static manner via a configuration file or setting the configuration directly in code. See [documentation](#documentation) for specifics.\n\n\n### \u003ca id=\"documentation\"\u003e\u003c/a\u003eEverything Else\n\nFor more detailed examples of usage, see the documentation [here](https://github.com/enkessler/cuke_linter/tree/master/testing/cucumber/features).\n\n## Development and Contributing\n\nSee [CONTRIBUTING.md](https://github.com/enkessler/cuke_linter/blob/master/CONTRIBUTING.md)\n\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","funding_links":[],"categories":["Tools, Libraries \u0026 Frameworks","Tools"],"sub_categories":["Ruby"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenkessler%2Fcuke_linter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenkessler%2Fcuke_linter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenkessler%2Fcuke_linter/lists"}