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 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.
@@ -0,0 +1,31 @@
1
+ [![Code Climate](https://codeclimate.com/github/LukeWinikates/lmk.png)](https://codeclimate.com/github/LukeWinikates/lmk)
2
+ [![Build Status](https://travis-ci.org/LukeWinikates/lmk.png?branch=master)](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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
3
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
4
+ require 'lmk'
5
+ require 'thor'
6
+
7
+ LMK::CLI.start
@@ -0,0 +1,8 @@
1
+ require 'lmk/config'
2
+ require 'lmk/version'
3
+ require 'lmk/twilio_client_wrapper'
4
+ require 'lmk/twilio_sender'
5
+ require 'lmk/shell_command'
6
+ require 'lmk/runner'
7
+ require 'lmk/gist_sender'
8
+ require 'lmk/cli'
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module LMK
2
+ VERSION = "0.0.1"
3
+ end
@@ -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: