heidi 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +15 -1
- data/README.rdoc +8 -3
- data/VERSION +1 -1
- data/bin/heidi +61 -57
- data/bin/heidi_web +2 -6
- data/heidi.gemspec +11 -5
- data/lib/heidi/build.rb +83 -27
- data/lib/heidi/builder.rb +3 -8
- data/lib/heidi/hook.rb +11 -5
- data/lib/heidi/tester.rb +3 -8
- data/lib/heidi/web/public/css/screen.css +93 -0
- data/lib/heidi/web/public/images/heidi.jpeg +0 -0
- data/lib/heidi/web/views/build.erb +20 -0
- data/lib/heidi/web/views/home.erb +7 -0
- data/lib/heidi/web/views/layout.erb +13 -0
- data/lib/heidi/web/views/project.erb +11 -0
- data/lib/heidi/web.rb +71 -4
- metadata +36 -22
- data/lib/heidi/web/routes/home.rb +0 -9
- data/lib/heidi/web/routes/projects.rb +0 -61
- data/lib/heidi/web/routes.rb +0 -13
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/rstacruz/sinatra-assetpack.git
|
3
|
+
revision: ab2a413026099492807bd19affd60bd3d3bc1cca
|
4
|
+
specs:
|
5
|
+
sinatra-assetpack (0.0.10)
|
6
|
+
jsmin
|
7
|
+
rack-test
|
8
|
+
sinatra
|
9
|
+
tilt (>= 1.3.0)
|
10
|
+
|
1
11
|
GEM
|
2
12
|
remote: http://rubygems.org/
|
3
13
|
specs:
|
@@ -10,10 +20,13 @@ GEM
|
|
10
20
|
git (>= 1.2.5)
|
11
21
|
rake
|
12
22
|
rdoc
|
23
|
+
jsmin (1.0.1)
|
13
24
|
json (1.6.5)
|
14
25
|
rack (1.4.1)
|
15
26
|
rack-protection (1.2.0)
|
16
27
|
rack
|
28
|
+
rack-test (0.6.1)
|
29
|
+
rack (>= 1.0)
|
17
30
|
rake (0.9.2.2)
|
18
31
|
rcov (0.9.10)
|
19
32
|
rdoc (3.12)
|
@@ -26,7 +39,7 @@ GEM
|
|
26
39
|
rspec-expectations (2.8.0)
|
27
40
|
diff-lcs (~> 1.1.2)
|
28
41
|
rspec-mocks (2.8.0)
|
29
|
-
simple_shell (1.0.
|
42
|
+
simple_shell (1.0.1)
|
30
43
|
sinatra (1.3.2)
|
31
44
|
rack (~> 1.3, >= 1.3.6)
|
32
45
|
rack-protection (~> 1.2)
|
@@ -48,4 +61,5 @@ DEPENDENCIES
|
|
48
61
|
rspec (~> 2.8.0)
|
49
62
|
simple_shell
|
50
63
|
sinatra
|
64
|
+
sinatra-assetpack!
|
51
65
|
thin
|
data/README.rdoc
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
-
=
|
1
|
+
= Heidi
|
2
2
|
|
3
|
-
|
3
|
+
A Continious Integration thingy. Naive, and therefor called Heidi.
|
4
|
+
|
5
|
+
http://www.tv-nostalgie.de/sound/Heidi2.jpg
|
6
|
+
|
7
|
+
Heidi is still taking form and is/will-be used to do CI at OrganisedMinds.com
|
8
|
+
(http://organisedminds.com) - Why don't you sign up there? It's free!
|
4
9
|
|
5
10
|
== Contributing to heidi
|
6
|
-
|
11
|
+
|
7
12
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
13
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
14
|
* Fork the project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/bin/heidi
CHANGED
@@ -1,70 +1,74 @@
|
|
1
|
-
#!/bin/
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'simple_shell'
|
4
|
+
require 'heidi'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
cmd = ARGV.shift
|
7
|
+
for_a = ARGV.shift
|
8
|
+
|
9
|
+
shell = SimpleShell.new
|
10
|
+
|
11
|
+
def check_heidi_root()
|
12
|
+
if !File.exists?("./projects") && File.directory?("./projects")
|
13
|
+
$stderr.puts "You're not inside Heidi"
|
11
14
|
exit 1
|
12
|
-
|
13
|
-
|
15
|
+
end
|
16
|
+
end
|
14
17
|
|
15
|
-
case
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
;;
|
18
|
+
case cmd
|
19
|
+
when "new"
|
20
|
+
puts "creating #{for_a}"
|
21
|
+
puts "creating #{for_a}/projects"
|
22
|
+
shell.mkdir %W(-p #{for_a}/projects)
|
23
|
+
puts "creating #{for_a}/bin"
|
24
|
+
shell.mkdir %W(-p #{for_a}/bin)
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
+
when "project"
|
27
|
+
check_heidi_root
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
# create a logs dir
|
30
|
+
puts "creating projects/#{for_a}"
|
31
|
+
puts "creating projects/#{for_a}/logs"
|
32
|
+
shell.mkdir %W(-p projects/#{for_a}/logs)
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
mkdir -p projects
|
35
|
-
|
34
|
+
%w(build tests failure success before).each do |hook|
|
35
|
+
puts "creating projects/#{for_a}/hooks/#{hook}"
|
36
|
+
shell.mkdir %W(-p projects/#{for_a}/hooks/#{hook})
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
# make a clone
|
40
|
+
shell.in("projects/#{for_a}") do |sh|
|
41
|
+
puts "filling #{for_a} cache"
|
42
|
+
repo = ARGV.shift
|
43
|
+
puts "git clone #{repo}"
|
44
|
+
sh.git %W(clone #{repo} cached)
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
sh.in("cached") do |cached|
|
47
|
+
puts "setting the name of the project to: #{for_a}"
|
48
|
+
cached.git %W(config heidi.name #{for_a})
|
49
|
+
end
|
50
|
+
end
|
51
|
+
puts "\n"
|
52
|
+
puts "Now define some hooks in projects/#{for_a}/hooks/tests"
|
46
53
|
|
47
|
-
|
48
|
-
|
54
|
+
when "drop"
|
55
|
+
check_heidi_root
|
49
56
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
;;
|
60
|
-
web)
|
61
|
-
check_heidi_root
|
57
|
+
# remove build and cache dir, expose logs directly
|
58
|
+
puts "removing build dir"
|
59
|
+
shell.rm %W(-r projects/#{for_a}/build)
|
60
|
+
puts "removing cache (preserving project config)"
|
61
|
+
shell.cp %W(-pr projects/#{for_a}/cached/.git/config projects/#{for_a})
|
62
|
+
shell.rm %W(-r projects/#{for_a}/cached)
|
63
|
+
puts "exposing builds"
|
64
|
+
shell.mv %W(projects/#{for_a}/logs/* projects/#{for_a}/)
|
65
|
+
shell.rm %W(-r projects/#{for_a}/logs)
|
62
66
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
+
when "integrate"
|
68
|
+
heidi = Heidi.new
|
69
|
+
heidi.projects.each do |project|
|
70
|
+
next if !for_a.nil? && project.name != for_a
|
71
|
+
project.fetch && project.integrate
|
72
|
+
end
|
67
73
|
|
68
|
-
|
69
|
-
;;
|
70
|
-
esac
|
74
|
+
end
|
data/bin/heidi_web
CHANGED
@@ -2,11 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# hartog/20120131: Heidi, the CI mistress
|
4
4
|
|
5
|
-
require 'sinatra'
|
6
|
-
require 'heidi'
|
7
|
-
require 'heidi/web'
|
8
5
|
|
9
|
-
|
6
|
+
require 'heidi/web'
|
7
|
+
Heidi::Web.start
|
10
8
|
|
11
|
-
# modular setup with all the freebees of a non modular setup.
|
12
|
-
include Heidi::Web::Routes
|
data/heidi.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "heidi"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Hartog C. de Mik"]
|
12
|
-
s.date = "2012-02-
|
12
|
+
s.date = "2012-02-06"
|
13
13
|
s.description = "CI-Joe alike CI system called Heidi."
|
14
14
|
s.email = "hartog@organisedminds.com"
|
15
15
|
s.executables = ["heidi", "heidi_console", "heidi_cron", "heidi_web"]
|
@@ -40,9 +40,12 @@ Gem::Specification.new do |s|
|
|
40
40
|
"lib/heidi/project.rb",
|
41
41
|
"lib/heidi/tester.rb",
|
42
42
|
"lib/heidi/web.rb",
|
43
|
-
"lib/heidi/web/
|
44
|
-
"lib/heidi/web/
|
45
|
-
"lib/heidi/web/
|
43
|
+
"lib/heidi/web/public/css/screen.css",
|
44
|
+
"lib/heidi/web/public/images/heidi.jpeg",
|
45
|
+
"lib/heidi/web/views/build.erb",
|
46
|
+
"lib/heidi/web/views/home.erb",
|
47
|
+
"lib/heidi/web/views/layout.erb",
|
48
|
+
"lib/heidi/web/views/project.erb",
|
46
49
|
"spec/heidi/build_spec.rb",
|
47
50
|
"spec/heidi/builder_spec.rb",
|
48
51
|
"spec/heidi/git_spec.rb",
|
@@ -66,6 +69,7 @@ Gem::Specification.new do |s|
|
|
66
69
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
67
70
|
s.add_runtime_dependency(%q<thin>, [">= 0"])
|
68
71
|
s.add_runtime_dependency(%q<sinatra>, [">= 0"])
|
72
|
+
s.add_runtime_dependency(%q<sinatra-assetpack>, [">= 0"])
|
69
73
|
s.add_runtime_dependency(%q<simple_shell>, [">= 0"])
|
70
74
|
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
71
75
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
@@ -75,6 +79,7 @@ Gem::Specification.new do |s|
|
|
75
79
|
else
|
76
80
|
s.add_dependency(%q<thin>, [">= 0"])
|
77
81
|
s.add_dependency(%q<sinatra>, [">= 0"])
|
82
|
+
s.add_dependency(%q<sinatra-assetpack>, [">= 0"])
|
78
83
|
s.add_dependency(%q<simple_shell>, [">= 0"])
|
79
84
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
80
85
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
@@ -85,6 +90,7 @@ Gem::Specification.new do |s|
|
|
85
90
|
else
|
86
91
|
s.add_dependency(%q<thin>, [">= 0"])
|
87
92
|
s.add_dependency(%q<sinatra>, [">= 0"])
|
93
|
+
s.add_dependency(%q<sinatra-assetpack>, [">= 0"])
|
88
94
|
s.add_dependency(%q<simple_shell>, [">= 0"])
|
89
95
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
90
96
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
data/lib/heidi/build.rb
CHANGED
@@ -8,40 +8,46 @@ class Heidi
|
|
8
8
|
# A build is tied to a commit
|
9
9
|
#
|
10
10
|
class Build
|
11
|
-
attr_reader :project, :commit, :root, :
|
11
|
+
attr_reader :project, :commit, :root, :log_root, :build_root, :shell,
|
12
|
+
:hooks, :logs
|
12
13
|
|
13
14
|
def initialize(project, commit=project.commit)
|
14
15
|
@project = project
|
15
16
|
@commit = commit
|
16
|
-
|
17
|
+
|
18
|
+
@root = File.join(project.root, "logs", commit)
|
19
|
+
@log_root = File.join(@root, "logs")
|
20
|
+
@build_root = File.join(@root, "build")
|
17
21
|
|
18
22
|
if !File.exists? @root
|
19
23
|
SimpleShell.new(project.root).mkdir %W(-p #{@root})
|
20
24
|
end
|
21
|
-
|
22
25
|
@shell = SimpleShell.new(@root)
|
26
|
+
|
27
|
+
@shell.mkdir %W(-p #{@log_root}) unless File.exists?(@log_root)
|
28
|
+
@logs = Logs.new(@log_root)
|
23
29
|
end
|
24
30
|
|
25
31
|
def load_hooks
|
26
32
|
log :info, "Loading hooks"
|
27
33
|
@hooks = {
|
28
|
-
:build
|
29
|
-
:tests
|
30
|
-
:before
|
31
|
-
:
|
32
|
-
:
|
34
|
+
:build => [],
|
35
|
+
:tests => [],
|
36
|
+
:before => [],
|
37
|
+
:success => [],
|
38
|
+
:failure => [],
|
33
39
|
}
|
34
40
|
|
35
41
|
@hooks.keys.each do |key|
|
36
42
|
log :debug, "Loading #{key} hooks"
|
37
43
|
|
38
|
-
Dir[File.join(project.root, "hooks", key.to_s, "*")].each do |hook|
|
44
|
+
Dir[File.join(project.root, "hooks", key.to_s, "*")].sort.each do |hook|
|
39
45
|
next if File.directory? hook
|
40
46
|
next unless File.executable? hook
|
41
47
|
|
42
48
|
log :debug, "Loaded hook: #{hook}"
|
43
49
|
|
44
|
-
@hooks[key] << Heidi::Hook.new(self
|
50
|
+
@hooks[key] << Heidi::Hook.new(self, hook)
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
@@ -49,13 +55,26 @@ class Heidi
|
|
49
55
|
end
|
50
56
|
|
51
57
|
def clean
|
52
|
-
|
58
|
+
1.downto(0) do |i|
|
59
|
+
if File.exists? "#{@log_root}.#{i}"
|
60
|
+
if i - 1 < 0
|
61
|
+
shell.mv %W(#{@log_root}.#{i} #{@log_root}.#{i+1})
|
62
|
+
else
|
63
|
+
shell.rm %W(-rf #{@log_root}.#{i})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if File.exists? "#{@log_root}"
|
69
|
+
shell.mv %W(#{@log_root} #{@log_root}.0)
|
70
|
+
end
|
71
|
+
|
72
|
+
%w(build/ SUCCESS FAILURE).each do |inode|
|
53
73
|
shell.rm("-r", "-f", inode) if File.exists? File.join(@root, inode)
|
54
74
|
end
|
55
|
-
end
|
56
75
|
|
57
|
-
|
58
|
-
|
76
|
+
# re-instate the logs
|
77
|
+
@shell.mkdir %W(-p #{@log_root})
|
59
78
|
end
|
60
79
|
|
61
80
|
def log(type, msg)
|
@@ -66,12 +85,7 @@ class Heidi
|
|
66
85
|
"heidi.#{type}"
|
67
86
|
end
|
68
87
|
|
69
|
-
|
70
|
-
File.join(@root, name),
|
71
|
-
File::CREAT|File::WRONLY|File::APPEND
|
72
|
-
) do |f|
|
73
|
-
f.puts "%s\t%s" % [ Time.now.strftime("%c"), msg ]
|
74
|
-
end
|
88
|
+
logs[name].write(msg)
|
75
89
|
end
|
76
90
|
|
77
91
|
def lock_file
|
@@ -134,14 +148,56 @@ class Heidi
|
|
134
148
|
"DNF"
|
135
149
|
end
|
136
150
|
|
137
|
-
def logs(what)
|
138
|
-
File.read(File.join(@root, what))
|
139
|
-
rescue
|
140
|
-
""
|
141
|
-
end
|
142
|
-
|
143
151
|
def create_tar_ball
|
144
152
|
# TODO
|
145
153
|
end
|
154
|
+
|
155
|
+
class Logs
|
156
|
+
def initialize(log_root)
|
157
|
+
@log_root = log_root
|
158
|
+
@logs = []
|
159
|
+
|
160
|
+
Dir[File.join(@log_root, "*")].each do |file|
|
161
|
+
@logs << Log.new(file)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def [](key)
|
166
|
+
log = @logs.select { |log| log.file_name == "#{key}" }.first
|
167
|
+
if log.nil?
|
168
|
+
@logs << ( log = Log.new( File.join(@log_root, "#{key}") ) )
|
169
|
+
end
|
170
|
+
|
171
|
+
return log
|
172
|
+
end
|
173
|
+
|
174
|
+
def each(&block)
|
175
|
+
@logs.each(&block)
|
176
|
+
end
|
177
|
+
|
178
|
+
class Log
|
179
|
+
attr_reader :file_name, :contents
|
180
|
+
def initialize(file)
|
181
|
+
@file = file
|
182
|
+
@file_name = File.basename(file)
|
183
|
+
@contents = File.read(file) rescue ""
|
184
|
+
end
|
185
|
+
|
186
|
+
def write(msg,fmt=true)
|
187
|
+
File.open(@file, File::CREAT|File::APPEND|File::WRONLY) do |f|
|
188
|
+
if fmt == true
|
189
|
+
f.puts "%s\t%s" % [ Time.now.strftime("%c"), msg ]
|
190
|
+
else
|
191
|
+
f.puts msg
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def raw(msg)
|
197
|
+
write(msg, false)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
146
202
|
end
|
147
|
-
end
|
203
|
+
end
|
data/lib/heidi/builder.rb
CHANGED
@@ -21,12 +21,12 @@ class Heidi
|
|
21
21
|
res = hook.perform(build.build_root)
|
22
22
|
if res.S?.to_i != 0
|
23
23
|
log("--- Build hook #{hook.name} failed ---")
|
24
|
-
log(res.err)
|
24
|
+
log(res.err.empty? ? "no error message given" : res.err)
|
25
25
|
build_failed = true
|
26
26
|
break
|
27
27
|
|
28
28
|
else
|
29
|
-
log(res.out)
|
29
|
+
log(res.out) unless res.out.empty?
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -83,12 +83,7 @@ class Heidi
|
|
83
83
|
|
84
84
|
|
85
85
|
def log(string)
|
86
|
-
|
87
|
-
File.join(project.log_root, "builder.log"),
|
88
|
-
File::CREAT|File::WRONLY|File::APPEND
|
89
|
-
) do |f|
|
90
|
-
f.puts string
|
91
|
-
end
|
86
|
+
build.logs["builder.log"].raw(string)
|
92
87
|
end
|
93
88
|
|
94
89
|
end
|
data/lib/heidi/hook.rb
CHANGED
@@ -2,13 +2,19 @@ require 'simple_shell'
|
|
2
2
|
|
3
3
|
class Heidi
|
4
4
|
class Hook
|
5
|
-
|
6
|
-
|
7
|
-
@
|
5
|
+
attr_reader :build
|
6
|
+
def initialize(build, script)
|
7
|
+
@build = build
|
8
|
+
@script = script
|
8
9
|
end
|
9
10
|
|
10
|
-
def perform(where)
|
11
|
-
|
11
|
+
def perform(where=build.build_root)
|
12
|
+
env = {
|
13
|
+
'HEIDI_LOG_DIR' => build.log_root,
|
14
|
+
'HEIDI_BUILD_DIR' => build.build_root,
|
15
|
+
}
|
16
|
+
|
17
|
+
shell = SimpleShell.new(where, env)
|
12
18
|
res = shell.do @script
|
13
19
|
return res
|
14
20
|
end
|
data/lib/heidi/tester.rb
CHANGED
@@ -24,14 +24,14 @@ class Heidi
|
|
24
24
|
|
25
25
|
if res.S?.to_i != 0
|
26
26
|
log "--- test #{hook.name} failed ---"
|
27
|
-
log res.err
|
27
|
+
log(res.err.empty? ? "No error message given" : res.err)
|
28
28
|
|
29
29
|
@message = "tests failed"
|
30
30
|
tests_failed = true
|
31
31
|
break
|
32
32
|
|
33
33
|
else
|
34
|
-
log res.out
|
34
|
+
log(res.out) unless res.out.empty?
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -39,12 +39,7 @@ class Heidi
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def log(string)
|
42
|
-
|
43
|
-
File.join(build.root, "test.log"),
|
44
|
-
File::CREAT|File::WRONLY|File::APPEND
|
45
|
-
) do |f|
|
46
|
-
f.puts string
|
47
|
-
end
|
42
|
+
build.logs["test.log"].raw(string)
|
48
43
|
end
|
49
44
|
|
50
45
|
|
@@ -0,0 +1,93 @@
|
|
1
|
+
* {
|
2
|
+
margin: 0;
|
3
|
+
padding: 0;
|
4
|
+
}
|
5
|
+
|
6
|
+
html, body {
|
7
|
+
height: 100%;
|
8
|
+
}
|
9
|
+
|
10
|
+
body {
|
11
|
+
background-color: white;
|
12
|
+
font: 13.34px helvetica, arial, clean, sans-serif;
|
13
|
+
*font-size: small;
|
14
|
+
text-align: center;
|
15
|
+
}
|
16
|
+
|
17
|
+
h1, h2, h3 {
|
18
|
+
margin-bottom: 1em;
|
19
|
+
}
|
20
|
+
|
21
|
+
h1 a {
|
22
|
+
text-decoration: none;
|
23
|
+
color: #000;
|
24
|
+
}
|
25
|
+
|
26
|
+
.failed, .color31 {
|
27
|
+
color: red !important;
|
28
|
+
}
|
29
|
+
|
30
|
+
.passed, .worked, .color32 {
|
31
|
+
color: green !important;
|
32
|
+
}
|
33
|
+
|
34
|
+
.errored, .color33 {
|
35
|
+
color: yellow !important;
|
36
|
+
}
|
37
|
+
|
38
|
+
p {
|
39
|
+
margin: 1em 0;
|
40
|
+
}
|
41
|
+
|
42
|
+
a {
|
43
|
+
color: #00a;
|
44
|
+
}
|
45
|
+
|
46
|
+
a:hover {
|
47
|
+
color: black;
|
48
|
+
}
|
49
|
+
|
50
|
+
a:visited {
|
51
|
+
color: #a0a;
|
52
|
+
}
|
53
|
+
|
54
|
+
table {
|
55
|
+
font-size: inherit;
|
56
|
+
font: 100%;
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
.container {
|
61
|
+
width: 80%;
|
62
|
+
text-align: justify;
|
63
|
+
margin: 2em auto;
|
64
|
+
}
|
65
|
+
|
66
|
+
pre.terminal {
|
67
|
+
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
|
68
|
+
border: 1px solid black;
|
69
|
+
background-color: #333;
|
70
|
+
color: white;
|
71
|
+
padding: 5px;
|
72
|
+
overflow: auto;
|
73
|
+
word-wrap: break-word;
|
74
|
+
margin-bottom: 1em;
|
75
|
+
clear: both;
|
76
|
+
}
|
77
|
+
|
78
|
+
ul {
|
79
|
+
margin-left: 3em;
|
80
|
+
}
|
81
|
+
|
82
|
+
.top {
|
83
|
+
float: left;
|
84
|
+
padding-left: 2em;
|
85
|
+
}
|
86
|
+
|
87
|
+
.log {
|
88
|
+
float: left;
|
89
|
+
}
|
90
|
+
|
91
|
+
.clear {
|
92
|
+
clear: both;
|
93
|
+
}
|
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<h1><%= project.name %></h1>
|
2
|
+
|
3
|
+
<a href="/projects/<%= project.name %>"><< back</a>
|
4
|
+
<br /><br />
|
5
|
+
|
6
|
+
<h2 class="<%= build.status %>"><%= build.commit %></h2>
|
7
|
+
|
8
|
+
| <% build.logs.each do |log| %>
|
9
|
+
<a href="#<%= log.file_name %>"><%= log.file_name %></a> |
|
10
|
+
<% end %>
|
11
|
+
<br class="clear" />
|
12
|
+
<br />
|
13
|
+
<br />
|
14
|
+
|
15
|
+
<% build.logs.each do |log| %>
|
16
|
+
<h3 class="log"><%= log.file_name %></h3>
|
17
|
+
<a name="<%= log.file_name %>" href="#top" class="top">top</a>
|
18
|
+
<pre class="terminal"><%= ansi_color_codes(log.contents) %></pre>
|
19
|
+
<% end %>
|
20
|
+
<br /><br />
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<link rel="stylesheet" media="screen" href="/css/screen.css" />
|
5
|
+
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
|
6
|
+
<title>Heidi!</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<div class="container">
|
10
|
+
<%= yield %>
|
11
|
+
</div>
|
12
|
+
</body>
|
13
|
+
</html>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<h1><%= project.name %></h1>
|
2
|
+
|
3
|
+
<h2 class="<%= project.build_status %>"><%= project.build_status %></h2>
|
4
|
+
|
5
|
+
<h2>Build history</h2>
|
6
|
+
|
7
|
+
<ul>
|
8
|
+
<% project.builds.each do |build| %>
|
9
|
+
<li class="<%= build.status %>"><a href='/projects/<%= project.name %>/build/<%= build.commit %>'><%= build.commit %></a> - <%= build.status %></li>
|
10
|
+
<% end %>
|
11
|
+
</ul>
|
data/lib/heidi/web.rb
CHANGED
@@ -1,8 +1,75 @@
|
|
1
|
-
require 'sinatra'
|
2
|
-
require 'heidi
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'heidi'
|
3
|
+
require 'simple_shell'
|
3
4
|
|
4
5
|
class Heidi
|
5
|
-
|
6
|
-
|
6
|
+
class Web < Sinatra::Base
|
7
|
+
|
8
|
+
def self.start(host="0.0.0.0", port="4567", project_path=Dir.pwd)
|
9
|
+
@project_path = project_path
|
10
|
+
Heidi::Web.run! :host => host, :port => port
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.project_path
|
14
|
+
@project_path
|
15
|
+
end
|
16
|
+
|
17
|
+
before {
|
18
|
+
@heidi = Heidi.new(self.class.project_path)
|
19
|
+
}
|
20
|
+
|
21
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
22
|
+
$stderr.puts dir
|
23
|
+
|
24
|
+
set :sessions, true
|
25
|
+
|
26
|
+
set :views, "#{dir}/web/views"
|
27
|
+
set :public_folder, "#{dir}/web/public"
|
28
|
+
set :root, dir
|
29
|
+
|
30
|
+
get '/' do
|
31
|
+
redirect '/projects', 302
|
32
|
+
end
|
33
|
+
|
34
|
+
get '/projects' do
|
35
|
+
erb(:home, { :locals => { :projects => @heidi.projects }})
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/projects/:name' do
|
39
|
+
project = @heidi[params[:name]]
|
40
|
+
if project.nil?
|
41
|
+
return "no project by that name: #{params[:name]}"
|
42
|
+
end
|
43
|
+
|
44
|
+
erb(:project, { :locals => { :project => project }})
|
45
|
+
end
|
46
|
+
|
47
|
+
get '/projects/:name/build/:commit' do
|
48
|
+
project = @heidi[params[:name]]
|
49
|
+
if project.nil?
|
50
|
+
return "no project by that name: #{params[:name]}"
|
51
|
+
end
|
52
|
+
|
53
|
+
# load build of project
|
54
|
+
build = Heidi::Build.new(project, params[:commit])
|
55
|
+
erb(:build, { :locals => { :build => build, :project => project }})
|
56
|
+
end
|
57
|
+
|
58
|
+
put '/projects/:name/build' do
|
59
|
+
project = $heidi[params[:name]]
|
60
|
+
if project.nil?
|
61
|
+
return "no project by that name: #{params[:name]}"
|
62
|
+
end
|
63
|
+
|
64
|
+
project.integrate
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
helpers do
|
69
|
+
def ansi_color_codes(string)
|
70
|
+
string.gsub("\e[0m", '</span>').
|
71
|
+
gsub(/\e\[(\d+)m/, "<span class=\"color\\1\">")
|
72
|
+
end
|
73
|
+
end
|
7
74
|
end
|
8
75
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heidi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-06 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thin
|
16
|
-
requirement: &
|
16
|
+
requirement: &78955270 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *78955270
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: sinatra
|
27
|
-
requirement: &
|
27
|
+
requirement: &78955000 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,21 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *78955000
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sinatra-assetpack
|
38
|
+
requirement: &78954750 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *78954750
|
36
47
|
- !ruby/object:Gem::Dependency
|
37
48
|
name: simple_shell
|
38
|
-
requirement: &
|
49
|
+
requirement: &78954490 !ruby/object:Gem::Requirement
|
39
50
|
none: false
|
40
51
|
requirements:
|
41
52
|
- - ! '>='
|
@@ -43,10 +54,10 @@ dependencies:
|
|
43
54
|
version: '0'
|
44
55
|
type: :runtime
|
45
56
|
prerelease: false
|
46
|
-
version_requirements: *
|
57
|
+
version_requirements: *78954490
|
47
58
|
- !ruby/object:Gem::Dependency
|
48
59
|
name: rspec
|
49
|
-
requirement: &
|
60
|
+
requirement: &78954240 !ruby/object:Gem::Requirement
|
50
61
|
none: false
|
51
62
|
requirements:
|
52
63
|
- - ~>
|
@@ -54,10 +65,10 @@ dependencies:
|
|
54
65
|
version: 2.8.0
|
55
66
|
type: :development
|
56
67
|
prerelease: false
|
57
|
-
version_requirements: *
|
68
|
+
version_requirements: *78954240
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: rdoc
|
60
|
-
requirement: &
|
71
|
+
requirement: &78950220 !ruby/object:Gem::Requirement
|
61
72
|
none: false
|
62
73
|
requirements:
|
63
74
|
- - ~>
|
@@ -65,10 +76,10 @@ dependencies:
|
|
65
76
|
version: '3.12'
|
66
77
|
type: :development
|
67
78
|
prerelease: false
|
68
|
-
version_requirements: *
|
79
|
+
version_requirements: *78950220
|
69
80
|
- !ruby/object:Gem::Dependency
|
70
81
|
name: bundler
|
71
|
-
requirement: &
|
82
|
+
requirement: &78949910 !ruby/object:Gem::Requirement
|
72
83
|
none: false
|
73
84
|
requirements:
|
74
85
|
- - ~>
|
@@ -76,10 +87,10 @@ dependencies:
|
|
76
87
|
version: 1.0.0
|
77
88
|
type: :development
|
78
89
|
prerelease: false
|
79
|
-
version_requirements: *
|
90
|
+
version_requirements: *78949910
|
80
91
|
- !ruby/object:Gem::Dependency
|
81
92
|
name: jeweler
|
82
|
-
requirement: &
|
93
|
+
requirement: &78949650 !ruby/object:Gem::Requirement
|
83
94
|
none: false
|
84
95
|
requirements:
|
85
96
|
- - ~>
|
@@ -87,10 +98,10 @@ dependencies:
|
|
87
98
|
version: 1.8.3
|
88
99
|
type: :development
|
89
100
|
prerelease: false
|
90
|
-
version_requirements: *
|
101
|
+
version_requirements: *78949650
|
91
102
|
- !ruby/object:Gem::Dependency
|
92
103
|
name: rcov
|
93
|
-
requirement: &
|
104
|
+
requirement: &78949400 !ruby/object:Gem::Requirement
|
94
105
|
none: false
|
95
106
|
requirements:
|
96
107
|
- - ! '>='
|
@@ -98,7 +109,7 @@ dependencies:
|
|
98
109
|
version: '0'
|
99
110
|
type: :development
|
100
111
|
prerelease: false
|
101
|
-
version_requirements: *
|
112
|
+
version_requirements: *78949400
|
102
113
|
description: CI-Joe alike CI system called Heidi.
|
103
114
|
email: hartog@organisedminds.com
|
104
115
|
executables:
|
@@ -133,9 +144,12 @@ files:
|
|
133
144
|
- lib/heidi/project.rb
|
134
145
|
- lib/heidi/tester.rb
|
135
146
|
- lib/heidi/web.rb
|
136
|
-
- lib/heidi/web/
|
137
|
-
- lib/heidi/web/
|
138
|
-
- lib/heidi/web/
|
147
|
+
- lib/heidi/web/public/css/screen.css
|
148
|
+
- lib/heidi/web/public/images/heidi.jpeg
|
149
|
+
- lib/heidi/web/views/build.erb
|
150
|
+
- lib/heidi/web/views/home.erb
|
151
|
+
- lib/heidi/web/views/layout.erb
|
152
|
+
- lib/heidi/web/views/project.erb
|
139
153
|
- spec/heidi/build_spec.rb
|
140
154
|
- spec/heidi/builder_spec.rb
|
141
155
|
- spec/heidi/git_spec.rb
|
@@ -161,7 +175,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
161
175
|
version: '0'
|
162
176
|
segments:
|
163
177
|
- 0
|
164
|
-
hash:
|
178
|
+
hash: 785079379
|
165
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
180
|
none: false
|
167
181
|
requirements:
|
@@ -1,61 +0,0 @@
|
|
1
|
-
class Heidi; module Web; module Routes
|
2
|
-
|
3
|
-
module Projects
|
4
|
-
get '/projects' do
|
5
|
-
output = ""
|
6
|
-
$heidi.projects.each do |project|
|
7
|
-
output += "<a href='/projects/#{project.name}'>#{project.name}</a><br />"
|
8
|
-
end
|
9
|
-
|
10
|
-
output
|
11
|
-
end
|
12
|
-
|
13
|
-
get '/projects/:name' do
|
14
|
-
project = $heidi[params[:name]]
|
15
|
-
if project.nil?
|
16
|
-
return "no project by that name: #{params[:name]}"
|
17
|
-
end
|
18
|
-
|
19
|
-
output = "<h1>#{project.name}</h1>"
|
20
|
-
output += "Build status: #{project.build_status}"
|
21
|
-
output += "<br /><br /><h2>Build history</h2>"
|
22
|
-
project.builds.each do |build|
|
23
|
-
output += %Q{<a href="/projects/#{project.name}/build/#{build.commit}">#{build.commit}</a> - #{build.status}<br />}
|
24
|
-
end
|
25
|
-
|
26
|
-
output
|
27
|
-
end
|
28
|
-
|
29
|
-
get '/projects/:name/build/:commit' do
|
30
|
-
project = $heidi[params[:name]]
|
31
|
-
if project.nil?
|
32
|
-
return "no project by that name: #{params[:name]}"
|
33
|
-
end
|
34
|
-
|
35
|
-
# load build of project
|
36
|
-
build = Heidi::Build.new(project, params[:commit])
|
37
|
-
output = "<h1>#{project.name}</h1>"
|
38
|
-
output += "<h2>Build: #{build.commit} - #{build.status}<h2>"
|
39
|
-
|
40
|
-
%w(heidi.info heidi.errors build.log test.log).each do |log_file|
|
41
|
-
log = build.logs(log_file)
|
42
|
-
if (!log.nil? and !log.empty?)
|
43
|
-
output += "<h3>#{log_file}</h3>"
|
44
|
-
output += "<pre>#{log}</pre>"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
output
|
49
|
-
end
|
50
|
-
|
51
|
-
put '/projects/:name/build' do
|
52
|
-
project = $heidi[params[:name]]
|
53
|
-
if project.nil?
|
54
|
-
return "no project by that name: #{params[:name]}"
|
55
|
-
end
|
56
|
-
|
57
|
-
project.integrate
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
end; end; end
|
data/lib/heidi/web/routes.rb
DELETED