flash 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTEyMWQwMmZmMzU5ZTVmODE0MzJlYjIxNjI1ZmU4NzgwYTNiNGFiNw==
5
+ data.tar.gz: !binary |-
6
+ MDVjYTBkN2Q2ZGM4M2M5ZWU2YmNiMjg5NTAyZDczNDY1MzgxMzdiYQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OTk4ZjJkZDExZjYxYjI5Y2MzMmFhMDJkODRlMTYxYjkxMDY1NTQzZjUxYTgz
10
+ ODJmNjM1MmZhMGFiMzI3YWQ2MzkzM2MyM2QxZWMwZjBjNjFiNzA0MjY3YjZh
11
+ N2M2YjkyMDA1NzEyZWNlMDY4N2Q0YzUwMjQ4ZTYyY2FlMGQzMTY=
12
+ data.tar.gz: !binary |-
13
+ NzhkZWE3Y2NkYjE5OWZmMTkzODhmNjVmMzI5MDYwNzczZTQzMjQwZGQ2Yjgz
14
+ YmRiZWM4N2ZiMTg3ZWU4Y2M2NzI0ZDAyYzI2NTYyODlkYmQ1MGNiYzM3YmRm
15
+ ZDFlNTVjMTcxZDQwMGQ2MWI1NzBiNzJiOTZlY2ZkYjkzNDE0NDc=
data/README.md CHANGED
@@ -1,40 +1,195 @@
1
- # Flash
1
+ Flash
2
+ =====
2
3
 
