Skip to content

Commit 0c7ba1e

Browse files
committed
Add search capabilities to build table
1 parent 1def14e commit 0c7ba1e

8 files changed

Lines changed: 233 additions & 28 deletions

File tree

src/api/handlers/build.py

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from flask import g
1+
from flask import g, request
22
from flask_restplus import Resource, fields
33

44
from pyinfraboxutils.ibrestplus import api
@@ -22,15 +22,58 @@ class Builds(Resource):
2222
@api.marshal_list_with(build_model)
2323
def get(self, project_id):
2424
'''
25-
Returns the latest 100 builds of the project
25+
Returns builds
2626
'''
27+
28+
build_from = request.args.get('from', None)
29+
build_to = request.args.get('to', None)
30+
sha = request.args.get('sha', None)
31+
branch = request.args.get('branch', None)
32+
cronjob = request.args.get('cronjob', None)
33+
34+
if cronjob == "true":
35+
cronjob = True
36+
elif cronjob == "false":
37+
cronjob = False
38+
else:
39+
cronjob = None
40+
41+
if not build_to:
42+
r = g.db.execute_one_dict('''
43+
SELECT max(build_number) as max
44+
FROM build
45+
WHERE project_id = %s
46+
''', [project_id])
47+
48+
if not r or not r['max']:
49+
build_to = 1
50+
else:
51+
build_to = r['max'] + 1
52+
53+
if not build_from:
54+
build_from = max(build_to - 10, 0)
55+
2756
p = g.db.execute_many_dict('''
28-
SELECT id, build_number, restart_counter, is_cronjob
29-
FROM build
30-
WHERE project_id = %s
57+
SELECT b.id, b.build_number, b.restart_counter, b.is_cronjob
58+
FROM build b
59+
LEFT OUTER JOIN commit c
60+
ON b.commit_id = c.id
61+
WHERE b.project_id = %(pid)s
62+
AND b.build_number < %(to)s
63+
AND b.build_number >= %(from)s
64+
AND (%(sha)s IS NULL OR c.id = %(sha)s)
65+
AND (%(branch)s IS NULL OR c.branch = %(branch)s)
66+
AND (%(cronjob)s IS NULL OR b.is_cronjob = %(cronjob)s)
3167
ORDER BY build_number DESC, restart_counter DESC
32-
LIMIT 100
33-
''', [project_id])
68+
''', {
69+
'pid': project_id,
70+
'from': build_from,
71+
'to': build_to,
72+
'sha': sha,
73+
'branch': branch,
74+
'cronjob': cronjob,
75+
})
76+
3477
return p
3578

3679
@ns.route('/<build_id>')

src/api/handlers/project.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ def get(self, project_id):
229229
)
230230
AND j.name LIKE CONCAT(%s, '%')
231231
)
232-
''', [project_id, project_id, project_id, project_id, job_name, build_number, build_restart_count, job_name])
232+
''', [project_id, project_id, project_id, project_id,
233+
job_name, build_number, build_restart_count, job_name])
233234
else:
234235
r = g.db.execute_one_dict('''
235236
SELECT

src/api/handlers/projects/jobs.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ class Jobs(Resource):
3434
def get(self, project_id):
3535
build_from = request.args.get('from', None)
3636
build_to = request.args.get('to', None)
37+
sha = request.args.get('sha', None)
38+
branch = request.args.get('branch', None)
39+
cronjob = request.args.get('cronjob', None)
40+
state = request.args.get('state', None)
41+
42+
if cronjob == "true":
43+
cronjob = True
44+
elif cronjob == "false":
45+
cronjob = False
46+
else:
47+
cronjob = None
3748

