├── .gitignore ├── .rspec ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── belugas-ruby.gemspec ├── belugas.png ├── bin ├── belugas-ruby ├── console └── setup ├── dev.Dockerfile ├── docker-compose.yml ├── lib ├── belugas │ ├── ruby.rb │ └── ruby │ │ ├── dependency.rb │ │ ├── dispatcher.rb │ │ ├── feature │ │ ├── builder.rb │ │ └── handler.rb │ │ ├── libraries_collection.rb │ │ ├── parser │ │ ├── .#patterns.rb │ │ ├── gemfile.rb │ │ └── patterns.rb │ │ ├── standard_names │ │ └── base.rb │ │ └── version.rb └── rescuer.rb └── spec ├── belugas ├── ruby │ ├── dependency_spec.rb │ ├── dispatcher_spec.rb │ ├── feature │ │ ├── builder_spec.rb │ │ └── handler_spec.rb │ ├── libraries_collection_spec.rb │ ├── parser │ │ ├── gemfile_spec.rb │ │ └── patterns_spec.rb │ └── standard_names │ │ └── base_spec.rb └── ruby_spec.rb ├── spec_helper.rb └── support ├── Gemfile ├── empty_Gemfile ├── no_postgres_Gemfile ├── no_ruby_Gemfile └── ruby_version_with_symbols_Gemfile /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.swp 11 | *.swo 12 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.3.3 4 | script: 5 | - bundle exec rspec spec/ 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at TODO: mayra@icalialabs.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 1: Use ruby 2.3.3 as base: 2 | FROM ruby:2.3.3-alpine 3 | 4 | # 3: We'll add the app's binaries path to $PATH, and set the environment name to 'production': 5 | ENV PATH=/usr/src/app/bin:$PATH 6 | 7 | RUN adduser -u 9000 -D app 8 | 9 | # 4: Copy just the Gemfile & Gemfile.lock, to avoid the build cache failing whenever any other 10 | # file changed and installing dependencies all over again - a must if your'e developing this 11 | # Dockerfile... 12 | ADD ./belugas-ruby.gemspec* /usr/src/app/ 13 | ADD ./lib/belugas/ruby/version.rb /usr/src/app/lib/belugas/ruby/version.rb 14 | ADD ./Gemfile* /usr/src/app/ 15 | 16 | # 5: Install build + runtime dependencies, install/build the app gems, and remove build deps: 17 | RUN set -ex \ 18 | && apk add --no-cache --virtual .app-rundeps icu-libs \ 19 | && apk add --no-cache --virtual .app-builddeps build-base icu-dev cmake \ 20 | && cd /usr/src/app \ 21 | && bundle install --without development test \ 22 | && apk del .app-builddeps 23 | 24 | # 6: Copy the rest of the application code, then change the owner of the code to 'app': 25 | ADD . /usr/src/app 26 | 27 | VOLUME /code 28 | WORKDIR /code 29 | 30 | CMD ["/usr/src/app/bin/belugas-ruby", "analyze"] 31 | 32 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem "pry" 3 | gem "slack-notifier" 4 | 5 | group :test do 6 | gem "simplecov" 7 | gem "codeclimate-test-reporter", "~> 1.0.0" 8 | end 9 | 10 | # Specify your gem's dependencies in belugas-ruby.gemspec 11 | gemspec 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Icalia Labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Belugas Ruby 3 |

