status_page_ruby 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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +25 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +10 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +61 -0
- data/README.md +53 -0
- data/bin/status-page +6 -0
- data/lib/status_page_ruby.rb +20 -0
- data/lib/status_page_ruby/pages/base.rb +52 -0
- data/lib/status_page_ruby/pages/bitbucket.rb +14 -0
- data/lib/status_page_ruby/pages/cloudflare.rb +29 -0
- data/lib/status_page_ruby/pages/github.rb +19 -0
- data/lib/status_page_ruby/pages/rubygems.rb +14 -0
- data/lib/status_page_ruby/repositories/status.rb +40 -0
- data/lib/status_page_ruby/services/backup_data.rb +15 -0
- data/lib/status_page_ruby/services/build_history_table.rb +32 -0
- data/lib/status_page_ruby/services/build_log_table.rb +14 -0
- data/lib/status_page_ruby/services/build_stats_table.rb +79 -0
- data/lib/status_page_ruby/services/pull_statuses.rb +44 -0
- data/lib/status_page_ruby/services/restore_data.rb +15 -0
- data/lib/status_page_ruby/status.rb +36 -0
- data/lib/status_page_ruby/storage.rb +55 -0
- data/lib/status_page_ruby/version.rb +3 -0
- data/lib/status_page_ruby_cli.rb +76 -0
- data/spec/lib/status_page_ruby/pages/bitbucket_spec.rb +39 -0
- data/spec/lib/status_page_ruby/pages/cloudflare_spec.rb +64 -0
- data/spec/lib/status_page_ruby/pages/github_spec.rb +57 -0
- data/spec/lib/status_page_ruby/pages/rubygems_spec.rb +39 -0
- data/spec/lib/status_page_ruby/repositories/status_spec.rb +124 -0
- data/spec/lib/status_page_ruby/services/backup_data_spec.rb +13 -0
- data/spec/lib/status_page_ruby/services/build_history_table_spec.rb +71 -0
- data/spec/lib/status_page_ruby/services/build_log_table_spec.rb +43 -0
- data/spec/lib/status_page_ruby/services/build_stats_table_spec.rb +72 -0
- data/spec/lib/status_page_ruby/services/pull_statuses_spec.rb +30 -0
- data/spec/lib/status_page_ruby/services/restore_data_spec.rb +13 -0
- data/spec/lib/status_page_ruby/status_spec.rb +65 -0
- data/spec/lib/status_page_ruby/storage_spec.rb +134 -0
- data/spec/spec_helper.rb +15 -0
- data/status_page_ruby.gemspec +22 -0
- metadata +139 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Pages::Rubygems do
|
4
|
+
let(:html) { "<html><body><div class='page-status'><div class='status'>#{status}</div></div></body></html>" }
|
5
|
+
|
6
|
+
before { allow(OpenURI).to receive(:open_uri).with('https://status.rubygems.org/') { html } }
|
7
|
+
|
8
|
+
describe '#status' do
|
9
|
+
subject { described_class.open.status }
|
10
|
+
|
11
|
+
context 'when success status' do
|
12
|
+
let(:status) { 'All Systems Operational' }
|
13
|
+
|
14
|
+
it { is_expected.to eq('All Systems Operational') }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when not success status' do
|
18
|
+
let(:status) { 'All is Failed' }
|
19
|
+
|
20
|
+
it { is_expected.to eq('All is Failed') }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#success?' do
|
25
|
+
subject { described_class.open.success? }
|
26
|
+
|
27
|
+
context 'when success status' do
|
28
|
+
let(:status) { 'All Systems Operational' }
|
29
|
+
|
30
|
+
it { is_expected.to be_truthy }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when not success status' do
|
34
|
+
let(:status) { 'All is Failed' }
|
35
|
+
|
36
|
+
it { is_expected.to be_falsey }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Repositories::Status do
|
4
|
+
let(:storage) { double }
|
5
|
+
let(:repository) { described_class.new(storage) }
|
6
|
+
|
7
|
+
describe '#exist?' do
|
8
|
+
subject { repository.exist?(status) }
|
9
|
+
let(:status) { double(record: double) }
|
10
|
+
|
11
|
+
before { allow(storage).to receive(:include?).with(status.record) { is_include } }
|
12
|
+
|
13
|
+
context 'when storage includes status record' do
|
14
|
+
let(:is_include) { true }
|
15
|
+
it { is_expected.to be_truthy }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when storage does not include status record' do
|
19
|
+
let(:is_include) { false }
|
20
|
+
it { is_expected.to be_falsey }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#where' do
|
25
|
+
subject { repository.where(service: 'a') }
|
26
|
+
|
27
|
+
context 'when storage is not empty' do
|
28
|
+
context 'when service exists' do
|
29
|
+
before { allow(storage).to receive(:read) { [%w[a b c]] } }
|
30
|
+
|
31
|
+
it 'builds statuses' do
|
32
|
+
expect(StatusPageRuby::Status).to receive(:new).with('a', 'b', 'c')
|
33
|
+
subject
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when service does not exist' do
|
38
|
+
before { allow(storage).to receive(:read) { [%w[x x x]] } }
|
39
|
+
|
40
|
+
it 'builds statuses' do
|
41
|
+
expect(StatusPageRuby::Status).not_to receive(:new)
|
42
|
+
subject
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when storage is empty' do
|
48
|
+
before { allow(storage).to receive(:read) { [] } }
|
49
|
+
|
50
|
+
it 'does not build statuses' do
|
51
|
+
expect(StatusPageRuby::Status).not_to receive(:new)
|
52
|
+
subject
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#all' do
|
58
|
+
subject { repository.all }
|
59
|
+
|
60
|
+
context 'when storage is not empty' do
|
61
|
+
before { allow(storage).to receive(:read) { [%w[a b c]] } }
|
62
|
+
|
63
|
+
it 'builds statuses' do
|
64
|
+
expect(StatusPageRuby::Status).to receive(:new).with('a', 'b', 'c')
|
65
|
+
subject
|
66
|
+
end
|
67
|
+
end
|
68
|
+
context 'when storage is empty' do
|
69
|
+
before { allow(storage).to receive(:read) { [] } }
|
70
|
+
|
71
|
+
it 'does not build statuses' do
|
72
|
+
expect(StatusPageRuby::Status).not_to receive(:new)
|
73
|
+
subject
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#create' do
|
79
|
+
subject { repository.create(status) }
|
80
|
+
let(:status) { double(record: double) }
|
81
|
+
|
82
|
+
before { allow(repository).to receive(:exist?) { status_exists } }
|
83
|
+
|
84
|
+
context 'when status does not exist' do
|
85
|
+
let(:status_exists) { false }
|
86
|
+
|
87
|
+
it 'triggers write on storage' do
|
88
|
+
expect(storage).to receive(:write).with(status.record).once
|
89
|
+
subject
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'with status exists' do
|
94
|
+
let(:status_exists) { true }
|
95
|
+
|
96
|
+
it 'does not trigger write on storage' do
|
97
|
+
expect(storage).not_to receive(:write)
|
98
|
+
subject
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#create_batch' do
|
104
|
+
subject { repository.create_batch(statuses) }
|
105
|
+
|
106
|
+
context 'with statuses' do
|
107
|
+
let(:statuses) { [double(record: double)] }
|
108
|
+
|
109
|
+
it 'triggers merge on storage' do
|
110
|
+
expect(storage).to receive(:merge).with(statuses.map(&:record)).once
|
111
|
+
subject
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'with empty statuses' do
|
116
|
+
let(:statuses) { [] }
|
117
|
+
|
118
|
+
it 'does not trigger merge on storage' do
|
119
|
+
expect(storage).not_to receive(:merge)
|
120
|
+
subject
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::BackupData do
|
4
|
+
let(:storage) { double }
|
5
|
+
let(:service) { described_class.new(storage) }
|
6
|
+
|
7
|
+
describe '#call' do
|
8
|
+
it 'triggers copy on storage' do
|
9
|
+
expect(storage).to receive(:copy).with('test_path').once
|
10
|
+
service.call('test_path')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::BuildHistoryTable do
|
4
|
+
let(:data_file_path) { Tempfile.new('data_file_path').path }
|
5
|
+
let(:service) do
|
6
|
+
described_class.new(
|
7
|
+
StatusPageRuby::Repositories::Status.new(
|
8
|
+
StatusPageRuby::Storage.new(data_file_path)
|
9
|
+
)
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#call' do
|
14
|
+
before do
|
15
|
+
File.write(data_file_path, <<-CSV.delete(' '))
|
16
|
+
test1,up,Success,1539506590
|
17
|
+
test1,down,Failure,1539507591
|
18
|
+
test2,up,Success,1539508592
|
19
|
+
CSV
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with service parameter' do
|
23
|
+
context 'when service exists' do
|
24
|
+
subject { service.call('test1') }
|
25
|
+
let(:expected_table) do
|
26
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
27
|
+
+---------+--------+---------------------+
|
28
|
+
| Service | Status | Time |
|
29
|
+
+---------+--------+---------------------+
|
30
|
+
| test1 | up | 14.10.2018 08:43:10 |
|
31
|
+
| test1 | down | 14.10.2018 08:59:51 |
|
32
|
+
+---------+--------+---------------------+
|
33
|
+
TABLE
|
34
|
+
end
|
35
|
+
|
36
|
+
it { is_expected.to eq(expected_table) }
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when service does not exists' do
|
40
|
+
subject { service.call('test3') }
|
41
|
+
let(:expected_table) do
|
42
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
43
|
+
+---------+--------+------+
|
44
|
+
| Service | Status | Time |
|
45
|
+
+---------+--------+------+
|
46
|
+
+---------+--------+------+
|
47
|
+
TABLE
|
48
|
+
end
|
49
|
+
|
50
|
+
it { is_expected.to eq(expected_table) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'without service parameter' do
|
55
|
+
subject { service.call }
|
56
|
+
let(:expected_table) do
|
57
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
58
|
+
+---------+--------+---------------------+
|
59
|
+
| Service | Status | Time |
|
60
|
+
+---------+--------+---------------------+
|
61
|
+
| test1 | up | 14.10.2018 08:43:10 |
|
62
|
+
| test1 | down | 14.10.2018 08:59:51 |
|
63
|
+
| test2 | up | 14.10.2018 09:16:32 |
|
64
|
+
+---------+--------+---------------------+
|
65
|
+
TABLE
|
66
|
+
end
|
67
|
+
|
68
|
+
it { is_expected.to eq(expected_table) }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::BuildLogTable do
|
4
|
+
describe '#call' do
|
5
|
+
subject { described_class.new.call(records) }
|
6
|
+
|
7
|
+
context 'with records' do
|
8
|
+
let(:records) do
|
9
|
+
[
|
10
|
+
StatusPageRuby::Status.new('test1', 'up', 'Success', '1539506590'),
|
11
|
+
StatusPageRuby::Status.new('test2', 'up', 'Success', '1539508592')
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:expected_table) do
|
16
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
17
|
+
+---------+--------+---------------------+
|
18
|
+
| Service | Status | Time |
|
19
|
+
+---------+--------+---------------------+
|
20
|
+
| test1 | up | 14.10.2018 08:43:10 |
|
21
|
+
| test2 | up | 14.10.2018 09:16:32 |
|
22
|
+
+---------+--------+---------------------+
|
23
|
+
TABLE
|
24
|
+
end
|
25
|
+
|
26
|
+
it { is_expected.to eq(expected_table) }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with empty records' do
|
30
|
+
let(:records) { [] }
|
31
|
+
let(:expected_table) do
|
32
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
33
|
+
+---------+--------+------+
|
34
|
+
| Service | Status | Time |
|
35
|
+
+---------+--------+------+
|
36
|
+
+---------+--------+------+
|
37
|
+
TABLE
|
38
|
+
end
|
39
|
+
|
40
|
+
it { is_expected.to eq(expected_table) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::BuildStatsTable do
|
4
|
+
let(:data_file_path) { Tempfile.new('data_file_path').path }
|
5
|
+
let(:service) do
|
6
|
+
described_class.new(
|
7
|
+
StatusPageRuby::Repositories::Status.new(
|
8
|
+
StatusPageRuby::Storage.new(data_file_path)
|
9
|
+
)
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#call' do
|
14
|
+
before do
|
15
|
+
Timecop.freeze(Time.at(1_539_520_990))
|
16
|
+
File.write(data_file_path, <<-CSV.delete(' '))
|
17
|
+
test1,up,Success,1539506590
|
18
|
+
test1,down,Failure,1539510190
|
19
|
+
test1,down,Failure,1539513790
|
20
|
+
test2,up,Success,1539519190
|
21
|
+
test1,up,Success,1539517390
|
22
|
+
CSV
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with service parameter' do
|
26
|
+
context 'when service exists' do
|
27
|
+
subject { service.call('test1') }
|
28
|
+
let(:expected_table) do
|
29
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
30
|
+
+---------+----------+-----------+
|
31
|
+
| Service | Up since | Down time |
|
32
|
+
+---------+----------+-----------+
|
33
|
+
| test1 | 1 hours | 2 hours |
|
34
|
+
+---------+----------+-----------+
|
35
|
+
TABLE
|
36
|
+
end
|
37
|
+
|
38
|
+
it { is_expected.to eq(expected_table) }
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when service does not exists' do
|
42
|
+
subject { service.call('test3') }
|
43
|
+
let(:expected_table) do
|
44
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
45
|
+
+---------+----------+-----------+
|
46
|
+
| Service | Up since | Down time |
|
47
|
+
+---------+----------+-----------+
|
48
|
+
+---------+----------+-----------+
|
49
|
+
TABLE
|
50
|
+
end
|
51
|
+
|
52
|
+
it { is_expected.to eq(expected_table) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'without service parameter' do
|
57
|
+
subject { service.call }
|
58
|
+
let(:expected_table) do
|
59
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
60
|
+
+---------+------------+-----------+
|
61
|
+
| Service | Up since | Down time |
|
62
|
+
+---------+------------+-----------+
|
63
|
+
| test1 | 1 hours | 2 hours |
|
64
|
+
| test2 | 30 minutes | 0 minutes |
|
65
|
+
+---------+------------+-----------+
|
66
|
+
TABLE
|
67
|
+
end
|
68
|
+
|
69
|
+
it { is_expected.to eq(expected_table) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::PullStatuses do
|
4
|
+
let(:status_repository) { double }
|
5
|
+
let(:service) { described_class.new(status_repository) }
|
6
|
+
|
7
|
+
describe '#call' do
|
8
|
+
context 'when there is page classes' do
|
9
|
+
let(:page_class) { double(open: page) }
|
10
|
+
let(:page) { double(class: double(name: 'TestPage'), success?: true, status: 'Success', time: 123) }
|
11
|
+
let(:status) { double }
|
12
|
+
before { allow(service).to receive(:page_classes) { [page_class] } }
|
13
|
+
|
14
|
+
it 'does not trigger create_batch for status_repository' do
|
15
|
+
expect(status_repository).to receive(:create_batch).with([status]).once
|
16
|
+
expect(StatusPageRuby::Status).to receive(:new).with('TestPage', 'up', 'Success', 123) { status }.once
|
17
|
+
service.call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when there is no page classes' do
|
22
|
+
before { allow(service).to receive(:page_class?) { false } }
|
23
|
+
|
24
|
+
it 'does not trigger create_batch for status_repository' do
|
25
|
+
expect(status_repository).not_to receive(:create_batch)
|
26
|
+
service.call
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::RestoreData do
|
4
|
+
let(:storage) { double }
|
5
|
+
let(:service) { described_class.new(storage) }
|
6
|
+
|
7
|
+
describe '#call' do
|
8
|
+
it 'triggers restore on storage' do
|
9
|
+
expect(storage).to receive(:restore).with('test_path').once
|
10
|
+
service.call('test_path')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Status do
|
4
|
+
describe '.new' do
|
5
|
+
[
|
6
|
+
[nil, nil, nil, nil],
|
7
|
+
['', '', '', ''],
|
8
|
+
[1, 2, 2, 3],
|
9
|
+
['Github', 'up', 'All Good', 1_539_506_590]
|
10
|
+
].each do |service, state, status, time|
|
11
|
+
context "with service: #{service}, state: #{state}, status: #{status} and time: #{time}" do
|
12
|
+
subject { described_class.new(service, state, status, time) }
|
13
|
+
|
14
|
+
it { expect(subject.service).to eq(service.to_s) }
|
15
|
+
it { expect(subject.state).to eq(state.to_s) }
|
16
|
+
it { expect(subject.time).to eq(time.to_s) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#record' do
|
22
|
+
[
|
23
|
+
[nil, nil, nil, nil],
|
24
|
+
['', '', '', ''],
|
25
|
+
[1, 2, 3, 4],
|
26
|
+
['Github', 'up', 'All Good', 1_539_506_590]
|
27
|
+
].each do |service, state, status, time|
|
28
|
+
context "with service: #{service}, state: #{state}, status: #{status} and time: #{time}" do
|
29
|
+
subject { described_class.new(service, state, status, time).record }
|
30
|
+
|
31
|
+
it { is_expected.to eq([service.to_s, state.to_s, status.to_s, time.to_s]) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#history_record' do
|
37
|
+
[
|
38
|
+
[[nil, nil, nil, 1_539_506_590], ['', '', '14.10.2018 08:43:10']],
|
39
|
+
[['', '', '', 1_539_506_590], ['', '', '14.10.2018 08:43:10']],
|
40
|
+
[[1, 2, 3, 1_539_506_590], ['1', '2', '14.10.2018 08:43:10']],
|
41
|
+
[['Github', 'up', 'All Good', 1_539_506_590], ['Github', 'up', '14.10.2018 08:43:10']]
|
42
|
+
].each do |args, result|
|
43
|
+
context "with service: #{args[0]}, state: #{args[1]}, status: #{args[2]} and time: #{args[3]}" do
|
44
|
+
subject { described_class.new(*args).history_record }
|
45
|
+
|
46
|
+
it { is_expected.to eq(result) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#to_csv' do
|
52
|
+
[
|
53
|
+
[[nil, nil, nil, nil], "\"\",\"\",\"\",\"\"\n"],
|
54
|
+
[['', '', '', ''], "\"\",\"\",\"\",\"\"\n"],
|
55
|
+
[[1, 2, 3, 4], "1,2,3,4\n"],
|
56
|
+
[['Github', 'up', 'All Good', 1_539_506_590], "Github,up,All Good,1539506590\n"]
|
57
|
+
].each do |args, result|
|
58
|
+
context "with service: #{args[0]}, state: #{args[1]}, status: #{args[2]} and time: #{args[3]}" do
|
59
|
+
subject { described_class.new(*args).to_csv }
|
60
|
+
|
61
|
+
it { is_expected.to eq(result) }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|