patch_life 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +16 -0
- data/README.md +33 -0
- data/lib/patch_life.rb +28 -0
- data/lib/version.rb +9 -0
- data/patch_life.gemspec +32 -0
- data/spec/print_patch_warning_spec.rb +86 -0
- data/spec/spec_helper.rb +2 -0
- metadata +86 -0
data/LICENSE
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
This software is free to use, modify, and distribute.
|
2
|
+
|
3
|
+
You aren't allowed to sell it, under any condition, to anyone, at any time, for any reason.
|
4
|
+
|
5
|
+
If you use this to write some evil shit, then fuck you.
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in
|
8
|
+
all copies or substantial portions of the Software.
|
9
|
+
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
11
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
12
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
13
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
14
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
15
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
16
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#Patch Life
|
2
|
+
|
3
|
+
Sometimes in Ruby, it's necessary to backport things like security fixes and stability patches to earlier versions, because upgrading a large-scale ecosystem in ruby can require many months of testing, bug fixes, partial rollouts, etc. Occasionally, you need a way to apply newer fixes to older Ruby runtimes.
|
4
|
+
|
5
|
+
But, as often happens, large scale ecosystems tend to collect dust, and hide secrets. Todays quick thinking patch could be tomorrows unexpected production issue, because lets face it - you're going to forget you ever did this in 6 months.
|
6
|
+
|
7
|
+
The first, uses a Warning, printed every time your application starts, when the patch is loaded. If your defined Ruby Version and Patch level are equal to or older than the version of Ruby you're running the application with, you'll receive a Warning.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
define_patch_life :version => '1.9.3', :patch=> 448, :message => "It's time to remove me, as you've upgraded to a version of ruby where this code is no longer needed"
|
11
|
+
|
12
|
+
#Dirty hack that is considered a bold move
|
13
|
+
```
|
14
|
+
|
15
|
+
The second, allows you to pass the patch into define_patch_life as a block, only to be executed if the defined version / patch level of Ruby is not equal to or higher than the Ruby Version the application is running with.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
define_patch_life :version => '1.9.3', :patch=> 448 do
|
19
|
+
#World saving code
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
You can also combine the two, and have the patch execute only if ruby is beneath it's defined version, and have the message emitted as a Warning as well
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
define_patch_life :version => '1.9.3', :patch=> 448, :message => "It's time to remove me, as you've upgraded to a version of ruby where this code is no longer needed" do
|
27
|
+
#There will be much scorn and derision when this bites someone in the ass
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
##Upcoming Features
|
32
|
+
|
33
|
+
Ability to define arbitrary checks to apply patches with (not just based on ruby version)
|
data/lib/patch_life.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module PatchLife
|
2
|
+
def define_patch_life(options={})
|
3
|
+
raise(ArgumentError, "print_patch_warning requires a :version argument to be set") unless options[:version]
|
4
|
+
raise(ArgumentError, "print_patch_warning requires a :patch argument to be set") unless options[:patch]
|
5
|
+
raise(ArgumentError, "print_patch_warning requires either a :message argument, a block to yield, or both") unless options[:message] || block_given?
|
6
|
+
|
7
|
+
past_due = Gem::Version.new(ruby_version) >= Gem::Version.new(options[:version]) && ruby_patch_level >= options[:patch].to_i
|
8
|
+
Kernel.warn(options[:message]) if past_due && options[:message]
|
9
|
+
yield if !past_due && block_given?
|
10
|
+
#Don't want to return anything at all...
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
module_function :define_patch_life
|
14
|
+
|
15
|
+
def ruby_version
|
16
|
+
RUBY_VERSION.dup
|
17
|
+
end
|
18
|
+
module_function :ruby_version
|
19
|
+
|
20
|
+
def ruby_patch_level
|
21
|
+
RUBY_PATCHLEVEL
|
22
|
+
end
|
23
|
+
module_function :ruby_patch_level
|
24
|
+
end
|
25
|
+
|
26
|
+
def patch_life(options={})
|
27
|
+
PatchLife.define_patch_life(options)
|
28
|
+
end
|
data/lib/version.rb
ADDED
data/patch_life.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$: << File.expand_path('lib', File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "patch_life"
|
8
|
+
s.version = PatchLife::Version::STRING
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Stabby Cutyou"]
|
12
|
+
s.date = Time.new.strftime("%Y-%m-%d")
|
13
|
+
s.description = "Allows you to define a patch to ruby in a block that only gets executed if you're below the version which obsoletes the patch."
|
14
|
+
|
15
|
+
s.files = Dir[*%w(
|
16
|
+
patch_life.gemspec
|
17
|
+
lib/**/*
|
18
|
+
spec/**/*
|
19
|
+
README.md
|
20
|
+
LICENSE
|
21
|
+
)]
|
22
|
+
|
23
|
+
s.homepage = "http://github.com/StabbyCutyou/patch_life"
|
24
|
+
s.licenses = ["Custom with a touch of MIT"]
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
s.rubygems_version = "1.8.25"
|
27
|
+
s.summary = "Yells at you when you should have removed a particular patch by now"
|
28
|
+
|
29
|
+
s.add_development_dependency("rspec")
|
30
|
+
s.add_development_dependency("bundler")
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PrintPatchWarning do
|
4
|
+
before(:each) do
|
5
|
+
#Don't wanna actually fire it...
|
6
|
+
Kernel.stub(:warn)
|
7
|
+
end
|
8
|
+
|
9
|
+
context "when being defined" do
|
10
|
+
let (:version) {"1.0.0"}
|
11
|
+
let (:patch) {1}
|
12
|
+
let (:message) {"You're outdated"}
|
13
|
+
it "requires a version to be delcared" do
|
14
|
+
expect {subject.print_patch_warning}.to raise_error(ArgumentError)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "requires a patch level to be declared" do
|
18
|
+
expect {subject.print_patch_warning(:version=>version)}.to raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "requires a message when no block has been yielded" do
|
22
|
+
expect {subject.print_patch_warning(:version=>version, :patch=>patch, :message=>message)}.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it "requires a block when no message was declared" do
|
26
|
+
expect {subject.print_patch_warning(:version=>version, :patch=>patch) {nil} }.not_to raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it "allows both a message and a block at the same time" do
|
30
|
+
expect {subject.print_patch_warning(:version=>version, :patch=>patch, :message=>message) {nil} }.not_to raise_error
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when comparing ruby versions" do
|
35
|
+
context "and the current ruby version is less than the declared version" do
|
36
|
+
let (:version) {"9.9.9"}
|
37
|
+
let (:patch) {999}
|
38
|
+
let (:message) {"You're outdated"}
|
39
|
+
|
40
|
+
it "will not print a message if defined" do
|
41
|
+
Kernel.should_not_receive(:warn).with(message)
|
42
|
+
subject.print_patch_warning(:version=>version, :patch=>patch, :message=>message) {nil}
|
43
|
+
end
|
44
|
+
|
45
|
+
it "will yield a block if given" do
|
46
|
+
block_called = false
|
47
|
+
subject.print_patch_warning(:version=>version, :patch=>patch, :message=>message) {block_called=true}
|
48
|
+
block_called.should == true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "and the current ruby version is equal to the declared version" do
|
53
|
+
let (:version) {RUBY_VERSION.dup}
|
54
|
+
let (:patch) {RUBY_PATCHLEVEL}
|
55
|
+
let (:message) {"You're outdated"}
|
56
|
+
|
57
|
+
it "will print a message if defined" do
|
58
|
+
Kernel.should_receive(:warn).with(message)
|
59
|
+
subject.print_patch_warning(:version=>version, :patch=>patch, :message=>message) {nil}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "will not yield a block if given" do
|
63
|
+
block_called = false
|
64
|
+
subject.print_patch_warning(:version=>version, :patch=>patch, :message=>message) {block_called=true}
|
65
|
+
block_called.should == false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "and the current ruby version is greater than the declared version" do
|
70
|
+
let (:version) {"1.0.0"}
|
71
|
+
let (:patch) {1}
|
72
|
+
let (:message) {"You're outdated"}
|
73
|
+
|
74
|
+
it "will print a message if defined" do
|
75
|
+
Kernel.should_receive(:warn).with(message)
|
76
|
+
subject.print_patch_warning(:version=>version, :patch=>patch, :message=>message) {nil}
|
77
|
+
end
|
78
|
+
|
79
|
+
it "will not yield a block if given" do
|
80
|
+
block_called = false
|
81
|
+
subject.print_patch_warning(:version=>version, :patch=>patch, :message=>message) {block_called=true}
|
82
|
+
block_called.should == false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: patch_life
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Stabby Cutyou
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Allows you to define a patch to ruby in a block that only gets executed
|
47
|
+
if you're below the version which obsoletes the patch.
|
48
|
+
email:
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- patch_life.gemspec
|
54
|
+
- lib/patch_life.rb
|
55
|
+
- lib/version.rb
|
56
|
+
- spec/print_patch_warning_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
- README.md
|
59
|
+
- LICENSE
|
60
|
+
homepage: http://github.com/StabbyCutyou/patch_life
|
61
|
+
licenses:
|
62
|
+
- Custom with a touch of MIT
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.8.24
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: Yells at you when you should have removed a particular patch by now
|
85
|
+
test_files: []
|
86
|
+
has_rdoc:
|