5 from flask
import Flask
, render_template
, request
, abort
, jsonify
6 from flask_bootstrap
import Bootstrap
7 from flask_caching
import Cache
8 from flask_migrate
import Migrate
9 from flask_nav
import Nav
10 from flask_nav
.elements
import Navbar
, Text
, View
11 from flask_sqlalchemy
import SQLAlchemy
13 from sqlalchemy
import orm
, func
15 from ui
import gitlab
, config
, models
19 app
.config
.from_object(config
)
21 models
.db
.init_app(app
)
22 migrate
= Migrate(app
, models
.db
)
25 nav
.register_element('top', Navbar(
27 View('Builds', '.web_index'),
28 View('Runners', '.web_runners'),
29 View('Stats', '.web_stats')
32 headers
= {'Private-Token': os
.environ
.get('GITLAB_TOKEN', '')}
37 if 'status' in request
.args
:
38 args
['build_status'] = request
.args
.get('status')
39 if 'device' in request
.args
:
40 args
['build_device'] = request
.args
.get('device')
41 if 'version' in request
.args
:
42 args
['build_version'] = request
.args
.get('version')
43 if 'type' in request
.args
:
44 args
['build_type'] = request
.args
.get('type')
45 if 'date' in request
.args
:
46 date
= datetime
.datetime
.strptime(request
.args
.get('date'), '%Y-%m-%d').date()
47 args
['build_date'] = datetime
.datetime
.strptime(request
.args
.get('date'), '%Y-%m-%d').date()
53 runner_build_times
= models
.Build
.query
.join(models
.Build
.build_runner
).with_entities(
54 models
.Runner
.runner_name
,
55 models
.Build
.build_version
,
56 func
.avg(models
.Build
.build_duration
),
57 func
.max(models
.Build
.build_duration
),
58 func
.min(models
.Build
.build_duration
),
59 func
.sum(models
.Build
.build_duration
)
60 ).group_by(models
.Build
.build_version
, models
.Runner
.runner_name
).all()
62 all_build_times
= models
.Build
.query
.with_entities(
63 models
.Build
.build_version
,
64 func
.avg(models
.Build
.build_duration
),
65 func
.max(models
.Build
.build_duration
),
66 func
.min(models
.Build
.build_duration
),
67 func
.sum(models
.Build
.build_duration
)
68 ).group_by(models
.Build
.build_version
).all()
70 runner_build_status
= models
.Build
.query
.join(models
.Build
.build_runner
).with_entities(
71 models
.Runner
.runner_name
,
72 models
.Build
.build_status
,
73 func
.count(models
.Build
.build_status
)
74 ).group_by(models
.Runner
.runner_name
, models
.Build
.build_status
).all()
86 for build_time
in all_build_times
:
87 stats
['times']['all'][build_time
[0]] = {
88 'avg': build_time
[1] if build_time
[1] else 0,
89 'max': build_time
[2] if build_time
[2] else 0,
90 'min': build_time
[3] if build_time
[3] else 0,
91 'sum': build_time
[4] if build_time
[4] else 0,
94 for build_time
in runner_build_times
:
95 stats
['times'].setdefault(build_time
[0], {})[build_time
[1]] = {
96 'avg': build_time
[2] if build_time
[2] else 0,
97 'max': build_time
[3] if build_time
[3] else 0,
98 'min': build_time
[4] if build_time
[4] else 0,
99 'sum': build_time
[5] if build_time
[5] else 0,
102 for build_status
in runner_build_status
:
103 stats
['builds']['all'].setdefault(build_status
[1], 0)
104 stats
['builds']['all'][build_status
[1]] += build_status
[2]
106 stats
['builds'].setdefault(build_status
[0], {})[build_status
[1]] = build_status
[2]
114 return "Invalid Date", 400
115 builds
= models
.Build
.paginate(args
)
116 return render_template('builds.html', builds
=builds
)
118 @app.route('/runners/<string:runner>')
119 def web_runner(runner
):
123 return "Invalid Date", 400
124 runner
= models
.Runner
.get({'runner_name': runner
}).first()
125 args
['build_runner'] = runner
126 builds
= models
.Build
.paginate(args
)
127 return render_template('runner.html', runner
=runner
, builds
=builds
)
132 runners
= ['all'] + [x
for x
in sorted(stats_
['builds'].keys()) if x
!= 'all']
133 return render_template('stats.html', stats
=stats_
, runners
=runners
)
135 @app.route("/runners/")
137 runners
= models
.Runner
.get().all()
138 return render_template('runners.html', runners
=runners
)
140 @app.route('/api/v1/builds')
145 return jsonify({'error': 'Invalid Date'}), 400
146 builds
= models
.Build
.paginate(args
).items
149 return jsonify([x
.as_dict() for x
in builds
])
151 @app.route('/api/v1/runners')
153 runners
= models
.Runner
.get().all()
156 return jsonify([x
.as_dict() for x
in runners
])
158 @app.route('/api/v1/runners/<string:runner>')
159 def api_runner(runner
):
163 return jsonify({"Invalid Date"}), 400
164 runner
= models
.Runner
.get({"runner_name": runner
}).first()
167 return jsonify(runner
.as_dict())
169 @app.route('/api/v1/stats')
171 return jsonify(stats())
174 @app.route("/webhook", methods
=('POST',))
175 def process_webhook():
176 gitlab
.webhooks
.process(request
)
179 if __name__
== '__main__':
180 app
.run(host
='0.0.0.0', port
=5000)