3849
if not build_to:
3950
r = g.db.execute_one_dict('''
@@ -112,8 +123,20 @@ def get(self, project_id):
112123
AND b.project_id = %(pid)s
113124
AND b.build_number < %(to)s
114125
AND b.build_number >= %(from)s
126+
AND (%(sha)s IS NULL OR c.id = %(sha)s)
127+
AND (%(branch)s IS NULL OR c.branch = %(branch)s)
128+
AND (%(cronjob)s IS NULL OR b.is_cronjob = %(cronjob)s)
129+
AND (%(state)s IS NULL OR j.state = %(state)s)
115130
ORDER BY j.created_at DESC
116-
''', {'pid': project_id, 'from': build_from, 'to': build_to})
131+
''', {
132+
'pid': project_id,
133+
'from': build_from,
134+
'to': build_to,
135+
'sha': sha,
136+
'branch': branch,
137+
'cronjob': cronjob,
138+
'state': state
139+
})
117140

118141
result = []
119142
for j in jobs:
@@ -426,8 +449,8 @@ def get(self, project_id, job_id):
426449
f.seek(0)
427450

428451
if not f:
429-
logger.error(key)
430452
abort(404)
453+
431454
filename = os.path.basename(filename)
432455

433456
return send_file(f, as_attachment=force_download, attachment_filename=filename,\

src/api/handlers/projects/projects.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ def post(self, project_id):
300300
WHERE id = %s
301301
''', [not private, project_id])
302302

303+
g.db.commit()
303304
return OK('updated visibility')
304305

305306
@ns.route('/<project_id>')

src/dashboard-client/src/components/build/BuildTable.vue

Lines changed: 125 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,54 @@
11
<template>
22
<div>
3+
<md-card md-theme="white" class="full-height clean-card">
4+
<md-card-area>
5+
<md-list class="m-t-md m-b-md">
6+
<md-list-item>
7+
<md-input-container class="m-r-sm">
8+
<label>From Build Number</label>
9+
<md-input v-model="form.from"></md-input>
10+
</md-input-container>
11+
<md-input-container class="m-r-sm">
12+
<label>To Build Number</label>
13+
<md-input v-model="form.to"></md-input>
14+
</md-input-container>
15+
<md-input-container class="m-r-sm">
16+
<label>Sha</label>
17+
<md-input v-model="form.sha"></md-input>
18+
</md-input-container>
19+
<md-input-container class="m-l-sm">
20+
<label>Branch</label>
21+
<md-input v-model="form.branch"></md-input>
22+
</md-input-container>
23+
<md-input-container>
24+
<label>Cronjob</label>
25+
<md-select name="cronjob" id="cronjob" v-model="form.cronjob">
26+
<md-option value="" class="bg-white">Any</md-option>
27+
<md-option value="true" class="bg-white">Yes</md-option>
28+
<md-option value="false" class="bg-white">No</md-option>
29+
</md-select>
30+
</md-input-container>
31+
<md-input-container>
32+
<label>State</label>
33+
<md-select name="state" id="state" v-model="form.state">
34+
<md-option value="" class="bg-white">Any</md-option>
35+
<md-option value="running" class="bg-white">Running</md-option>
36+
<md-option value="failed" class="bg-white">Failed</md-option>
37+
<md-option value="unstable" class="bg-white">Unstable</md-option>
38+
<md-option value="killed" class="bg-white">Killed</md-option>
39+
<md-option value="error" class="bg-white">Error</md-option>
40+
<md-option value="finished" class="bg-white">Finished</md-option>
41+
</md-select>
42+
</md-input-container>
43+
<md-button class="md-icon-button md-list-action" @click="doSearch()">
44+
<md-icon md-theme="running" class="md-primary">search</md-icon>
45+
<md-tooltip>Search</md-tooltip>
46+
</md-button>
47+
</md-list-item>
48+
</md-list>
49+
</md-card-area>
50+
</md-card>
51+
352
<md-table-card class="clean-card add-overflow">
453
<md-table class="min-medium">
554
<md-table-header>
@@ -62,13 +111,35 @@
62111
</template>
63112

