Package coprs :: Package views :: Package coprs_ns :: Module coprs_builds
[hide private]
[frames] | no frames]

Source Code for Module coprs.views.coprs_ns.coprs_builds

  1  import flask 
  2  from flask import request, render_template, url_for, stream_with_context 
  3  import re 
  4  import os 
  5  import shutil 
  6  import tempfile 
  7   
  8  from functools import wraps 
  9  from werkzeug import secure_filename 
 10   
 11  from coprs import app 
 12  from coprs import db 
 13  from coprs import forms 
 14  from coprs import helpers 
 15   
 16  from coprs.logic import builds_logic 
 17  from coprs.logic import coprs_logic 
 18  from coprs.logic.builds_logic import BuildsLogic 
 19  from coprs.logic.complex_logic import ComplexLogic 
 20   
 21  from coprs.views.misc import (login_required, page_not_found, req_with_copr, 
 22          req_with_copr, send_build_icon) 
 23  from coprs.views.coprs_ns import coprs_ns 
 24   
 25  from coprs.exceptions import (ActionInProgressException, 
 26                                InsufficientRightsException, 
 27                                UnrepeatableBuildException) 
28 29 30 @coprs_ns.route("/build/<int:build_id>/") 31 -def copr_build_redirect(build_id):
32 build = ComplexLogic.get_build_safe(build_id) 33 copr = build.copr 34 return flask.redirect(helpers.copr_url("coprs_ns.copr_build", copr, build_id=build_id))
35
36 37 @coprs_ns.route("/build/<int:build_id>/status_image.png") 38 -def copr_build_icon(build_id):
39 return send_build_icon(BuildsLogic.get_by_id(int(build_id)).first())
40
41 42 ################################ Build detail ################################ 43 44 @coprs_ns.route("/<username>/<coprname>/build/<int:build_id>/") 45 @coprs_ns.route("/g/<group_name>/<coprname>/build/<int:build_id>/") 46 @req_with_copr 47 -def copr_build(copr, build_id):
48 return render_copr_build(build_id, copr)
49
50 51 -def render_copr_build(build_id, copr):
52 build = ComplexLogic.get_build_safe(build_id) 53 return render_template("coprs/detail/build.html", build=build, copr=copr)
54
55 56 ################################ Build table ################################ 57 58 @coprs_ns.route("/<username>/<coprname>/builds/") 59 @coprs_ns.route("/g/<group_name>/<coprname>/builds/") 60 @req_with_copr 61 -def copr_builds(copr):
62 return render_copr_builds(copr)
63
64 65 -def render_copr_builds(copr):
66 flashes = flask.session.pop('_flashes', []) 67 builds_query = builds_logic.BuildsLogic.get_copr_builds_list(copr=copr) 68 response = flask.Response(stream_with_context(helpers.stream_template("coprs/detail/builds.html", 69 copr=copr, 70 builds=list(builds_query), 71 flashes=flashes, 72 ))) 73 74 flask.session.pop('_flashes', []) 75 app.save_session(flask.session, response) 76 return response
77
78 ################################ Url builds ################################ 79 80 @coprs_ns.route("/<username>/<coprname>/add_build/") 81 @coprs_ns.route("/g/<group_name>/<coprname>/add_build/") 82 @login_required 83 @req_with_copr 84 -def copr_add_build(copr, form=None):
85 return render_add_build( 86 copr, form, view='coprs_ns.copr_new_build')
87
88 89 -def render_add_build(copr, form, view):
90 if not form: 91 form = forms.BuildFormUrlFactory(copr.active_chroots)() 92 return flask.render_template("coprs/detail/add_build/url.html", 93 copr=copr, view=view, form=form)
94
95 96 @coprs_ns.route("/<username>/<coprname>/new_build/", methods=["POST"]) 97 @coprs_ns.route("/g/<group_name>/<coprname>/new_build/", methods=["POST"]) 98 @login_required 99 @req_with_copr 100 -def copr_new_build(copr):
101 return process_new_build_url( 102 copr, 103 "coprs_ns.copr_new_build", 104 url_on_success=helpers.copr_url("coprs_ns.copr_builds", copr))
105
106 107 -def process_new_build_url(copr, add_view, url_on_success):
108 def factory(**build_options): 109 pkgs = form.pkgs.data.split("\n") 110 for pkg in pkgs: 111 BuildsLogic.create_new_from_url( 112 flask.g.user, copr, pkg, 113 chroot_names=form.selected_chroots, 114 **build_options 115 ) 116 for pkg in pkgs: 117 flask.flash("New build has been created: {}".format(pkg), "success")
118 119 form = forms.BuildFormUrlFactory(copr.active_chroots)() 120 return process_new_build(copr, form, factory, render_add_build, 121 add_view, url_on_success, msg_on_success=False) 122
123 124 -def process_new_build(copr, form, create_new_build_factory, add_function, add_view, url_on_success, msg_on_success=True):
125 if form.validate_on_submit(): 126 build_options = { 127 "enable_net": form.enable_net.data, 128 "timeout": form.timeout.data, 129 } 130 131 try: 132 create_new_build_factory(**build_options) 133 db.session.commit() 134 except (ActionInProgressException, InsufficientRightsException, UnrepeatableBuildException) as e: 135 db.session.rollback() 136 flask.flash(str(e), "error") 137 else: 138 if msg_on_success: 139 flask.flash("New build has been created.", "success") 140 141 return flask.redirect(url_on_success) 142 else: 143 return add_function(copr, form, add_view)
144
145 146 ################################ SCM builds ######################################### 147 148 @coprs_ns.route("/<username>/<coprname>/add_build_scm/") 149 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_scm/") 150 @login_required 151 @req_with_copr 152 -def copr_add_build_scm(copr, form=None):
153 return render_add_build_scm( 154 copr, form, view='coprs_ns.copr_new_build_scm')
155
156 157 -def render_add_build_scm(copr, form, view, package=None):
158 if not form: 159 form = forms.BuildFormScmFactory(copr.active_chroots)() 160 return flask.render_template("coprs/detail/add_build/scm.html", 161 copr=copr, form=form, view=view, package=package)
162
163 164 @coprs_ns.route("/<username>/<coprname>/new_build_scm/", methods=["POST"]) 165 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_scm/", methods=["POST"]) 166 @login_required 167 @req_with_copr 168 -def copr_new_build_scm(copr):
169 view = 'coprs_ns.copr_new_build_scm' 170 url_on_success = helpers.copr_url("coprs_ns.copr_builds", copr) 171 return process_new_build_scm(copr, view, url_on_success)
172
173 174 -def process_new_build_scm(copr, add_view, url_on_success):
175 def factory(**build_options): 176 BuildsLogic.create_new_from_scm( 177 flask.g.user, 178 copr, 179 form.scm_type.data, 180 form.clone_url.data, 181 form.committish.data, 182 form.subdirectory.data, 183 form.spec.data, 184 form.srpm_build_method.data, 185 form.selected_chroots, 186 **build_options 187 )
188 form = forms.BuildFormScmFactory(copr.active_chroots)() 189 return process_new_build(copr, form, factory, render_add_build_scm, add_view, url_on_success) 190
191 192 ################################ PyPI builds ################################ 193 194 @coprs_ns.route("/<username>/<coprname>/add_build_pypi/") 195 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_pypi/") 196 @login_required 197 @req_with_copr 198 -def copr_add_build_pypi(copr, form=None):
199 return render_add_build_pypi( 200 copr, form, view='coprs_ns.copr_new_build_pypi')
201
202 203 -def render_add_build_pypi(copr, form, view, package=None):
204 if not form: 205 form = forms.BuildFormPyPIFactory(copr.active_chroots)() 206 return flask.render_template("coprs/detail/add_build/pypi.html", 207 copr=copr, form=form, view=view, package=package)
208
209 210 @coprs_ns.route("/<username>/<coprname>/new_build_pypi/", methods=["POST"]) 211 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_pypi/", methods=["POST"]) 212 @login_required 213 @req_with_copr 214 -def copr_new_build_pypi(copr):
215 view = 'coprs_ns.copr_new_build_pypi' 216 url_on_success = helpers.copr_url("coprs_ns.copr_builds", copr) 217 return process_new_build_pypi(copr, view, url_on_success)
218
219 220 -def process_new_build_pypi(copr, add_view, url_on_success):
221 def factory(**build_options): 222 BuildsLogic.create_new_from_pypi( 223 flask.g.user, 224 copr, 225 form.pypi_package_name.data, 226 form.pypi_package_version.data, 227 form.python_versions.data, 228 form.selected_chroots, 229 **build_options 230 )
231 form = forms.BuildFormPyPIFactory(copr.active_chroots)() 232 return process_new_build(copr, form, factory, render_add_build_pypi, add_view, url_on_success) 233
234 235 ############################### RubyGems builds ############################### 236 237 @coprs_ns.route("/<username>/<coprname>/add_build_rubygems/") 238 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_rubygems/") 239 @login_required 240 @req_with_copr 241 -def copr_add_build_rubygems(copr, form=None):
242 return render_add_build_rubygems( 243 copr, form, view='coprs_ns.copr_new_build_rubygems')
244
245 246 -def render_add_build_rubygems(copr, form, view, package=None):
247 if not form: 248 form = forms.BuildFormRubyGemsFactory(copr.active_chroots)() 249 return flask.render_template("coprs/detail/add_build/rubygems.html", 250 copr=copr, form=form, view=view, package=package)
251
252 253 @coprs_ns.route("/<username>/<coprname>/new_build_rubygems/", methods=["POST"]) 254 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_rubygems/", methods=["POST"]) 255 @login_required 256 @req_with_copr 257 -def copr_new_build_rubygems(copr):
258 view = 'coprs_ns.copr_new_build_rubygems' 259 url_on_success = helpers.copr_url("coprs_ns.copr_builds", copr) 260 return process_new_build_rubygems(copr, view, url_on_success)
261
262 263 -def process_new_build_rubygems(copr, add_view, url_on_success):
264 def factory(**build_options): 265 BuildsLogic.create_new_from_rubygems( 266 flask.g.user, 267 copr, 268 form.gem_name.data, 269 form.selected_chroots, 270 **build_options 271 )
272 form = forms.BuildFormRubyGemsFactory(copr.active_chroots)() 273 return process_new_build(copr, form, factory, render_add_build_rubygems, add_view, url_on_success) 274
275 ############################### Custom builds ############################### 276 277 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_custom/", methods=["POST"]) 278 @coprs_ns.route("/<username>/<coprname>/new_build_custom/", methods=["POST"]) 279 @login_required 280 @req_with_copr 281 -def copr_new_build_custom(copr):
282 """ Handle the build request and redirect back. """ 283 284 # TODO: parametric decorator for this view && url_on_success 285 view = 'coprs_ns.copr_new_build_custom' 286 url_on_success = helpers.copr_url('coprs_ns.copr_add_build_custom', copr) 287 288 def factory(**build_options): 289 BuildsLogic.create_new_from_custom( 290 flask.g.user, 291 copr, 292 form.script.data, 293 form.chroot.data, 294 form.builddeps.data, 295 form.resultdir.data, 296 chroot_names=form.selected_chroots, 297 **build_options 298 )
299 300 form = forms.BuildFormCustomFactory(copr.active_chroots)() 301 302 return process_new_build(copr, form, factory, render_add_build_custom, 303 view, url_on_success) 304
305 306 307 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_custom/") 308 @coprs_ns.route("/<username>/<coprname>/add_build_custom/") 309 @login_required 310 @req_with_copr 311 -def copr_add_build_custom(copr, form=None):
312 return render_add_build_custom(copr, form, 313 'coprs_ns.copr_new_build_custom')
314
315 -def render_add_build_custom(copr, form, view, package=None):
316 if not form: 317 form = forms.BuildFormCustomFactory(copr.active_chroots)() 318 return flask.render_template("coprs/detail/add_build/custom.html", 319 copr=copr, form=form, view=view)
320
321 322 ################################ Upload builds ################################ 323 324 @coprs_ns.route("/<username>/<coprname>/add_build_upload/") 325 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_upload/") 326 @login_required 327 @req_with_copr 328 -def copr_add_build_upload(copr, form=None):
329 return render_add_build_upload( 330 copr, form, view='coprs_ns.copr_new_build_upload')
331
332 333 -def render_add_build_upload(copr, form, view):
334 if not form: 335 form = forms.BuildFormUploadFactory(copr.active_chroots)() 336 return flask.render_template("coprs/detail/add_build/upload.html", 337 copr=copr, form=form, view=view)
338
339 340 @coprs_ns.route("/<username>/<coprname>/new_build_upload/", methods=["POST"]) 341 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_upload/", methods=["POST"]) 342 @login_required 343 @req_with_copr 344 -def copr_new_build_upload(copr):
345 view = 'coprs_ns.copr_new_build_upload' 346 url_on_success = helpers.copr_url("coprs_ns.copr_builds", copr) 347 return process_new_build_upload(copr, view, url_on_success)
348
349 350 -def process_new_build_upload(copr, add_view, url_on_success):
351 def factory(**build_options): 352 BuildsLogic.create_new_from_upload( 353 flask.g.user, copr, 354 f_uploader=lambda path: form.pkgs.data.save(path), 355 orig_filename=form.pkgs.data.filename, 356 chroot_names=form.selected_chroots, 357 **build_options 358 )
359 form = forms.BuildFormUploadFactory(copr.active_chroots)() 360 return process_new_build(copr, form, factory, render_add_build_upload, add_view, url_on_success) 361
362 363 ################################ Builds rebuilds ################################ 364 365 @coprs_ns.route("/<username>/<coprname>/new_build_rebuild/<int:build_id>/", methods=["POST"]) 366 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_rebuild/<int:build_id>/", methods=["POST"]) 367 @login_required 368 @req_with_copr 369 -def copr_new_build_rebuild(copr, build_id):
370 view='coprs_ns.copr_new_build' 371 url_on_success = helpers.copr_url("coprs_ns.copr_builds", copr) 372 return process_rebuild(copr, build_id, view=view, url_on_success=url_on_success)
373
374 375 -def process_rebuild(copr, build_id, view, url_on_success):
376 def factory(**build_options): 377 source_build = ComplexLogic.get_build_safe(build_id) 378 BuildsLogic.create_new_from_other_build( 379 flask.g.user, copr, source_build, 380 chroot_names=form.selected_chroots, 381 **build_options 382 )
383 form = forms.BuildFormRebuildFactory.create_form_cls(copr.active_chroots)() 384 return process_new_build(copr, form, factory, render_add_build, view, url_on_success) 385
386 387 ################################ Repeat ################################ 388 389 @coprs_ns.route("/<username>/<coprname>/repeat_build/<int:build_id>/", methods=["GET", "POST"]) 390 @coprs_ns.route("/g/<group_name>/<coprname>/repeat_build/<int:build_id>/", methods=["GET", "POST"]) 391 @login_required 392 @req_with_copr 393 -def copr_repeat_build(copr, build_id):
394 return process_copr_repeat_build(build_id, copr)
395
396 397 -def process_copr_repeat_build(build_id, copr):
398 build = ComplexLogic.get_build_safe(build_id) 399 if not flask.g.user.can_build_in(build.copr): 400 flask.flash("You are not allowed to repeat this build.") 401 402 if build.source_type == helpers.BuildSourceEnum('upload'): 403 # If the original build's source is 'upload', we will show only the 404 # original build's chroots and skip import. 405 available_chroots = build.chroots 406 407 else: 408 # For all other sources, we will show all chroots enabled in the project 409 # and proceed with import. 410 available_chroots = copr.active_chroots 411 412 form = forms.BuildFormRebuildFactory.create_form_cls(available_chroots)( 413 build_id=build_id, enable_net=build.enable_net) 414 415 # remove all checkboxes by default 416 for ch in available_chroots: 417 field = getattr(form, ch.name) 418 field.data = False 419 chroot_to_build = request.args.get("chroot") 420 app.logger.debug("got param chroot: {}".format(chroot_to_build)) 421 if chroot_to_build: 422 # set single checkbox if chroot query arg was provided 423 if hasattr(form, chroot_to_build): 424 getattr(form, chroot_to_build).data = True 425 else: 426 build_chroot_names = set(ch.name for ch in build.chroots) 427 build_failed_chroot_names = set(ch.name for ch in build.get_chroots_by_status([ 428 helpers.StatusEnum('failed'), helpers.StatusEnum('canceled'), 429 ])) 430 for ch in available_chroots: 431 # check checkbox on all the chroots that have not been (successfully) built before 432 if (ch.name not in build_chroot_names) or (ch.name in build_failed_chroot_names): 433 getattr(form, ch.name).data = True 434 return flask.render_template( 435 "coprs/detail/add_build/rebuild.html", 436 copr=copr, build=build, form=form)
437
438 439 ################################ Cancel ################################ 440 441 -def process_cancel_build(build):
442 try: 443 builds_logic.BuildsLogic.cancel_build(flask.g.user, build) 444 except InsufficientRightsException as e: 445 flask.flash(str(e), "error") 446 else: 447 db.session.commit() 448 flask.flash("Build {} has been canceled successfully.".format(build.id)) 449 return flask.redirect(helpers.url_for_copr_builds(build.copr))
450
451 452 @coprs_ns.route("/<username>/<coprname>/cancel_build/<int:build_id>/", methods=["POST"]) 453 @coprs_ns.route("/g/<group_name>/<coprname>/cancel_build/<int:build_id>/", methods=["POST"]) 454 @login_required 455 @req_with_copr 456 -def copr_cancel_build(copr, build_id):
457 # only the user who ran the build can cancel it 458 build = ComplexLogic.get_build_safe(build_id) 459 return process_cancel_build(build)
460 461 462 ################################ Delete ################################ 463 464 @coprs_ns.route("/<username>/<coprname>/delete_build/<int:build_id>/", 465 methods=["POST"])
466 @login_required 467 -def copr_delete_build(username, coprname, build_id):
468 build = ComplexLogic.get_build_safe(build_id) 469 470 try: 471 builds_logic.BuildsLogic.delete_build(flask.g.user, build) 472 except (InsufficientRightsException, ActionInProgressException) as e: 473 flask.flash(str(e), "error") 474 else: 475 db.session.commit() 476 flask.flash("Build has been deleted successfully.") 477 478 return flask.redirect(helpers.url_for_copr_builds(build.copr))
479