travis-client 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/README.textile +111 -0
- data/Rakefile +8 -0
- data/bin/travis +21 -0
- data/features/repositories.feature +117 -0
- data/features/step_definitions/repositories_steps.rb +51 -0
- data/features/support/env.rb +2 -0
- data/lib/travis.rb +2 -0
- data/lib/travis/api.rb +3 -0
- data/lib/travis/api/client.rb +95 -0
- data/lib/travis/api/client/repositories.rb +234 -0
- data/lib/travis/api/entity.rb +44 -0
- data/lib/travis/api/entity/build.rb +129 -0
- data/lib/travis/api/entity/repository.rb +79 -0
- data/lib/travis/client.rb +109 -0
- data/lib/travis/client/repositories.rb +345 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/travis/api/client/repositories_spec.rb +2 -0
- data/spec/travis/api/client_spec.rb +15 -0
- data/spec/travis/api/entity/build_spec.rb +84 -0
- data/spec/travis/api/entity/repository_spec.rb +79 -0
- data/spec/travis/api/entity_spec.rb +46 -0
- data/spec/travis/api/shared_client_examples.rb +3 -0
- data/spec/travis/api/shared_entity_examples.rb +16 -0
- data/travis-client.gemspec +26 -0
- metadata +128 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.textile
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
h1. Travis Ruby Client - "!https://secure.travis-ci.org/travis-ci/travis-ruby-client.png?branch=master!":http://travis-ci.org/travis-ci/travis-ruby-client
|
2
|
+
|
3
|
+
h2. Contact
|
4
|
+
* "Github":http://github.com/travis-ci/travis-ruby-client
|
5
|
+
* "Twitter":http://twitter.com/travisci
|
6
|
+
* "IRC":irc://irc.freenode.net#travis
|
7
|
+
* "Mailinglist":http://groups.google.com/group/travis-ci
|
8
|
+
|
9
|
+
h2. Documentation
|
10
|
+
|
11
|
+
* "YARD docs":http://rdoc.info/github/travis-ci/travis-ruby-client/master/file/README.textile
|
12
|
+
|
13
|
+
h2. Usage [As a Command Line Tool]
|
14
|
+
|
15
|
+
<pre>
|
16
|
+
Supported Commands:
|
17
|
+
travis repositories|repos|repo|r {options}
|
18
|
+
travis status|stat|s {options}
|
19
|
+
|
20
|
+
Repositories:
|
21
|
+
travis status|stat|s
|
22
|
+
travis repositories|repos|repo|r [--recent]
|
23
|
+
travis repositories --slugs={repository_slug}[,{repository_slug}[,...]]
|
24
|
+
travis repositories --name={repository_name} --owner={owner_name}
|
25
|
+
travis repositories --slug={repository_slug}
|
26
|
+
travis repositories --builds
|
27
|
+
travis repositories --name={repository_name} --owner={owner_name} --build_id={build_id}
|
28
|
+
travis repositories --slug={repository_slug} --build_id={build_id}
|
29
|
+
|
30
|
+
Supported Options:
|
31
|
+
--recent lists the recent processed repositories.
|
32
|
+
-B, --builds lists the recent builds for a repository.
|
33
|
+
-o, --owner= sets the target repository owner's name.
|
34
|
+
-n, --name= sets the target repository name.
|
35
|
+
-s, --slug= sets the target repositorys slug.
|
36
|
+
-S, --slugs= sets the target repositories slugs (comma separated).
|
37
|
+
-b, --build_id= sets the target repository build id.
|
38
|
+
-h, -H, --help display this help message.
|
39
|
+
</pre>
|
40
|
+
|
41
|
+
The `status` command should be run from your project directory. It will try to identify and dispaly the Travis status of the target repository based on the current directory remote git urls.
|
42
|
+
|
43
|
+
h2. Usage [As a Ruby Library]
|
44
|
+
|
45
|
+
h3. Fetching Repositories
|
46
|
+
|
47
|
+
<pre>
|
48
|
+
Travis::API::Client::Repositories.all #Collection of Repository instances
|
49
|
+
|
50
|
+
Travis::API::Client::Repositories.all! #Collection of Repository instances bypassing cache
|
51
|
+
|
52
|
+
Travis::API::Client::Repositories.owner('owner_name_here').name('name_here').fetch #Repository
|
53
|
+
|
54
|
+
Travis::API::Client::Repositories.owner('owner_name_here').name('name_here').fetch! #Repository bypassing cache
|
55
|
+
|
56
|
+
Travis::API::Client::Repositories.slug('owner_name_here/name_here').fetch #Repository
|
57
|
+
|
58
|
+
Travis::API::Client::Repositories.slug('owner_name_here/name_here').fetch! #Repository bypassing cache
|
59
|
+
</pre>
|
60
|
+
|
61
|
+
h3. Fetching Builds
|
62
|
+
|
63
|
+
<pre>
|
64
|
+
Travis::API::Client::Repositories.owner('owner_name_here').name('name_here').builds #Collection of Build instances
|
65
|
+
|
66
|
+
Travis::API::Client::Repositories.owner('owner_name_here').name('name_here').builds! #Collection of Build instances bypassing cache
|
67
|
+
|
68
|
+
Travis::API::Client::Repositories.slug('owner_name_here/name_here').builds #Collection of Build instances
|
69
|
+
|
70
|
+
Travis::API::Client::Repositories.slug('owner_name_here/name_here').builds! #Collection of Build instances bypassing cache
|
71
|
+
|
72
|
+
Travis::API::Client::Repositories.owner('owner_name_here').name('name_here').build('id_here') #Build
|
73
|
+
|
74
|
+
Travis::API::Client::Repositories.owner('owner_name_here').name('name_here').build!('id_here') #Build bypassing cache
|
75
|
+
|
76
|
+
Travis::API::Client::Repositories.slug('owner_name_here/name_here').build('id_here') #Build
|
77
|
+
|
78
|
+
Travis::API::Client::Repositories.slug('owner_name_here/name_here').build!('id_here') #Build bypassing cache
|
79
|
+
</pre>
|
80
|
+
|
81
|
+
h3. Repository methods
|
82
|
+
|
83
|
+
The main attributes from the API will be accessible via the following methods:
|
84
|
+
|
85
|
+
bc. [:slug, :id, :status, :last_build_id, :last_build_status, :last_build_number, :last_build_finished_at]
|
86
|
+
|
87
|
+
Some relationships can be retrieved using the following methods:
|
88
|
+
|
89
|
+
bc. repository.builds #=> Collection of Build instances
|
90
|
+
repository.last_build #=> Build
|
91
|
+
|
92
|
+
You can also update the repository information from the API usign:
|
93
|
+
|
94
|
+
bc. repository.reload! #=> Fetch the updated repository data from the API and updates its attributes and relationships
|
95
|
+
|
96
|
+
h3. Build methods
|
97
|
+
|
98
|
+
The main attributes from the API will be accessible via the following methods:
|
99
|
+
|
100
|
+
bc. [:number, :commited_at, :commit, :finished_at, :config, :author_name, :log, :branch, :id, :parent_id, :started_at, :author_email, :status, :repository_id, :message, :compare_url]
|
101
|
+
|
102
|
+
Some relationships can be retrieved using the following methods:
|
103
|
+
|
104
|
+
bc. build.parent #=> Build or nil
|
105
|
+
build.repository #=> Repository
|
106
|
+
build.matrix #=> Collection of Build instances or nil
|
107
|
+
|
108
|
+
You can also update the build information from the API usign:
|
109
|
+
|
110
|
+
bc. build.reload! #=> Fetch the updated build data from the API and updates its attributes and relationships
|
111
|
+
|
data/Rakefile
ADDED
data/bin/travis
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH << './lib/'
|
3
|
+
require 'travis/client'
|
4
|
+
|
5
|
+
available_commands = ['repositories', 'status']
|
6
|
+
|
7
|
+
command = ARGV.first.to_s.downcase
|
8
|
+
|
9
|
+
if !available_commands.include?(command) && available_commands.select {|c| c =~ Regexp.new("^#{command}.*")}.length == 1
|
10
|
+
command = available_commands.detect {|c| c =~ Regexp.new("^#{command}.*")}
|
11
|
+
end
|
12
|
+
|
13
|
+
if ['repositories'].include?(command)
|
14
|
+
Travis::Client.const_get(command.capitalize).new.run
|
15
|
+
elsif ['status'].include?(command)
|
16
|
+
Travis::Client.send(command)
|
17
|
+
else
|
18
|
+
ARGV << '-h'
|
19
|
+
Travis::Client.new.run
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
Feature: Repositories
|
2
|
+
In order to get informatio about the Travis CI repoisitories
|
3
|
+
As ruby application
|
4
|
+
I want to get the the repositories information through the API wrapper
|
5
|
+
|
6
|
+
Scenario Outline: Get all repositories
|
7
|
+
Given I am using the Travis::API::Client::Repositories client
|
8
|
+
When I request <method>
|
9
|
+
Then I should get a collection of Travis::API::Entity::Repository instances
|
10
|
+
|
11
|
+
Examples:
|
12
|
+
|method |
|
13
|
+
|all |
|
14
|
+
|all! |
|
15
|
+
|
16
|
+
Scenario Outline: Get a repository by name and owner
|
17
|
+
Given I am using the Travis::API::Client::Repositories client
|
18
|
+
When I set the name to "travis-ci"
|
19
|
+
And I set the owner to "travis-ci"
|
20
|
+
And I request <method>
|
21
|
+
Then I should get a Travis::API::Entity::Repository
|
22
|
+
And the result should have the following values:
|
23
|
+
| name | travis-ci |
|
24
|
+
| owner | travis-ci |
|
25
|
+
| slug | travis-ci/travis-ci |
|
26
|
+
And the result should have the following numeric values:
|
27
|
+
| id | 59 |
|
28
|
+
|
29
|
+
Examples:
|
30
|
+
|method |
|
31
|
+
|fetch |
|
32
|
+
|fetch! |
|
33
|
+
|
34
|
+
# Right now there's no way to get a repository directly by id.
|
35
|
+
#
|
36
|
+
# We are iterating over the recent repositories trying to find the target repo by id.
|
37
|
+
#
|
38
|
+
# It will fail most of the times since the recent repositories is a really small list.
|
39
|
+
#
|
40
|
+
# Looking forward for an API call to get repos by id or at list one to get all the repos and
|
41
|
+
# not just the recent ones.
|
42
|
+
#
|
43
|
+
# Scenario Outline: Get a repository by name and owner
|
44
|
+
# Given I am using the Travis::API::Client::Repositories client
|
45
|
+
# When I set the id to "59"
|
46
|
+
# And I request <method>
|
47
|
+
# Then I should get a Travis::API::Entity::Repository
|
48
|
+
# And the result should have the following values:
|
49
|
+
# | name | travis-ci |
|
50
|
+
# | owner | travis-ci |
|
51
|
+
# | slug | travis-ci/travis-ci |
|
52
|
+
# And the result should have the following numeric values:
|
53
|
+
# | id | 59 |
|
54
|
+
#
|
55
|
+
# Examples:
|
56
|
+
# |method |
|
57
|
+
# |fetch |
|
58
|
+
# |fetch! |
|
59
|
+
#
|
60
|
+
|
61
|
+
Scenario Outline: Get a repository by name and owner
|
62
|
+
Given I am using the Travis::API::Client::Repositories client
|
63
|
+
When I set the slug to "travis-ci/travis-ci"
|
64
|
+
And I request <method>
|
65
|
+
Then I should get a Travis::API::Entity::Repository
|
66
|
+
And the result should have the following values:
|
67
|
+
| name | travis-ci |
|
68
|
+
| owner | travis-ci |
|
69
|
+
| slug | travis-ci/travis-ci |
|
70
|
+
And the result should have the following numeric values:
|
71
|
+
| id | 59 |
|
72
|
+
|
73
|
+
Examples:
|
74
|
+
|method |
|
75
|
+
|fetch |
|
76
|
+
|fetch! |
|
77
|
+
|
78
|
+
Scenario Outline: Get the builds from a repository
|
79
|
+
Given I am using the Travis::API::Client::Repositories client
|
80
|
+
When I set the owner to "travis-ci"
|
81
|
+
And I set the name to "travis-ci"
|
82
|
+
And I request <method>
|
83
|
+
Then I should get a collection of Travis::API::Entity::Build instances
|
84
|
+
|
85
|
+
Examples:
|
86
|
+
|method |
|
87
|
+
|builds |
|
88
|
+
|builds! |
|
89
|
+
|
90
|
+
Scenario Outline: Get a build from a repository by id
|
91
|
+
Given I am using the Travis::API::Client::Repositories client
|
92
|
+
When I set the owner to "travis-ci"
|
93
|
+
And I set the name to "travis-ci"
|
94
|
+
And I request <method> with the following params:
|
95
|
+
|69619 |
|
96
|
+
Then I should get a Travis::API::Entity::Build
|
97
|
+
And the result should have the following values:
|
98
|
+
| author_email | svenfuchs@artweb-design.de |
|
99
|
+
| author_name | Sven Fuchs |
|
100
|
+
| branch | statemachine |
|
101
|
+
| commit | 04beda102abcb37b353e406663535d2bc2c4da5c |
|
102
|
+
| committed_at | 2011-08-07T00:03:40Z |
|
103
|
+
| compare_url | https://github.com/travis-ci/travis-ci/compare/5878605...04beda1 |
|
104
|
+
| finished_at | 2011-08-07T00:18:36Z |
|
105
|
+
| message | Merge branch 'statemachine' of github.com:travis-ci/travis-ci into statemachine |
|
106
|
+
| number | 772 |
|
107
|
+
| started_at | 2011-08-07T00:14:41Z |
|
108
|
+
And the result should have the following numeric values:
|
109
|
+
| id | 69619 |
|
110
|
+
| repository_id | 59 |
|
111
|
+
| status | 1 |
|
112
|
+
And the result should respond to "matrix" with a collection of Travis::API::Entity::Build instances
|
113
|
+
And the result should respond to "repository" with a Travis::API::Entity::Repository instances
|
114
|
+
Examples:
|
115
|
+
|method |
|
116
|
+
|build |
|
117
|
+
|build! |
|
@@ -0,0 +1,51 @@
|
|
1
|
+
Given /^I am using the ((?:\:?{2}\w+)+) client$/ do |class_name|
|
2
|
+
@client = class_name.split('::').inject(Object) {|x,y| x = x.const_get(y)}
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^I should get a collection of ((?:\:?{2}\w+)+) instances$/ do |class_name|
|
6
|
+
expected_class = class_name.split('::').inject(Object) {|x,y| x = x.const_get(y)}
|
7
|
+
@result.each do |element|
|
8
|
+
element.should be_instance_of expected_class
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
When /^I set the (\w+) to "([^"]*)"$/ do |method, value|
|
13
|
+
@client = @client.send(method, value)
|
14
|
+
end
|
15
|
+
|
16
|
+
Then /^I should get a ((?:\:?{2}\w+)+)$/ do |class_name|
|
17
|
+
@result.should be_instance_of class_name.split('::').inject(Object) {|x,y| x = x.const_get(y)}
|
18
|
+
end
|
19
|
+
|
20
|
+
Then /^the result should have the following values:$/ do |table|
|
21
|
+
table.rows_hash.each_pair do |key, value|
|
22
|
+
@result.send(key).should == value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Then /^the result should have the following numeric values:$/ do |table|
|
27
|
+
table.rows_hash.each_pair do |key, value|
|
28
|
+
@result.send(key).should == value.to_f
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
When /^I request (\w+\!?)$/ do |method|
|
33
|
+
@result = @client.send(method)
|
34
|
+
end
|
35
|
+
|
36
|
+
When /^I request (\w+\!?) with the following params:$/ do |method, table|
|
37
|
+
@result = @client.send(method, *table.raw.collect(&:first))
|
38
|
+
end
|
39
|
+
|
40
|
+
Then /^the result should respond to "([^"]*)" with a collection of ((?:\:?{2}\w+)+) instances$/ do |method, class_name|
|
41
|
+
expected_class = class_name.split('::').inject(Object) {|x,y| x = x.const_get(y)}
|
42
|
+
@result.send(method).each do |element|
|
43
|
+
element.should be_instance_of expected_class
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Then /^the result should respond to "([^"]*)" with a ((?:\:?{2}\w+)+) instances$/ do |method, class_name|
|
48
|
+
expected_class = class_name.split('::').inject(Object) {|x,y| x = x.const_get(y)}
|
49
|
+
@result.send(method).should be_instance_of expected_class
|
50
|
+
end
|
51
|
+
|
data/lib/travis.rb
ADDED
data/lib/travis/api.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
require 'faraday'
|
4
|
+
require 'travis/api/client/repositories'
|
5
|
+
|
6
|
+
module Travis
|
7
|
+
|
8
|
+
module API
|
9
|
+
|
10
|
+
# Travis API Client
|
11
|
+
|
12
|
+
class Client
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
@options = {:format => DEFAULT_FORMAT}.merge(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Sets the response format and returns the host client instance
|
19
|
+
#
|
20
|
+
# @param [Symbol, String] format The desired response format, <tt>:json</tt>.
|
21
|
+
# @return [Client, Client::Repositories] The host client instance.
|
22
|
+
def format(format)
|
23
|
+
@options[:format] = format.to_s
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.method_missing(method, *args, &block)
|
28
|
+
return self.new.send(method, *args, &block) if self.client.respond_to?(method)
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.respond_to?(method, include_private = false)
|
33
|
+
self.client.respond_to?(method, include_private) || super(method, include_private)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Client default host
|
39
|
+
API_HOST = 'http://travis-ci.org'
|
40
|
+
|
41
|
+
# Response default format
|
42
|
+
DEFAULT_FORMAT = 'json'
|
43
|
+
|
44
|
+
# Returns the HTTP connection handler
|
45
|
+
#
|
46
|
+
# @return [Faraday]
|
47
|
+
def connection
|
48
|
+
@@connection ||= Faraday.new(:url => API_HOST) do |builder|
|
49
|
+
builder.adapter :net_http
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the encoded response for the given path and previouly set options
|
54
|
+
#
|
55
|
+
# @param [String] path API target path
|
56
|
+
# @return Encoded response
|
57
|
+
def results_for(path_template)
|
58
|
+
path = path_template.dup
|
59
|
+
|
60
|
+
@options.each_pair do |key, value|
|
61
|
+
path.gsub!(":#{key}", value)
|
62
|
+
end
|
63
|
+
|
64
|
+
response = connection().get(path)
|
65
|
+
|
66
|
+
return response.status == 200 ? parse(response.body) : nil
|
67
|
+
end
|
68
|
+
|
69
|
+
# Encodes and return the given content based on the previously set format
|
70
|
+
#
|
71
|
+
# @param [String] content Content to be encoded
|
72
|
+
# @return Encoded conter
|
73
|
+
def parse(content)
|
74
|
+
case @options[:format]
|
75
|
+
when 'json' then
|
76
|
+
return JSON.parse(content)
|
77
|
+
when 'xml'
|
78
|
+
return REXML::Document.new(content)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Initializes and return an instance of the current class
|
84
|
+
#
|
85
|
+
# @return A new instance of the current class
|
86
|
+
def self.client
|
87
|
+
self.new
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
@@ -0,0 +1,234 @@
|
|
1
|
+
module Travis
|
2
|
+
|
3
|
+
module API
|
4
|
+
|
5
|
+
class Client
|
6
|
+
|
7
|
+
# Travis API Client for Repositories
|
8
|
+
|
9
|
+
class Repositories < Client
|
10
|
+
|
11
|
+
# Returns the cached list of repositories or fetches the
|
12
|
+
# recent list if there's nothing already cached.
|
13
|
+
#
|
14
|
+
# @return [Array<Entity::Repository>]
|
15
|
+
def all
|
16
|
+
#Having some issues with the cached repositories
|
17
|
+
#@@repositories || self.all!
|
18
|
+
self.all!
|
19
|
+
end
|
20
|
+
|
21
|
+
# Fetches and return the list of recent repositories.
|
22
|
+
# It also updates the repositorires cache.
|
23
|
+
#
|
24
|
+
# @return [Array<Entity::Repository>]
|
25
|
+
def all!
|
26
|
+
@@repositories = results_for(REPOSITORIES_PATH).map {|repository_data| Entity::Repository.new(repository_data)}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a repository from the cache or fetches it
|
30
|
+
# based on the previously set options (name and owner or slug or id).
|
31
|
+
#
|
32
|
+
# @return [Entity::Repository]
|
33
|
+
def fetch
|
34
|
+
#Having some issues with the cached repositories
|
35
|
+
#fetch_from_cache() || self.fetch!
|
36
|
+
self.fetch!
|
37
|
+
end
|
38
|
+
|
39
|
+
# Fetches and return a repository based on the previously
|
40
|
+
# set options (name and owner or slug or id).
|
41
|
+
# It also adds this repository to the repositories cache.
|
42
|
+
#
|
43
|
+
# @return [Entity::Repository]
|
44
|
+
def fetch!
|
45
|
+
repository = @options[:id] ? fetch_by_id!() : fetch_by_owner_and_name!()
|
46
|
+
repositories_cache() << repository
|
47
|
+
repository
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the cached list of builds or fetches the
|
51
|
+
# recent list if there's nothing already cached.
|
52
|
+
#
|
53
|
+
# @return [Array<Entity::Build>]
|
54
|
+
def builds
|
55
|
+
#Having some issues with the cahced builds
|
56
|
+
#@@builds || self.builds!
|
57
|
+
self.builds!
|
58
|
+
end
|
59
|
+
|
60
|
+
# Fetches and return the list of recent builds.
|
61
|
+
# It also updates the builds cache.
|
62
|
+
#
|
63
|
+
# @return [Array<Entity::Build>]
|
64
|
+
def builds!
|
65
|
+
@@builds = results_for(REPOSITORY_BUILDS_PATH).map {|build_data| Entity::Build.new(build_data, @options[:owner], @options[:name])}
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns a build from the cache or fetches it
|
69
|
+
# based on the given build id and the previously set
|
70
|
+
# options (name and owner or slug or id).
|
71
|
+
#
|
72
|
+
# @return [Entity::Build]
|
73
|
+
def build(build_id)
|
74
|
+
#Having some issues with the cached builds
|
75
|
+
#build_from_cache(build_id) || self.build!(build_id)
|
76
|
+
self.build!(build_id)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Fetches and return a build based on the given
|
80
|
+
# build id and the previously set options (name and owner or
|
81
|
+
# slug or id).
|
82
|
+
# It also adds this build to the builds cache.
|
83
|
+
#
|
84
|
+
# @return [Entity::Build]
|
85
|
+
def build!(build_id)
|
86
|
+
@options[:build_id] = build_id.to_s
|
87
|
+
builds_cache().delete_if {|b| b.id == @options[:build_id]}
|
88
|
+
build = Entity::Build.new(results_for(REPOSITORY_BUILD_PATH), @options[:owner], @options[:name])
|
89
|
+
builds_cache() << build
|
90
|
+
build
|
91
|
+
end
|
92
|
+
|
93
|
+
# Sets the target repository id and return the host client instance.
|
94
|
+
# @param [Fixnum, String] id The target repository id.
|
95
|
+
# @return [Client::Repositories] The host client instance.
|
96
|
+
def id(id)
|
97
|
+
@options[:id] = id
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
# Sets the target repository owner and return the host client instance.
|
102
|
+
# @param [String] owner The target repository owner.
|
103
|
+
# @return [Client::Repositories] The host client instance.
|
104
|
+
def owner(owner)
|
105
|
+
@options[:owner] = owner
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
# Sets the target repository name and return the host client instance.
|
110
|
+
# @param [String] name The target repository name.
|
111
|
+
# @return [Client::Repositories] The host client instance.
|
112
|
+
def name(name)
|
113
|
+
@options[:name] = name
|
114
|
+
self
|
115
|
+
end
|
116
|
+
|
117
|
+
# Sets the target repository slug and return the host client instance.
|
118
|
+
# @param [String] slug The target repository slug.
|
119
|
+
# @return [Client::Repositories] The host client instance.
|
120
|
+
def slug(slug)
|
121
|
+
@options[:owner], @options[:name] = slug.split('/')
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
# Twick to accept `self.name(param)` as class method. It won't
|
126
|
+
# raise the NoMethodError but an ArgumentError so we can not
|
127
|
+
# apply reflection.
|
128
|
+
# Sice we are polite programmers the class still respond to the
|
129
|
+
# `self.name()` class method
|
130
|
+
#
|
131
|
+
# Creates an instance of the client, sets the target repository
|
132
|
+
# name and returns the host client instance.
|
133
|
+
#
|
134
|
+
# @param [String] name The target repository name.
|
135
|
+
|
136
|
+
# @return [Client::Repositories] The host client instance.
|
137
|
+
def self.name(name = nil)
|
138
|
+
return super unless name
|
139
|
+
self.new.name(name)
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# API Path template for a repository
|
145
|
+
REPOSITORY_PATH = '/:owner/:name.:format'
|
146
|
+
|
147
|
+
# API Path template for the repository listing
|
148
|
+
REPOSITORIES_PATH = '/repositories.:format'
|
149
|
+
|
150
|
+
# API Path template for a repository build
|
151
|
+
REPOSITORY_BUILD_PATH = '/:owner/:name/builds/:build_id.:format'
|
152
|
+
|
153
|
+
# API Path template for the repository build listing
|
154
|
+
REPOSITORY_BUILDS_PATH = '/:owner/:name/builds.:format'
|
155
|
+
|
156
|
+
# Cached repositories
|
157
|
+
# @return [Array<Entity::Repository>, NilClass]
|
158
|
+
@@repositories = nil
|
159
|
+
|
160
|
+
# Cached builds
|
161
|
+
# @return [Array<Entity::Build>, NilClass]
|
162
|
+
@@builds = nil
|
163
|
+
|
164
|
+
# Returns the cached collection of repositories
|
165
|
+
# or an empty array if it was not initialized yet.
|
166
|
+
#
|
167
|
+
# @return [Array<Entity::Repository>, NilClass]
|
168
|
+
def repositories_cache
|
169
|
+
@@repositories || []
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns the cached collection of builds
|
173
|
+
# or an empty array if it was not initialized yet.
|
174
|
+
#
|
175
|
+
# @return [Array<Entity::Build>, NilClass]
|
176
|
+
def builds_cache
|
177
|
+
@@builds || []
|
178
|
+
end
|
179
|
+
|
180
|
+
# Fetches and returns a repository based on the
|
181
|
+
# owner and name option values.
|
182
|
+
#
|
183
|
+
# @return [Entity::Repository]
|
184
|
+
def fetch_by_owner_and_name!
|
185
|
+
repositories_cache().delete_if {|r| r.owner == @options[:owner] && r.name == @options[:name]}
|
186
|
+
repository_data = results_for(REPOSITORY_PATH)
|
187
|
+
return repository_data && Entity::Repository.new(repository_data, @options[:owner], @options[:name])
|
188
|
+
end
|
189
|
+
|
190
|
+
# Right now there's no way to get a repository directly by id.
|
191
|
+
#
|
192
|
+
# Iterates over the recent repositories trying to find the target repo by id.
|
193
|
+
#
|
194
|
+
# It will fail most of the times since the recent repositories is a really small list.
|
195
|
+
# Looking forward for an API call to get repos by id or at list one to get all the repos and
|
196
|
+
# not just the recent ones.
|
197
|
+
#
|
198
|
+
# Fetches and returns a repository based the id option value.
|
199
|
+
# If the Repository can not be found an exception will be rised.
|
200
|
+
#
|
201
|
+
# @return [Entity::Repository]
|
202
|
+
def fetch_by_id!
|
203
|
+
repositories_cache().delete_if {|r| r.id == @options[:id]}
|
204
|
+
return self.all!.find {|r| r.id == @options[:id]} || raise("Repository not found: id => #{@options[:id]}")
|
205
|
+
end
|
206
|
+
|
207
|
+
# Looks into the cache for a repository, based on the previously set
|
208
|
+
# id or name and owner, returning the repository or nil if it's not present.
|
209
|
+
#
|
210
|
+
# @return [Entity::Repository, NilClass]
|
211
|
+
def fetch_from_cache
|
212
|
+
if @options[:id]
|
213
|
+
repositories_cache().find {|repository| repository.id == @options[:id].to_i}
|
214
|
+
else
|
215
|
+
repositories_cache().find {|repository| repository.owner == @options[:owner] && repository.name == @options[:name]}
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Looks into the cache for a build, based on the given build id,
|
220
|
+
# returning the build or nil if it's not present.
|
221
|
+
#
|
222
|
+
# @return [Entity::Build, NilClass]
|
223
|
+
def build_from_cache(build_id)
|
224
|
+
builds_cache().find {|build| build.id == build_id.to_s}
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|