lmk 0.0.1
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.
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/bin/lmk +7 -0
- data/lib/lmk.rb +8 -0
- data/lib/lmk/cli.rb +28 -0
- data/lib/lmk/config.rb +52 -0
- data/lib/lmk/gist_sender.rb +27 -0
- data/lib/lmk/runner.rb +64 -0
- data/lib/lmk/shell_command.rb +70 -0
- data/lib/lmk/twilio_client_wrapper.rb +26 -0
- data/lib/lmk/twilio_sender.rb +16 -0
- data/lib/lmk/version.rb +3 -0
- data/lmk.gemspec +15 -0
- metadata +59 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Luke Winikates
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
[](https://codeclimate.com/github/LukeWinikates/lmk)
|
2
|
+
[](https://travis-ci.org/LukeWinikates/lmk)
|
3
|
+
LMK
|
4
|
+
===========
|
5
|
+
|
6
|
+
Don't sit around waiting for rake/make/tests/etc to finish. Let the machine tell you when it's done.
|
7
|
+
|
8
|
+
## PREREQUISITES:
|
9
|
+
You need a twilio account, including API Key and Account SID for sending [SMSes](http://www.twilio.com/sms).
|
10
|
+
|
11
|
+
## USAGE:
|
12
|
+
`$ lmk exec [command]`
|
13
|
+
|
14
|
+
executes [command], sending a digest of the result as an SMS to the specified phone number and creating a private, anonymous gist with the full command output.
|
15
|
+
|
16
|
+
For example:
|
17
|
+
`$ lmk exec bundle install`
|
18
|
+
|
19
|
+
## INSTALLATION/CONFIGURATION:
|
20
|
+
LMK requires a ~/.lmkrc file in order to run. The .lmkrc is a simple YAML file with four required values:
|
21
|
+
- phone_number: The number at which you want to receive a message when the command has finished running.
|
22
|
+
- from: a number associated with your Twilio account & set up for SMS sending
|
23
|
+
- account_sid: from your Twilio Account
|
24
|
+
- auth_token: from your Twilio Account
|
25
|
+
|
26
|
+
You can validate your .lmkrc at any time by running LMK's `config` command:
|
27
|
+
|
28
|
+
`$ lmk config`
|
29
|
+
|
30
|
+
## LICENSE:
|
31
|
+
MIT Licensed. See LICENSE file.
|
data/bin/lmk
ADDED
data/lib/lmk.rb
ADDED
data/lib/lmk/cli.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module LMK
|
4
|
+
class CLI < ::Thor
|
5
|
+
desc "exec COMMAND", "run a command and get an SMS with its result"
|
6
|
+
def exec(*command)
|
7
|
+
command = command.join ' '
|
8
|
+
Runner.run(command, options)
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "config", "read the current twilio config file"
|
12
|
+
def config
|
13
|
+
Kernel.puts Config.from_file.debug
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "debug COMMAND", "view template output for the given command"
|
17
|
+
def debug(*command)
|
18
|
+
command = command.join ' '
|
19
|
+
cmd = ShellCommand.new(command).tap do |c|
|
20
|
+
c.html_url = "http://gist.example.com"
|
21
|
+
end
|
22
|
+
puts "concise"
|
23
|
+
puts cmd.concise_output
|
24
|
+
puts "\n\nfull"
|
25
|
+
puts cmd.full_output
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/lmk/config.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'hashie'
|
3
|
+
|
4
|
+
module LMK
|
5
|
+
class Config
|
6
|
+
def self.default_path
|
7
|
+
"#{ENV['HOME']}/.lmkrc"
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.from_file(path = default_path)
|
11
|
+
attrs = ::YAML.load_file(path) if File.exists?(path)
|
12
|
+
new(attrs, path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(attributes, file = nil)
|
16
|
+
(attributes || {}).each do |k, v|
|
17
|
+
setter = "#{k}=".to_sym
|
18
|
+
send(setter, v) if respond_to?(setter)
|
19
|
+
end
|
20
|
+
@file = file
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid?
|
24
|
+
required_attributes.map { |attr| send(attr) }.all?
|
25
|
+
end
|
26
|
+
|
27
|
+
def required_attributes
|
28
|
+
[:auth_token, :from, :phone_number, :account_sid]
|
29
|
+
end
|
30
|
+
|
31
|
+
def missing_values
|
32
|
+
required_attributes.select { |method| send(method).nil? }
|
33
|
+
end
|
34
|
+
|
35
|
+
def debug
|
36
|
+
<<-RESULT
|
37
|
+
LMK Configuration #{valid? ? 'valid' : 'invalid'}
|
38
|
+
#{'Config file missing, create ' + @file + ' with required values.' if @file && !File.exists?(@file) }
|
39
|
+
missing values: #{valid? ? 'none' : missing_values }
|
40
|
+
#{raw}
|
41
|
+
RESULT
|
42
|
+
end
|
43
|
+
|
44
|
+
def raw
|
45
|
+
instance_variables.map do |ivar|
|
46
|
+
"#{ivar.to_s.gsub("@", "")}: #{instance_variable_get ivar}"
|
47
|
+
end.join "\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
attr_accessor :auth_token, :from, :phone_number, :account_sid
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
|
3
|
+
module LMK
|
4
|
+
class GistSender
|
5
|
+
def send(commmand)
|
6
|
+
result = client.create_gist options(commmand)
|
7
|
+
commmand.html_url = result[:html_url]
|
8
|
+
commmand
|
9
|
+
end
|
10
|
+
|
11
|
+
def options(command)
|
12
|
+
{
|
13
|
+
:description => command.command,
|
14
|
+
:public => false,
|
15
|
+
:files => {
|
16
|
+
"#{command.timestamp.strftime '%FT%R'}.lmk" => {
|
17
|
+
:content => command.full_output
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def client
|
24
|
+
Octokit::Client.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/lmk/runner.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module LMK
|
2
|
+
class Runner
|
3
|
+
class Configuration
|
4
|
+
attr_accessor :sms_service, :gist_service, :console_service, :shell_service
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@sms_service = LMK::TwilioSender.new
|
8
|
+
@gist_service = LMK::GistSender.new
|
9
|
+
@console_service = Kernel
|
10
|
+
@shell_service = LMK::ShellCommand
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.configure
|
15
|
+
yield self.configuration
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.configuration
|
19
|
+
@@default_configuration ||= Configuration.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.run(command, options)
|
23
|
+
new.run(command, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(configuration = Runner.configuration)
|
27
|
+
@configuration = configuration
|
28
|
+
end
|
29
|
+
|
30
|
+
def console(message)
|
31
|
+
@configuration.console_service.puts(message)
|
32
|
+
end
|
33
|
+
|
34
|
+
def shell(command)
|
35
|
+
@configuration.shell_service.exec(command)
|
36
|
+
end
|
37
|
+
|
38
|
+
def sms(command)
|
39
|
+
@configuration.sms_service.send(command)
|
40
|
+
end
|
41
|
+
|
42
|
+
def post_to_web(command)
|
43
|
+
@configuration.gist_service.send(command)
|
44
|
+
end
|
45
|
+
|
46
|
+
def run(command, options)
|
47
|
+
return unless validate!
|
48
|
+
console("running command `#{command}`")
|
49
|
+
result = shell(command)
|
50
|
+
result = post_to_web(result)
|
51
|
+
result = sms(result)
|
52
|
+
console(result.output)
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate!
|
56
|
+
unless @configuration.sms_service.runnable?
|
57
|
+
console("Configuration invalid. Run `lmk config` for more info")
|
58
|
+
false
|
59
|
+
else
|
60
|
+
true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'popen4'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module LMK
|
5
|
+
class ShellCommand
|
6
|
+
attr_reader :command, :timestamp
|
7
|
+
attr_accessor :html_url
|
8
|
+
|
9
|
+
def initialize(command)
|
10
|
+
@timestamp = Time.now
|
11
|
+
@command = command
|
12
|
+
@status = ::POpen4.popen4(command) do |stdout, stderr, stdin, pid|
|
13
|
+
@error = stderr.read
|
14
|
+
@output = stdout.read
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_binding
|
19
|
+
binding
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.exec(command)
|
23
|
+
new(command)
|
24
|
+
end
|
25
|
+
|
26
|
+
def success?
|
27
|
+
status == 0
|
28
|
+
end
|
29
|
+
|
30
|
+
def status
|
31
|
+
@status.exitstatus
|
32
|
+
end
|
33
|
+
|
34
|
+
def output
|
35
|
+
if success?
|
36
|
+
@output
|
37
|
+
else
|
38
|
+
@error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def concise_output
|
43
|
+
concise_template.result get_binding
|
44
|
+
end
|
45
|
+
|
46
|
+
def full_output
|
47
|
+
full_template.result get_binding
|
48
|
+
end
|
49
|
+
|
50
|
+
def full_template
|
51
|
+
ERB.new %q{
|
52
|
+
%%% LMK Command Result: %%%
|
53
|
+
> <%= command %>
|
54
|
+
<% if success? %>succeeded
|
55
|
+
<% else %> failed (<%=status%>)<% end %>
|
56
|
+
full output:
|
57
|
+
----------------------------
|
58
|
+
<%=output%>
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def concise_template
|
63
|
+
ERB.new %q{LMK Command Result:
|
64
|
+
> <%=command%>
|
65
|
+
<% if success? %>succeeded
|
66
|
+
<% else %>failed (<%=status%>)<% end %>
|
67
|
+
<% if html_url %>full result @ <%= html_url %><% end %>}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'twilio-ruby'
|
2
|
+
|
3
|
+
module LMK
|
4
|
+
class TwilioClientWrapper
|
5
|
+
def initialize(config = Config.from_file)
|
6
|
+
@config = config
|
7
|
+
@client = ::Twilio::REST::Client.new(@config.account_sid, @config.auth_token) if runnable?
|
8
|
+
end
|
9
|
+
|
10
|
+
def runnable?
|
11
|
+
@config.valid?
|
12
|
+
end
|
13
|
+
|
14
|
+
def send(message)
|
15
|
+
@client.account.sms.messages.create options.merge(:body => message)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def options
|
20
|
+
{
|
21
|
+
:from => @config.from,
|
22
|
+
:to => @config.phone_number
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module LMK
|
2
|
+
class TwilioSender
|
3
|
+
def initialize(client = TwilioClientWrapper.new)
|
4
|
+
@client = client
|
5
|
+
end
|
6
|
+
|
7
|
+
def runnable?
|
8
|
+
!!@client && @client.runnable?
|
9
|
+
end
|
10
|
+
|
11
|
+
def send(command)
|
12
|
+
@client.send command.concise_output
|
13
|
+
command
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/lmk/version.rb
ADDED
data/lmk.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
lib = File.expand_path('../lib/', __FILE__)
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
3
|
+
|
4
|
+
require 'lmk/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'lmk'
|
8
|
+
s.summary = 'runs a command and sends the output via sms'
|
9
|
+
s.authors = ["Luke Winikates"]
|
10
|
+
s.version = LMK::VERSION
|
11
|
+
s.executables << 'lmk'
|
12
|
+
s.files = %w(LICENSE README.md lmk.gemspec)
|
13
|
+
s.files += Dir.glob("bin/**/*")
|
14
|
+
s.files += Dir.glob("lib/**/*.rb")
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lmk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Luke Winikates
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-06 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email:
|
16
|
+
executables:
|
17
|
+
- lmk
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- LICENSE
|
22
|
+
- README.md
|
23
|
+
- lmk.gemspec
|
24
|
+
- bin/lmk
|
25
|
+
- lib/lmk/cli.rb
|
26
|
+
- lib/lmk/config.rb
|
27
|
+
- lib/lmk/gist_sender.rb
|
28
|
+
- lib/lmk/runner.rb
|
29
|
+
- lib/lmk/shell_command.rb
|
30
|
+
- lib/lmk/twilio_client_wrapper.rb
|
31
|
+
- lib/lmk/twilio_sender.rb
|
32
|
+
- lib/lmk/version.rb
|
33
|
+
- lib/lmk.rb
|
34
|
+
homepage:
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.8.16
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: runs a command and sends the output via sms
|
58
|
+
test_files: []
|
59
|
+
has_rdoc:
|