foca-integrity 0.1.8 → 0.1.9.0
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/README.markdown +7 -0
- data/Rakefile +89 -81
- data/config/config.sample.ru +11 -21
- data/config/config.sample.yml +15 -12
- data/lib/integrity.rb +21 -23
- data/lib/integrity/app.rb +138 -0
- data/lib/integrity/author.rb +39 -0
- data/lib/integrity/build.rb +54 -31
- data/lib/integrity/commit.rb +71 -0
- data/lib/integrity/helpers.rb +3 -3
- data/lib/integrity/helpers/authorization.rb +2 -2
- data/lib/integrity/helpers/forms.rb +3 -3
- data/lib/integrity/helpers/pretty_output.rb +1 -1
- data/lib/integrity/helpers/rendering.rb +6 -1
- data/lib/integrity/helpers/resources.rb +9 -3
- data/lib/integrity/helpers/urls.rb +15 -13
- data/lib/integrity/installer.rb +43 -60
- data/lib/integrity/migrations.rb +31 -48
- data/lib/integrity/notifier.rb +14 -16
- data/lib/integrity/notifier/base.rb +29 -19
- data/lib/integrity/notifier/test_helpers.rb +100 -0
- data/lib/integrity/project.rb +69 -33
- data/lib/integrity/project_builder.rb +23 -14
- data/lib/integrity/scm/git.rb +15 -14
- data/lib/integrity/scm/git/uri.rb +9 -9
- data/test/acceptance/api_test.rb +97 -0
- data/test/acceptance/browse_project_builds_test.rb +65 -0
- data/test/acceptance/browse_project_test.rb +95 -0
- data/test/acceptance/build_notifications_test.rb +42 -0
- data/test/acceptance/create_project_test.rb +97 -0
- data/test/acceptance/delete_project_test.rb +53 -0
- data/test/acceptance/edit_project_test.rb +117 -0
- data/test/acceptance/error_page_test.rb +18 -0
- data/test/acceptance/helpers.rb +2 -0
- data/test/acceptance/installer_test.rb +62 -0
- data/test/acceptance/manual_build_project_test.rb +82 -0
- data/test/acceptance/notifier_test.rb +109 -0
- data/test/acceptance/project_syndication_test.rb +30 -0
- data/test/acceptance/stylesheet_test.rb +18 -0
- data/test/helpers.rb +59 -27
- data/test/helpers/acceptance.rb +19 -64
- data/test/helpers/acceptance/email_notifier.rb +55 -0
- data/test/helpers/acceptance/git_helper.rb +15 -15
- data/test/helpers/acceptance/textfile_notifier.rb +3 -3
- data/test/helpers/expectations.rb +0 -1
- data/test/helpers/expectations/be_a.rb +4 -4
- data/test/helpers/expectations/change.rb +5 -5
- data/test/helpers/expectations/have.rb +4 -4
- data/test/helpers/expectations/predicates.rb +4 -4
- data/test/helpers/fixtures.rb +44 -18
- data/test/helpers/initial_migration_fixture.sql +44 -0
- data/test/unit/build_test.rb +51 -0
- data/test/unit/commit_test.rb +83 -0
- data/test/unit/helpers_test.rb +56 -0
- data/test/unit/integrity_test.rb +18 -0
- data/test/unit/migrations_test.rb +56 -0
- data/test/unit/notifier_test.rb +123 -0
- data/test/unit/project_builder_test.rb +108 -0
- data/test/unit/project_test.rb +282 -0
- data/test/unit/scm_test.rb +54 -0
- data/views/_commit_info.haml +24 -0
- data/views/build.haml +2 -2
- data/views/error.haml +4 -3
- data/views/home.haml +3 -5
- data/views/integrity.sass +19 -6
- data/views/new.haml +6 -6
- data/views/project.builder +9 -9
- data/views/project.haml +14 -12
- metadata +98 -116
- data/VERSION.yml +0 -4
- data/app.rb +0 -137
- data/integrity.gemspec +0 -76
- data/lib/integrity/core_ext/string.rb +0 -5
- data/test/helpers/expectations/have_tag.rb +0 -128
- data/views/_build_info.haml +0 -18
data/lib/integrity/migrations.rb
CHANGED
@@ -2,13 +2,38 @@ require "dm-migrations"
|
|
2
2
|
require "migration_runner"
|
3
3
|
|
4
4
|
module Integrity
|
5
|
-
|
6
|
-
|
5
|
+
def self.migrate_db
|
6
|
+
setup_initial_migration if pre_migrations?
|
7
|
+
Integrity::Migrations.migrate_up!
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.setup_initial_migration
|
11
|
+
database_adapter.execute %q(CREATE TABLE "migration_info" ("migration_name" VARCHAR(255));)
|
12
|
+
database_adapter.execute %q(INSERT INTO "migration_info" ("migration_name") VALUES ("initial"))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.pre_migrations?
|
16
|
+
!table_exists?("migration_info") &&
|
17
|
+
( table_exists?("integrity_projects") &&
|
18
|
+
table_exists?("integrity_builds") &&
|
19
|
+
table_exists?("integrity_notifiers") )
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.table_exists?(table_name)
|
23
|
+
database_adapter.storage_exists?(table_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.database_adapter
|
27
|
+
DataMapper.repository(:default).adapter
|
28
|
+
end
|
29
|
+
|
30
|
+
module Migrations
|
31
|
+
# This is what is actually happening:
|
32
|
+
# include DataMapper::MigrationRunner
|
7
33
|
|
8
|
-
|
9
|
-
include DataMapper::MigrationRunner
|
34
|
+
include DataMapper::Types
|
10
35
|
|
11
|
-
migration 1, :initial, :verbose =>
|
36
|
+
migration 1, :initial, :verbose => true do
|
12
37
|
up do
|
13
38
|
create_table :integrity_projects do
|
14
39
|
column :id, Integer, :serial => true
|
@@ -46,15 +71,9 @@ module Integrity
|
|
46
71
|
column :project_id, Integer
|
47
72
|
end
|
48
73
|
end
|
49
|
-
|
50
|
-
down do
|
51
|
-
drop_table :integrity_notifiers
|
52
|
-
drop_table :integrity_projects
|
53
|
-
drop_table :integrity_builds
|
54
|
-
end
|
55
74
|
end
|
56
75
|
|
57
|
-
migration 2, :add_commits, :verbose =>
|
76
|
+
migration 2, :add_commits, :verbose => true do
|
58
77
|
up do
|
59
78
|
class ::Integrity::Build
|
60
79
|
property :commit_identifier, String
|
@@ -116,42 +135,6 @@ module Integrity
|
|
116
135
|
:output => build.output)
|
117
136
|
end
|
118
137
|
end
|
119
|
-
|
120
|
-
down do
|
121
|
-
modify_table :integrity_builds do
|
122
|
-
add_column :commit_identifier, String, :nullable => false
|
123
|
-
add_column :commit_metadata, Yaml, :nullable => false
|
124
|
-
add_column :project_id, Integer
|
125
|
-
end
|
126
|
-
|
127
|
-
# sqlite hodgepockery
|
128
|
-
all_builds = Build.all.map {|b| b.freeze }
|
129
|
-
drop_table :integrity_builds
|
130
|
-
create_table :integrity_builds do
|
131
|
-
column :id, Integer, :serial => true
|
132
|
-
column :output, Text, :nullable => false, :default => ""
|
133
|
-
column :successful, Boolean, :nullable => false, :default => false
|
134
|
-
column :commit_identifier, String, :nullable => false
|
135
|
-
column :commit_metadata, Yaml, :nullable => false
|
136
|
-
column :created_at, DateTime
|
137
|
-
column :updated_at, DateTime
|
138
|
-
column :project_id, Integer
|
139
|
-
end
|
140
|
-
|
141
|
-
all_builds.each do |build|
|
142
|
-
Build.create(:project_id => build.commit.project_id,
|
143
|
-
:output => build.output,
|
144
|
-
:successful => build.successful,
|
145
|
-
:commit_identifier => build.commit.identifier,
|
146
|
-
:commit_metadata => {
|
147
|
-
:message => build.commit.message,
|
148
|
-
:author => build.commit.author.full,
|
149
|
-
:date => commit.committed_at
|
150
|
-
}.to_yaml)
|
151
|
-
end
|
152
|
-
|
153
|
-
drop_table :commits
|
154
|
-
end
|
155
138
|
end
|
156
139
|
end
|
157
140
|
end
|
data/lib/integrity/notifier.rb
CHANGED
@@ -1,38 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/notifier/base"
|
2
|
+
|
1
3
|
module Integrity
|
2
4
|
class Notifier
|
3
5
|
include DataMapper::Resource
|
4
|
-
|
5
|
-
property :id,
|
6
|
+
|
7
|
+
property :id, Integer, :serial => true
|
6
8
|
property :name, String, :nullable => false
|
7
9
|
property :config, Yaml, :nullable => false, :lazy => false
|
8
|
-
|
10
|
+
|
9
11
|
belongs_to :project, :class_name => "Integrity::Project"
|
10
|
-
|
12
|
+
|
11
13
|
validates_is_unique :name, :scope => :project_id
|
12
14
|
validates_present :project_id
|
13
|
-
|
15
|
+
|
14
16
|
def self.available
|
15
|
-
|
17
|
+
constants.map { |name| const_get(name) }.select { |notifier| valid_notifier?(notifier) }
|
16
18
|
end
|
17
|
-
|
19
|
+
|
18
20
|
def self.enable_notifiers(project, enabled, config={})
|
19
21
|
all(:project_id => project).destroy!
|
20
22
|
list_of_enabled_notifiers(enabled).each do |name|
|
21
23
|
create! :project_id => project, :name => name, :config => config[name]
|
22
24
|
end
|
23
|
-
|
25
|
+
|
24
26
|
end
|
25
|
-
|
27
|
+
|
26
28
|
def notify_of_build(build)
|
27
29
|
to_const.notify_of_build(build, config)
|
28
30
|
end
|
29
|
-
|
31
|
+
|
30
32
|
private
|
31
|
-
|
33
|
+
|
32
34
|
def to_const
|
33
35
|
self.class.module_eval(name)
|
34
36
|
end
|
35
|
-
|
37
|
+
|
36
38
|
def self.list_of_enabled_notifiers(names)
|
37
39
|
[*names].reject { |n| n.nil? }
|
38
40
|
end
|
@@ -44,7 +46,3 @@ module Integrity
|
|
44
46
|
private_class_method :valid_notifier?
|
45
47
|
end
|
46
48
|
end
|
47
|
-
|
48
|
-
require File.dirname(__FILE__) / "notifier" / "base"
|
49
|
-
|
50
|
-
Dir["#{File.dirname(__FILE__)}/notifier/*.rb"].each &method(:require)
|
@@ -8,47 +8,57 @@ module Integrity
|
|
8
8
|
def self.to_haml
|
9
9
|
raise NoMethodError, "you need to implement this method in your notifier"
|
10
10
|
end
|
11
|
-
|
12
|
-
attr_reader :
|
13
|
-
|
14
|
-
def initialize(
|
15
|
-
@
|
11
|
+
|
12
|
+
attr_reader :commit
|
13
|
+
|
14
|
+
def initialize(commit, config)
|
15
|
+
@commit = commit
|
16
16
|
@config = config
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
|
+
def build
|
20
|
+
warn "Notifier::Base#build is deprecated, use Notifier::Base#commit instead"
|
21
|
+
commit
|
22
|
+
end
|
23
|
+
|
19
24
|
def deliver!
|
20
25
|
raise NoMethodError, "you need to implement this method in your notifier"
|
21
26
|
end
|
22
|
-
|
27
|
+
|
23
28
|
def short_message
|
24
|
-
|
29
|
+
commit.human_readable_status
|
25
30
|
end
|
26
|
-
|
31
|
+
|
27
32
|
def full_message
|
28
33
|
<<-EOM
|
29
|
-
"Build #{
|
34
|
+
"Build #{commit.identifier} #{commit.successful? ? "was successful" : "failed"}"
|
30
35
|
|
31
|
-
Commit Message: #{
|
32
|
-
Commit Date: #{
|
33
|
-
Commit Author: #{
|
36
|
+
Commit Message: #{commit.message}
|
37
|
+
Commit Date: #{commit.committed_at}
|
38
|
+
Commit Author: #{commit.author.name}
|
34
39
|
|
35
|
-
Link: #{
|
40
|
+
Link: #{commit_url}
|
36
41
|
|
37
42
|
Build Output:
|
38
43
|
|
39
|
-
#{
|
44
|
+
#{stripped_commit_output}
|
40
45
|
EOM
|
41
46
|
end
|
42
|
-
|
43
|
-
def
|
47
|
+
|
48
|
+
def commit_url
|
44
49
|
raise if Integrity.config[:base_uri].nil?
|
45
|
-
Integrity.config[:base_uri] /
|
50
|
+
Integrity.config[:base_uri] / commit.project.permalink / "commits" / commit.identifier
|
46
51
|
end
|
47
52
|
|
48
53
|
private
|
49
54
|
|
55
|
+
def stripped_commit_output
|
56
|
+
commit.output.gsub("\e[0m", "").gsub(/\e\[3[1-7]m/, "")
|
57
|
+
end
|
58
|
+
|
50
59
|
def stripped_build_output
|
51
|
-
|
60
|
+
warn "Notifier::Base#stripped_build_output is deprecated, use Notifier::base#stripped_commit_output instead"
|
61
|
+
stripped_commit_output
|
52
62
|
end
|
53
63
|
end
|
54
64
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require "hpricot"
|
2
|
+
require "haml"
|
3
|
+
require File.dirname(__FILE__) + "/../../integrity"
|
4
|
+
|
5
|
+
module Integrity
|
6
|
+
class Notifier
|
7
|
+
module TestHelpers
|
8
|
+
module HpricotAssertions
|
9
|
+
# Thanks Harry! http://gist.github.com/39960
|
10
|
+
|
11
|
+
class HpricotMatcher
|
12
|
+
def initialize(html)
|
13
|
+
@doc = Hpricot(html)
|
14
|
+
end
|
15
|
+
|
16
|
+
# elements('h1') returns a Hpricot::Elements object with all h1-tags.
|
17
|
+
def elements(selector)
|
18
|
+
@doc.search(selector)
|
19
|
+
end
|
20
|
+
|
21
|
+
# element('h1') returns Hpricot::Elem with first h1-tag, or nil if
|
22
|
+
# none exist.
|
23
|
+
def element(selector)
|
24
|
+
@doc.at(selector)
|
25
|
+
end
|
26
|
+
|
27
|
+
# tags('h1') returns the inner HTML of all matched elements mathed.
|
28
|
+
def tags(selector)
|
29
|
+
e = elements(selector)
|
30
|
+
e.map {|x| x.inner_html}
|
31
|
+
end
|
32
|
+
|
33
|
+
# tag('h1') returns the inner HTML of the first mached element, or
|
34
|
+
# nil if none matched.
|
35
|
+
def tag(selector)
|
36
|
+
e = element(selector)
|
37
|
+
e && e.inner_html
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def assert_have_tag(html, selector, content=nil)
|
42
|
+
matcher = HpricotMatcher.new(html)
|
43
|
+
assert_equal content, matcher.tag(selector) if content
|
44
|
+
assert matcher.tag(selector)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module NotifierFormHelpers
|
49
|
+
include HpricotAssertions
|
50
|
+
|
51
|
+
def form(config={})
|
52
|
+
Haml::Engine.new(notifier_class.to_haml).
|
53
|
+
render(OpenStruct.new(:config => config))
|
54
|
+
end
|
55
|
+
|
56
|
+
def assert_form_have_tag(selector, options={})
|
57
|
+
content = options.delete(:content)
|
58
|
+
assert_have_tag(form(options), selector, content)
|
59
|
+
end
|
60
|
+
|
61
|
+
def assert_form_have_option(option, value=nil)
|
62
|
+
selector = "input##{notifier.downcase}_notifier_#{option}"
|
63
|
+
selector << "[@name='notifiers[#{notifier}][#{option}]']"
|
64
|
+
selector << "[@value='#{value}']" if value
|
65
|
+
|
66
|
+
assert_form_have_tag(selector, option => value)
|
67
|
+
end
|
68
|
+
|
69
|
+
def assert_form_have_options(*options)
|
70
|
+
options.each { |option| assert_form_have_option(option) }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
include NotifierFormHelpers
|
75
|
+
|
76
|
+
def build
|
77
|
+
@build ||= Integrity::Build.gen(:successful)
|
78
|
+
end
|
79
|
+
|
80
|
+
def commit
|
81
|
+
@commit ||= build.commit
|
82
|
+
end
|
83
|
+
|
84
|
+
def notifier_class
|
85
|
+
Integrity::Notifier.const_get(notifier)
|
86
|
+
end
|
87
|
+
|
88
|
+
def notification
|
89
|
+
notifier_class.new(commit).body
|
90
|
+
end
|
91
|
+
|
92
|
+
def setup_database
|
93
|
+
DataMapper.setup(:default, "sqlite3::memory:")
|
94
|
+
DataMapper.auto_migrate!
|
95
|
+
|
96
|
+
require File.dirname(__FILE__) + "/../../../test/helpers/fixtures"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/integrity/project.rb
CHANGED
@@ -2,7 +2,7 @@ module Integrity
|
|
2
2
|
class Project
|
3
3
|
include DataMapper::Resource
|
4
4
|
|
5
|
-
property :id,
|
5
|
+
property :id, Integer, :serial => true
|
6
6
|
property :name, String, :nullable => false
|
7
7
|
property :permalink, String
|
8
8
|
property :uri, URI, :nullable => false, :length => 255
|
@@ -13,7 +13,7 @@ module Integrity
|
|
13
13
|
property :created_at, DateTime
|
14
14
|
property :updated_at, DateTime
|
15
15
|
|
16
|
-
has n, :
|
16
|
+
has n, :commits, :class_name => "Integrity::Commit"
|
17
17
|
has n, :notifiers, :class_name => "Integrity::Notifier"
|
18
18
|
|
19
19
|
before :save, :set_permalink
|
@@ -30,36 +30,52 @@ module Integrity
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def build(commit_identifier="HEAD")
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
ensure
|
37
|
-
update_attributes(:building => false)
|
38
|
-
send_notifications
|
33
|
+
commit_identifier = head_of_remote_repo if commit_identifier == "HEAD"
|
34
|
+
commit = find_or_create_commit_with_identifier(commit_identifier)
|
35
|
+
commit.queue_build
|
39
36
|
end
|
40
37
|
|
41
38
|
def push(payload)
|
42
|
-
payload =
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
payload = parse_payload(payload)
|
40
|
+
raise ArgumentError unless valid_payload?(payload)
|
41
|
+
|
42
|
+
commits =
|
43
|
+
if Integrity.config[:build_all_commits]
|
44
|
+
payload["commits"]
|
45
|
+
else
|
46
|
+
[ payload["commits"].first ]
|
47
47
|
end
|
48
|
-
|
49
|
-
|
48
|
+
|
49
|
+
commits.each do |commit_data|
|
50
|
+
create_commit_from(commit_data)
|
51
|
+
build(commit_data["id"])
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
55
|
+
def last_commit
|
56
|
+
commits.first(:project_id => id, :order => [:committed_at.desc])
|
57
|
+
end
|
58
|
+
|
53
59
|
def last_build
|
54
|
-
|
60
|
+
warn "Project#last_build is deprecated, use Project#last_commit"
|
61
|
+
last_commit
|
62
|
+
end
|
63
|
+
|
64
|
+
def previous_commits
|
65
|
+
commits.all(:project_id => id, :order => [:committed_at.desc]).tap {|commits| commits.shift }
|
55
66
|
end
|
56
67
|
|
57
68
|
def previous_builds
|
58
|
-
|
69
|
+
warn "Project#previous_builds is deprecated, use Project#previous_commits"
|
70
|
+
previous_commits
|
59
71
|
end
|
60
72
|
|
61
73
|
def status
|
62
|
-
|
74
|
+
last_commit && last_commit.status
|
75
|
+
end
|
76
|
+
|
77
|
+
def human_readable_status
|
78
|
+
last_commit && last_commit.human_readable_status
|
63
79
|
end
|
64
80
|
|
65
81
|
def public=(flag)
|
@@ -70,12 +86,12 @@ module Integrity
|
|
70
86
|
end
|
71
87
|
|
72
88
|
def config_for(notifier)
|
73
|
-
notifier = notifiers.first(:name => notifier.to_s.split(/::/).last)
|
89
|
+
notifier = notifiers.first(:name => notifier.to_s.split(/::/).last, :project_id => id)
|
74
90
|
notifier.blank? ? {} : notifier.config
|
75
91
|
end
|
76
92
|
|
77
93
|
def notifies?(notifier)
|
78
|
-
!notifiers.first(:name => notifier.to_s.split(/::/).last).blank?
|
94
|
+
!notifiers.first(:name => notifier.to_s.split(/::/).last, :project_id => id).blank?
|
79
95
|
end
|
80
96
|
|
81
97
|
def enable_notifiers(*args)
|
@@ -83,6 +99,30 @@ module Integrity
|
|
83
99
|
end
|
84
100
|
|
85
101
|
private
|
102
|
+
def find_or_create_commit_with_identifier(commit_identifier)
|
103
|
+
# We abuse +committed_at+ here setting it to Time.now because we use it
|
104
|
+
# to sort (for last_commit and previous_commits). I don't like this
|
105
|
+
# very much, but for now it's the only solution I can find.
|
106
|
+
#
|
107
|
+
# This also creates a dependency, as now we *always* have to update the
|
108
|
+
# +committed_at+ field after building to ensure the date is correct :(
|
109
|
+
#
|
110
|
+
# This might also make your commit listings a little jumpy, if some
|
111
|
+
# commits change place every time a build finishes =\
|
112
|
+
commits.first_or_create({ :identifier => commit_identifier, :project_id => id }, :committed_at => Time.now)
|
113
|
+
end
|
114
|
+
|
115
|
+
def head_of_remote_repo
|
116
|
+
SCM.new(uri, branch).head
|
117
|
+
end
|
118
|
+
|
119
|
+
def create_commit_from(data)
|
120
|
+
commits.create(:identifier => data["id"],
|
121
|
+
:author => "#{data["author"]["name"]} <#{data["author"]["email"]}>",
|
122
|
+
:message => data["message"],
|
123
|
+
:committed_at => data["timestamp"])
|
124
|
+
end
|
125
|
+
|
86
126
|
def set_permalink
|
87
127
|
self.permalink = (name || "").downcase.
|
88
128
|
gsub(/'s/, "s").
|
@@ -92,26 +132,22 @@ module Integrity
|
|
92
132
|
end
|
93
133
|
|
94
134
|
def delete_code
|
95
|
-
|
135
|
+
commits.all(:project_id => id).destroy!
|
96
136
|
ProjectBuilder.new(self).delete_code
|
97
137
|
rescue SCM::SCMUnknownError => error
|
98
138
|
Integrity.log "Problem while trying to deleting code: #{error}"
|
99
139
|
end
|
100
140
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
notifier.notify_of_build last_build
|
106
|
-
rescue Timeout::Error
|
107
|
-
Integrity.log "#{notifier.name} notifier timed out"
|
108
|
-
next
|
109
|
-
end
|
110
|
-
end
|
141
|
+
def valid_payload?(payload)
|
142
|
+
payload && payload["ref"].to_s.include?(branch) &&
|
143
|
+
!payload["commits"].nil? &&
|
144
|
+
!payload["commits"].to_a.empty?
|
111
145
|
end
|
112
146
|
|
113
|
-
def
|
114
|
-
|
147
|
+
def parse_payload(payload)
|
148
|
+
JSON.parse(payload.to_s)
|
149
|
+
rescue JSON::ParserError
|
150
|
+
false
|
115
151
|
end
|
116
152
|
end
|
117
153
|
end
|