modulorails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e7a96938b07505567d256c051a9de1c495e145d2a3b5e8e0e90fbbb5e0eb0376
4
+ data.tar.gz: 3f11b735571b42d431ee155a3fd7169d6bf2b8eb40b88042ab7d98d5f9636119
5
+ SHA512:
6
+ metadata.gz: 26076299430329d25d6137e293e4c7ba5d3577269358f59070b9f32dec7b8ea033be1c5c9f2d0016227d26c12d685124060f3188afb77318b7320e3acdcb0a36
7
+ data.tar.gz: 13d8bef4d1847342bdbf286546252bb570b96d3120f0d492170a19eff0d8aea25318e73583b69f695e3e8fa221ddce831399a5b70dad634254b5d47c302e35cc
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,9 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.5
6
+ - 2.6
7
+ - 2.7
8
+ before_install:
9
+ - gem install bundler -v 2.1.4
@@ -0,0 +1 @@
1
+ # CHANGELOG
@@ -0,0 +1,74 @@
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 rails@modulotech.fr. 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 [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in modulorails.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "rspec", "~> 3.0"
@@ -0,0 +1,105 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ modulorails (0.1.0)
5
+ git (~> 1.7, >= 1.7.0)
6
+ httparty
7
+ railties (>= 4.2.0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actionpack (6.0.3.2)
13
+ actionview (= 6.0.3.2)
14
+ activesupport (= 6.0.3.2)
15
+ rack (~> 2.0, >= 2.0.8)
16
+ rack-test (>= 0.6.3)
17
+ rails-dom-testing (~> 2.0)
18
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
19
+ actionview (6.0.3.2)
20
+ activesupport (= 6.0.3.2)
21
+ builder (~> 3.1)
22
+ erubi (~> 1.4)
23
+ rails-dom-testing (~> 2.0)
24
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
25
+ activemodel (6.0.3.2)
26
+ activesupport (= 6.0.3.2)
27
+ activerecord (6.0.3.2)
28
+ activemodel (= 6.0.3.2)
29
+ activesupport (= 6.0.3.2)
30
+ activesupport (6.0.3.2)
31
+ concurrent-ruby (~> 1.0, >= 1.0.2)
32
+ i18n (>= 0.7, < 2)
33
+ minitest (~> 5.1)
34
+ tzinfo (~> 1.1)
35
+ zeitwerk (~> 2.2, >= 2.2.2)
36
+ builder (3.2.4)
37
+ concurrent-ruby (1.1.7)
38
+ crass (1.0.6)
39
+ diff-lcs (1.4.4)
40
+ erubi (1.9.0)
41
+ git (1.7.0)
42
+ rchardet (~> 1.8)
43
+ httparty (0.18.1)
44
+ mime-types (~> 3.0)
45
+ multi_xml (>= 0.5.2)
46
+ i18n (1.8.5)
47
+ concurrent-ruby (~> 1.0)
48
+ loofah (2.7.0)
49
+ crass (~> 1.0.2)
50
+ nokogiri (>= 1.5.9)
51
+ method_source (1.0.0)
52
+ mime-types (3.3.1)
53
+ mime-types-data (~> 3.2015)
54
+ mime-types-data (3.2020.0512)
55
+ mini_portile2 (2.4.0)
56
+ minitest (5.14.1)
57
+ multi_xml (0.6.0)
58
+ nokogiri (1.10.10)
59
+ mini_portile2 (~> 2.4.0)
60
+ rack (2.2.3)
61
+ rack-test (1.1.0)
62
+ rack (>= 1.0, < 3)
63
+ rails-dom-testing (2.0.3)
64
+ activesupport (>= 4.2.0)
65
+ nokogiri (>= 1.6)
66
+ rails-html-sanitizer (1.3.0)
67
+ loofah (~> 2.3)
68
+ railties (6.0.3.2)
69
+ actionpack (= 6.0.3.2)
70
+ activesupport (= 6.0.3.2)
71
+ method_source
72
+ rake (>= 0.8.7)
73
+ thor (>= 0.20.3, < 2.0)
74
+ rake (12.3.3)
75
+ rchardet (1.8.0)
76
+ rspec (3.9.0)
77
+ rspec-core (~> 3.9.0)
78
+ rspec-expectations (~> 3.9.0)
79
+ rspec-mocks (~> 3.9.0)
80
+ rspec-core (3.9.2)
81
+ rspec-support (~> 3.9.3)
82
+ rspec-expectations (3.9.2)
83
+ diff-lcs (>= 1.2.0, < 2.0)
84
+ rspec-support (~> 3.9.0)
85
+ rspec-mocks (3.9.1)
86
+ diff-lcs (>= 1.2.0, < 2.0)
87
+ rspec-support (~> 3.9.0)
88
+ rspec-support (3.9.3)
89
+ thor (1.0.1)
90
+ thread_safe (0.3.6)
91
+ tzinfo (1.2.7)
92
+ thread_safe (~> 0.1)
93
+ zeitwerk (2.4.0)
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ activerecord (>= 4.2.0)
100
+ modulorails!
101
+ rake (~> 12.0)
102
+ rspec (~> 3.0)
103
+
104
+ BUNDLED WITH
105
+ 2.1.4
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Modulotech
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.
@@ -0,0 +1,50 @@
1
+ # Modulorails [![Build Status](https://travis-ci.com/Ezveus/modulorails.svg?branch=master)](https://travis-ci.com/Ezveus/modulorails)
2
+
3
+ **Modulorails** is the common base for the Ruby on Rails project at [Modulotech](https://www.modulotech.fr/).
4
+
5
+ It registers each application using it on the company's intranet,
6
+ provides templates for the common configurations and defines common dependencies.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'modulorails', git: 'git://github.com/moduloTech/modulorails.git'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle install
19
+
20
+ ## Usage
21
+
22
+ To work the gem needs to be configured. Add an initializer `config/modulorails.rb`:
23
+
24
+ ```ruby
25
+ Modulorails.configure do |config|
26
+ config.name 'The usual name of the application'
27
+ config.main_developer 'The email of the main developer/maintainer of the application'
28
+ config.project_manager 'The email of the project manager of the application'
29
+ config.endpoint 'The url to the intranet'
30
+ config.api_key 'The API key'
31
+ end
32
+ ```
33
+
34
+ ## Development
35
+
36
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
+
38
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
+
40
+ ## Contributing
41
+
42
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/moduloTech/modulorails](https://github.com/moduloTech/modulorails). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/moduloTech/modulorails/blob/master/CODE_OF_CONDUCT.md).
43
+
44
+ ## License
45
+
46
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
47
+
48
+ ## Code of Conduct
49
+
50
+ Everyone interacting in the Modulorails project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/moduloTech/modulorails/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "modulorails"
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(__FILE__)
@@ -0,0 +1,8 @@
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
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ class GitlabciGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('templates', __dir__)
7
+ class_option(:app,
8
+ required: true, type: :string,
9
+ desc: 'Specify the application name.')
10
+ class_option(:database,
11
+ required: true, type: :string,
12
+ desc: 'Specify the database to use (either mysql or postgres).')
13
+ class_option(:bundler,
14
+ required: true, type: :string,
15
+ desc: 'Specify the Bundler version.')
16
+ class_option(:ruby_version,
17
+ required: true, type: :string,
18
+ desc: 'Specify the Ruby version.')
19
+ desc 'This generator creates a template for a .gitlab-ci.yml file at root'
20
+
21
+ # Configurations for MySQL/Postgres dockers
22
+ MYSQL_DOCKER_DB = <<~EOS
23
+ # Install a MySQL 5.7 database and configure mandatory environment variables
24
+ # (https://hub.docker.com/_/mysql/)
25
+ services:
26
+ - mysql:5.7
27
+ variables:
28
+ MYSQL_DATABASE: test
29
+ MYSQL_ROOT_PASSWORD: password
30
+ EOS
31
+ POSTGRES_DOCKER_DB = <<~EOS
32
+ # Install a Postgres 11 database and configure mandatory environment variables
33
+ # (https://hub.docker.com/_/postgres/)
34
+ services:
35
+ - postgresql:11
36
+ variables:
37
+ POSTGRES_DB: test
38
+ POSTGRES_PASSWORD: password
39
+ EOS
40
+
41
+ def create_config_file
42
+ # Get the configuration for the database engine
43
+ db_conf = database_config(options[:database])
44
+
45
+ # Update the gitlab-ci template
46
+ update_gitlab_ci(options, db_conf)
47
+
48
+ # Update the database-ci template
49
+ update_database_ci(db_conf)
50
+
51
+ # Create file to avoid this generator on next modulorails launch
52
+ create_keep_file
53
+ end
54
+
55
+ private
56
+
57
+ def update_gitlab_ci(options, db_conf)
58
+ file = '.gitlab-ci.yml'
59
+ exists = File.exists?(file)
60
+
61
+ # Remove original file if there is one
62
+ remove_file file if exists
63
+
64
+ # Copy file
65
+ copy_file file, file
66
+
67
+ # Add the correct database docker
68
+ prepend_file file, db_conf[:header]
69
+
70
+ # Replace key for CI/CD cache
71
+ gsub_file file, 'CI_CD_CACHE_KEY', "#{options[:app]}-ci_cd"
72
+
73
+ # Replace key for bundler version
74
+ gsub_file file, 'BUNDLER_VERSION', options[:bundler]
75
+
76
+ # Replace ruby version
77
+ gsub_file file, 'RUBY_VERSION', '2.5.0'
78
+
79
+ # Warn the user about file overwrite/creation
80
+ warn_file_update(file, exists)
81
+ end
82
+
83
+ def update_database_ci(db_conf)
84
+ file = 'config/database-ci.yml'
85
+ exists = File.exists?(file)
86
+
87
+ # Remove original file if there is one
88
+ remove_file file if exists
89
+
90
+ # Copy file
91
+ copy_file file, file
92
+
93
+ # Replace configuration
94
+ gsub_file file, 'HOST', db_conf[:host]
95
+ gsub_file file, 'ADAPTER', db_conf[:adapter]
96
+ gsub_file file, 'DATABASE', 'test'
97
+
98
+ # Warn the user about file overwrite/creation
99
+ warn_file_update(file, exists)
100
+ end
101
+
102
+ def database_config(database)
103
+ case database
104
+ when 'mysql', 'mysql2'
105
+ { header: MYSQL_DOCKER_DB, host: 'mysql', adapter: 'mysql2' }
106
+ when 'postgres', 'postgresql'
107
+ { header: POSTGRES_DOCKER_DB, host: 'postgres', adapter: 'postgresql' }
108
+ else
109
+ raise 'Unknown database: either mysql or postgres'
110
+ end
111
+ end
112
+
113
+ def warn_file_update(file, exists)
114
+ intro = if exists
115
+ "/!\\ Watch out! Your #{file} was overwritten"
116
+ else
117
+ "A new file #{file} was added"
118
+ end
119
+
120
+ say "#{intro} by Modulorails. Ensure everything is correct!"
121
+ end
122
+
123
+ def create_keep_file
124
+ file = '.modulorails-gitlab-ci'
125
+
126
+ # Create file to avoid this generator on next modulorails launch
127
+ create_file(file)
128
+
129
+ say "Add #{file} to git"
130
+ %x(git add #{file})
131
+ end
132
+ end
@@ -0,0 +1,72 @@
1
+ image: ruby:RUBY_VERSION
2
+ stages:
3
+ - lint
4
+ - test
5
+ - deploy
6
+ cache:
7
+ key: CI_CD_CACHE_KEY
8
+ paths:
9
+ - vendor/ruby
10
+
11
+ before_script:
12
+ - apt-get update -qy
13
+ - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
14
+ - eval $(ssh-agent -s)
15
+ - ssh-add <(echo "$SSH_PRIVATE_KEY")
16
+ - mkdir -p ~/.ssh
17
+ - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
18
+ - apt-get install -y ruby-dev
19
+ - gem install bundler -v BUNDLER_VERSION --no-document
20
+ # You might need DPL if you're deploying using Heroku
21
+ #- gem install dpl -v 1.10.15 --no-document
22
+ # You might need to add some configurations here like a key for a theme
23
+ #- bundle config gems.rapidrailsthemes.com "$RRT_CFG"
24
+ - bundle install -j $(nproc) --path vendor
25
+
26
+ rubocop:
27
+ stage: lint
28
+ script:
29
+ - bundle exec rubocop -D
30
+ tags:
31
+ - rails
32
+ except:
33
+ - master
34
+ - staging
35
+
36
+ test:
37
+ stage: test
38
+ script:
39
+ - cp config/database-ci.yml config/database.yml
40
+ - "bundle exec rake db:create RAILS_ENV=test"
41
+ - "RAILS_ENV=test bundle exec rake db:migrate:reset"
42
+ - bundle exec rspec
43
+ tags:
44
+ - rails
45
+ except:
46
+ - master
47
+
48
+ staging:
49
+ stage: deploy
50
+ script:
51
+ # Uncomment the next line and update the application name if you're using DPL to deploy on
52
+ # Heroku
53
+ #- dpl --provider=heroku --app=APP_NAME --api-key=$HEROKU_API_KEY
54
+ # Remove the next line if you're not using Capistrano
55
+ - bundle exec cap staging deploy
56
+ only:
57
+ - staging
58
+ tags:
59
+ - rails
60
+
61
+ production:
62
+ stage: deploy
63
+ script:
64
+ # Uncomment the next line and update the application name if you're using DPL to deploy on
65
+ # Heroku
66
+ #- dpl --provider=heroku --app=APP_NAME --api-key=$HEROKU_API_KEY
67
+ # Remove the next line if you're not using Capistrano
68
+ - bundle exec cap production deploy
69
+ only:
70
+ - master
71
+ tags:
72
+ - rails
@@ -0,0 +1,7 @@
1
+ test:
2
+ host: HOST
3
+ adapter: ADAPTER
4
+ database: DATABASE
5
+ username: root
6
+ password: password
7
+ encoding: utf8
@@ -0,0 +1,126 @@
1
+ require 'modulorails/version'
2
+ require 'modulorails/configuration'
3
+ require 'modulorails/data'
4
+ require 'modulorails/validators/database_configuration'
5
+ require 'modulorails/railtie' if defined?(Rails::Railtie)
6
+ require 'generators/gitlabci_generator'
7
+ require 'httparty'
8
+
9
+ # Author: Matthieu 'ciappa_m' Ciappara
10
+ # The entry point of the gem. It exposes the configurator, the gathered data and the method to
11
+ # send those data to the intranet.
12
+ module Modulorails
13
+ # Author: Matthieu 'ciappa_m' Ciappara
14
+ # The error class of the gem. Allow to identify all functional errors raised by the gem.
15
+ class Error < StandardError; end
16
+
17
+ class << self
18
+ # Useful to update the configuration
19
+ attr_writer :configuration
20
+
21
+ # @author Matthieu 'ciappa_m' Ciappara
22
+ #
23
+ # When a block is given, it allows to define or update the current configuration. Without a
24
+ # block, this methods is just a configuration getter.
25
+ #
26
+ # @yield [configuration] Block with the current configuration; optional
27
+ # @yieldparam [Modulorails::Configuration] The current configuration
28
+ # @return [Modulorails::Configuration] The current configuration; updated if a block was given
29
+ def configure
30
+ # Get the current configuration if no block is given
31
+ return configuration unless block_given?
32
+
33
+ # Pass the configuration to the block and let the block do what it wants (probably update the
34
+ # configuration)
35
+ yield configuration
36
+
37
+ # Return the (probably updated) current configuration
38
+ configuration
39
+ end
40
+
41
+ # @author Matthieu 'ciappa_m' Ciappara
42
+ #
43
+ # A configuration getter.
44
+ #
45
+ # @return [Modulorails::Configuration] The current configuration
46
+ def configuration
47
+ @configuration ||= Modulorails::Configuration.new
48
+ end
49
+
50
+ # @author Matthieu 'ciappa_m' Ciappara
51
+ #
52
+ # A data getter.
53
+ #
54
+ # @return [Modulorails::Data] The current data
55
+ def data
56
+ @data ||= Modulorails::Data.new
57
+ end
58
+
59
+ # @author Matthieu 'ciappa_m' Ciappara
60
+ #
61
+ # Send the `#data` to the Intranet as JSON. HTTParty is used to send the POST request.
62
+ #
63
+ # @return [HTTParty::Response] The response of the intranet
64
+ # @raise [Modulorails::Error] If the endpoint or the API key of the intranet were not configured
65
+ def send_data
66
+ # If no endpoint and/or no API key is configured, it is impossible to send the data to the
67
+ # intranet and thus we raise an error: it is the only error we want to raise since it goes
68
+ # against one of the main goals of the gem and the gem's user is responsible.
69
+ if configuration.endpoint && configuration.api_key
70
+ # Define the headers of the request ; sending JSON and API key to authenticate the gem on
71
+ # the intranet
72
+ headers = {
73
+ 'Content-Type' => 'application/json', 'X-MODULORAILS-TOKEN' => configuration.api_key
74
+ }
75
+
76
+ # Define the JSON body of the request
77
+ body = data.to_params.to_json
78
+
79
+ # Post to the configured endpoint on the Intranet
80
+ response = HTTParty.post(configuration.endpoint, headers: headers, body: body)
81
+
82
+ # According to the API specification, on a "Bad request" response, the server explicits what
83
+ # went wrong with an `errors` field. We do not want to raise since the gem's user is not
84
+ # (necessarily) responsible for the error but we still need to display it somewhere to warn
85
+ # the user something went wrong.
86
+ puts("Modulorails errors: #{response['errors'].join(', ')}") if response.code == 400
87
+
88
+ # Return the response to allow users to do some more
89
+ response
90
+ else
91
+ raise Error.new('No endpoint or api key')
92
+ end
93
+ end
94
+
95
+ # @author Matthieu 'ciappa_m' Ciappara
96
+ #
97
+ # Generate a CI/CD template unless it was already done.
98
+ # The check is done using a 'keepfile'.
99
+ def generate_ci_template
100
+ return if File.exists?(Rails.root.join('.modulorails-gitlab-ci'))
101
+
102
+ generator_options = [
103
+ '--app', data.rails_name.parameterize,
104
+ '--database', data.adapter,
105
+ '--bundler', data.bundler_version,
106
+ '--ruby_version', data.ruby_version
107
+ ]
108
+ GitlabciGenerator.new([], generator_options, {}).invoke_all
109
+ end
110
+
111
+ # @author Matthieu 'ciappa_m' Ciappara
112
+ #
113
+ # Check the database configuration respects Modulotech's norms
114
+ def check_database_config
115
+ invalid_rules = Modulorails::Validators::DatabaseConfiguration.call
116
+ return true if invalid_rules.empty?
117
+
118
+ puts('[Modulorails] The database configuration (config/database.yml) has errors:')
119
+ invalid_rules.each do |rule|
120
+ puts("[Modulorails] Invalid database configuration for rule: #{rule}")
121
+ end
122
+
123
+ false
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,27 @@
1
+ module Modulorails
2
+ # Author: Matthieu 'ciappa_m' Ciappara
3
+ # The configuration of the gem
4
+ class Configuration
5
+ # All the keys to configure the gem
6
+ attr_accessor :_name, :_main_developer, :_project_manager, :_endpoint, :_api_key
7
+
8
+ # This allows to define a DSL to configure the gem
9
+ # Example:
10
+ # Modulorails.configure do |config|
11
+ # config.name 'MySuperApp'
12
+ # config.main_developer 'dev@modulotech.fr'
13
+ # config.project_manager 'pm@modulotech.fr'
14
+ # config.endpoint "intranet's endpoint"
15
+ # config.api_key "intranet's api key"
16
+ # end
17
+ %i[name main_developer project_manager endpoint api_key].each do |field|
18
+ define_method(field) do |value=nil|
19
+ # No value means we want to get the field
20
+ return send("_#{field}") unless value
21
+
22
+ # Else we want to set the field
23
+ send("_#{field}=", value)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,103 @@
1
+ require 'rails'
2
+ require 'active_record'
3
+ require 'git'
4
+
5
+ module Modulorails
6
+ # Author: Matthieu 'ciappa_m' Ciappara
7
+ # This holds the data gathered by the gem. Some come from the configuration by the gem's user.
8
+ # Some are fetched dynamically.
9
+ class Data
10
+ # All the data handled by this class
11
+ ATTRIBUTE_KEYS = %i[
12
+ name main_developer project_manager repository type rails_name ruby_version rails_version
13
+ bundler_version modulorails_version adapter db_version adapter_version
14
+ ].freeze
15
+
16
+ # Useful if the gem's user need to read one of the data
17
+ attr_reader *ATTRIBUTE_KEYS
18
+
19
+ def initialize
20
+ # Get the gem's configuration to get the application's usual name, main dev and PM
21
+ configuration = Modulorails.configuration
22
+ # Get the database connection to identify the database used by the application
23
+ db_connection = ActiveRecord::Base.connection
24
+ # Get the gem's specifications to fetch the versions of critical gems
25
+ loaded_specs = Gem.loaded_specs
26
+
27
+ # The three data written by the user in the configuration
28
+ # The name is the usual name of the project, the one used in conversations at Modulotech
29
+ @name = configuration.name
30
+ # The main developer, the lead developer, in short the developer to call when something's
31
+ # wrong with the application ;)
32
+ @main_developer = configuration.main_developer
33
+ # The project manager of the application; the other person to call when something's wrong with
34
+ # the application ;)
35
+ @project_manager = configuration.project_manager
36
+
37
+ # Theorically, origin is the main repository of the project and git is the sole VCS we use
38
+ # at Modulotech
39
+ @repository = Git.open(::Rails.root).config('remote.origin.url')
40
+
41
+ # The API can handle more project types but this gem is (obviously) intended for Rails
42
+ # projects only
43
+ @type = 'rails'
44
+
45
+ # The name defined for the Rails application; it can be completely different from the usual
46
+ # name or can be the same
47
+ @rails_name = ::Rails.application.class.name.split('::').first
48
+
49
+ # The Ruby version used by the application
50
+ @ruby_version = RUBY_VERSION
51
+
52
+ # The Rails version used by the application
53
+ @rails_version = loaded_specs['rails'].version.version
54
+
55
+ # The bundler version used by the application (especially useful since Bundler 2 and
56
+ # Bundler 1 are not compatible)
57
+ @bundler_version = loaded_specs['bundler'].version.version
58
+
59
+ # The version of the gem
60
+ @modulorails_version = Modulorails::VERSION
61
+
62
+ # The name of the ActiveRecord adapter; it gives the name of the database system too
63
+ @adapter = db_connection&.adapter_name&.downcase
64
+
65
+ # The version of the database engine; this request works only on MySQL and PostgreSQL
66
+ # It should not be a problem since those are the sole database engines used at Modulotech
67
+ @db_version = db_connection.select_value('SELECT version()')
68
+
69
+ # The version of the ActiveRecord adapter
70
+ @adapter_version = loaded_specs[@adapter]&.version&.version
71
+ end
72
+
73
+ # @author Matthieu 'ciappa_m' Ciappara
74
+ # @return [String] Text version of the data
75
+ def to_s
76
+ ATTRIBUTE_KEYS.map { |key| "#{key}: #{send(key)}" }.join(', ')
77
+ end
78
+
79
+ # @author Matthieu 'ciappa_m' Ciappara
80
+ # @return [Hash] The payload for the request to the intranet
81
+ def to_params
82
+ {
83
+ 'name' => @name,
84
+ 'main_developer' => @main_developer,
85
+ 'project_manager' => @project_manager,
86
+ 'repository' => @repository,
87
+ 'app_type' => @type,
88
+ 'project_data' => {
89
+ 'name' => @rails_name,
90
+ 'ruby_version' => @ruby_version,
91
+ 'rails_version' => @rails_version,
92
+ 'bundler_version' => @bundler_version,
93
+ 'modulorails_version' => @modulorails_version,
94
+ 'database' => {
95
+ 'adapter' => @adapter,
96
+ 'db_version' => @db_version,
97
+ 'gem_version' => @adapter_version
98
+ }
99
+ }
100
+ }
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,19 @@
1
+ module Modulorails
2
+ class Railtie < ::Rails::Railtie
3
+ # Binding in the Rails lifecycle. Sending data after the initialization ensures we can access
4
+ # all gems and symbols we might have to use.
5
+ config.after_initialize do
6
+ # For now, we limit everything to the development environment
7
+ if Rails.env.development?
8
+ # Effectively send the data to the intranet
9
+ Modulorails.send_data
10
+
11
+ # Generate a template for CI/CD
12
+ Modulorails.generate_ci_template
13
+
14
+ # Check database configuration
15
+ Modulorails.check_database_config
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,93 @@
1
+ module Modulorails
2
+ module Validators
3
+ # Author: Matthieu 'ciappa_m' Ciappara
4
+ # This holds the rules to configure the database by respecting Modulotech's norms.
5
+ class DatabaseConfiguration
6
+ def initialize
7
+ # All rules are invalid by default
8
+ @rules = {
9
+ standard_config_file_location: false,
10
+ test_database_not_equals_dev_database: false,
11
+ development: {
12
+ configurable_username: false,
13
+ configurable_password: false,
14
+ configurable_database: false,
15
+ configurable_host: false,
16
+ configurable_port: false
17
+ },
18
+ test: {
19
+ configurable_username: false,
20
+ configurable_password: false,
21
+ configurable_database: false,
22
+ configurable_host: false,
23
+ configurable_port: false
24
+ }
25
+ }
26
+ end
27
+
28
+ def self.call
29
+ new.call
30
+ end
31
+
32
+ def call
33
+ database_configuration = check_standard_config_file_location
34
+ return false unless database_configuration
35
+
36
+ check_test_database_not_equals_dev_database(database_configuration)
37
+ check_rules_for_environment(database_configuration, :development)
38
+ check_rules_for_environment(database_configuration, :test)
39
+
40
+ get_invalid_rules
41
+ end
42
+
43
+ private
44
+
45
+ def get_invalid_rules
46
+ dev = @rules[:development].select { |_k, v| v == false }.keys.map { |k| "development.#{k}" }
47
+ test = @rules[:test].select { |_k, v| v == false }.keys.map { |k| "test.#{k}" }
48
+ general = @rules.select { |_k, v| v == false }.keys
49
+
50
+ general + dev + test
51
+ end
52
+
53
+ def check_standard_config_file_location
54
+ # Load the configuration
55
+ config = Psych.load_file(Rails.root.join('config/database.yml'))
56
+
57
+ # If no exception was raised, then the database configuration file is at standard location
58
+ @rules[:standard_config_file_location] = true
59
+
60
+ config
61
+ rescue StandardError =>e
62
+ # An exception was raised, either the file is not a the standard location, either it just
63
+ # cannot be read. Either way, we consider the config as invalid
64
+ @rules[:standard_config_file_location] = false
65
+ nil
66
+ end
67
+
68
+ # The database for tests MUST NOT be the same as the development database since the test
69
+ # database is rewritten each time the tests are launched
70
+ def check_test_database_not_equals_dev_database(config)
71
+ test_eq_database = config['test']['database'] != config['development']['database']
72
+ @rules[:test_database_not_equals_dev_database] = test_eq_database
73
+ end
74
+
75
+ # Check all rules for an environment
76
+ def check_rules_for_environment(config, env)
77
+ @rules[env].keys.each do |rule|
78
+ key = rule.to_s.gsub(/configurable_/, '')
79
+ check_configurable_key_for_environment(config, env, key)
80
+ end
81
+ end
82
+
83
+ # Check if the given key is configurable for the given environment
84
+ def check_configurable_key_for_environment(config, env, key)
85
+ valid_rule = config[env.to_s][key] =~ /<%=\s*ENV\.fetch\(\S+,\s*\S+\)\s*%>/
86
+ valid_rule ||= config[env.to_s][key] =~ /<%=\s*ENV\.fetch\(.+\)\s*\{\s*\S+\s*\}\s*%>/
87
+
88
+ # Use of `!!` to convert `nil` to `false` and `0` to `true`
89
+ @rules[env][:"configurable_#{key}"] = !!valid_rule
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,3 @@
1
+ module Modulorails
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'lib/modulorails/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'modulorails'
5
+ spec.version = Modulorails::VERSION
6
+ spec.authors = ['Matthieu Ciappara']
7
+ spec.email = ['ciappa_m@modulotech.fr']
8
+
9
+ spec.summary = 'Common base for Ruby on Rails projects at Modulotech'
10
+ spec.description =<<~END_OF_TEXT
11
+ Modulorails is the common base for the Ruby on Rails project at Modulotech
12
+ (https://www.modulotech.fr/).
13
+
14
+ It registers each application using it on the company's intranet, provides templates for the
15
+ common configurations and defines common dependencies.
16
+ END_OF_TEXT
17
+ spec.homepage = 'https://github.com/moduloTech/modulorails'
18
+ spec.license = 'MIT'
19
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
20
+
21
+ spec.metadata['homepage_uri'] = spec.homepage
22
+ spec.metadata['source_code_uri'] = spec.homepage
23
+ spec.metadata['changelog_uri'] = 'https://github.com/moduloTech/modulorails/blob/master/CHANGELOG.md'
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
29
+ end
30
+ spec.require_paths = ['lib']
31
+
32
+ spec.add_runtime_dependency 'railties', '>= 4.2.0'
33
+ spec.add_runtime_dependency 'git', '~> 1.7', '>= 1.7.0'
34
+ spec.add_runtime_dependency 'httparty'
35
+
36
+ spec.add_development_dependency 'activerecord', '>= 4.2.0'
37
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: modulorails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matthieu Ciappara
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-10-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: git
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.7.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.7'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.7.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: httparty
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: activerecord
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 4.2.0
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 4.2.0
75
+ description: |
76
+ Modulorails is the common base for the Ruby on Rails project at Modulotech
77
+ (https://www.modulotech.fr/).
78
+
79
+ It registers each application using it on the company's intranet, provides templates for the
80
+ common configurations and defines common dependencies.
81
+ email:
82
+ - ciappa_m@modulotech.fr
83
+ executables: []
84
+ extensions: []
85
+ extra_rdoc_files: []
86
+ files:
87
+ - ".gitignore"
88
+ - ".rspec"
89
+ - ".travis.yml"
90
+ - CHANGELOG.md
91
+ - CODE_OF_CONDUCT.md
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - bin/console
98
+ - bin/setup
99
+ - lib/generators/gitlabci_generator.rb
100
+ - lib/generators/templates/.gitlab-ci.yml
101
+ - lib/generators/templates/config/database-ci.yml
102
+ - lib/modulorails.rb
103
+ - lib/modulorails/configuration.rb
104
+ - lib/modulorails/data.rb
105
+ - lib/modulorails/railtie.rb
106
+ - lib/modulorails/validators/database_configuration.rb
107
+ - lib/modulorails/version.rb
108
+ - modulorails.gemspec
109
+ homepage: https://github.com/moduloTech/modulorails
110
+ licenses:
111
+ - MIT
112
+ metadata:
113
+ homepage_uri: https://github.com/moduloTech/modulorails
114
+ source_code_uri: https://github.com/moduloTech/modulorails
115
+ changelog_uri: https://github.com/moduloTech/modulorails/blob/master/CHANGELOG.md
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 2.5.0
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubygems_version: 3.1.2
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Common base for Ruby on Rails projects at Modulotech
135
+ test_files: []