4 | 5 | ![Made with Love by Icalia Labs](https://img.shields.io/badge/With%20love%20by-Icalia%20Labs-ff3434.svg) 6 | 7 | ## Overview 8 | 9 | `belugas-ruby` is an engine for detecting application [features](#what-is-a-feature) for Ruby projects based on static analysis, in other words `belugas-ruby` engine can detect the language, framework, database & dependencies your Ruby application is using. 10 | 11 | This engine works as command line interface on your local machine of a Docker container: 12 | 13 |

14 | 15 |

16 | 17 | ## Table of contents 18 | 19 | - [Why?](#why) 20 | - [What is a feature?](#what-is-a-feature) 21 | - [Installation](#installation) 22 | - [Usage](#usage) 23 | - [Contributing](#contributing) 24 | - [Credits](#credits) 25 | 26 | ## Why? 27 | 28 | `belugas-ruby` is part of the [Whales](https://github.com/gueils/whales) ecosystem: A set of tools to automatically dockerize your applications. 29 | 30 | ## What is a feature? 31 | 32 | A feature is an application attribute detected during the static analysis. This analysis is the act of derivating data from code such as programming language, frameworks, service dependencies and so on. See [here](#supported-features) for a list of attributes this engine currently supports. 33 | 34 | A feature has the following format: 35 | 36 | ``` 37 | { 38 | "type":"feature", 39 | "name":"Ruby", 40 | "version":"2.4", 41 | "description":"The application uses Ruby code", 42 | "content":"", 43 | "categories":["Language"], 44 | "cue_locations":[""], 45 | "engines":["belugas","belugas-ruby"] 46 | } 47 | ``` 48 | 49 | Where: 50 | 51 | - **type**: Will always be a _feature_. 52 | - **name**: This is the name of the language, framework or database that is being used in the application. 53 | - **version**: The detected version of the feature. This one is optional 54 | - **description**: A string explaining the feature that was detected. 55 | - **content**: A markdown snippet describing the feature, including deeper explanations and links to other resources. This one is optional 56 | - **categories**: Features are associated with one or more of the following categories: Language, Framework, Database, Library & Service. 57 | - **cue_locations**: An array of Location objects representing the places in the source code that provide evidence of the detected feature. This one is optional 58 | - **engines**: An array of engine names that detected the feature, or refined the data detected by the previous engines. 59 | 60 | ### Supported Features 61 | 62 | Currently `belugas-ruby` can detect the following frameworks, databases, libraries and services: 63 | 64 | Frameworks: 65 | 66 | - Rails 67 | - Sinatra 68 | - Middleman 69 | 70 | Databases: 71 | 72 | - MySQL 73 | - PostgreSQL 74 | - Mongoid 75 | 76 | Libraries & Services: 77 | 78 | - Webkit 79 | - Rmagick 80 | - Sidekiq 81 | 82 | 83 | ## Installation 84 | 85 | ### Prerequisites 86 | 87 | The Belugas Ruby CLI is distributed and run as a [Docker](https://hub.docker.com/r/gueils/belugas-ruby/) image, so you only need to have Docker [installed](https://docs.docker.com/engine/installation/) and running on your machine. 88 | 89 | ### Setup 90 | 91 | Fire up your terminal and run: 92 | 93 | ```console 94 | docker pull gueils/belugas-ruby:development 95 | ``` 96 | 97 | And that's it! 98 | 99 | ## Usage 100 | 101 | Here's where the magic begins, first of all in your terminal go to the project directory you want to analyze: 102 | 103 | ```console 104 | cd code/path_to_project/ 105 | ``` 106 | 107 | And then just execute the following command: 108 | 109 | ```console 110 | docker run \ 111 | --interactive --tty --rm \ 112 | --volume "$PWD":/code \ 113 | gueils/belugas-ruby:development 114 | ``` 115 | 116 | And voilá! The terminal will stream a json output for each of the features detected in the following format: 117 | 118 | ``` 119 | { 120 | "type":"feature", 121 | "name":"Ruby", 122 | "version":"2.3.1", 123 | "description":"The application uses Ruby code", 124 | "categories":["Language"], 125 | "engines":["belugas","belugas-ruby"] 126 | } 127 | { 128 | "type":"feature", 129 | "name":"rails", 130 | "version":"4.2.6", 131 | "description":"The application uses rails", 132 | "content":"", 133 | "categories":["Framework"], 134 | "cue_locations":[""], 135 | "engines":["belugas","belugas-ruby"] 136 | } 137 | { 138 | "type":"feature", 139 | "name":"postgresql", 140 | "version":"9.5.6", 141 | "description":"The application uses postgresql", 142 | "content":"", 143 | "categories":["Database"], 144 | "cue_locations":[""], 145 | "engines":["belugas","belugas-ruby"] 146 | } 147 | { 148 | "type":"feature", 149 | "name":"sidekiq", 150 | "version":"0", 151 | "description":"The application uses sidekiq", 152 | "content":"", 153 | "categories":["Service"], 154 | "cue_locations":[""], 155 | "engines":["belugas","belugas-ruby"] 156 | } 157 | ``` 158 | 159 | ## Contributing 160 | 161 | Everyone is freely to collaborate, just make sure you follow our [code of conduct](https://github.com/gueils/belugas-ruby/blob/master/CODE_OF_CONDUCT.md). Thank you [contributors](https://github.com/gueils/belugas-ruby/graphs/contributors)! 162 | 163 | ### Create an Issue 164 | 165 | Find a bug and don't know how to fix it? Have trouble following the documentation or have a question about the project? Then by all means, please [create an issue](https://github.com/gueils/belugas-ruby/issues/new). 166 | 167 | Just please make sure you check [existing issues](https://github.com/gueils/belugas-ruby/issues) to see if what you're running into has been addressed already. 168 | 169 | ### Submit a Pull Request 170 | 171 | That's great! Just follow this steps: 172 | 173 | 1. Create a separate branch for your edits 174 | 2. Make sure your changes doesn't break the project by running your changes against current specs. **We love tests!** so it'll be even better if you create new ones when needed 175 | 3. Open your pull request against `master` 176 | 177 | Once you've created a pull request, mainteners will chime in to review your proposed changes and to merged it if everything is right :tada: 178 | 179 | ### I want to contribute but don't know where to start 180 | 181 | That's great also! We already have some [open issues](https://github.com/gueils/belugas-ruby/issues) for you to dive in. 182 | 183 | ## Copyright 184 | 185 | See [LICENSE](https://github.com/gueils/belugas-ruby/blob/master/LICENSE.txt) 186 | 187 | ![Icalia Labs](https://raw.githubusercontent.com/icalialabs/kaishi/master/logo.png) 188 | 189 | Belugas-Ruby is maintained by [Icalia Labs](http://www.icalialabs.com/team) 190 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | -------------------------------------------------------------------------------- /belugas-ruby.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'belugas/ruby/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "belugas-ruby" 8 | spec.version = Belugas::Ruby::VERSION 9 | spec.authors = ["Roberto Quintanilla", "Abraham Kuri", "Cejas"] 10 | spec.email = ["weare@icalialabs.com"] 11 | 12 | spec.summary = %q{A Ruby CLI for ruby feature detection} 13 | spec.description = %q{A Ruby CLI for ruby feature detection using awesome Belugas} 14 | spec.homepage = "https://github.com/icalialabs/belugas-ruby" 15 | spec.license = "MIT" 16 | 17 | spec.bindir = "bin" 18 | spec.executables = ["belugas-ruby"] 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_dependency "thor", "~> 0.19" 22 | spec.add_dependency "bundler", "~> 1.13" 23 | 24 | spec.add_development_dependency "rake", "~> 10.0" 25 | spec.add_development_dependency "rspec", "~> 3.0" 26 | end 27 | -------------------------------------------------------------------------------- /belugas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gueils/belugas-ruby/d40af624b55c3899e56889097882eb4b67e920b4/belugas.png -------------------------------------------------------------------------------- /bin/belugas-ruby: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | source_path = (Pathname.new(__FILE__).dirname + '../lib').expand_path 5 | $LOAD_PATH << source_path 6 | 7 | require 'belugas/ruby' 8 | 9 | Belugas::Ruby::Sonar.start 10 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "belugas/ruby" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /dev.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.4 2 | 3 | RUN mkdir -p /usr/src/app 4 | ADD ./Gemfile* /usr/src/app/ 5 | ADD . /usr/src/app 6 | WORKDIR /usr/src/app 7 | 8 | RUN gem install bundler --no-ri --no-rdoc 9 | 10 | RUN bundle 11 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | volumes: 4 | gems: 5 | driver: local 6 | 7 | services: 8 | belugas_ruby: 9 | image: gueils/belugas-ruby:development 10 | build: 11 | context: . 12 | dockerfile: dev.Dockerfile 13 | command: bash 14 | working_dir: /usr/src/app 15 | volumes: 16 | - .:/usr/src/app 17 | - gems:/usr/local/bundle 18 | stdin_open: true 19 | tty: true 20 | -------------------------------------------------------------------------------- /lib/belugas/ruby.rb: -------------------------------------------------------------------------------- 1 | require "thor" 2 | require "json" 3 | require 'belugas/ruby/parser/gemfile' 4 | require 'belugas/ruby/dispatcher' 5 | require 'rescuer' 6 | 7 | module Belugas 8 | module Ruby 9 | class Sonar < Thor 10 | package_name "belugas-ruby" 11 | 12 | desc "analyze --gemfile-path=/app/code", "Ruby feature detection JSON" 13 | method_option "gemfile-path", type: :string, default: "/code/Gemfile", required: false, aliases: "-p" 14 | def analyze 15 | rescuer = Rescuer.new 16 | 17 | begin 18 | dispatcher = Belugas::Ruby::Dispatcher.new(options["gemfile-path"]) 19 | dispatcher.render 20 | rescue Exception => e 21 | rescuer.ping e 22 | raise e 23 | end 24 | 25 | end 26 | end 27 | end 28 | end 29 | 30 | require "belugas/ruby/version" 31 | -------------------------------------------------------------------------------- /lib/belugas/ruby/dependency.rb: -------------------------------------------------------------------------------- 1 | module Belugas 2 | module Ruby 3 | class Dependency 4 | attr_accessor :standard_name 5 | 6 | def initialize(bundler_dependency) 7 | @bundler_dependency = bundler_dependency 8 | end 9 | 10 | def name 11 | @bundler_dependency.name 12 | end 13 | 14 | def version 15 | @version ||= if categories.include?("Database") 16 | database_version 17 | else 18 | @bundler_dependency.requirement.requirements.flatten.join.match(Belugas::Ruby::Parser::Patterns::GEM_VERSION).to_s 19 | end 20 | end 21 | 22 | def update(new_name) 23 | @standard_name = new_name 24 | self 25 | end 26 | 27 | def categories 28 | StandardNames::NAMES[name] && StandardNames::NAMES[name]["categories"] 29 | end 30 | 31 | def to_json(*a) 32 | { 33 | name: name, 34 | version: version 35 | }.to_json(*a) 36 | end 37 | 38 | private 39 | 40 | def database_version 41 | case StandardNames::NAMES[name]["standard_name"] 42 | when "postgresql" then "9.6" 43 | when "mysql" then "5.7" 44 | else 45 | "0" 46 | end 47 | end 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/belugas/ruby/dispatcher.rb: -------------------------------------------------------------------------------- 1 | require 'belugas/ruby/feature/handler' 2 | require 'belugas/ruby/feature/builder' 3 | require 'belugas/ruby/parser/gemfile' 4 | require 'belugas/ruby/standard_names/base' 5 | require 'belugas/ruby/libraries_collection' 6 | 7 | module Belugas 8 | module Ruby 9 | class Dispatcher 10 | def initialize(path) 11 | @gemfile = Belugas::Ruby::Parser::Gemfile.new(path) 12 | @feature_handler = Belugas::Ruby::Feature::Handler.new(ruby_feature) 13 | end 14 | 15 | def render 16 | append_features 17 | @feature_handler.encode.each do |feature| 18 | STDOUT.print feature.to_json 19 | STDOUT.print "\0" 20 | end 21 | end 22 | 23 | private 24 | 25 | def ruby_feature 26 | @ruby_feature ||= [{ 27 | "type" => "feature", 28 | "name" => "Ruby", 29 | "version" => @gemfile.ruby_version, 30 | "description" => "The application uses Ruby code", 31 | "categories" => ["Language"], 32 | "engines" => ["belugas", "belugas-ruby"] 33 | }] 34 | end 35 | 36 | def dependencies 37 | @dependencies ||= Belugas::Ruby::LibrariesCollection.new(@gemfile.dependencies).dependencies 38 | end 39 | 40 | def features 41 | @features ||= dependencies.map do |dependency| 42 | Belugas::Ruby::Feature::Builder.new(dependency) 43 | end 44 | end 45 | 46 | def append_features 47 | features.each do |feature| 48 | transcoded[feature.name] = feature.attributes 49 | end 50 | end 51 | 52 | def transcoded 53 | @transcoded ||= @feature_handler.transcode 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/belugas/ruby/feature/builder.rb: -------------------------------------------------------------------------------- 1 | module Belugas 2 | module Ruby 3 | module Feature 4 | class Builder 5 | attr_reader :name 6 | 7 | def initialize(dependency) 8 | @dependency = dependency 9 | @name = dependency.name 10 | end 11 | 12 | def attributes 13 | { 14 | "type" => "feature", 15 | "name" => @dependency.standard_name, 16 | "version" => @dependency.version, 17 | "description" => "The application uses #{@dependency.standard_name}", 18 | "content" => "", 19 | "categories" => @dependency.categories, 20 | "cue_locations" => [""], 21 | "engines" => ["belugas", "belugas-ruby"] 22 | } 23 | end 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/belugas/ruby/feature/handler.rb: -------------------------------------------------------------------------------- 1 | module Belugas 2 | module Ruby 3 | module Feature 4 | class Handler 5 | def initialize(data) 6 | @data = data 7 | end 8 | 9 | def transcode 10 | @transcode ||= @data.reduce({}) do |hash, feature| 11 | hash[feature["name"]] = feature 12 | hash 13 | end 14 | end 15 | 16 | def encode 17 | transcode.values 18 | end 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/belugas/ruby/libraries_collection.rb: -------------------------------------------------------------------------------- 1 | module Belugas 2 | module Ruby 3 | class LibrariesCollection 4 | def initialize(dependencies) 5 | @dependencies = dependencies 6 | end 7 | 8 | def dependencies 9 | @dependencies.map do |dependency| 10 | dependency_name = StandardNames::NAMES[dependency.name] #=> {standard_name: "", categories: []} 11 | if dependency_name && dependency_name["standard_name"] 12 | dependency.update dependency_name["standard_name"] 13 | end 14 | end.compact 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/belugas/ruby/parser/.#patterns.rb: -------------------------------------------------------------------------------- 1 | icalialabs@icalialabs.local.674 -------------------------------------------------------------------------------- /lib/belugas/ruby/parser/gemfile.rb: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | require 'belugas/ruby/dependency' 3 | 4 | # This code belongs to GemnasiumParser 5 | # url: https://github.com/gemnasium/gemnasium-parser 6 | require 'belugas/ruby/parser/patterns' 7 | 8 | module Belugas 9 | module Ruby 10 | module Parser 11 | class Gemfile 12 | FALLBACK_RUBY_VERSION = "2.4.0" 13 | 14 | attr_reader :content 15 | attr_writer :runtime_groups 16 | 17 | def initialize(path) 18 | @content = File.read(path) 19 | end 20 | 21 | 22 | def dependencies 23 | @bundler_dependencies ||= [].tap do |deps| 24 | gem_matches.each do |match| 25 | dep = Belugas::Ruby::Dependency.new dependency(match) 26 | deps << dep if dep 27 | end 28 | end 29 | end 30 | 31 | def ruby_version 32 | ENV['FALLBACK_RUBY_VERSION'] || remove_symbols_from_ruby_version(content.scan(/ruby ["'](.*?)["']/).flatten[0]) || FALLBACK_RUBY_VERSION 33 | end 34 | 35 | private 36 | 37 | def remove_symbols_from_ruby_version(ruby_version) 38 | return nil if ruby_version.nil? 39 | 40 | (ruby_version.match Patterns::DIGITS_REGEX)[0].to_s 41 | end 42 | 43 | def runtime_groups 44 | @runtime_groups ||= [:default, :production] 45 | end 46 | 47 | def gem_matches 48 | @gem_matches ||= matches(Patterns::GEM_CALL) 49 | end 50 | 51 | def matches(pattern) 52 | [].tap{|m| content.scan(pattern){ m << Regexp.last_match } } 53 | end 54 | 55 | def dependency(match) 56 | opts = Patterns.options(match["opts"]) 57 | clean!(match, opts) 58 | name, reqs = match["name"], [match["req1"], match["req2"]].compact 59 | Bundler::Dependency.new(name, reqs, opts).tap do |dep| 60 | line = content.slice(0, match.begin(0)).count("\n") + 1 61 | dep.instance_variable_set(:@line, line) 62 | end 63 | end 64 | 65 | def groups(match) 66 | group = group_matches.detect{|m| in_block?(match, m) } 67 | group && Patterns.values(group[:grps]) 68 | end 69 | 70 | def in_block?(inner, outer) 71 | outer.begin(:blk) <= inner.begin(0) && outer.end(:blk) >= inner.end(0) 72 | end 73 | 74 | def group_matches 75 | @group_matches ||= matches(Patterns::GROUP_CALL) 76 | end 77 | 78 | def exclude?(match, opts) 79 | git?(match, opts) || github?(match, opts) || path?(match, opts) 80 | end 81 | 82 | def git?(match, opts) 83 | opts["git"] || in_git_block?(match) 84 | end 85 | 86 | def github?(match, opts) 87 | opts["github"] 88 | end 89 | 90 | def in_git_block?(match) 91 | git_matches.any?{|m| in_block?(match, m) } 92 | end 93 | 94 | def git_matches 95 | @git_matches ||= matches(Patterns::GIT_CALL) 96 | end 97 | 98 | def path?(match, opts) 99 | opts["path"] || in_path_block?(match) 100 | end 101 | 102 | def in_path_block?(match) 103 | path_matches.any?{|m| in_block?(match, m) } 104 | end 105 | 106 | def path_matches 107 | @path_matches ||= matches(Patterns::PATH_CALL) 108 | end 109 | 110 | def clean!(match, opts) 111 | opts["group"] ||= opts.delete("groups") 112 | opts["group"] ||= groups(match) 113 | groups = Array(opts["group"]).flatten.compact 114 | runtime = groups.empty? || !(groups & runtime_groups).empty? 115 | opts["type"] ||= runtime ? :runtime : :development 116 | end 117 | 118 | def gemspec_match 119 | return @gemspec_match if defined?(@gemspec_match) 120 | @gemspec_match = content.match(Patterns::GEMSPEC_CALL) 121 | end 122 | end 123 | end 124 | end 125 | end 126 | -------------------------------------------------------------------------------- /lib/belugas/ruby/parser/patterns.rb: -------------------------------------------------------------------------------- 1 | module Belugas 2 | module Ruby 3 | module Parser 4 | module Patterns 5 | GEM_NAME = /[a-zA-Z0-9\-_\.]+/ 6 | QUOTED_GEM_NAME = /(?:(?["'])(?#{GEM_NAME})\k|%q<(?#{GEM_NAME})>)/ 7 | 8 | MATCHER = /(?:=|!=|>|<|>=|<=|~>)/ 9 | VERSION = /[0-9]+(?:\.[a-zA-Z0-9]+)*/ 10 | REQUIREMENT = /[ \t]*(?:#{MATCHER}[ \t]*)?#{VERSION}[ \t]*/ 11 | REQUIREMENT_LIST = /(?["'])(?#{REQUIREMENT})\k(?:[ \t]*,[ \t]*(?["'])(?#{REQUIREMENT})\k)?/ 12 | REQUIREMENTS = /(?:#{REQUIREMENT_LIST}|\[[ \t]*#{REQUIREMENT_LIST}[ \t]*\])/ 13 | 14 | KEY = /(?::\w+|:?"\w+"|:?'\w+')/ 15 | SYMBOL = /(?::\w+|:"[^"#]+"|:'[^']+')/ 16 | STRING = /(?:"[^"#]*"|'[^']*')/ 17 | BOOLEAN = /(?:true|false)/ 18 | NIL = /nil/ 19 | ELEMENT = /(?:#{SYMBOL}|#{STRING})/ 20 | ARRAY = /\[(?:#{ELEMENT}(?:[ \t]*,[ \t]*#{ELEMENT})*)?\]/ 21 | VALUE = /(?:#{BOOLEAN}|#{NIL}|#{ELEMENT}|#{ARRAY}|)/ 22 | PAIR = /(?:(#{KEY})[ \t]*=>[ \t]*(#{VALUE})|(\w+):[ \t]+(#{VALUE}))/ 23 | OPTIONS = /#{PAIR}(?:[ \t]*,[ \t]*#{PAIR})*/ 24 | COMMENT = /(#[^\n]*)?/ 25 | 26 | GEM_CALL = /^[ \t]*gem\(?[ \t]*#{QUOTED_GEM_NAME}(?:[ \t]*,[ \t]*#{REQUIREMENT_LIST})?(?:[ \t]*,[ \t]*(?#{OPTIONS}))?[ \t]*\)?[ \t]*#{COMMENT}$/ 27 | 28 | SYMBOLS = /#{SYMBOL}([ \t]*,[ \t]*#{SYMBOL})*/ 29 | GROUP_CALL = /^(?[ \t]*)group\(?[ \t]*(?#{SYMBOLS})[ \t]*\)?[ \t]+do[ \t]*?\n(?.*?)\n^\kend[ \t]*$/m 30 | 31 | GIT_CALL = /^(?[ \t]*)git[ \(][^\n]*?do[ \t]*?\n(?.*?)\n^\kend[ \t]*$/m 32 | 33 | PATH_CALL = /^(?[ \t]*)path[ \(][^\n]*?do[ \t]*?\n(?.*?)\n^\kend[ \t]*$/m 34 | 35 | GEMSPEC_CALL = /^[ \t]*gemspec(?:\(?[ \t]*(?#{OPTIONS}))?[ \t]*\)?[ \t]*$/ 36 | 37 | ADD_DEPENDENCY_CALL = /^[ \t]*\w+\.add(?_runtime|_development)?_dependency\(?[ \t]*#{QUOTED_GEM_NAME}(?:[ \t]*,[ \t]*#{REQUIREMENTS})?[ \t]*\)?[ \t]*#{COMMENT}$/ 38 | 39 | GEM_VERSION = /[^~><=>==><](\d*?)[^~><=>==><]*/ 40 | DIGITS_REGEX = /(\d+([,.]\d)+)/ 41 | 42 | def self.options(string) 43 | {}.tap do |hash| 44 | return hash unless string 45 | pairs = Hash[*string.match(OPTIONS).captures.compact] 46 | pairs.each{|k,v| hash[key(k)] = value(v) } 47 | end 48 | end 49 | 50 | def self.key(string) 51 | string.tr(%(:"'), "") 52 | end 53 | 54 | def self.value(string) 55 | case string 56 | when ARRAY then values(string.tr("[]", "")) 57 | when SYMBOL then string.tr(%(:"'), "").to_sym 58 | when STRING then string.tr(%("'), "") 59 | when BOOLEAN then string == "true" 60 | when NIL then nil 61 | end 62 | end 63 | 64 | def self.values(string) 65 | string.strip.split(/[ \t]*,[ \t]*/).map{|v| value(v) } 66 | end 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/belugas/ruby/standard_names/base.rb: -------------------------------------------------------------------------------- 1 | module Belugas 2 | module Ruby 3 | module StandardNames 4 | NAMES = { 5 | "capybara-webkit" => { "standard_name" => "webkit", 6 | "categories" => ["Library"] }, 7 | "sinatra" => { "standard_name" => "sinatra", 8 | "categories" => ["Framework"] }, 9 | "middleman" => { "standard_name" => "middleman", 10 | "categories" => ["Framework"] }, 11 | "rails" => { "standard_name" => "rails", 12 | "categories" => ["Framework"] }, 13 | "pg" => { "standard_name" => "postgresql", 14 | "categories" => ["Database"] }, 15 | "mysql" => { "standard_name" => "mysql", 16 | "categories" => ["Database"] }, 17 | "mysql2" => { "standard_name" => "mysql", 18 | "categories" => ["Database"] }, 19 | "sidekiq" => { "standard_name" => "sidekiq", 20 | "categories" => ["Service"]}, 21 | "sidekiq-scheduler" => { "standard_name" => "sidekiq", 22 | "categories" => ["Service"] }, 23 | "mini_magick" => { "standard_name" => "rmagick", 24 | "categories" => ["Library"] }, 25 | "rmagick" => { "standard_name" => "rmagick", 26 | "categories" => ["Library"] }, 27 | "mongoid" => { "standard_name" => "mongodb", 28 | "categories" => ["Database"] } 29 | } 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/belugas/ruby/version.rb: -------------------------------------------------------------------------------- 1 | module Belugas 2 | module Ruby 3 | VERSION = "0.1.0" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/rescuer.rb: -------------------------------------------------------------------------------- 1 | require 'slack-notifier' 2 | 3 | class Rescuer 4 | SLACK_WEBHOOK = "https://hooks.slack.com/services/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".freeze 5 | 6 | def initialize 7 | @notifier = Slack::Notifier.new SLACK_WEBHOOK 8 | end 9 | 10 | def ping(e) 11 | @notifier.ping "uncaught #{e} exception while handling connection: #{e.message}\n\nStack trace: #{e.backtrace.map {|l| " #{l}\n"}.join}" 12 | end 13 | end 14 | 15 | 16 | -------------------------------------------------------------------------------- /spec/belugas/ruby/dependency_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Belugas::Ruby::Dependency do 4 | before { 5 | requirement = double("requirement") 6 | allow(requirement).to receive(:requirements).and_return(["=>2.3"]) 7 | @bundler_dependency = double("bundler_dependency") 8 | allow(@bundler_dependency).to receive(:name).and_return("sinatra") 9 | allow(@bundler_dependency).to receive(:requirement).and_return(requirement) 10 | } 11 | 12 | subject { Belugas::Ruby::Dependency.new(@bundler_dependency) } 13 | 14 | it "updates its standard_name" do 15 | expect(subject.update("sinatra")).to eq(subject) 16 | expect(subject.standard_name).to eq("sinatra") 17 | end 18 | 19 | it "has a name" do 20 | expect(subject.name).to eq("sinatra") 21 | end 22 | 23 | it "has a category named Framework" do 24 | subject.update("sinatra") 25 | expect(subject.categories).to eq(["Framework"]) 26 | end 27 | 28 | it "renders a json" do 29 | expect(subject.to_json).to eq({name: "sinatra", version: "2.3"}.to_json) 30 | end 31 | 32 | describe "#version" do 33 | context "with category DATABASE" do 34 | before { 35 | requirement = double("requirement") 36 | allow(requirement).to receive(:requirements).and_return(["=>0.15"]) 37 | @bundler_dependency = double("bundler_dependency") 38 | allow(@bundler_dependency).to receive(:requirement).and_return(requirement) 39 | } 40 | 41 | it "should return 9.6 for postgresql" do 42 | allow(@bundler_dependency).to receive(:name).and_return("pg") 43 | postgresql_dependency = Belugas::Ruby::Dependency.new(@bundler_dependency) 44 | expect(postgresql_dependency.version).to eq "9.6" 45 | end 46 | 47 | it "should return 5.7 for mysql" do 48 | allow(@bundler_dependency).to receive(:name).and_return("mysql") 49 | postgresql_dependency = Belugas::Ruby::Dependency.new(@bundler_dependency) 50 | expect(postgresql_dependency.version).to eq "5.7" 51 | end 52 | 53 | it "should return 0 for anything else" do 54 | allow(@bundler_dependency).to receive(:name).and_return("mongoid") 55 | postgresql_dependency = Belugas::Ruby::Dependency.new(@bundler_dependency) 56 | expect(postgresql_dependency.version).to eq "0" 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /spec/belugas/ruby/dispatcher_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Belugas::Ruby::Dispatcher do 4 | subject { Belugas::Ruby::Dispatcher.new("spec/support/Gemfile") } 5 | 6 | context "has valid categories" do 7 | it "renders proper database features" do 8 | expect(subject.render).to eq([{ "type" => "feature", 9 | "name" => "Ruby", 10 | "version" => "2.3.1", 11 | "description" => "The application uses Ruby code", 12 | "categories" => ["Language"], 13 | "engines" => ["belugas", "belugas-ruby"] }, 14 | { "type" => "feature", 15 | "name" => "rails", 16 | "version" => "4.2.6", 17 | "description" => "The application uses rails", 18 | "content" => "", 19 | "categories" => ["Framework"], 20 | "cue_locations" => [""], 21 | "engines" => ["belugas", "belugas-ruby"] }, 22 | { "type" => "feature", 23 | "name" => "postgresql", 24 | "version" => "9.6", 25 | "description" => "The application uses postgresql", 26 | "content" => "", 27 | "categories" => ["Database"], 28 | "cue_locations" => [""], 29 | "engines" => ["belugas", "belugas-ruby"] }, 30 | { "type" => "feature", 31 | "name" => "sidekiq", 32 | "version" => "0", 33 | "description" => "The application uses sidekiq", 34 | "content" => "", 35 | "categories" => ["Service"], 36 | "cue_locations" => [""], 37 | "engines" => ["belugas", "belugas-ruby"] }, 38 | { "type" => "feature", 39 | "name" => "sidekiq", 40 | "version" => "0", 41 | "description" => "The application uses sidekiq", 42 | "content" => "", 43 | "categories" => ["Service"], 44 | "cue_locations" => [""], 45 | "engines" => ["belugas", "belugas-ruby"] }, 46 | { "type" => "feature", 47 | "name" => "rmagick", 48 | "version" => "0", 49 | "description" => "The application uses rmagick", 50 | "content" => "", 51 | "categories" => ["Library"], 52 | "cue_locations" => [""], 53 | "engines" => ["belugas", "belugas-ruby"] }]) 54 | end 55 | end 56 | 57 | context "has empty categories" do 58 | it "for a known requirement" do 59 | missing_framework_subject = Belugas::Ruby::Dispatcher.new("spec/support/empty_Gemfile") 60 | expect(missing_framework_subject.render).to eq([{ "type" => "feature", 61 | "name" => "Ruby", 62 | "version" => "2.4.0", 63 | "description" => "The application uses Ruby code", 64 | "categories" => ["Language"], 65 | "engines" => ["belugas", "belugas-ruby"] }]) 66 | end 67 | end 68 | 69 | context "without postgres version" do 70 | it "return version 9.6" do 71 | no_postgres_version_subject = Belugas::Ruby::Dispatcher.new("spec/support/no_postgres_Gemfile") 72 | expect(no_postgres_version_subject.render).to eq([{ "type" => "feature", 73 | "name" => "Ruby", 74 | "version" => "2.3.1", 75 | "description" => "The application uses Ruby code", 76 | "categories" => ["Language"], 77 | "engines" => ["belugas", "belugas-ruby"] }, 78 | { "type" => "feature", 79 | "name" => "rails", 80 | "version" => "4.2.6", 81 | "description" => "The application uses rails", 82 | "content" => "", 83 | "categories" => ["Framework"], 84 | "cue_locations" => [""], 85 | "engines" => ["belugas", "belugas-ruby"] }, 86 | { "type" => "feature", 87 | "name" => "postgresql", 88 | "version" => "9.6", 89 | "description" => "The application uses postgresql", 90 | "content" => "", 91 | "categories" => ["Database"], 92 | "cue_locations" => [""], 93 | "engines" => ["belugas", "belugas-ruby"] }, 94 | { "type" => "feature", 95 | "name" => "sidekiq", 96 | "version" => "0", 97 | "description" => "The application uses sidekiq", 98 | "content" => "", 99 | "categories" => ["Service"], 100 | "cue_locations" => [""], 101 | "engines" => ["belugas", "belugas-ruby"] }, 102 | { "type" => "feature", 103 | "name" => "sidekiq", 104 | "version" => "0", 105 | "description" => "The application uses sidekiq", 106 | "content" => "", 107 | "categories" => ["Service"], 108 | "cue_locations" => [""], 109 | "engines" => ["belugas", "belugas-ruby"] }, 110 | { "type" => "feature", 111 | "name" => "rmagick", 112 | "version" => "0", 113 | "description" => "The application uses rmagick", 114 | "content" => "", 115 | "categories" => ["Library"], 116 | "cue_locations" => [""], 117 | "engines" => ["belugas", "belugas-ruby"] }]) 118 | end 119 | end 120 | 121 | context "with ruby version with symbols (>,=>,<,=<)" do 122 | it "return version without symbols" do 123 | ruby_version_with_symbols = Belugas::Ruby::Dispatcher.new("spec/support/ruby_version_with_symbols_Gemfile") 124 | expect(ruby_version_with_symbols.render).to eq([{ "type" => "feature", 125 | "name" => "Ruby", 126 | "version" => "2.3.1", 127 | "description" => "The application uses Ruby code", 128 | "categories" => ["Language"], 129 | "engines" => ["belugas", "belugas-ruby"] }]) 130 | end 131 | end 132 | end 133 | -------------------------------------------------------------------------------- /spec/belugas/ruby/feature/builder_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Belugas::Ruby::Feature::Builder do 4 | before { 5 | @requirement = double("requirement") 6 | allow(@requirement).to receive(:name).and_return("fake") 7 | allow(@requirement).to receive(:standard_name).and_return("fake") 8 | allow(@requirement).to receive(:version).and_return(0.0) 9 | allow(@requirement).to receive(:categories).and_return(["Category"]) 10 | } 11 | 12 | subject { Belugas::Ruby::Feature::Builder.new(@requirement) } 13 | 14 | it "has all attributes" do 15 | expect(subject.attributes["type"]).to eq("feature") 16 | expect(subject.attributes["name"]).to eq("fake") 17 | expect(subject.attributes["version"]).to eq(0.0) 18 | expect(subject.attributes["description"]).to eq("The application uses fake") 19 | expect(subject.attributes["categories"]).to eq(["Category"]) 20 | expect(subject.attributes["cue_locations"]).to eq([""]) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/belugas/ruby/feature/handler_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Belugas::Ruby::Feature::Handler do 4 | before { 5 | @data = [{ 6 | "name" => "sinatra", 7 | "version" => "1.2", 8 | "category" => ["Framework"] 9 | }] 10 | } 11 | 12 | subject { Belugas::Ruby::Feature::Handler.new(@data) } 13 | 14 | it "transcodes" do 15 | expect(subject.transcode).to have_key("sinatra") 16 | end 17 | 18 | it "encodes" do 19 | expect(subject.encode.first).to have_key("version") 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/belugas/ruby/libraries_collection_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Belugas::Ruby::LibrariesCollection do 4 | before { 5 | @dependencies = [] 6 | 7 | sinatra_requirement = double("requirement") 8 | allow(sinatra_requirement).to receive(:requirements).and_return(["=>2.3"]) 9 | sinatra_bundler_dependency = double("bundler_dependency") 10 | allow(sinatra_bundler_dependency).to receive(:name).and_return("sinatra") 11 | allow(sinatra_bundler_dependency).to receive(:requirement).and_return(sinatra_requirement) 12 | sinatra = Belugas::Ruby::Dependency.new(sinatra_bundler_dependency) 13 | 14 | pg_requirement = double("requirement") 15 | allow(pg_requirement).to receive(:requirements).and_return(["=>1.5"]) 16 | pg_bundler_dependency = double("bundler_dependency") 17 | allow(pg_bundler_dependency).to receive(:name).and_return("pg") 18 | allow(pg_bundler_dependency).to receive(:requirement).and_return(pg_requirement) 19 | pg = Belugas::Ruby::Dependency.new(pg_bundler_dependency) 20 | 21 | @dependencies << sinatra 22 | @dependencies << pg 23 | } 24 | 25 | subject { Belugas::Ruby::LibrariesCollection.new(@dependencies) } 26 | 27 | it "has dependecies with standard names" do 28 | expect(subject.dependencies.count).to eq(2) 29 | expect(subject.dependencies.first.standard_name).to eq("sinatra") 30 | expect(subject.dependencies.last.standard_name).to eq("postgresql") 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/belugas/ruby/parser/gemfile_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Belugas::Ruby::Parser::Gemfile do 4 | subject { Belugas::Ruby::Parser::Gemfile.new("spec/support/Gemfile") } 5 | 6 | it "has a bunch of dependencies" do 7 | expect(subject.dependencies).not_to be_empty 8 | end 9 | 10 | context "an empty Gemfile" do 11 | it "has nothing" do 12 | empty_gemfile_subject = Belugas::Ruby::Parser::Gemfile.new("spec/support/empty_Gemfile") 13 | expect(empty_gemfile_subject.dependencies).to be_empty 14 | end 15 | end 16 | 17 | it "has_a ruby version" do 18 | empty_gemfile_subject = Belugas::Ruby::Parser::Gemfile.new("spec/support/Gemfile") 19 | expect(empty_gemfile_subject.ruby_version).to eq("2.3.1") 20 | end 21 | 22 | it "has_no ruby version" do 23 | empty_gemfile_subject = Belugas::Ruby::Parser::Gemfile.new("spec/support/no_ruby_Gemfile") 24 | expect(empty_gemfile_subject.ruby_version).to eq("2.4.0") 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/belugas/ruby/parser/patterns_spec.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gueils/belugas-ruby/d40af624b55c3899e56889097882eb4b67e920b4/spec/belugas/ruby/parser/patterns_spec.rb -------------------------------------------------------------------------------- /spec/belugas/ruby/standard_names/base_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Belugas::Ruby::StandardNames do 4 | it "has a NAMES defined" do 5 | expect(Belugas::Ruby::StandardNames::NAMES).not_to be nil 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/belugas/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Belugas::Ruby do 4 | it "has a version number" do 5 | expect(Belugas::Ruby::VERSION).not_to be nil 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | SimpleCov.start 3 | 4 | $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__) 5 | require "pry" 6 | require "belugas/ruby/standard_names/base" 7 | require "belugas/ruby/parser/gemfile" 8 | require "belugas/ruby/dependency.rb" 9 | require "belugas/ruby/feature/handler" 10 | require "belugas/ruby/feature/builder" 11 | require "belugas/ruby/libraries_collection" 12 | require "belugas/ruby/dispatcher" 13 | require "belugas/ruby" 14 | -------------------------------------------------------------------------------- /spec/support/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby '2.3.1' 4 | 5 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 6 | gem 'rails', '4.2.6' 7 | # Use postgresql as the database for Active Record 8 | gem 'pg', '~> 0.15' 9 | # Use SCSS for stylesheets 10 | gem 'sass-rails', '~> 5.0' 11 | # Use Uglifier as compressor for JavaScript assets 12 | gem 'uglifier', '>= 1.3.0' 13 | # Use CoffeeScript for .coffee assets and views 14 | gem 'coffee-rails', '~> 4.1.0' 15 | gem 'compass-rails' 16 | # See https://github.com/rails/execjs#readme for more supported runtimes 17 | gem 'therubyracer', platforms: :ruby 18 | # Use jquery as the JavaScript library 19 | gem 'jquery-rails' 20 | gem 'jquery-ui-rails' 21 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 22 | gem 'turbolinks' 23 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 24 | gem 'jbuilder', '~> 2.0' 25 | # bundle exec rake doc:rails generates the API under doc/api. 26 | gem 'sdoc', '~> 0.4.0', group: :doc 27 | gem 'activerecord-postgis-adapter' 28 | gem 'devise' 29 | gem 'rubocop', require: false 30 | gem 'kaminari' 31 | gem 'draper' 32 | gem 'ransack' 33 | gem "httparty" 34 | gem "sidekiq" 35 | gem "sidekiq-scheduler" 36 | gem 'carrierwave', github: 'carrierwaveuploader/carrierwave' 37 | gem 'remotipart', '~> 1.2' 38 | gem 'jquery-fileupload-rails' 39 | gem 'rgeo' 40 | gem 'rgeo-activerecord' 41 | gem "select2-rails" 42 | gem 'geocoder' 43 | gem 'fog-aws' 44 | gem 'omniauth-oauth2', '~> 1.3.1' 45 | gem 'omniauth-linkedin-oauth2' 46 | gem "mini_magick" 47 | gem "pdfkit", github: "IcaliaLabs/pdfkit", branch: "xvfb-run-support" 48 | gem 'render_anywhere', require: false 49 | gem "json", "~> 1.8.6" 50 | # Use ActiveModel has_secure_password 51 | # gem 'bcrypt', '~> 3.1.7' 52 | 53 | # Use Unicorn as the app server 54 | # gem 'unicorn' 55 | 56 | # Use Capistrano for deployment 57 | # gem 'capistrano-rails', group: :development 58 | 59 | group :development, :test do 60 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 61 | gem 'byebug' 62 | gem 'pry' 63 | gem 'rspec-rails' 64 | gem 'factory_girl_rails' 65 | end 66 | 67 | group :development do 68 | # Access an IRB console on exception pages or by using <%= console %> in views 69 | gem 'web-console', '~> 2.0' 70 | 71 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 72 | gem 'spring' 73 | gem 'mailcatcher' 74 | end 75 | 76 | group :test do 77 | gem 'faker' 78 | gem 'database_cleaner' 79 | gem 'rspec-collection_matchers' 80 | gem 'shoulda-matchers', '~> 3.1' 81 | gem 'capybara' 82 | gem "simplecov" 83 | gem "codeclimate-test-reporter", "~> 1.0.0" 84 | end 85 | 86 | group :production, :staging do 87 | gem 'rails_12factor' 88 | end 89 | -------------------------------------------------------------------------------- /spec/support/empty_Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in belugas-ruby.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /spec/support/no_postgres_Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby '2.3.1' 4 | 5 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 6 | gem 'rails', '4.2.6' 7 | # Use postgresql as the database for Active Record 8 | gem 'pg' 9 | # Use SCSS for stylesheets 10 | gem 'sass-rails', '~> 5.0' 11 | # Use Uglifier as compressor for JavaScript assets 12 | gem 'uglifier', '>= 1.3.0' 13 | # Use CoffeeScript for .coffee assets and views 14 | gem 'coffee-rails', '~> 4.1.0' 15 | gem 'compass-rails' 16 | # See https://github.com/rails/execjs#readme for more supported runtimes 17 | gem 'therubyracer', platforms: :ruby 18 | # Use jquery as the JavaScript library 19 | gem 'jquery-rails' 20 | gem 'jquery-ui-rails' 21 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 22 | gem 'turbolinks' 23 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 24 | gem 'jbuilder', '~> 2.0' 25 | # bundle exec rake doc:rails generates the API under doc/api. 26 | gem 'sdoc', '~> 0.4.0', group: :doc 27 | gem 'activerecord-postgis-adapter' 28 | gem 'devise' 29 | gem 'rubocop', require: false 30 | gem 'kaminari' 31 | gem 'draper' 32 | gem 'ransack' 33 | gem "httparty" 34 | gem "sidekiq" 35 | gem "sidekiq-scheduler" 36 | gem 'carrierwave', github: 'carrierwaveuploader/carrierwave' 37 | gem 'remotipart', '~> 1.2' 38 | gem 'jquery-fileupload-rails' 39 | gem 'rgeo' 40 | gem 'rgeo-activerecord' 41 | gem "select2-rails" 42 | gem 'geocoder' 43 | gem 'fog-aws' 44 | gem 'omniauth-oauth2', '~> 1.3.1' 45 | gem 'omniauth-linkedin-oauth2' 46 | gem "mini_magick" 47 | gem "pdfkit", github: "IcaliaLabs/pdfkit", branch: "xvfb-run-support" 48 | gem 'render_anywhere', require: false 49 | gem "json", "~> 1.8.6" 50 | # Use ActiveModel has_secure_password 51 | # gem 'bcrypt', '~> 3.1.7' 52 | 53 | # Use Unicorn as the app server 54 | # gem 'unicorn' 55 | 56 | # Use Capistrano for deployment 57 | # gem 'capistrano-rails', group: :development 58 | 59 | group :development, :test do 60 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 61 | gem 'byebug' 62 | gem 'pry' 63 | gem 'rspec-rails' 64 | gem 'factory_girl_rails' 65 | end 66 | 67 | group :development do 68 | # Access an IRB console on exception pages or by using <%= console %> in views 69 | gem 'web-console', '~> 2.0' 70 | 71 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 72 | gem 'spring' 73 | gem 'mailcatcher' 74 | end 75 | 76 | group :test do 77 | gem 'faker' 78 | gem 'database_cleaner' 79 | gem 'rspec-collection_matchers' 80 | gem 'shoulda-matchers', '~> 3.1' 81 | gem 'capybara' 82 | gem "simplecov" 83 | gem "codeclimate-test-reporter", "~> 1.0.0" 84 | end 85 | 86 | group :production, :staging do 87 | gem 'rails_12factor' 88 | end 89 | -------------------------------------------------------------------------------- /spec/support/no_ruby_Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 4 | gem 'rails', '4.2.6' 5 | # Use postgresql as the database for Active Record 6 | gem 'pg', '~> 0.15' 7 | # Use SCSS for stylesheets 8 | gem 'sass-rails', '~> 5.0' 9 | # Use Uglifier as compressor for JavaScript assets 10 | gem 'uglifier', '>= 1.3.0' 11 | # Use CoffeeScript for .coffee assets and views 12 | gem 'coffee-rails', '~> 4.1.0' 13 | gem 'compass-rails' 14 | # See https://github.com/rails/execjs#readme for more supported runtimes 15 | gem 'therubyracer', platforms: :ruby 16 | # Use jquery as the JavaScript library 17 | gem 'jquery-rails' 18 | gem 'jquery-ui-rails' 19 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 20 | gem 'turbolinks' 21 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 22 | gem 'jbuilder', '~> 2.0' 23 | # bundle exec rake doc:rails generates the API under doc/api. 24 | gem 'sdoc', '~> 0.4.0', group: :doc 25 | gem 'activerecord-postgis-adapter' 26 | gem 'devise' 27 | gem 'rubocop', require: false 28 | gem 'kaminari' 29 | gem 'draper' 30 | gem 'ransack' 31 | gem "httparty" 32 | gem "sidekiq" 33 | gem "sidekiq-scheduler" 34 | gem 'carrierwave', github: 'carrierwaveuploader/carrierwave' 35 | gem 'remotipart', '~> 1.2' 36 | gem 'jquery-fileupload-rails' 37 | gem 'rgeo' 38 | gem 'rgeo-activerecord' 39 | gem "select2-rails" 40 | gem 'geocoder' 41 | gem 'fog-aws' 42 | gem 'omniauth-oauth2', '~> 1.3.1' 43 | gem 'omniauth-linkedin-oauth2' 44 | gem "mini_magick" 45 | gem "pdfkit", github: "IcaliaLabs/pdfkit", branch: "xvfb-run-support" 46 | gem 'render_anywhere', require: false 47 | gem "json", "~> 1.8.6" 48 | # Use ActiveModel has_secure_password 49 | # gem 'bcrypt', '~> 3.1.7' 50 | 51 | # Use Unicorn as the app server 52 | # gem 'unicorn' 53 | 54 | # Use Capistrano for deployment 55 | # gem 'capistrano-rails', group: :development 56 | 57 | group :development, :test do 58 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 59 | gem 'byebug' 60 | gem 'pry' 61 | gem 'rspec-rails' 62 | gem 'factory_girl_rails' 63 | end 64 | 65 | group :development do 66 | # Access an IRB console on exception pages or by using <%= console %> in views 67 | gem 'web-console', '~> 2.0' 68 | 69 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 70 | gem 'spring' 71 | gem 'mailcatcher' 72 | end 73 | 74 | group :test do 75 | gem 'faker' 76 | gem 'database_cleaner' 77 | gem 'rspec-collection_matchers' 78 | gem 'shoulda-matchers', '~> 3.1' 79 | gem 'capybara' 80 | gem "simplecov" 81 | gem "codeclimate-test-reporter", "~> 1.0.0" 82 | end 83 | 84 | group :production, :staging do 85 | gem 'rails_12factor' 86 | end 87 | -------------------------------------------------------------------------------- /spec/support/ruby_version_with_symbols_Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby '>= 2.3.1' 4 | --------------------------------------------------------------------------------