vx-gitlab_status_service 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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/vx/gitlab_status_service.rb +7 -0
- data/lib/vx/gitlab_status_service/railtie.rb +58 -0
- data/lib/vx/gitlab_status_service/version.rb +5 -0
- data/lib/vx/gitlab_status_service/vexor_ci_service.rb +74 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/vexor_ci_service_spec.rb +90 -0
- data/vx-gitlab_status_service.gemspec +29 -0
- metadata +171 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 91a32135748fc94f999f8728cc2cd9da6f0b0809
|
4
|
+
data.tar.gz: dffe91ddd1f1d33e703e37f95df97b23ffb801e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 22729b0eceb02db49fc8c5a96700636baa3426b18356cb95316d71c76a36296ebb55d4b298ab6440409c8d2372000cba5574660ed9c4d24a35673de5b3563b87
|
7
|
+
data.tar.gz: 0a9356572a39c8482a86f52f1989f3d817fc7f4d884b1501ef6940dd552e97547b2823067f9a6651e36a43430b66bbd78f56051c96c01f6e16030bf585f487b8
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Semenyuk Dmitriy
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Vx::GitlabStatusService
|
2
|
+
|
3
|
+
Vexor CI status service for Gitlab. It provides build status to use on Gitlab merge request pages.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'vx-gitlab_status_service'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install vx-gitlab_status_service
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Just add it to `Gemfile` and fill out Vexor CI token & project URL on `Project services` page (in Gitlab).
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( https://github.com/semenyukdmitriy/vx-gitlab_status_service/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Vx
|
2
|
+
module GitlabStatusService
|
3
|
+
class Railtie < ::Rails::Railtie
|
4
|
+
config.after_initialize do
|
5
|
+
|
6
|
+
# Register Vexor CI in list of project services
|
7
|
+
available_services_names_with_vexor = Project.new.available_services_names + %w(vexor_ci)
|
8
|
+
|
9
|
+
Project.instance_eval do
|
10
|
+
has_one :vexor_ci_service, dependent: :destroy
|
11
|
+
define_method(:available_services_names) { available_services_names_with_vexor }
|
12
|
+
end
|
13
|
+
|
14
|
+
require_relative "vexor_ci_service"
|
15
|
+
|
16
|
+
|
17
|
+
# patch controller to make possible to show Vexor CI status on MR page instead of Gitlab CI
|
18
|
+
Projects::MergeRequestsController.class_eval do
|
19
|
+
def ci_status
|
20
|
+
status = @merge_request.source_project.vexor_ci_service.commit_status(merge_request.last_commit.sha)
|
21
|
+
vexor_ci_build_status_to_gitlab_status_map = {
|
22
|
+
initialized: :pending,
|
23
|
+
started: :running,
|
24
|
+
passed: :success,
|
25
|
+
failed: :failed,
|
26
|
+
errored: :failed
|
27
|
+
}.with_indifferent_access
|
28
|
+
response = {status: vexor_ci_build_status_to_gitlab_status_map[status]}
|
29
|
+
|
30
|
+
render json: response
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Project.class_eval do
|
35
|
+
# call to `gitlab_ci?` (and `@project.gitlab_ci_service.builds_path`) is hardcoded in `app/views/projects/merge_requests/_show.html.haml`
|
36
|
+
# so we need to patch it
|
37
|
+
def gitlab_ci?
|
38
|
+
vexor_ci?
|
39
|
+
end
|
40
|
+
|
41
|
+
def vexor_ci?
|
42
|
+
vexor_ci_service && vexor_ci_service.active
|
43
|
+
end
|
44
|
+
|
45
|
+
def gitlab_ci_service
|
46
|
+
vexor_ci_service
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
MergeRequestsHelper.module_eval do
|
51
|
+
def ci_build_details_path(merge_request)
|
52
|
+
merge_request.source_project.vexor_ci_service.build_page(merge_request.last_commit.sha)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# == Schema Information
|
2
|
+
#
|
3
|
+
# Table name: services
|
4
|
+
#
|
5
|
+
# id :integer not null, primary key
|
6
|
+
# type :string(255)
|
7
|
+
# title :string(255)
|
8
|
+
# token :string(255)
|
9
|
+
# project_id :integer not null
|
10
|
+
# created_at :datetime not null
|
11
|
+
# updated_at :datetime not null
|
12
|
+
# active :boolean default(FALSE), not null
|
13
|
+
# project_url :string(255)
|
14
|
+
# subdomain :string(255)
|
15
|
+
# room :string(255)
|
16
|
+
# api_key :string(255)
|
17
|
+
#
|
18
|
+
|
19
|
+
class ::VexorCiService < ::Service
|
20
|
+
attr_accessible :project_url
|
21
|
+
|
22
|
+
validates :project_url, presence: true, if: :activated?
|
23
|
+
validates :token, presence: true, if: :activated?
|
24
|
+
|
25
|
+
def commit_status_path(sha)
|
26
|
+
project_url + "/api/builds/sha/#{sha}.json?token=#{token}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def commit_status(sha)
|
30
|
+
response = HTTParty.get(commit_status_path(sha), verify: false)
|
31
|
+
|
32
|
+
if response.code == 200 && response["status"]
|
33
|
+
response["status"]
|
34
|
+
else
|
35
|
+
:error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_page(sha)
|
40
|
+
project_url + "/builds/sha/#{sha}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def builds_path
|
44
|
+
""
|
45
|
+
end
|
46
|
+
|
47
|
+
def status_img_path
|
48
|
+
# project_url + "/status.png?ref=" + project.default_branch
|
49
|
+
""
|
50
|
+
end
|
51
|
+
|
52
|
+
def title
|
53
|
+
"Vexor CI"
|
54
|
+
end
|
55
|
+
|
56
|
+
def description
|
57
|
+
"Continuous integration server from Vexor"
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_param
|
61
|
+
"vexor_ci"
|
62
|
+
end
|
63
|
+
|
64
|
+
def fields
|
65
|
+
[
|
66
|
+
{ type: "text", name: "token", placeholder: "Vexor CI project specific token" },
|
67
|
+
{ type: "text", name: "project_url", placeholder: "http://ci.vexor.io/projects/3"}
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def execute(push_data)
|
72
|
+
# NOOP
|
73
|
+
end
|
74
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "active_record"
|
2
|
+
|
3
|
+
ServiceHook = Class.new(ActiveRecord::Base)
|
4
|
+
Service = Class.new(ActiveRecord::Base) do
|
5
|
+
belongs_to :project
|
6
|
+
has_one :service_hook
|
7
|
+
end
|
8
|
+
|
9
|
+
require "protected_attributes"
|
10
|
+
require "shoulda-matchers"
|
11
|
+
require "httparty"
|
12
|
+
|
13
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
14
|
+
ActiveSupport.silence(:stdout) do
|
15
|
+
ActiveRecord::Migration.class_eval do
|
16
|
+
create_table(:services) { |t| t.integer :project_id }
|
17
|
+
create_table(:service_hooks) { |t| t.integer :service_id }
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# == Schema Information
|
2
|
+
#
|
3
|
+
# Table name: services
|
4
|
+
#
|
5
|
+
# id :integer not null, primary key
|
6
|
+
# type :string(255)
|
7
|
+
# title :string(255)
|
8
|
+
# token :string(255)
|
9
|
+
# project_id :integer not null
|
10
|
+
# created_at :datetime not null
|
11
|
+
# updated_at :datetime not null
|
12
|
+
# active :boolean default(FALSE), not null
|
13
|
+
# project_url :string(255)
|
14
|
+
# subdomain :string(255)
|
15
|
+
# room :string(255)
|
16
|
+
# api_key :string(255)
|
17
|
+
#
|
18
|
+
|
19
|
+
require "spec_helper"
|
20
|
+
require "vx/gitlab_status_service/vexor_ci_service"
|
21
|
+
|
22
|
+
describe VexorCiService do
|
23
|
+
describe "Associations" do
|
24
|
+
it { should belong_to :project }
|
25
|
+
it { should have_one :service_hook }
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "Mass assignment" do
|
29
|
+
it { should_not allow_mass_assignment_of(:project_id) }
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "commit_status" do
|
33
|
+
before do
|
34
|
+
subject.stub(:project_url).and_return("")
|
35
|
+
subject.stub(:token).and_return("")
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "pending" do
|
39
|
+
before do
|
40
|
+
response = double(code: 200, :[] => "pending")
|
41
|
+
HTTParty.stub(:get).and_return(response)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns correct status" do
|
45
|
+
expect(subject.commit_status("somecommitsha")).to be == "pending"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "error" do
|
50
|
+
before do
|
51
|
+
response = double(code: 200, :[] => nil)
|
52
|
+
HTTParty.stub(:get).and_return(response)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns correct status" do
|
56
|
+
expect(subject.commit_status("somecommitsha")).to be == :error
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "unavailable" do
|
61
|
+
before do
|
62
|
+
response = double(code: 404)
|
63
|
+
HTTParty.stub(:get).and_return(response)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns correct status" do
|
67
|
+
expect(subject.commit_status("somecommitsha")).to be == :error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'commits methods' do
|
73
|
+
before do
|
74
|
+
@service = VexorCiService.new
|
75
|
+
@service.stub(
|
76
|
+
service_hook: true,
|
77
|
+
project_url: 'http://ci.gitlab.org/projects/2',
|
78
|
+
token: 'verySecret'
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
describe :commit_status_path do
|
83
|
+
it { @service.commit_status_path("2ab7834c").should == "http://ci.gitlab.org/projects/2/builds/2ab7834c/status.json?token=verySecret"}
|
84
|
+
end
|
85
|
+
|
86
|
+
describe :build_page do
|
87
|
+
it { @service.build_page("2ab7834c").should == "http://ci.gitlab.org/projects/2/builds/2ab7834c"}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'vx/gitlab_status_service/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "vx-gitlab_status_service"
|
8
|
+
spec.version = Vx::GitlabStatusService::VERSION
|
9
|
+
spec.authors = ["Semenyuk Dmitriy"]
|
10
|
+
spec.email = ["mail@semenyukdmitriy.com"]
|
11
|
+
spec.summary = %q{Gitlab v6 build status service.}
|
12
|
+
spec.description = %q{Integrates Gitlab with Vexor CI (build status & build link on merge request pages)}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "shoulda-matchers", "~> 2.1.0"
|
25
|
+
spec.add_development_dependency "sqlite3"
|
26
|
+
spec.add_development_dependency "httparty"
|
27
|
+
spec.add_dependency "activerecord"
|
28
|
+
spec.add_dependency "protected_attributes"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vx-gitlab_status_service
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Semenyuk Dmitriy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: shoulda-matchers
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.1.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: httparty
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activerecord
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: protected_attributes
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: Integrates Gitlab with Vexor CI (build status & build link on merge request
|
126
|
+
pages)
|
127
|
+
email:
|
128
|
+
- mail@semenyukdmitriy.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".gitignore"
|
134
|
+
- Gemfile
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- lib/vx/gitlab_status_service.rb
|
139
|
+
- lib/vx/gitlab_status_service/railtie.rb
|
140
|
+
- lib/vx/gitlab_status_service/version.rb
|
141
|
+
- lib/vx/gitlab_status_service/vexor_ci_service.rb
|
142
|
+
- spec/spec_helper.rb
|
143
|
+
- spec/vexor_ci_service_spec.rb
|
144
|
+
- vx-gitlab_status_service.gemspec
|
145
|
+
homepage: ''
|
146
|
+
licenses:
|
147
|
+
- MIT
|
148
|
+
metadata: {}
|
149
|
+
post_install_message:
|
150
|
+
rdoc_options: []
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
requirements: []
|
164
|
+
rubyforge_project:
|
165
|
+
rubygems_version: 2.2.2
|
166
|
+
signing_key:
|
167
|
+
specification_version: 4
|
168
|
+
summary: Gitlab v6 build status service.
|
169
|
+
test_files:
|
170
|
+
- spec/spec_helper.rb
|
171
|
+
- spec/vexor_ci_service_spec.rb
|