citrus-core 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.citrus/config.rb +1 -1
- data/.gitignore +2 -1
- data/.travis.yml +4 -5
- data/README.md +1 -1
- data/Rakefile +3 -6
- data/citrus-core.gemspec +4 -2
- data/examples/bootstrap.rb +17 -17
- data/examples/payload.json +128 -1
- data/lib/citrus/core.rb +4 -18
- data/lib/citrus/core/build.rb +4 -2
- data/lib/citrus/core/cached_code_fetcher.rb +6 -5
- data/lib/citrus/core/configuration_loader.rb +2 -2
- data/lib/citrus/core/execute_build.rb +42 -0
- data/lib/citrus/core/exit_code.rb +21 -0
- data/lib/citrus/core/result.rb +7 -0
- data/lib/citrus/core/test_output.rb +19 -0
- data/lib/citrus/core/test_runner.rb +4 -6
- data/lib/citrus/core/version.rb +1 -1
- data/lib/citrus/core/workspace_builder.rb +5 -5
- data/lib/citrus/core/world.rb +21 -0
- data/spec/citrus/core/build_spec.rb +16 -0
- data/spec/{cached_code_fetcher_spec.rb → citrus/core/cached_code_fetcher_spec.rb} +17 -16
- data/spec/{changeset_spec.rb → citrus/core/changeset_spec.rb} +0 -0
- data/spec/citrus/core/clean_ruby_spec.rb +17 -0
- data/spec/{commit_changes_spec.rb → citrus/core/commit_changes_spec.rb} +0 -0
- data/spec/{commit_spec.rb → citrus/core/commit_spec.rb} +0 -0
- data/spec/{cofiguration_loader_spec.rb → citrus/core/configuration_loader_spec.rb} +1 -1
- data/spec/{cofiguration_spec.rb → citrus/core/configuration_spec.rb} +0 -0
- data/spec/{cofiguration_validator_spec.rb → citrus/core/configuration_validator_spec.rb} +0 -0
- data/spec/{execute_build_service_spec.rb → citrus/core/execute_build_spec.rb} +20 -15
- data/spec/{test_result_spec.rb → citrus/core/exit_code_spec.rb} +7 -6
- data/spec/{github_adapter_spec.rb → citrus/core/github_adapter_spec.rb} +1 -1
- data/spec/{publisher_spec.rb → citrus/core/publisher_spec.rb} +1 -1
- data/spec/{repository_spec.rb → citrus/core/repository_spec.rb} +0 -0
- data/spec/citrus/core/test_output_spec.rb +16 -0
- data/spec/citrus/core/test_runner_spec.rb +55 -0
- data/spec/citrus/core/workspace_builder_spec.rb +37 -0
- data/spec/citrus/core/world_spec.rb +11 -0
- data/spec/spec_helper.rb +6 -2
- metadata +81 -47
- data/examples/web.rb +0 -53
- data/lib/citrus/core/execute_build_service.rb +0 -30
- data/lib/citrus/core/test_result.rb +0 -24
- data/spec/build_spec.rb +0 -13
- data/spec/citrus_spec.rb +0 -18
- data/spec/test_runner_spec.rb +0 -44
- data/spec/workspace_builder_spec.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e337f6fe4503cd22f913b58c3b405349b2095502
|
4
|
+
data.tar.gz: 8ab789326e014e9b37f08786751fa69a6fc0c35f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d375c55555d424fb8c3449180e037aecdb394dbaf8b6300648b354c8665c8b0f2e600fc59d2e5ef161e943b82ee34bc60b077fbaf0665dbccf05b26d8f4651c
|
7
|
+
data.tar.gz: 55c5b6cee6ee95852d10395bef0b88a2f510e115e08d7bb6eccb12b727bc67d45329899842c1d4b73f486da7c3c1f3f0fefdf9c1484ab762c5b739bac12bf08c
|
data/.citrus/config.rb
CHANGED
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
## Citrus Core
|
2
2
|
|
3
|
-
[![Build Status](https://secure.travis-ci.org/pawelpacana/citrus-core.png)](http://travis-ci.org/pawelpacana/citrus-core) [![Dependency Status](https://gemnasium.com/pawelpacana/citrus-core.png)](https://gemnasium.com/pawelpacana/citrus-core) [![Code Climate](https://codeclimate.com/github/pawelpacana/citrus-core.png)](https://codeclimate.com/github/
|
3
|
+
[![Build Status](https://secure.travis-ci.org/pawelpacana/citrus-core.png)](http://travis-ci.org/pawelpacana/citrus-core) [![Dependency Status](https://gemnasium.com/pawelpacana/citrus-core.png)](https://gemnasium.com/pawelpacana/citrus-core) [![Code Climate](https://codeclimate.com/github/pawelpacana/citrus-core.png)](https://codeclimate.com/github/pawelpacana/citrus-core) [![Gem Version](https://badge.fury.io/rb/citrus-core.png)](http://badge.fury.io/rb/citrus-core) [![Coverage Status](https://coveralls.io/repos/pawelpacana/citrus-core/badge.png)](https://coveralls.io/r/pawelpacana/citrus-core)
|
4
4
|
|
5
5
|
Spartan CI environment. Watch it build itself:
|
6
6
|
|
data/Rakefile
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
require '
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
|
5
|
-
t.libs = %w(lib test)
|
6
|
-
t.pattern = 'test/*_test.rb'
|
7
|
-
end
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
5
|
|
9
|
-
task :default => :
|
6
|
+
task :default => :spec
|
data/citrus-core.gemspec
CHANGED
@@ -19,7 +19,9 @@ Gem::Specification.new do |gem|
|
|
19
19
|
|
20
20
|
gem.add_dependency 'childprocess', '~> 0.3.9'
|
21
21
|
|
22
|
-
gem.add_development_dependency 'fakefs', '~> 0.4.2'
|
23
22
|
gem.add_development_dependency 'rspec', '~> 2.13'
|
24
|
-
gem.add_development_dependency 'bogus', '~> 0.
|
23
|
+
gem.add_development_dependency 'bogus', '~> 0.1'
|
24
|
+
gem.add_development_dependency 'rake'
|
25
|
+
gem.add_development_dependency 'mutant', '~> 0.3.0.rc3'
|
26
|
+
gem.add_development_dependency 'coveralls', '~> 0.7'
|
25
27
|
end
|
data/examples/bootstrap.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'citrus/core'
|
2
2
|
require 'pathname'
|
3
|
+
require 'tmpdir'
|
3
4
|
|
4
|
-
class
|
5
|
-
def build_succeeded(build,
|
5
|
+
class EventSubscriber
|
6
|
+
def build_succeeded(build, result)
|
6
7
|
puts "[#{build.uuid}] Build has succeeded."
|
7
8
|
end
|
8
9
|
|
9
|
-
def build_failed(build,
|
10
|
+
def build_failed(build, result)
|
10
11
|
puts "[#{build.uuid}] Build has failed."
|
11
12
|
end
|
12
13
|
|
@@ -18,23 +19,22 @@ class Notifier
|
|
18
19
|
puts "[#{build.uuid}] Build has started."
|
19
20
|
end
|
20
21
|
|
21
|
-
def
|
22
|
+
def build_output_received(build, data)
|
22
23
|
print data
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
workspace_builder = WorkspaceBuilder.new
|
32
|
-
|
33
|
-
test_runner
|
34
|
-
|
35
|
-
|
36
|
-
build_service
|
37
|
-
build_service.
|
38
|
-
build_service.start(build)
|
27
|
+
world = Citrus::Core::World.new(Dir.mktmpdir('citrus'))
|
28
|
+
github_adapter = Citrus::Core::GithubAdapter.new
|
29
|
+
changeset = github_adapter.create_changeset_from_push_data(Pathname.new(File.dirname(__FILE__)).join('payload.json').read)
|
30
|
+
event_subscriber = EventSubscriber.new
|
31
|
+
code_fetcher = Citrus::Core::CachedCodeFetcher.new(world.cache_root)
|
32
|
+
workspace_builder = Citrus::Core::WorkspaceBuilder.new(world.build_root, code_fetcher)
|
33
|
+
config_loader = Citrus::Core::ConfigurationLoader.new
|
34
|
+
test_runner = Citrus::Core::TestRunner.new
|
35
|
+
build_service = Citrus::Core::ExecuteBuild.new(workspace_builder, config_loader, test_runner)
|
36
|
+
|
37
|
+
[test_runner, build_service].each { |publisher| publisher.add_subscriber(event_subscriber) }
|
38
|
+
build_service.start(Citrus::Core::Build.new(changeset))
|
39
39
|
|
40
40
|
|
data/examples/payload.json
CHANGED
@@ -1 +1,128 @@
|
|
1
|
-
{
|
1
|
+
{
|
2
|
+
"after": "d71454f98d4f1ba0c1974838e4883cbee72d4233",
|
3
|
+
"before": "5425bd6d5ebf6c99cf2fbc56db3fab9ce0ed4516",
|
4
|
+
"commits": [
|
5
|
+
{
|
6
|
+
"added": [],
|
7
|
+
"author": {
|
8
|
+
"email": "pawel.pacana@gmail.com",
|
9
|
+
"name": "Pawe\u0142 Pacana",
|
10
|
+
"username": "pawelpacana"
|
11
|
+
},
|
12
|
+
"committer": {
|
13
|
+
"email": "pawel.pacana@gmail.com",
|
14
|
+
"name": "Pawe\u0142 Pacana",
|
15
|
+
"username": "pawelpacana"
|
16
|
+
},
|
17
|
+
"distinct": true,
|
18
|
+
"id": "02a402784a8caf58de5b610afd12388e0325549c",
|
19
|
+
"message": "Move publishing to private methods.\n\nThey make visual clutter and I'd love to see them somewhere else\nso aspects maybe?",
|
20
|
+
"modified": [
|
21
|
+
"lib/citrus/core/execute_build_service.rb"
|
22
|
+
],
|
23
|
+
"removed": [],
|
24
|
+
"timestamp": "2013-08-11T01:50:27-07:00",
|
25
|
+
"url": "https://github.com/pawelpacana/citrus-core/commit/02a402784a8caf58de5b610afd12388e0325549c"
|
26
|
+
},
|
27
|
+
{
|
28
|
+
"added": [],
|
29
|
+
"author": {
|
30
|
+
"email": "pawel.pacana@gmail.com",
|
31
|
+
"name": "Pawe\u0142 Pacana",
|
32
|
+
"username": "pawelpacana"
|
33
|
+
},
|
34
|
+
"committer": {
|
35
|
+
"email": "pawel.pacana@gmail.com",
|
36
|
+
"name": "Pawe\u0142 Pacana",
|
37
|
+
"username": "pawelpacana"
|
38
|
+
},
|
39
|
+
"distinct": true,
|
40
|
+
"id": "d665af0790d4671626a63e34ea013d5616498e5c",
|
41
|
+
"message": "Pass build to test runner to be more specific about published output.",
|
42
|
+
"modified": [
|
43
|
+
"lib/citrus/core/execute_build_service.rb",
|
44
|
+
"lib/citrus/core/test_runner.rb",
|
45
|
+
"spec/execute_build_service_spec.rb",
|
46
|
+
"spec/test_runner_spec.rb"
|
47
|
+
],
|
48
|
+
"removed": [],
|
49
|
+
"timestamp": "2013-08-11T02:57:39-07:00",
|
50
|
+
"url": "https://github.com/pawelpacana/citrus-core/commit/d665af0790d4671626a63e34ea013d5616498e5c"
|
51
|
+
},
|
52
|
+
{
|
53
|
+
"added": [],
|
54
|
+
"author": {
|
55
|
+
"email": "pawel.pacana@gmail.com",
|
56
|
+
"name": "Pawe\u0142 Pacana",
|
57
|
+
"username": "pawelpacana"
|
58
|
+
},
|
59
|
+
"committer": {
|
60
|
+
"email": "pawel.pacana@gmail.com",
|
61
|
+
"name": "Pawe\u0142 Pacana",
|
62
|
+
"username": "pawelpacana"
|
63
|
+
},
|
64
|
+
"distinct": true,
|
65
|
+
"id": "d71454f98d4f1ba0c1974838e4883cbee72d4233",
|
66
|
+
"message": "Improve naming.",
|
67
|
+
"modified": [
|
68
|
+
"lib/citrus/core/execute_build_service.rb"
|
69
|
+
],
|
70
|
+
"removed": [],
|
71
|
+
"timestamp": "2013-08-11T03:24:10-07:00",
|
72
|
+
"url": "https://github.com/pawelpacana/citrus-core/commit/d71454f98d4f1ba0c1974838e4883cbee72d4233"
|
73
|
+
}
|
74
|
+
],
|
75
|
+
"compare": "https://github.com/pawelpacana/citrus-core/compare/5425bd6d5ebf...d71454f98d4f",
|
76
|
+
"created": false,
|
77
|
+
"deleted": false,
|
78
|
+
"forced": false,
|
79
|
+
"head_commit": {
|
80
|
+
"added": [],
|
81
|
+
"author": {
|
82
|
+
"email": "pawel.pacana@gmail.com",
|
83
|
+
"name": "Pawe\u0142 Pacana",
|
84
|
+
"username": "pawelpacana"
|
85
|
+
},
|
86
|
+
"committer": {
|
87
|
+
"email": "pawel.pacana@gmail.com",
|
88
|
+
"name": "Pawe\u0142 Pacana",
|
89
|
+
"username": "pawelpacana"
|
90
|
+
},
|
91
|
+
"distinct": true,
|
92
|
+
"id": "d71454f98d4f1ba0c1974838e4883cbee72d4233",
|
93
|
+
"message": "Improve naming.",
|
94
|
+
"modified": [
|
95
|
+
"lib/citrus/core/execute_build_service.rb"
|
96
|
+
],
|
97
|
+
"removed": [],
|
98
|
+
"timestamp": "2013-08-11T03:24:10-07:00",
|
99
|
+
"url": "https://github.com/pawelpacana/citrus-core/commit/d71454f98d4f1ba0c1974838e4883cbee72d4233"
|
100
|
+
},
|
101
|
+
"pusher": {
|
102
|
+
"name": "none"
|
103
|
+
},
|
104
|
+
"ref": "refs/heads/master",
|
105
|
+
"repository": {
|
106
|
+
"created_at": 1360404806,
|
107
|
+
"fork": false,
|
108
|
+
"forks": 0,
|
109
|
+
"has_downloads": true,
|
110
|
+
"has_issues": true,
|
111
|
+
"has_wiki": true,
|
112
|
+
"id": 8108400,
|
113
|
+
"language": "Ruby",
|
114
|
+
"master_branch": "master",
|
115
|
+
"name": "citrus-core",
|
116
|
+
"open_issues": 0,
|
117
|
+
"owner": {
|
118
|
+
"email": "pawel.pacana@gmail.com",
|
119
|
+
"name": "pawelpacana"
|
120
|
+
},
|
121
|
+
"private": false,
|
122
|
+
"pushed_at": 1376217577,
|
123
|
+
"size": 236,
|
124
|
+
"stargazers": 1,
|
125
|
+
"url": "https://github.com/pawelpacana/citrus-core",
|
126
|
+
"watchers": 1
|
127
|
+
}
|
128
|
+
}
|
data/lib/citrus/core.rb
CHANGED
@@ -1,31 +1,17 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
|
3
1
|
module Citrus
|
4
2
|
module Core
|
5
|
-
class << self
|
6
|
-
|
7
|
-
def build_root
|
8
|
-
@build_root || root.join('builds')
|
9
|
-
end
|
10
|
-
|
11
|
-
def cache_root
|
12
|
-
@cache_root || root.join('cache')
|
13
|
-
end
|
14
|
-
|
15
|
-
def root
|
16
|
-
Pathname.new(File.expand_path('../../', File.dirname(__FILE__)))
|
17
|
-
end
|
18
3
|
|
19
|
-
end
|
20
4
|
end
|
21
5
|
end
|
22
6
|
|
7
|
+
require 'citrus/core/world'
|
23
8
|
require 'citrus/core/publisher'
|
24
9
|
require 'citrus/core/build'
|
25
|
-
require 'citrus/core/
|
10
|
+
require 'citrus/core/exit_code'
|
26
11
|
require 'citrus/core/workspace_builder'
|
27
12
|
require 'citrus/core/cached_code_fetcher'
|
28
13
|
require 'citrus/core/changeset'
|
14
|
+
require 'citrus/core/test_output'
|
29
15
|
require 'citrus/core/test_runner'
|
30
16
|
require 'citrus/core/github_adapter'
|
31
17
|
require 'citrus/core/commit'
|
@@ -34,4 +20,4 @@ require 'citrus/core/configuration'
|
|
34
20
|
require 'citrus/core/configuration_loader'
|
35
21
|
require 'citrus/core/configuration_validator'
|
36
22
|
require 'citrus/core/git_adapter'
|
37
|
-
require 'citrus/core/
|
23
|
+
require 'citrus/core/execute_build'
|
data/lib/citrus/core/build.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
+
require 'stringio'
|
1
2
|
require 'securerandom'
|
2
3
|
|
3
4
|
module Citrus
|
4
5
|
module Core
|
5
6
|
class Build
|
6
7
|
|
7
|
-
attr_reader :changeset, :uuid
|
8
|
+
attr_reader :changeset, :uuid, :output
|
8
9
|
|
9
|
-
def initialize(changeset, uuid = SecureRandom.uuid)
|
10
|
+
def initialize(changeset, uuid = SecureRandom.uuid, output = TestOutput.new)
|
10
11
|
@changeset = changeset
|
11
12
|
@uuid = uuid
|
13
|
+
@output = output
|
12
14
|
end
|
13
15
|
|
14
16
|
end
|
@@ -4,18 +4,19 @@ module Citrus
|
|
4
4
|
module Core
|
5
5
|
class CachedCodeFetcher
|
6
6
|
|
7
|
-
attr_reader :cache_root, :vcs_adapter
|
7
|
+
attr_reader :cache_root, :vcs_adapter, :digester
|
8
8
|
|
9
|
-
def initialize(cache_root =
|
9
|
+
def initialize(cache_root, vcs_adapter = GitAdapter.new, digester = Digest::SHA1)
|
10
10
|
@cache_root = cache_root
|
11
11
|
@vcs_adapter = vcs_adapter
|
12
|
+
@digester = digester
|
12
13
|
end
|
13
14
|
|
14
15
|
def fetch(changeset, destination)
|
15
16
|
url = changeset.repository_url
|
16
17
|
head = changeset.head
|
17
|
-
cache_dir =
|
18
|
-
|
18
|
+
cache_dir = File.join(cache_root, digester.hexdigest(url))
|
19
|
+
FileUtils.mkpath(cache_dir)
|
19
20
|
update_cache(url, cache_dir)
|
20
21
|
vcs_adapter.clone_repository(cache_dir, destination)
|
21
22
|
vcs_adapter.checkout(destination, head)
|
@@ -24,7 +25,7 @@ module Citrus
|
|
24
25
|
protected
|
25
26
|
|
26
27
|
def update_cache(url, cache_dir)
|
27
|
-
return vcs_adapter.clone_repository(url, cache_dir)
|
28
|
+
return vcs_adapter.clone_repository(url, cache_dir) if Dir.entries(cache_dir).size == 2
|
28
29
|
vcs_adapter.fetch_remote(cache_dir)
|
29
30
|
vcs_adapter.reset(cache_dir)
|
30
31
|
end
|
@@ -12,8 +12,8 @@ module Citrus
|
|
12
12
|
@validator = validator
|
13
13
|
end
|
14
14
|
|
15
|
-
def load_from_path(
|
16
|
-
data =
|
15
|
+
def load_from_path(path)
|
16
|
+
data = File.read(File.join(path, '.citrus/config.rb'))
|
17
17
|
config = eval(data)
|
18
18
|
raise ConfigurationFileInvalidError unless validator.validate(config)
|
19
19
|
config
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Citrus
|
2
|
+
module Core
|
3
|
+
class ExecuteBuild
|
4
|
+
include Publisher
|
5
|
+
|
6
|
+
attr_reader :workspace_builder, :configuration_loader, :test_runner
|
7
|
+
|
8
|
+
def initialize(workspace_builder, configuration_loader = ConfigurationLoader.new, test_runner = TestRunner.new)
|
9
|
+
@workspace_builder = workspace_builder
|
10
|
+
@configuration_loader = configuration_loader
|
11
|
+
@test_runner = test_runner
|
12
|
+
end
|
13
|
+
|
14
|
+
def start(build)
|
15
|
+
workspace_path = workspace_builder.create_workspace(build)
|
16
|
+
configuration = configuration_loader.load_from_path(workspace_path)
|
17
|
+
notify_build_start(build)
|
18
|
+
result = test_runner.start(build, configuration, workspace_path)
|
19
|
+
notify_build_result(build, result)
|
20
|
+
rescue ConfigurationError => error
|
21
|
+
notify_build_abort(build, error)
|
22
|
+
raise
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def notify_build_start(build)
|
28
|
+
publish(:build_started, build)
|
29
|
+
end
|
30
|
+
|
31
|
+
def notify_build_result(build, result)
|
32
|
+
publish(:build_succeeded, build, result) if result.success?
|
33
|
+
publish(:build_failed, build, result) if result.failure?
|
34
|
+
end
|
35
|
+
|
36
|
+
def notify_build_abort(build, error)
|
37
|
+
publish(:build_aborted, build, error)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|