rails-dev-tools 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8521d4f1cf1ae2731589db49050da30beb1b71b857cb47ae132f7c62be024af5
4
+ data.tar.gz: e6f4994b5adcd9ab50e043b2c348b58af9ae5ba837e78bff2503454d7fe40a0f
5
+ SHA512:
6
+ metadata.gz: aae21b0b0c2df5aa30e51e3beadeb801a233d3311ea36806b4dedc8680131f28a19872a01d2fe1b976b32242564ee9a52d4bccad059983cd08642861cdda8a16
7
+ data.tar.gz: 550f75d96be2edb8003d97ad4fec13a392e09e32e6ca1e5caccb377e393f78480fc09ca7704cda0b0e014ad3eba917a04e23847c439926fdecd3c1995245a8d8
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2018 Francesco Ballardin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # Dev
2
+ This gem installs an executable command named `dev` which aims to help you develop and maintain Ruby or Ruby on Rails projects.
3
+
4
+ This gem takes inspiration from the Git Workflow published on [this page](https://nvie.com/posts/a-successful-git-branching-model/).
5
+
6
+ This gem can be used with mini Ruby projects composed of just one directory and a few files and at the same time with big Rails projects with many main apps and engines.
7
+
8
+ To work with big project, it is assumed that you organized your folders as follows:
9
+
10
+ ```bash
11
+ /path/to/project/ # Main project directory
12
+ /path/to/project/main_apps # Main apps directory
13
+ /path/to/project/main_apps/app1 # Main app 1
14
+ /path/to/project/main_apps/app2 # Main app 2
15
+ ...
16
+ /path/to/project/engines # Engines directory
17
+ /path/to/project/engines/engine1 # Engine 1
18
+ /path/to/project/engines/engine2 # Engine 2
19
+ ...
20
+ ```
21
+
22
+ ## Installation
23
+ Install with:
24
+ ```bash
25
+ $ gem install rails-dev-tools
26
+ ```
27
+
28
+ This will install an executable command named `dev`.
29
+
30
+ ## Usage
31
+ From the shell run:
32
+ ```
33
+ $ dev help
34
+ ```
35
+
36
+ To list all the available commands.
37
+
38
+ ## Commands
39
+
40
+ Usual git commands are `pull` and `push`. If you have a big project, this helps you pulling and pushing without moving from the current directory.
41
+
42
+ ### Pull
43
+
44
+ To pull data for a specific main app or engine:
45
+
46
+ ```bash
47
+ dev pull app1
48
+ dev pull engine2
49
+ ```
50
+
51
+ To pull data for all main apps and engines:
52
+ ```
53
+ dev pull
54
+ ```
55
+
56
+ ### Push
57
+
58
+ To push data for a specific main app or engine:
59
+
60
+ ```bash
61
+ dev push app1 "commit message"
62
+ dev push engine2 "commit message"
63
+ ```
64
+
65
+ ### Feature
66
+
67
+ If you want to start developing a new feature:
68
+ ```bash
69
+ dev feature open my-new-feat
70
+ ```
71
+
72
+ You will be placed on a new branch called `feature/my-new-feat`. Do all your work and then push it. After that, you can close your feature with:
73
+ ```bash
74
+ dev feature close my-new-feat
75
+ ```
76
+
77
+ This will merge the feature branch on the `develop` branch.
78
+
79
+ ### Release
80
+
81
+ When all your work into the develop branch is ready to become a new release, run:
82
+
83
+ ```bash
84
+ dev release open 0.2.0
85
+ ```
86
+
87
+ You will be placed on a new branch called `release/0.2.0`. You can work on this branch until it becomes stable and passes all tests. At this point commit and push your work and then run:
88
+ ```
89
+ dev release close 0.2.0
90
+ ```
91
+
92
+ This will merge the release branch on the `master` branch.
93
+
94
+ ### Hotfix
95
+
96
+ If you need to quickly fix a bug that accidentally made it to production, run:
97
+ ```bash
98
+ dev hotfix open 0.2.1
99
+ ```
100
+
101
+ You will be placed on a new branch called `hotfix/0.2.1`. While on this branch, write only code that fixes the bug(s) found. Do not start new features or continue developing existing ones. When you have fixed the bug run:
102
+ ```bash
103
+ dev hotfix close 0.2.1
104
+ ```
105
+
106
+ This will merge the hotfix branch on the `master` branch and on the `develop` branch.
107
+
108
+ ## License
109
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Dev'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ load 'rails/tasks/statistics.rake'
18
+
19
+ require 'bundler/gem_tasks'
20
+
21
+ require 'rake/testtask'
22
+
23
+ Rake::TestTask.new(:test) do |t|
24
+ t.libs << 'test'
25
+ t.pattern = 'test/**/*_test.rb'
26
+ t.verbose = false
27
+ end
28
+
29
+ task default: :test
File without changes
data/bin/dev ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'active_support/all'
4
+ require 'dev'
5
+
6
+ exec = Dev::Executable.new(*ARGV)
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
data/lib/dev.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'rainbow'
2
+
3
+ require 'dev/executable'
4
+ require 'dev/rainbow'
5
+ require 'dev/version'
6
+
7
+ module Dev
8
+
9
+ # Carica il file rainbow.rb per stampare a colori.
10
+ load "#{File.expand_path('..', __dir__)}/lib/dev/rainbow.rb"
11
+
12
+ end
data/lib/dev/engine.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Dev
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,205 @@
1
+ require 'open3'
2
+ require 'dev/project'
3
+ require 'dev/executables/commands/version'
4
+ require 'dev/executables/commands/status'
5
+ require 'dev/executables/commands/feature'
6
+ require 'dev/executables/commands/hotfix'
7
+ require 'dev/executables/commands/release'
8
+ require 'dev/executables/commands/pull'
9
+ require 'dev/executables/commands/push'
10
+ require 'dev/executables/commands/test'
11
+
12
+ module Dev
13
+
14
+ ##
15
+ # Classe per gestire l'esecuzione del comando +dev+.
16
+ class Executable
17
+
18
+ ##
19
+ # Definisce la classe per tutti gli errori interni
20
+ # all'esecuzione.
21
+ class ExecutionError < StandardError; end
22
+
23
+ include Dev::Executables::Commands::Version
24
+ include Dev::Executables::Commands::Status
25
+ include Dev::Executables::Commands::Feature
26
+ include Dev::Executables::Commands::Hotfix
27
+ include Dev::Executables::Commands::Release
28
+ include Dev::Executables::Commands::Pull
29
+ include Dev::Executables::Commands::Push
30
+ include Dev::Executables::Commands::Test
31
+
32
+ # @return [Dev::Executables::Project] il progetto di riferimento.
33
+ attr_accessor :project
34
+ # @return [StandardError] l'errore riscontrato, se presente.
35
+ attr_accessor :error
36
+ # @return [String] il backtrace dell'errore, se presente.
37
+ attr_accessor :backtrace
38
+
39
+ ##
40
+ # Inizializza l'eseguibile, in base al comando passato.
41
+ #
42
+ # @param [Array] argv gli argomenti del comando.
43
+ def initialize(*argv)
44
+ begin
45
+ if argv[0].present?
46
+ if self.respond_to?(argv[0])
47
+ # Carica i dati del progetto
48
+ load_project
49
+ # Lancia il comando passato
50
+ if self.method(argv[0]).arity.abs > 0
51
+ self.send(argv[0], *argv[1..-1])
52
+ else
53
+ self.send(argv[0])
54
+ end
55
+ else
56
+ raise ExecutionError.new "Command '#{argv[0]}' is not supported. Run "\
57
+ "'dev help' for a list of available commands."
58
+ end
59
+ else
60
+ raise ExecutionError.new "Missing required parameters. Run 'dev help' "\
61
+ "for a list of available commands."
62
+ end
63
+ rescue Dev::Executable::ExecutionError => e
64
+ @error = e.message
65
+ puts @error.red
66
+ rescue StandardError => e
67
+ @error = "#{e.class}: #{e.message}"
68
+ @backtrace = e.backtrace.join("\n")
69
+ puts @error.red
70
+ puts @backtrace.red
71
+ end
72
+ end
73
+
74
+ ##
75
+ # Carica i dati del progetto prendendoli dal file
76
+ # di configurazione del file 'dev.yml'.
77
+ #
78
+ # @return [nil]
79
+ def load_project
80
+ config_file = Dir.glob("#{Dir.pwd}/**/dev.yml").first
81
+ raise ExecutionError.new "No valid configuration files found. Searched for a file named 'dev.yml' "\
82
+ "in folder #{Dir.pwd} and all its subdirectories." if config_file.nil?
83
+ @project = Dev::Project.new(config_file)
84
+ end
85
+
86
+ ##
87
+ # Determina de l'env è valido.
88
+ #
89
+ # @return [Boolean] se l'env è fra quelli validi.
90
+ def valid_env?
91
+ unless @env.in? [ :production, :staging ]
92
+ raise ExecutionError.new "The environment '#{@env}' is not valid. "\
93
+ "Valid environments are 'production' or 'staging'."
94
+ else
95
+ true
96
+ end
97
+ end
98
+
99
+ ##
100
+ # Esegue un comando e cattura l'output ritornandolo come
101
+ # risultato di questo metodo. Si può passare l'opzione
102
+ # +flush+ per stampare subito l'output come se non fosse stato
103
+ # catturato.
104
+ #
105
+ # @param [String] command il comando da eseguire.
106
+ # @param [Hash] options le opzioni.
107
+ #
108
+ # @return [nil]
109
+ def exec(command, options = {})
110
+ out, err, status = Open3.capture3(command)
111
+ command_output = [ out.presence, err.presence ].compact.join("\n")
112
+ if options[:flush] == true
113
+ puts command_output
114
+ else
115
+ command_output
116
+ end
117
+ end
118
+
119
+ ##
120
+ # Stampa i comandi possibili.
121
+ #
122
+ # @return [nil]
123
+ def help
124
+ puts
125
+ print "Dev".green
126
+ print " - available commands:\n"
127
+ puts
128
+
129
+ print "\tversion\t\t".limegreen
130
+ print "Prints current version.\n"
131
+ puts
132
+
133
+ print "\tfeature\t\t".limegreen
134
+ print "Opens or closes a feature for the current app.\n"
135
+ print "\t\t\tWarning: the app is determined from the current working directory!\n"
136
+ print "\t\t\tExample: "
137
+ print "dev feature open my-new-feature".springgreen
138
+ print " (opens a new feature for the current app)"
139
+ print ".\n"
140
+ print "\t\t\tExample: "
141
+ print "dev feature close my-new-feature".springgreen
142
+ print " (closes a developed new feature for the current app)"
143
+ print ".\n"
144
+ puts
145
+
146
+ print "\thotfix\t\t".limegreen
147
+ print "Opens or closes a hotfix for the current app.\n"
148
+ print "\t\t\tWarning: the app is determined from the current working directory!\n"
149
+ print "\t\t\tExample: "
150
+ print "dev hotfix open 0.2.1".springgreen
151
+ print " (opens a new hotfix for the current app)"
152
+ print ".\n"
153
+ print "\t\t\tExample: "
154
+ print "dev hotfix close 0.2.1".springgreen
155
+ print " (closes a developed new hotfix for the current app)"
156
+ print ".\n"
157
+ puts
158
+
159
+ print "\trelease\t\t".limegreen
160
+ print "Opens or closes a release for the current app.\n"
161
+ print "\t\t\tWarning: the app is determined from the current working directory!\n"
162
+ print "\t\t\tExample: "
163
+ print "dev release open 0.2.0".springgreen
164
+ print " (opens a new release for the current app)"
165
+ print ".\n"
166
+ print "\t\t\tExample: "
167
+ print "dev release close 0.2.0".springgreen
168
+ print " (closes a developed new release for the current app)"
169
+ print ".\n"
170
+ puts
171
+
172
+ print "\tpull\t\t".limegreen
173
+ print "Pulls specified app's git repository, or pulls all apps if none are specified.\n"
174
+ print "\t\t\tWarning: the pulled branch is the one the app is currently on!\n"
175
+ print "\t\t\tExample: "
176
+ print "dev pull [myapp]".springgreen
177
+ print ".\n"
178
+ puts
179
+
180
+ print "\tpush\t\t".limegreen
181
+ print "Commits and pushes the specified app.\n"
182
+ print "\t\t\tWarning: the pushed branch is the one the app is currently on!\n"
183
+ print "\t\t\tExample: "
184
+ print "dev push myapp \"commit message\"".springgreen
185
+ print ".\n"
186
+ puts
187
+
188
+ print "\ttest\t\t".limegreen
189
+ print "Runs the app's test suite. Tests must be written with rspec.\n"
190
+ print "\t\t\tIt is possibile to specify which app's test suite to run.\n"
191
+ print "\t\t\tIf nothing is specified, all main app's test suites are run.\n"
192
+ print "\t\t\tExample: "
193
+ print "dev test mymainapp myengine".springgreen
194
+ print " (runs tests for 'mymainapp' and 'myengine')"
195
+ print ".\n"
196
+ print "\t\t\tExample: "
197
+ print "dev test".springgreen
198
+ print " (runs tests for all main apps and engines within this project)"
199
+ print ".\n"
200
+ puts
201
+ end
202
+
203
+ end
204
+
205
+ end
@@ -0,0 +1,111 @@
1
+ module Dev
2
+ module Executables
3
+ module Commands
4
+ module Feature
5
+
6
+ ##
7
+ # Comandi per gestire l'apertura e la chiusura di una nuova feature.
8
+ #
9
+ # @param [String] command il comando da eseguire.
10
+ # @param [String] name il nome della feature.
11
+ #
12
+ # @return [nil]
13
+ def feature(command = nil, name = nil)
14
+ raise Dev::Executable::ExecutionError.new "Wrong command syntax: "\
15
+ "specify whether to open or close a feature. "\
16
+ "Example: dev feature open my-new-feature" unless command.in? [ 'open', 'close' ]
17
+ name = name.to_s.squish
18
+
19
+ if @project.valid_app?
20
+ case command
21
+ when 'open' then feature_open(name)
22
+ when 'close' then feature_close(name)
23
+ end
24
+ end
25
+ end
26
+
27
+ ##
28
+ # Apre una nuova feature.
29
+ #
30
+ # @param [String] name il nome della feature.
31
+ #
32
+ # @return [nil]
33
+ def feature_open(name)
34
+ print "Preparing to open a new feature for app "
35
+ print @project.current_app.teal
36
+ print " named "
37
+ puts name.teal
38
+ puts
39
+
40
+ branches = `git branch -a`
41
+ unless branches.include? ("develop\n")
42
+ print "\tCreating develop branch.."
43
+ exec "git checkout -b develop"
44
+ exec "git add ."
45
+ exec "git commit -m \"Dev: automatically created 'develop' branch\""
46
+ exec "git push -u origin develop"
47
+ print "√\n".green
48
+ puts
49
+ end
50
+
51
+ print "\tOpening.. "
52
+ git_output = exec "git checkout -b feature/#{name} develop"
53
+ if git_output.include?('fatal') or git_output.include?('rejected') or git_output.include?('error')
54
+ print "X\n".red
55
+ puts "\t\tSomething went wrong, take a look at the output from git:".indianred
56
+ puts "\t\t#{git_output.split("\n").map(&:squish).join("\n\t\t")}".indianred
57
+ puts
58
+ else
59
+ print "√\n".green
60
+ puts "\t\tDone. Output from git:".cadetblue
61
+ puts "\t\t#{git_output.split("\n").map(&:squish).join("\n\t\t")}".cadetblue
62
+ puts
63
+ end
64
+ end
65
+
66
+ ##
67
+ # Chiude una feature esistente.
68
+ #
69
+ # @param [String] name il nome della feature.
70
+ #
71
+ # @return [nil]
72
+ def feature_close(name)
73
+ print "Preparing to close the feature for app "
74
+ print @project.current_app.teal
75
+ print " named "
76
+ puts name.teal
77
+ puts
78
+
79
+ status = `git status`
80
+ if status.include? "Changes not staged for commit:"
81
+ raise Dev::Executable::ExecutionError.new "Your current branch has unstaged changes. Please "\
82
+ "commit or stash them before closing the feature."
83
+ end
84
+
85
+ branches = `git branch -a`
86
+ unless branches.include? ("feature/#{name}\n")
87
+ raise Dev::Executable::ExecutionError.new "No feature named '#{name}' could be found "\
88
+ "for this app's repository."
89
+ end
90
+
91
+ print "\tClosing.. "
92
+ exec "git checkout develop"
93
+ exec "git merge --no-ff feature/#{name}"
94
+ git_output = exec "git push origin develop"
95
+ if git_output.include?('fatal') or git_output.include?('rejected') or git_output.include?('error')
96
+ print "X\n".red
97
+ puts "\t\tSomething went wrong, take a look at the output from git:".indianred
98
+ puts "\t\t#{git_output.split("\n").map(&:squish).join("\n\t\t")}".indianred
99
+ puts
100
+ else
101
+ print "√\n".green
102
+ puts "\t\tDone. Output from git:".cadetblue
103
+ puts "\t\t#{git_output.split("\n").map(&:squish).join("\n\t\t")}".cadetblue
104
+ puts
105
+ end
106
+ end
107
+
108
+ end
109
+ end
110
+ end
111
+ end