cijoe 0.1.1 → 0.1.2
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.
- data/README.markdown +10 -10
- data/Rakefile +5 -1
- data/lib/cijoe/public/screen.css +212 -0
- data/lib/cijoe/server.rb +15 -20
- data/lib/cijoe/version.rb +1 -1
- data/lib/cijoe/views/template.erb +5 -216
- metadata +3 -2
data/README.markdown
CHANGED
@@ -8,26 +8,26 @@ server that'll run your tests on demand and report their pass/fail status.
|
|
8
8
|
Because knowing is half the battle.
|
9
9
|
|
10
10
|

|
11
|
-
|
11
|
+
|
12
12
|
Quickstart
|
13
13
|
----------
|
14
14
|
|
15
15
|
Rip:
|
16
|
-
|
16
|
+
|
17
17
|
$ rip install git://github.com/defunkt/cijoe.git
|
18
18
|
$ git clone git://github.com/you/yourrepo.git
|
19
19
|
$ cijoe yourrepo
|
20
20
|
|
21
21
|
Gemcutter:
|
22
|
-
|
22
|
+
|
23
23
|
$ gem install cijoe
|
24
24
|
$ git clone git://github.com/you/yourrepo.git
|
25
25
|
$ cijoe yourrepo
|
26
26
|
|
27
|
-
Boom. Navigate to http://localhost:4567 to see Joe in action.
|
27
|
+
Boom. Navigate to http://localhost:4567 to see Joe in action.
|
28
28
|
Check `cijoe -h` for other options.
|
29
29
|
|
30
|
-
Basically you need to run `cijoe` and hand it the path to a git
|
30
|
+
Basically you need to run `cijoe` and hand it the path to a git
|
31
31
|
repo. Make sure this isn't a shared repo: Joe needs to own it.
|
32
32
|
|
33
33
|
Joe looks for various git config settings in the repo you hand it. For
|
@@ -35,14 +35,14 @@ instance, you can tell Joe what command to run by setting
|
|
35
35
|
`cijoe.runner`:
|
36
36
|
|
37
37
|
$ git config --add cijoe.runner "rake -s test:units"
|
38
|
-
|
38
|
+
|
39
39
|
Joe doesn't care about Ruby, Python, or whatever. As long as the
|
40
40
|
runner returns a non-zero exit status on fail and a zero on success,
|
41
41
|
everyone is happy.
|
42
42
|
|
43
43
|
Need to do some massaging of your repo before the tests run, like
|
44
44
|
maybe swapping in a new database.yml? No problem - Joe will try to
|
45
|
-
run `.git/hooks/after-reset` if it exists before each build phase.
|
45
|
+
run `.git/hooks/after-reset` if it exists before each build phase.
|
46
46
|
Do it in there. Just make sure it's executable.
|
47
47
|
|
48
48
|
Want to notify IRC or email on test pass or failure? Joe will run
|
@@ -86,10 +86,10 @@ Or do it the old fashion way:
|
|
86
86
|
Multiple Projects
|
87
87
|
-----------------
|
88
88
|
|
89
|
-
Want CI for multiple projects? Just start multiple instances of Joe!
|
89
|
+
Want CI for multiple projects? Just start multiple instances of Joe!
|
90
90
|
He can run on any port - try `cijoe -h` for more options.
|
91
91
|
|
92
|
-
Thanks to Dean Strelau you can also run multiple instances of CI Joe using
|
92
|
+
Thanks to Dean Strelau you can also run multiple instances of CI Joe using
|
93
93
|
a single `config.ru` file.
|
94
94
|
|
95
95
|
In particular, it is possible to mount Server at a subpath:
|
@@ -124,7 +124,7 @@ Any POST to Joe will trigger a build. If you are hiding Joe behind
|
|
124
124
|
HTTP auth, that's okay - GitHub knows how to authenticate properly.
|
125
125
|
|
126
126
|