3
- Flash helps you run arbitrary or predefined commands on multiple projects all defined in the Runfile.
4
+ [![Gem Version](https://badge.fury.io/rb/flash.svg)](http://badge.fury.io/rb/flash)
5
+ [![Build Status](https://travis-ci.org/colmarius/flash.svg?branch=master)](https://travis-ci.org/colmarius/flash?branch=master)
4
6
 
5
- # Installation
7
+ ![flash](http://colmarius.net/flash/images/flashtocat.png)
8
+
9
+ Overview
10
+ --------
11
+
12
+ Main purpose of Flash is to eliminate repetitive tasks, those of running the
13
+ same commands on multiple directories.
14
+
15
+ It allows one to define:
16
+ - __aliases__ for sets of commands to be run on multiple directories
17
+ - __groups__ for grouping together multiple directories
18
+
19
+ Both groups and aliases can be defined in the `.flash.yml` configuration file.
20
+
21
+ Motivation
22
+ ----------
23
+
24
+ __Simple configuration file__
25
+
26
+ A place to define both groups and aliases.
27
+
28
+ __Inspect output__
29
+
30
+ See the output of flash commands runned on a group of projects.
31
+
32
+ Installation
33
+ ------------
34
+
35
+ You can either install the gem manually:
6
36
 
7
37
  ```bash
8
- > gem install flash
38
+ gem install flash
9
39
  ```
10
40
 
11
- The command available is run:
41
+ or add it to your Gemfile:
12
42
 
13
- ```bash
14
- > run
15
- Group name is missing.
16
- Usage: run [options] group
17
- -c, --command command Commands to run (semicolon separated)
18
- -d, --debug Debug: print each command result
19
- -r, --recipe recipe Run registered recipe if present
20
- -l, --list-recipes List registered recipes
21
- -h, --help Help documentation
43
+ ```ruby
44
+ group :development do
45
+ gem 'flash'
46
+ end
22
47
  ```
23
48
 
24
- # Example
49
+ Usage
50
+ -----
25
51
 
26
- ```bash
27
- > cd example
28
- > run -c ls projects
29
- salsa> ls
30
- cubana
52
+ Flash requires a `.flash.yml` file in order to function. This should be
53
+ defined at the root of your workspace folder.
54
+
55
+ ```
56
+ # .flash.yml
31
57
 
32
- dancing> ls
33
- bouncing
58
+ frontend:
59
+ - super-product1
60
+ - super-product2
61
+ - super-api
62
+ - super-sso
34
63
 
35
- school> ls
36
- fun
64
+ libraries:
65
+ - super-rest-client
66
+ - super-core-js
67
+ - super-core-css
37
68
 
69
+ aliases:
70
+ update-master: git stash; git checkout master; git pull
71
+ status: git status -s
72
+
73
+ clone:
74
+ git: git@github.com:SuperDuper
38
75
  ```
39
76
 
40
- TODO: write detailed description
77
+ Here we define two groups _frontend_ and _libraries_. We will be allowed to run commands on each of these groups.
78
+
79
+ We can also define two special configuration sections:
80
+
81
+ - __aliases__: allows us two save repetitive and long commands
82
+ - __clone__: allows to define a base __git__ URL from where projects in a group can be cloned
83
+
84
+ With a valid `.flash.yml` configuration file set in your current workspace you
85
+ are now set to run flash commands.
86
+
87
+ Commands
88
+ --------
89
+
90
+ Running `flash` will give you the following output:
91
+
92
+ Commands:
93
+ flash clone GROUP # Clone all projects found in GROUP config file
94
+ flash help [COMMAND] # Describe available commands or one specific command
95
+ flash info [GROUP] # Display information from config file
96
+ flash run COMMAND GROUP # Run one or more COMMAND(s) on the specified GROUP
97
+ flash version # Display Flash gem version
98
+
99
+ ### flash clone
100
+
101
+ flash clone GROUP
102
+
103
+ Allows to clone all projects defined in a GROUP by using the clone git base
104
+ URL.
105
+
106
+ Getting back to our `.flash.yml` example file...
107
+
108
+ ```
109
+ # .flash.yml
110
+
111
+ frontend:
112
+ - super-product1
113
+ - super-product2
114
+ - super-api
115
+ - super-sso
116
+
117
+ ...
118
+
119
+ clone:
120
+ git: git@github.com:SuperDuper
121
+ ```
122
+
123
+ Running the following command...
124
+
125
+ flash clone frontend
126
+
127
+ will clone from SuperDuper organization all projects defined in _frontend_
128
+ group.
129
+
130
+ ### flash info
131
+
132
+ flash info [GROUP]
133
+
134
+ This is a helper command for printing `.flash.yml` contents. Prints all file
135
+ contents or just part of it (depending if group or other config section is
136
+ specified).
137
+
138
+ ### flash run
139
+
140
+ flash run COMMAND GROUP
141
+
142
+ The heart of flash is the __run__ command. It requires both a COMMAND and a
143
+ GROUP. With this command one can run same tasks on all projects of same GROUP.
144
+
145
+ Note: COMMAND can be a standalone command, or be defined in `aliases` section
146
+ (where it must be a list of commands, semi-column separated).
147
+
148
+ Getting back to our `.flash.yml` example file...
149
+
150
+ ```
151
+ # .flash.yml
152
+
153
+ frontend:
154
+ - super-product1
155
+ - super-product2
156
+ - super-api
157
+ - super-sso
158
+
159
+ libraries:
160
+ - super-rest-client
161
+ - super-core-js
162
+ - super-core-css
163
+
164
+ aliases:
165
+ update-master: git stash; git checkout master; git pull
166
+ status: git status -s
167
+ ```
168
+
169
+ here are some commands you can run:
170
+
171
+ # Update master branch.
172
+ flash run update-master frontend
173
+ flash run update-master libraries
174
+
175
+ # Display status.
176
+ flash run status frontend
177
+
178
+ # List some files.
179
+ flash run ls frontend
180
+
181
+ # Lets push master branch to origin/staging (forced) for all frontend projects.
182
+ flash run "git checkout master ; git checkout -B staging ; git push -f ; git checkout master" frontend
183
+
184
+ # This last command could be aliased to `master-to-staging`, which would result in:
185
+ flash run master-to-staging frontend
186
+
187
+ Contributing
188
+ ------------
189
+
190
+ Please see [CONTRIBUTING.md](https://github.com/colmarius/flash/blob/master/CONTRIBUTING.md).
191
+
192
+ Note
193
+ ----
194
+
195
+ This is a project to level up my gem skills.
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
+
5
+ require 'flash/cli'
6
+
7
+ Flash::CLI.start
@@ -0,0 +1,50 @@
1
+ require 'flash'
2
+ require 'flash/command/clone'
3
+ require 'flash/command/info'
4
+ require 'flash/command/run'
5
+ require 'thor'
6
+
7
+ class Flash::CLI < Thor
8
+ class << self
9
+ def is_thor_reserved_word?(word, type)
10
+ return false if word == 'run'
11
+ super
12
+ end
13
+ end
14
+
15
+ desc 'clone GROUP', 'Clone all projects found in GROUP config file'
16
+
17
+ def clone(group)
18
+ Flash::Command::Clone.new(group).execute
19
+ end
20
+
21
+ desc 'info [GROUP]', 'Display information from config file'
22
+
23
+ def info(group = nil)
24
+ Flash::Command::Info.new(group).execute
25
+ end
26
+
27
+ desc 'run COMMAND GROUP', 'Run one or more COMMAND(s) on the specified GROUP'
28
+
29
+ long_desc <<-LONGDESC
30
+ Run the COMMAND(s) on the specified GROUP.
31
+
32
+ More than one command can be specified if wrapped under quotes
33
+ and are semi-column separated.
34
+
35
+ In alternative aliases can be used, which can be defined under "aliases"
36
+ in .flash.yml config file.
37
+ LONGDESC
38
+
39
+ def run(command, group)
40
+ Flash::Command::Run.new(command, group).execute
41
+ end
42
+
43
+ desc 'version', 'Display Flash gem version'
44
+
45
+ map ['-v', '--version'] => :version
46
+
47
+ def version
48
+ puts Flash::VERSION
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ require 'flash'
2
+
3
+ module Flash::Command
4
+ end
@@ -0,0 +1,16 @@
1
+ require 'flash'
2
+ require 'flash/command'
3
+ require 'flash/config'
4
+
5
+ class Flash::Command::Base
6
+ def initialize
7
+ end
8
+
9
+ def config
10
+ @config ||= Flash::Config.new
11
+ end
12
+
13
+ def valid_group?(group)
14
+ (group && config[group]) ? true : false
15
+ end
16
+ end
@@ -0,0 +1,57 @@
1
+ require 'flash'
2
+ require 'flash/command/base'
3
+
4
+ class Flash::Command::Clone < Flash::Command::Base
5
+ def initialize(group)
6
+ @group = group
7
+ end
8
+
9
+ def execute
10
+ raise(ArgumentError, 'Missing required group parameter.') unless @group
11
+
12
+ unknown_group_and_exit(@group) unless valid_group?(@group)
13
+ missing_git_clone_url unless has_clone_git_url?
14
+ clone_projects(@group)
15
+ end
16
+
17
+ private
18
+
19
+ def unknown_group_and_exit(group)
20
+ puts "Unknown group \"#{group}\" in .flash.yml config."
21
+ exit 1
22
+ end
23
+
24
+ def missing_git_clone_url
25
+ puts 'Missing clone git URL defined in .flash.yml config.'
26
+ exit 1
27
+ end
28
+
29
+ def has_clone_git_url?
30
+ clone_git_url = (config['clone'] && config['clone']['git'])
31
+ clone_git_url ? true : false
32
+ end
33
+
34
+ def clone_projects(group)
35
+ projects(group).each do |project|
36
+ clone_single(project) unless File.exist?(project)
37
+ puts "\n[#{project}] Done cloning project.\n\n"
38
+ end
39
+ end
40
+
41
+ def projects(group)
42
+ config[group] || []
43
+ end
44
+
45
+ def clone_single(project)
46
+ system('git', 'clone', clone_path(project))
47
+ end
48
+
49
+ def clone_path(project)
50
+ "#{ base_clone_path }/#{ project }.git"
51
+ end
52
+
53
+ def base_clone_path
54
+ base_url = config['clone']['git']
55
+ base_url.gsub(/\/+$/, '')
56
+ end
57
+ end
@@ -0,0 +1,25 @@
1
+ require 'flash'
2
+ require 'flash/command/base'
3
+
4
+ class Flash::Command::Info < Flash::Command::Base
5
+ def initialize(group = nil)
6
+ @group = group
7
+ end
8
+
9
+ def execute
10
+ puts output(@group)
11
+ end
12
+
13
+ private
14
+
15
+ def output(group = nil)
16
+ return unknown_group(group) if group && !valid_group?(group)
17
+
18
+ result = valid_group?(group) ? config[group] : config
19
+ result.to_yaml
20
+ end
21
+
22
+ def unknown_group(group)
23
+ "Unknown group \"#{group}\" in .flash.yml config."
24
+ end
25
+ end
@@ -0,0 +1,78 @@
1
+ require 'flash'
2
+ require 'flash/command/base'
3
+ require 'pathname'
4
+
5
+ class Flash::Command::Run < Flash::Command::Base
6
+ def initialize(command, group)
7
+ @command = command
8
+ @group = group
9
+ end
10
+
11
+ def execute
12
+ raise(ArgumentError, 'Missing required command and group parameters.') unless @command && @group
13
+
14
+ unknown_group_and_exit(@group) unless valid_group?(@group)
15
+ run_command_in_group(@command, @group)
16
+ end
17
+
18
+ private
19
+
20
+ def unknown_group_and_exit(group)
21
+ puts "Unknown group \"#{group}\" in .flash.yml config."
22
+ exit 1
23
+ end
24
+
25
+ def run_command_in_group(command, group)
26
+ projects(group).each do |project|
27
+ color = new_color
28
+
29
+ system("cd #{ project_dir(project) }")
30
+ commands(command).each { |cmd| run(cmd, color: color, project: project) }
31
+
32
+ say('', color)
33
+ end
34
+ end
35
+
36
+ def projects(group)
37
+ config[group]
38
+ end
39
+
40
+ def run(command, options = {})
41
+ verbose = options[:verbose].nil? ? true : options[:verbose]
42
+ color = options[:color]
43
+ project = options[:project]
44
+
45
+ prompt(command, color: color, project: project) if verbose
46
+ system("cd #{ project_dir(project) } ; #{ command }")
47
+ end
48
+
49
+ def commands(alias_or_command)
50
+ commands = aliases[alias_or_command] || alias_or_command
51
+ commands.split(';').map(&:strip)
52
+ end
53
+
54
+ def aliases
55
+ config['aliases'] || {}
56
+ end
57
+
58
+ def prompt(message, options)
59
+ color = options[:color]
60
+ project = options[:project]
61
+
62
+ say("#{ project }> #{ message }", color)
63
+ end
64
+
65
+ def say(stuff, color)
66
+ prefix = "\e[38;5;#{ color }m"
67
+ suffix = "\e[0m"
68
+ system "echo '#{ prefix }#{ stuff }#{ suffix }'"
69
+ end
70
+
71
+ def new_color
72
+ rand((1..22)) * 10 + 2
73
+ end
74
+
75
+ def project_dir(project)
76
+ "#{ Dir.pwd }/#{ project }"
77
+ end
78
+ end
@@ -0,0 +1,26 @@
1
+ require 'flash'
2
+ require 'yaml'
3
+ require 'delegate'
4
+
5
+ class Flash::Config < SimpleDelegator
6
+ def initialize
7
+ check_config_file!
8
+ data = YAML.load_file(config_file)
9
+ super(data)
10
+ end
11
+
12
+ private
13
+
14
+ def check_config_file!
15
+ error("#{config_file} does not exist.") unless File.exist?(config_file)
16
+ end
17
+
18
+ def config_file
19
+ '.flash.yml'
20
+ end
21
+
22
+ def error(message)
23
+ puts "ERROR: #{message}"
24
+ exit 1
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Flash
2
- VERSION = '0.0.3'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+ require 'flash/cli'
3
+
4
+ describe Flash::CLI, :fakefs do
5
+ subject { described_class }
6
+
7
+ describe '.is_thor_reserved_word?' do
8
+ it 'should allow "run" to be defined as command' do
9
+ expect(subject.is_thor_reserved_word?('run', :command)).to be_falsey
10
+ end
11
+ end
12
+
13
+ describe '#clone' do
14
+ before { write_config_file_with_clone }
15
+
16
+ describe 'flash clone projects' do
17
+ let(:output) { flash('clone projects') }
18
+
19
+ it 'should show done cloning messages' do
20
+ expect_any_instance_of(Flash::Command::Clone)
21
+ .to receive(:system).exactly(3).times.and_return(nil)
22
+
23
+ expect(output).to match(/\[foo\] Done cloning project\./)
24
+ expect(output).to match(/\[bar\] Done cloning project\./)
25
+ expect(output).to match(/\[buz\] Done cloning project\./)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '#info' do
31
+ before { write_config_file }
32
+
33
+ describe 'flash info' do
34
+ let(:output) { flash('info') }
35
+
36
+ it 'should print all info from config file' do
37
+ expect(output).to match(/projects/)
38
+ expect(output).to match(/foo/)
39
+ expect(output).to match(/bar/)
40
+ expect(output).to match(/buz/)
41
+ expect(output).to match(/libraries/)
42
+ expect(output).to match(/cippa/)
43
+ expect(output).to match(/lippa/)
44
+ end
45
+ end
46
+
47
+ describe 'flash info projects' do
48
+ let(:output) { flash('info projects') }
49
+
50
+ it 'should print info from config file for "projects" group' do
51
+ expect(output).to match(/foo/)
52
+ expect(output).to match(/bar/)
53
+ expect(output).to match(/buz/)
54
+ end
55
+ end
56
+
57
+ describe 'flash info blabla' do
58
+ let(:output) { flash('info blabla') }
59
+
60
+ it 'should print unknown group' do
61
+ expect(output).to match(/Unknown group "blabla" in .flash.yml config.\n/)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe '#run' do
67
+ before { write_config_file }
68
+
69
+ describe 'flash run ls projects' do
70
+ let(:output) { flash('run ls projects') }
71
+
72
+ it 'should not raise error' do
73
+ expect_any_instance_of(Flash::Command::Run)
74
+ .to receive(:system).exactly(12).times
75
+
76
+ output
77
+ end
78
+ end
79
+ end
80
+
81
+ describe '#version' do
82
+ let(:output) { flash('version') }
83
+
84
+ it 'should print version number' do
85
+ expect(output).to match(/#{Flash::VERSION}\n/)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'flash/command/base'
3
+
4
+ describe Flash::Command::Base, :fakefs do
5
+ subject { described_class.new }
6
+
7
+ before { write_config_file }
8
+
9
+ describe '#config' do
10
+ let(:config) { subject.config }
11
+
12
+ it 'should be of correct kind' do
13
+ expect(config).to be_an_instance_of(Flash::Config)
14
+ end
15
+
16
+ it 'should behave as Hash' do
17
+ expect(config).to respond_to(:[])
18
+ end
19
+ end
20
+
21
+ describe '#valid_group?' do
22
+ it 'responds true for valid groups' do
23
+ expect(subject.valid_group?('projects')).to be_truthy
24
+ expect(subject.valid_group?('libraries')).to be_truthy
25
+ end
26
+
27
+ it 'responds false otherwise' do
28
+ expect(subject.valid_group?('unknkown')).to be_falsey
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+ require 'flash/command/clone'
3
+
4
+ describe Flash::Command::Clone, :fakefs do
5
+ subject { described_class.new(@group) }
6
+
7
+ before { write_config_file }
8
+
9
+ describe '#execute' do
10
+
11
+ context 'with invalid group' do
12
+ it 'with nil group' do
13
+ @group = nil
14
+ expect { subject.execute }.to raise_error ArgumentError
15
+ end
16
+
17
+ it 'with empty group' do
18
+ @group = ''
19
+ output = capture_stdout do
20
+ expect { subject.execute }.to raise_error SystemExit
21
+ end
22
+ expect(output).to match(/Unknown group "" in .flash.yml config./)
23
+ end
24
+
25
+ it 'with unknown group' do
26
+ @group = 'unknown'
27
+ output = capture_stdout do
28
+ expect { subject.execute }.to raise_error SystemExit
29
+ end
30
+ expect(output).to match(/Unknown group "unknown" in .flash.yml config./)
31
+ end
32
+ end
33
+
34
+ context 'with valid group' do
35
+ before { @group = 'projects' }
36
+
37
+ describe 'without clone git endpoint' do
38
+ it 'should raise error' do
39
+ output = capture_stdout do
40
+ expect { subject.execute }.to raise_error SystemExit
41
+ end
42
+ expect(output).to match(/Missing clone git URL defined in .flash.yml config./)
43
+ end
44
+ end
45
+
46
+ describe 'with clone git endpoint' do
47
+ before { write_config_file_with_clone }
48
+
49
+ it 'should clone projects in group' do
50
+ expect(subject).to receive(:clone_projects).with(@group).once
51
+ subject.execute
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ require 'flash/command/info'
3
+
4
+ describe Flash::Command::Info, :fakefs do
5
+ subject { described_class.new(group) }
6
+
7
+ before { write_config_file }
8
+
9
+ describe '#execute' do
10
+ let(:group) { 'projects' }
11
+
12
+ it 'calls output method with group' do
13
+ expect(subject).to receive(:output).with(group).once
14
+ subject.execute
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ require 'flash/command/run'
3
+
4
+ describe Flash::Command::Run, :fakefs do
5
+ subject { described_class.new(@command, @group) }
6
+
7
+ before { write_config_file }
8
+
9
+ describe '#execute' do
10
+
11
+ context 'with invalid args' do
12
+
13
+ it 'command and group are nil' do
14
+ @command, @group = [nil, nil]
15
+ expect { subject.execute }.to raise_error ArgumentError
16
+ end
17
+
18
+ it 'command and group are empty strings' do
19
+ @command, @group = ['', '']
20
+ output = capture_stdout do
21
+ expect { subject.execute }.to raise_error SystemExit
22
+ end
23
+ expect(output).to match(/Unknown group "" in \.flash\.yml config\./)
24
+ end
25
+
26
+ it 'unknown group' do
27
+ @command = ''
28
+ @group = 'unknown'
29
+ output = capture_stdout do
30
+ expect { subject.execute }.to raise_error SystemExit
31
+ end
32
+ expect(output).to match(/Unknown group "unknown" in \.flash\.yml config\./)
33
+ end
34
+ end
35
+
36
+ context 'with valid args' do
37
+
38
+ it 'example run ls command on projects group' do
39
+ @command = 'ls'
40
+ @group = 'projects'
41
+ expect_any_instance_of(described_class)
42
+ .to receive(:system).exactly(12).times
43
+ subject.execute
44
+ end
45
+
46
+ it 'calls run command in group once' do
47
+ @command = 'ls'
48
+ @group = 'projects'
49
+ expect_any_instance_of(described_class)
50
+ .to receive(:run_command_in_group).with(@command, @group).once
51
+ subject.execute
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'flash/config'
3
+
4
+ describe Flash::Config, :fakefs do
5
+ subject { described_class.new }
6
+
7
+ describe '#initialize' do
8
+ it 'can load from a file' do
9
+ write_config_file
10
+ expect(subject['projects']).to eq %w(foo bar buz)
11
+ end
12
+
13
+ it 'will exit with error message if no config file found' do
14
+ output = capture_stdout do
15
+ expect { subject }.to raise_error SystemExit
16
+ end
17
+ expect(output).to match(/ERROR: .flash.yml does not exist.\n/)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'flash'
3
+
4
+ describe Flash do
5
+
6
+ describe '#version' do
7
+ subject { Flash::VERSION }
8
+ it { should be_a String }
9
+ end
10
+ end
@@ -1,7 +1,84 @@
1
- require 'rspec/autorun'
1
+ if ENV['TRAVIS'] || ENV['COVERAGE']
2
+ require 'simplecov'
3
+
4
+ if ENV['TRAVIS']
5
+ require 'coveralls'
6
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
7
+ end
8
+
9
+ SimpleCov.start do
10
+ add_filter '/spec'
11
+ add_filter '/vendor'
12
+ end
13
+ end
14
+
15
+ require 'rspec'
16
+ require 'fakefs/safe'
17
+ require 'fakefs/spec_helpers'
18
+
19
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
20
 
3
21
  RSpec.configure do |config|
4
- config.expect_with :rspec do |c|
5
- c.syntax = :expect
22
+ config.color = true
23
+ config.order = 'rand'
24
+ config.raise_errors_for_deprecations!
25
+ config.include FakeFS::SpecHelpers, :fakefs
26
+ end
27
+
28
+ def flash(args)
29
+ capture_stdout do
30
+ begin
31
+ Flash::CLI.start(args.split(' '))
32
+ rescue SystemExit
33
+ nil
34
+ end
35
+ end
36
+ end
37
+
38
+ def write_config_file_with_clone
39
+ clone_contents = <<-SECTION
40
+ clone:
41
+ git: git@github.com:SuperDuper
42
+ SECTION
43
+
44
+ write_config_file(contents: default_contents + clone_contents)
45
+ end
46
+
47
+ def write_config_file(options = {})
48
+ config_file = options[:config_file] || '.flash.yml'
49
+ contents = options[:contents] || default_contents
50
+
51
+ File.open(config_file, 'w') do |file|
52
+ contents.split('\n').each do |line|
53
+ file.puts line
54
+ end
6
55
  end
56
+ File.expand_path(config_file)
57
+ end
58
+
59
+ def default_contents
60
+ <<-CONTENTS
61
+ projects:
62
+ - foo
63
+ - bar
64
+ - buz
65
+ libraries:
66
+ - cippa
67
+ - lippa
68
+ CONTENTS
69
+ end
70
+
71
+ def make_pipe
72
+ IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe('BINARY')
73
+ end
74
+
75
+ def capture_stdout
76
+ old_stdout = $stdout.dup
77
+ rd, wr = make_pipe
78
+ $stdout = wr
79
+ yield
80
+ wr.close
81
+ rd.read
82
+ ensure
83
+ $stdout = old_stdout
7
84
  end
metadata CHANGED
@@ -1,70 +1,80 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Marius Colacioiu
9
8
  autorequire:
10
- bindir: bin
9
+ bindir: exe
11
10
  cert_chain: []
12
- date: 2014-01-03 00:00:00.000000000 Z
13
- dependencies: []
14
- description: Flash helps you run commands on multiple projects all defined in the
15
- Runfile
11
+ date: 2014-08-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.19.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.19.1
27
+ description: Flash helps you run same commands on multiple projects all defined in
28
+ the `.flash.yml` config.
16
29
  email:
17
30
  - marius.colacioiu@gmail.com
18
31
  executables:
19
- - run
32
+ - flash
20
33
  extensions: []
21
34
  extra_rdoc_files: []
22
35
  files:
23
- - .gitignore
24
- - Gemfile
25
- - Gemfile.lock
26
36
  - README.md
27
- - Rakefile
28
- - bin/run
29
- - example/Runfile
30
- - example/dancing/bouncing
31
- - example/salsa/cubana
32
- - example/school/fun
33
- - flash.gemspec
37
+ - exe/flash
34
38
  - lib/flash.rb
35
- - lib/flash/runfile.rb
36
- - lib/flash/runner.rb
39
+ - lib/flash/cli.rb
40
+ - lib/flash/command.rb
41
+ - lib/flash/command/base.rb
42
+ - lib/flash/command/clone.rb
43
+ - lib/flash/command/info.rb
44
+ - lib/flash/command/run.rb
45
+ - lib/flash/config.rb
37
46
  - lib/flash/version.rb
47
+ - spec/flash/cli_spec.rb
48
+ - spec/flash/command/base_spec.rb
49
+ - spec/flash/command/clone_spec.rb
50
+ - spec/flash/command/info_spec.rb
51
+ - spec/flash/command/run_spec.rb
52
+ - spec/flash/config_spec.rb
53
+ - spec/flash_spec.rb
38
54
  - spec/spec_helper.rb
39
55
  homepage: http://github.com/colmarius/flash
40
56
  licenses:
41
- - MIT
57
+ - Apache-2.0
58
+ metadata: {}
42
59
  post_install_message:
43
60
  rdoc_options: []
44
61
  require_paths:
45
62
  - lib
46
63
  required_ruby_version: !ruby/object:Gem::Requirement
47
- none: false
48
64
  requirements:
49
65
  - - ! '>='
50
66
  - !ruby/object:Gem::Version
51
67
  version: '0'
52
- segments:
53
- - 0
54
- hash: -4469809819880840159
55
68
  required_rubygems_version: !ruby/object:Gem::Requirement
56
- none: false
57
69
  requirements:
58
70
  - - ! '>='
59
71
  - !ruby/object:Gem::Version
60
72
  version: '0'
61
- segments:
62
- - 0
63
- hash: -4469809819880840159
64
73
  requirements: []
65
- rubyforge_project: flash
66
- rubygems_version: 1.8.25
74
+ rubyforge_project:
75
+ rubygems_version: 2.3.0
67
76
  signing_key:
68
- specification_version: 3
69
- summary: Flash helps you run commands on multiple projects all defined in the Runfile
77
+ specification_version: 4
78
+ summary: Flash helps you run same commands on multiple projects all defined in the
79
+ `.flash.yml` config.
70
80
  test_files: []
data/.gitignore DELETED
@@ -1 +0,0 @@
1
- *.gem
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
5
- group :development do
6
- gem 'rake', '~> 0.9'
7
- gem 'rspec', '~> 2.0'
8
- end
@@ -1,26 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- flash (0.0.3)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- diff-lcs (1.2.5)
10
- rake (0.9.6)
11
- rspec (2.14.1)
12
- rspec-core (~> 2.14.0)
13
- rspec-expectations (~> 2.14.0)
14
- rspec-mocks (~> 2.14.0)
15
- rspec-core (2.14.7)
16
- rspec-expectations (2.14.4)
17
- diff-lcs (>= 1.1.3, < 2.0)
18
- rspec-mocks (2.14.4)
19
-
20
- PLATFORMS
21
- ruby
22
-
23
- DEPENDENCIES
24
- flash!
25
- rake (~> 0.9)
26
- rspec (~> 2.0)
data/Rakefile DELETED
@@ -1,16 +0,0 @@
1
- require "rspec/core/rake_task"
2
-
3
- RSpec::Core::RakeTask.new do |task|
4
- task.name = 'spec'
5
- task.rspec_opts = ['-c',' -f', 'd']
6
- end
7
-
8
- task :build do
9
- system "gem build flash.gemspec"
10
- end
11
-
12
- task :release => :build do
13
- system "gem push flash-#{Flash::VERSION}.gem"
14
- end
15
-
16
- task :default => :spec
data/bin/run DELETED
@@ -1,44 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'optparse'
4
- require 'pathname'
5
- require 'flash'
6
- require 'flash/runner'
7
-
8
- options = {}
9
- optparse = OptionParser.new do |opts|
10
- opts.banner = "Usage: run [options] group"
11
-
12
- opts.on("-c", "--command command", String, "Commands to run (semicolon separated)") do |command|
13
- options[:commands] = command.split(';').map(&:strip)
14
- end
15
-
16
- opts.on("-d", "--debug", "Debug: print each command result") do |d|
17
- options[:debug] = d
18
- end
19
-
20
- opts.on("-r", "--recipe recipe", "Run registered recipe if present") do |recipe|
21
- options[:recipe] = recipe
22
- end
23
-
24
- opts.on("-l", "--list-recipes", "List registered recipes") do |l|
25
- options[:list_recipes] = l
26
- end
27
-
28
- opts.on("-h", "--help", "Help documentation") do
29
- puts opts ; exit
30
- end
31
-
32
- opts
33
- end
34
-
35
- optparse.parse!
36
-
37
- if ARGV.empty?
38
- puts "Group name is missing."
39
- puts optparse ; exit
40
- end
41
-
42
- group = ARGV[0]
43
-
44
- Flash::Runner.new(options, group).start
@@ -1,8 +0,0 @@
1
- projects:
2
- - salsa
3
- - dancing
4
- - school
5
-
6
- some:
7
- - salsa
8
- - school
@@ -1 +0,0 @@
1
- test
@@ -1 +0,0 @@
1
- test
@@ -1 +0,0 @@
1
- test
@@ -1,23 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
-
4
- require "flash/version"
5
-
6
- Gem::Specification.new do |gem|
7
- gem.name = "flash"
8
- gem.license = "MIT"
9
- gem.version = Flash::VERSION
10
-
11
- gem.author = ["Marius Colacioiu"]
12
- gem.email = ["marius.colacioiu@gmail.com"]
13
- gem.homepage = "http://github.com/colmarius/flash"
14
- gem.summary = %q{ Flash helps you run commands on multiple projects all defined in the Runfile }
15
-
16
- gem.description = gem.summary
17
-
18
- gem.rubyforge_project = "flash"
19
-
20
- gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
- gem.files = `git ls-files`.split("\n")
22
- gem.test_files = `git ls-files -- {spec}`.split("\n")
23
- end
@@ -1,19 +0,0 @@
1
- require 'flash'
2
- require 'yaml'
3
-
4
- class Flash::Runfile
5
-
6
- attr_reader :groups
7
-
8
- def initialize(filename=nil)
9
- load(filename) if filename
10
- end
11
-
12
- def [](name=nil)
13
- @groups[name] if name
14
- end
15
-
16
- def load(filename)
17
- @groups = YAML.load_file(filename) if File.exists?(filename)
18
- end
19
- end
@@ -1,80 +0,0 @@
1
- require 'flash'
2
- require 'flash/runfile'
3
-
4
- class Flash::Runner
5
- attr_reader :options
6
- attr_accessor :debug, :color, :dir_name, :runfile, :group
7
-
8
- def initialize(options = {}, group)
9
- raise "Missing required group parameter." unless group
10
-
11
- @options = options
12
- @runfile = Flash::Runfile.new('Runfile')
13
- @group = group
14
- end
15
-
16
- def pwd
17
- Dir.pwd
18
- end
19
-
20
- def run(command, verbose=true)
21
- say "#{ prompt }#{ command }" if verbose
22
- system "cd #{ app_dir } && #{ command }"
23
- say "[Debug] Result: #{ $?.inspect }" if verbose && debug
24
- end
25
-
26
- def recipes
27
- @recipes ||= {
28
- 'update-master' => 'git stash ; git checkout master ; git pull ; git stash pop',
29
- 'status' => 'git status -s',
30
- 'branch' => 'git branch'
31
- }
32
- end
33
-
34
- def list_recipes
35
- recipes.each_pair { |recipe, commands| puts %Q(#{ recipe }:\n\t"#{ commands }"\n\n) }
36
- end
37
-
38
- def commands(recipe)
39
- commands = recipes[recipe] ? recipes[recipe] : 'echo "Unknown recipe!"'
40
- commands.split(';').map(&:strip)
41
- end
42
-
43
- def say(stuff)
44
- prefix = "\e[38;5;#{ color }m"
45
- suffix = "\e[0m"
46
- system "echo '#{ prefix }#{ stuff }#{ suffix }'"
47
- end
48
-
49
- def change_color!
50
- self.color = rand((1..22)) * 10 + 2
51
- end
52
-
53
- def app_dir
54
- "#{ pwd }/#{ dir_name }"
55
- end
56
-
57
- def prompt
58
- "#{ dir_name }> "
59
- end
60
-
61
- def group_dirs
62
- runfile[group]
63
- end
64
-
65
- def start
66
- list_recipes and exit if options[:list_recipes]
67
-
68
- self.debug = options[:debug]
69
- group_dirs.each do |dir_name|
70
- change_color!
71
- self.dir_name = dir_name
72
- run "cd #{ pwd }/#{ dir_name }", false
73
-
74
- commands = options[:recipe] ? commands(options[:recipe]) : options[:commands]
75
- commands.each { |command| run(command) }\
76
-
77
- say ""
78
- end
79
- end
80
- end