64113
<script>
114+
65115
export default {
66116
props: ['project'],
67117
data: () => {
68118
return {
69119
page: 1,
70120
size: 10,
71-
total: 0
121+
total: 0,
122+
123+
form: {
124+
from: null,
125+
to: null,
126+
sha: null,
127+
branch: null,
128+
cronjob: '',
129+
startDate: null,
130+
state: ''
131+
},
132+
133+
search: {
134+
from: null,
135+
to: null,
136+
sha: null,
137+
branch: null,
138+
cronjob: null,
139+
startDate: null,
140+
search: false,
141+
state: null
142+
}
72143
}
73144
},
74145
computed: {
@@ -85,18 +156,52 @@ export default {
85156
86157
let builds = []
87158
let foundFrom = maxBuildNumber
88-
for (let b of this.project.builds) {
89-
if (from <= b.number && b.number < to) {
159+
160+
if (this.search.search) {
161+
this.project.loadBuilds(this.search.from || 0, this.search.to || maxBuildNumber, this.search.sha, this.search.branch, this.search.cronjob)
162+
163+
for (let b of this.project.builds) {
164+
if (this.search.branch && b.commit && b.commit.branch !== this.search.branch) {
165+
continue
166+
}
167+
168+
if (this.search.sha && b.commit && b.commit.id !== this.search.sha) {
169+
continue
170+
}
171+
172+
if (this.search.cronjob && String(b.isCronjob) !== this.search.cronjob) {
173+
continue
174+
}
175+
176+
if (this.search.state && b.state !== this.search.state) {
177+
continue
178+
}
179+
180+
console.log(this.search.from)
181+
if (this.search.from && b.number < this.search.from) {
182+
continue
183+
}
184+
185+
if (this.search.to && b.number > this.search.to) {
186+
continue
187+
}
188+
90189
builds.push(b)
190+
}
191+
} else {
192+
for (let b of this.project.builds) {
193+
if (from <= b.number && b.number < to) {
194+
builds.push(b)
91195
92-
if (b.number < foundFrom) {
93-
foundFrom = b.number
196+
if (b.number < foundFrom) {
197+
foundFrom = b.number
198+
}
94199
}
95200
}
96-
}
97201
98-
if (foundFrom !== from) {
99-
this.project.loadBuilds(from, to)
202+
if (foundFrom !== from) {
203+
this.project.loadBuilds(from, to, this.search.sha, this.search.branch, this.search.cronjob)
204+
}
100205
}
101206
102207
return builds
@@ -111,6 +216,18 @@ export default {
111216
}
112217
113218
this.size = opt.size
219+
},
220+
221+
doSearch () {
222+
this.search = {
223+
from: this.form.from,
224+
to: this.form.to,
225+
sha: this.form.sha,
226+
branch: this.form.branch,
227+
cronjob: this.form.cronjob,
228+
state: this.form.state,
229+
search: true
230+
}
114231
}
115232
}
116233
}

src/dashboard-client/src/models/Build.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default class Build {
88
this.id = id
99
this.number = number
1010
this.restartCounter = restartCounter
11-
this.state = null
11+
this.state = 'finished'
1212
this.jobs = []
1313
this.commit = commit
1414
this.startDate = null
@@ -73,8 +73,6 @@ export default class Build {
7373
}
7474

7575
_updateBuildState () {
76-
this.state = 'finished'
77-
7876
let states = {
7977
'error': false,
8078
'killed': false,
@@ -96,13 +94,21 @@ export default class Build {
9694
}
9795

9896
if (states.killed) {
99-
this.state = 'killed'
97+
if (this.state !== 'killed') {
98+
this.state = 'killed'
99+
}
100100
} else if (states.error) {
101-
this.state = 'error'
101+
if (this.state !== 'error') {
102+
this.state = 'error'
103+
}
102104
} else if (states.failure) {
103-
this.state = 'failure'
105+
if (this.state !== 'failure') {
106+
this.state = 'failure'
107+
}
104108
} else if (states.unstable) {
105-
this.state = 'unstable'
109+
if (this.state !== 'unstable') {
110+
this.state = 'unstable'
111+
}
106112
}
107113
}
108114

src/dashboard-client/src/models/Project.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,22 @@ export default class Project {
5353
return builds
5454
}
5555

56-
loadBuilds (from, to) {
57-
return NewAPIService.get(`projects/${this.id}/jobs/?from=${from}&to=${to}`)
56+
loadBuilds (from, to, sha, branch, cronjob) {
57+
let url = `projects/${this.id}/jobs/?from=${from}&to=${to}`
58+
59+
if (sha) {
60+
url += `&sha=${sha}`
61+
}
62+
63+
if (branch) {
64+
url += `&branch=${branch}`
65+
}
66+
67+
if (cronjob) {
68+
url += `&cronjob=${cronjob}`
69+
}
70+
71+
return NewAPIService.get(url)
5872
.then((jobs) => {
5973
this._addJobs(jobs)
6074
})

src/pyinfraboxutils/ibflask.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def get_token():
109109

110110
return token
111111
else:
112-
logger.warn('Invalid auth header format')
112+
logger.debug('Invalid auth header format')
113113
return None
114114
elif cookie:
115115
token = cookie

0 commit comments

Comments
 (0)