|
127
|
-
|
127
|
+
|
128
128
|
You can find the Post-Receive option under the 'Service Hooks' subtab
|
129
129
|
of your project's "Admin" tab.
|
130
130
|
|
data/Rakefile
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
desc "Build a gem"
|
2
|
+
task :gem => [ :gemspec, :build ]
|
3
|
+
|
1
4
|
begin
|
2
5
|
require 'jeweler'
|
3
6
|
|
@@ -17,5 +20,6 @@ begin
|
|
17
20
|
gemspec.version = CIJoe::Version.to_s
|
18
21
|
end
|
19
22
|
rescue LoadError
|
20
|
-
puts "Jeweler not available.
|
23
|
+
puts "Jeweler not available."
|
24
|
+
puts "Install it with: gem install jeweler"
|
21
25
|
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
/*****************************************************************************/
|
2
|
+
/*
|
3
|
+
/* Common
|
4
|
+
/*
|
5
|
+
/*****************************************************************************/
|
6
|
+
|
7
|
+
/* Global Reset */
|
8
|
+
|
9
|
+
* {
|
10
|
+
margin: 0;
|
11
|
+
padding: 0;
|
12
|
+
}
|
13
|
+
|
14
|
+
html, body {
|
15
|
+
height: 100%;
|
16
|
+
}
|
17
|
+
|
18
|
+
body {
|
19
|
+
background-color: white;
|
20
|
+
font: 13.34px helvetica, arial, clean, sans-serif;
|
21
|
+
*font-size: small;
|
22
|
+
text-align: center;
|
23
|
+
}
|
24
|
+
|
25
|
+
h1, h2, h3, h4, h5, h6 {
|
26
|
+
font-size: 100%;
|
27
|
+
}
|
28
|
+
|
29
|
+
h1 {
|
30
|
+
margin-bottom: 1em;
|
31
|
+
}
|
32
|
+
|
33
|
+
h1 a {
|
34
|
+
text-decoration: none;
|
35
|
+
color: #000;
|
36
|
+
}
|
37
|
+
|
38
|
+
.failed, .color31 {
|
39
|
+
color: red !important;
|
40
|
+
}
|
41
|
+
|
42
|
+
.worked, .color32 {
|
43
|
+
color: green !important;
|
44
|
+
}
|
45
|
+
|
46
|
+
.errored, .color33 {
|
47
|
+
color: yellow !important;
|
48
|
+
}
|
49
|
+
|
50
|
+
p {
|
51
|
+
margin: 1em 0;
|
52
|
+
}
|
53
|
+
|
54
|
+
a {
|
55
|
+
color: #00a;
|
56
|
+
}
|
57
|
+
|
58
|
+
a:hover {
|
59
|
+
color: black;
|
60
|
+
}
|
61
|
+
|
62
|
+
a:visited {
|
63
|
+
color: #a0a;
|
64
|
+
}
|
65
|
+
|
66
|
+
table {
|
67
|
+
font-size: inherit;
|
68
|
+
font: 100%;
|
69
|
+
}
|
70
|
+
|
71
|
+
/*****************************************************************************/
|
72
|
+
/*
|
73
|
+
/* Home
|
74
|
+
/*
|
75
|
+
/*****************************************************************************/
|
76
|
+
|
77
|
+
ul.posts {
|
78
|
+
list-style-type: none;
|
79
|
+
margin-bottom: 2em;
|
80
|
+
}
|
81
|
+
|
82
|
+
ul.posts li {
|
83
|
+
line-height: 1.75em;
|
84
|
+
}
|
85
|
+
|
86
|
+
ul.posts .date {
|
87
|
+
color: #aaa;
|
88
|
+
font-family: Monaco, "Courier New", monospace;
|
89
|
+
font-size: 80%;
|
90
|
+
}
|
91
|
+
|
92
|
+
/*****************************************************************************/
|
93
|
+
/*
|
94
|
+
/* Site
|
95
|
+
/*
|
96
|
+
/*****************************************************************************/
|
97
|
+
|
98
|
+
.site {
|
99
|
+
font-size: 110%;
|
100
|
+
text-align: justify;
|
101
|
+
width: 40em;
|
102
|
+
margin: 3em auto 2em auto;
|
103
|
+
line-height: 1.5em;
|
104
|
+
}
|
105
|
+
|
106
|
+
.title {
|
107
|
+
color: #a00;
|
108
|
+
font-weight: bold;
|
109
|
+
margin-bottom: 2em;
|
110
|
+
}
|
111
|
+
|
112
|
+
.site .title a {
|
113
|
+
color: #a00;
|
114
|
+
text-decoration: none;
|
115
|
+
}
|
116
|
+
|
117
|
+
.site .title a:hover {
|
118
|
+
color: black;
|
119
|
+
}
|
120
|
+
|
121
|
+
.site .title .extra {
|
122
|
+
color: #aaa;
|
123
|
+
text-decoration: none;
|
124
|
+
margin-left: 1em;
|
125
|
+
font-size: 0.9em;
|
126
|
+
}
|
127
|
+
|
128
|
+
.site .title a.extra:hover {
|
129
|
+
color: black;
|
130
|
+
}
|
131
|
+
|
132
|
+
.site .meta {
|
133
|
+
color: #aaa;
|
134
|
+
}
|
135
|
+
|
136
|
+
.site .footer {
|
137
|
+
font-size: 80%;
|
138
|
+
color: #666;
|
139
|
+
border-top: 4px solid #eee;
|
140
|
+
margin-top: 2em;
|
141
|
+
overflow: hidden;
|
142
|
+
}
|
143
|
+
|
144
|
+
.site .footer .contact {
|
145
|
+
float: left;
|
146
|
+
margin-right: 3em;
|
147
|
+
}
|
148
|
+
|
149
|
+
.site .footer .contact a {
|
150
|
+
color: #8085C1;
|
151
|
+
}
|
152
|
+
|
153
|
+
.site .footer .rss {
|
154
|
+
margin-top: 1.1em;
|
155
|
+
margin-right: -.2em;
|
156
|
+
float: right;
|
157
|
+
}
|
158
|
+
|
159
|
+
.site .footer .rss img {
|
160
|
+
border: 0;
|
161
|
+
}
|
162
|
+
|
163
|
+
/*****************************************************************************/
|
164
|
+
/*
|
165
|
+
/* Posts
|
166
|
+
/*
|
167
|
+
/*****************************************************************************/
|
168
|
+
|
169
|
+
#post {
|
170
|
+
|
171
|
+
}
|
172
|
+
|
173
|
+
/* standard */
|
174
|
+
|
175
|
+
#post pre {
|
176
|
+
border: 1px solid #ddd;
|
177
|
+
background-color: #eef;
|
178
|
+
padding: 0 .4em;
|
179
|
+
}
|
180
|
+
|
181
|
+
#post ul,
|
182
|
+
#post ol {
|
183
|
+
margin-left: 1.25em;
|
184
|
+
}
|
185
|
+
|
186
|
+
#post code {
|
187
|
+
border: 1px solid #ddd;
|
188
|
+
background-color: #eef;
|
189
|
+
font-size: 95%;
|
190
|
+
padding: 0 .2em;
|
191
|
+
}
|
192
|
+
|
193
|
+
#post pre code {
|
194
|
+
border: none;
|
195
|
+
}
|
196
|
+
|
197
|
+
/* terminal */
|
198
|
+
|
199
|
+
pre.terminal {
|
200
|
+
border: 1px solid black;
|
201
|
+
background-color: #333;
|
202
|
+
color: white;
|
203
|
+
padding: 5px;
|
204
|
+
overflow: auto;
|
205
|
+
word-wrap: break-word;
|
206
|
+
}
|
207
|
+
|
208
|
+
pre.terminal code {
|
209
|
+
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
|
210
|
+
background-color: #333;
|
211
|
+
}
|
212
|
+
|
data/lib/cijoe/server.rb
CHANGED
@@ -21,33 +21,39 @@ class CIJoe
|
|
21
21
|
redirect request.path
|
22
22
|
end
|
23
23
|
|
24
|
+
user, pass = Config.cijoe.user.to_s, Config.cijoe.pass.to_s
|
25
|
+
if user != '' && pass != ''
|
26
|
+
use Rack::Auth::Basic do |username, password|
|
27
|
+
[ username, password ] == [ user, pass ]
|
28
|
+
end
|
29
|
+
puts "Using HTTP basic auth"
|
30
|
+
end
|
24
31
|
|
25
32
|
helpers do
|
26
33
|
include Rack::Utils
|
27
34
|
alias_method :h, :escape_html
|
28
35
|
|
29
36
|
# thanks integrity!
|
30
|
-
def
|
37
|
+
def ansi_color_codes(string)
|
31
38
|
string.gsub("\e[0m", '</span>').
|
32
|
-
gsub(
|
33
|
-
gsub("\e[32m", '<span class="color32">').
|
34
|
-
gsub("\e[33m", '<span class="color33">').
|
35
|
-
gsub("\e[34m", '<span class="color34">').
|
36
|
-
gsub("\e[35m", '<span class="color35">').
|
37
|
-
gsub("\e[36m", '<span class="color36">').
|
38
|
-
gsub("\e[37m", '<span class="color37">')
|
39
|
+
gsub(/\e\[(\d+)m/, "<span class=\"color\\1\">")
|
39
40
|
end
|
40
41
|
|
41
42
|
def pretty_time(time)
|
42
43
|
time.strftime("%Y-%m-%d %H:%M")
|
43
44
|
end
|
45
|
+
|
46
|
+
def cijoe_root
|
47
|
+
root = request.path
|
48
|
+
root = "" if root == "/"
|
49
|
+
root
|
50
|
+
end
|
44
51
|
end
|
45
52
|
|
46
53
|
def initialize(*args)
|
47
54
|
super
|
48
55
|
check_project
|
49
56
|
@joe = CIJoe.new(options.project_path)
|
50
|
-
setup_auth
|
51
57
|
|
52
58
|
CIJoe::Campfire.activate
|
53
59
|
end
|
@@ -64,16 +70,5 @@ class CIJoe
|
|
64
70
|
abort " $ cijoe project"
|
65
71
|
end
|
66
72
|
end
|
67
|
-
|
68
|
-
def setup_auth
|
69
|
-
user, pass = Config.cijoe.user.to_s, Config.cijoe.pass.to_s
|
70
|
-
|
71
|
-
if user != '' && pass != ''
|
72
|
-
use Rack::Auth::Basic do |username, password|
|
73
|
-
[ username, password ] == [ user, pass ]
|
74
|
-
end
|
75
|
-
puts "Using HTTP basic auth"
|
76
|
-
end
|
77
|
-
end
|
78
73
|
end
|
79
74
|
end
|
data/lib/cijoe/version.rb
CHANGED
@@ -1,224 +1,13 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<
|
5
|
-
|
6
|
-
/*
|
7
|
-
/* Common
|
8
|
-
/*
|
9
|
-
/*****************************************************************************/
|
10
|
-
|
11
|
-
/* Global Reset */
|
12
|
-
|
13
|
-
* {
|
14
|
-
margin: 0;
|
15
|
-
padding: 0;
|
16
|
-
}
|
17
|
-
|
18
|
-
html, body {
|
19
|
-
height: 100%;
|
20
|
-
}
|
21
|
-
|
22
|
-
body {
|
23
|
-
background-color: white;
|
24
|
-
font: 13.34px helvetica, arial, clean, sans-serif;
|
25
|
-
*font-size: small;
|
26
|
-
text-align: center;
|
27
|
-
}
|
28
|
-
|
29
|
-
h1, h2, h3, h4, h5, h6 {
|
30
|
-
font-size: 100%;
|
31
|
-
}
|
32
|
-
|
33
|
-
h1 {
|
34
|
-
margin-bottom: 1em;
|
35
|
-
}
|
36
|
-
|
37
|
-
h1 a {
|
38
|
-
text-decoration: none;
|
39
|
-
color: #000;
|
40
|
-
}
|
41
|
-
|
42
|
-
.failed, .color31 {
|
43
|
-
color: red !important;
|
44
|
-
}
|
45
|
-
|
46
|
-
.worked, .color32 {
|
47
|
-
color: green !important;
|
48
|
-
}
|
49
|
-
|
50
|
-
.errored, .color33 {
|
51
|
-
color: yellow !important;
|
52
|
-
}
|
53
|
-
|
54
|
-
p {
|
55
|
-
margin: 1em 0;
|
56
|
-
}
|
57
|
-
|
58
|
-
a {
|
59
|
-
color: #00a;
|
60
|
-
}
|
61
|
-
|
62
|
-
a:hover {
|
63
|
-
color: black;
|
64
|
-
}
|
65
|
-
|
66
|
-
a:visited {
|
67
|
-
color: #a0a;
|
68
|
-
}
|
69
|
-
|
70
|
-
table {
|
71
|
-
font-size: inherit;
|
72
|
-
font: 100%;
|
73
|
-
}
|
74
|
-
|
75
|
-
/*****************************************************************************/
|
76
|
-
/*
|
77
|
-
/* Home
|
78
|
-
/*
|
79
|
-
/*****************************************************************************/
|
80
|
-
|
81
|
-
ul.posts {
|
82
|
-
list-style-type: none;
|
83
|
-
margin-bottom: 2em;
|
84
|
-
}
|
85
|
-
|
86
|
-
ul.posts li {
|
87
|
-
line-height: 1.75em;
|
88
|
-
}
|
89
|
-
|
90
|
-
ul.posts .date {
|
91
|
-
color: #aaa;
|
92
|
-
font-family: Monaco, "Courier New", monospace;
|
93
|
-
font-size: 80%;
|
94
|
-
}
|
95
|
-
|
96
|
-
/*****************************************************************************/
|
97
|
-
/*
|
98
|
-
/* Site
|
99
|
-
/*
|
100
|
-
/*****************************************************************************/
|
101
|
-
|
102
|
-
.site {
|
103
|
-
font-size: 110%;
|
104
|
-
text-align: justify;
|
105
|
-
width: 40em;
|
106
|
-
margin: 3em auto 2em auto;
|
107
|
-
line-height: 1.5em;
|
108
|
-
}
|
109
|
-
|
110
|
-
.title {
|
111
|
-
color: #a00;
|
112
|
-
font-weight: bold;
|
113
|
-
margin-bottom: 2em;
|
114
|
-
}
|
115
|
-
|
116
|
-
.site .title a {
|
117
|
-
color: #a00;
|
118
|
-
text-decoration: none;
|
119
|
-
}
|
120
|
-
|
121
|
-
.site .title a:hover {
|
122
|
-
color: black;
|
123
|
-
}
|
124
|
-
|
125
|
-
.site .title .extra {
|
126
|
-
color: #aaa;
|
127
|
-
text-decoration: none;
|
128
|
-
margin-left: 1em;
|
129
|
-
font-size: 0.9em;
|
130
|
-
}
|
131
|
-
|
132
|
-
.site .title a.extra:hover {
|
133
|
-
color: black;
|
134
|
-
}
|
135
|
-
|
136
|
-
.site .meta {
|
137
|
-
color: #aaa;
|
138
|
-
}
|
139
|
-
|
140
|
-
.site .footer {
|
141
|
-
font-size: 80%;
|
142
|
-
color: #666;
|
143
|
-
border-top: 4px solid #eee;
|
144
|
-
margin-top: 2em;
|
145
|
-
overflow: hidden;
|
146
|
-
}
|
147
|
-
|
148
|
-
.site .footer .contact {
|
149
|
-
float: left;
|
150
|
-
margin-right: 3em;
|
151
|
-
}
|
152
|
-
|
153
|
-
.site .footer .contact a {
|
154
|
-
color: #8085C1;
|
155
|
-
}
|
156
|
-
|
157
|
-
.site .footer .rss {
|
158
|
-
margin-top: 1.1em;
|
159
|
-
margin-right: -.2em;
|
160
|
-
float: right;
|
161
|
-
}
|
162
|
-
|
163
|
-
.site .footer .rss img {
|
164
|
-
border: 0;
|
165
|
-
}
|
166
|
-
|
167
|
-
/*****************************************************************************/
|
168
|
-
/*
|
169
|
-
/* Posts
|
170
|
-
/*
|
171
|
-
/*****************************************************************************/
|
172
|
-
|
173
|
-
#post {
|
174
|
-
|
175
|
-
}
|
176
|
-
|
177
|
-
/* standard */
|
178
|
-
|
179
|
-
#post pre {
|
180
|
-
border: 1px solid #ddd;
|
181
|
-
background-color: #eef;
|
182
|
-
padding: 0 .4em;
|
183
|
-
}
|
184
|
-
|
185
|
-
#post ul,
|
186
|
-
#post ol {
|
187
|
-
margin-left: 1.25em;
|
188
|
-
}
|
189
|
-
|
190
|
-
#post code {
|
191
|
-
border: 1px solid #ddd;
|
192
|
-
background-color: #eef;
|
193
|
-
font-size: 95%;
|
194
|
-
padding: 0 .2em;
|
195
|
-
}
|
196
|
-
|
197
|
-
#post pre code {
|
198
|
-
border: none;
|
199
|
-
}
|
200
|
-
|
201
|
-
/* terminal */
|
202
|
-
|
203
|
-
pre.terminal {
|
204
|
-
border: 1px solid black;
|
205
|
-
background-color: #333;
|
206
|
-
color: white;
|
207
|
-
padding: 5px;
|
208
|
-
overflow: auto;
|
209
|
-
word-wrap: break-word;
|
210
|
-
}
|
211
|
-
|
212
|
-
pre.terminal code {
|
213
|
-
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
|
214
|
-
background-color: #333;
|
215
|
-
}
|
216
|
-
</style>
|
4
|
+
<link href="<%= cijoe_root %>/screen.css" media="screen" rel="stylesheet" type="text/css" />
|
5
|
+
<title><%= h(joe.project) %>: CI Joe</title>
|
217
6
|
</head>
|
218
7
|
<body>
|
219
8
|
<div class="site">
|
220
9
|
<div class="title">
|
221
|
-
<a href="
|
10
|
+
<a href="<%= cijoe_root %>/">CI Joe</a>
|
222
11
|
<span class="extra">because knowing is half the battle</span>
|
223
12
|
</div>
|
224
13
|
|
@@ -241,7 +30,7 @@ ul.posts {
|
|
241
30
|
<% if joe.last_build %>
|
242
31
|
<li><span class="date"><%= pretty_time(joe.last_build.finished_at) %></span> » Built <a href="<%= joe.url %>/commits/<%= joe.last_build.sha %>"><%= joe.last_build.short_sha %></a> <span class="<%= joe.last_build.status %>">(<%= joe.last_build.status %>)</span></li>
|
243
32
|
<% if joe.last_build.failed? %>
|
244
|
-
<li><pre class="terminal"><code><%=
|
33
|
+
<li><pre class="terminal"><code><%=ansi_color_codes h(joe.last_build.output) %></code></pre></li>
|
245
34
|
<% end %>
|
246
35
|
<% end %>
|
247
36
|
</ul>
|
@@ -266,7 +55,7 @@ ul.posts {
|
|
266
55
|
</div>
|
267
56
|
<div class="rss">
|
268
57
|
<a href="http://github.com/defunkt/cijoe">
|
269
|
-
<img src="<%=
|
58
|
+
<img src="<%= cijoe_root %>/octocat.png" alt="Octocat!" />
|
270
59
|
</a>
|
271
60
|
</div>
|
272
61
|
</div>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cijoe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Wanstrath
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-25 00:00:00 -07:00
|
13
13
|
default_executable: cijoe
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- lib/cijoe/commit.rb
|
64
64
|
- lib/cijoe/config.rb
|
65
65
|
- lib/cijoe/public/octocat.png
|
66
|
+
- lib/cijoe/public/screen.css
|
66
67
|
- lib/cijoe/server.rb
|
67
68
|
- lib/cijoe/version.rb
|
68
69
|
- lib/cijoe/views/template.erb
|