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, req_with_copr 
 22  from coprs.views.coprs_ns import coprs_ns 
 23   
 24  from coprs.exceptions import (ActionInProgressException, 
 25                                InsufficientRightsException, 
 26                                UnrepeatableBuildException) 
27 28 29 @coprs_ns.route("/build/<int:build_id>/") 30 -def copr_build_redirect(build_id):
31 build = ComplexLogic.get_build_safe(build_id) 32 copr = build.copr 33 if copr.is_a_group_project: 34 return flask.redirect(url_for( 35 "coprs_ns.group_copr_build", 36 group_name=build.copr.group.name, 37 coprname=build.copr.name, 38 build_id=build_id)) 39 else: 40 return flask.redirect(url_for( 41 "coprs_ns.copr_build", 42 username=build.copr.user.name, 43 coprname=build.copr.name, 44 build_id=build_id))
45
46 47 ################################ Build detail ################################ 48 49 @coprs_ns.route("/<username>/<coprname>/build/<int:build_id>/") 50 @req_with_copr 51 -def copr_build(copr, build_id):
52 return render_copr_build(build_id, copr)
53
54 55 @coprs_ns.route("/g/<group_name>/<coprname>/build/<int:build_id>/") 56 @req_with_copr 57 -def group_copr_build(copr, build_id):
58 return render_copr_build(build_id, copr)
59
60 61 -def render_copr_build(build_id, copr):
62 build = ComplexLogic.get_build_safe(build_id) 63 return render_template("coprs/detail/build.html", build=build, copr=copr)
64
65 66 ################################ Build table ################################ 67 68 @coprs_ns.route("/<username>/<coprname>/builds/") 69 @req_with_copr 70 -def copr_builds(copr):
71 return render_copr_builds(copr)
72
73 74 @coprs_ns.route("/g/<group_name>/<coprname>/builds/") 75 @req_with_copr 76 -def group_copr_builds(copr):
77 return render_copr_builds(copr)
78
79 80 -def render_copr_builds(copr):
81 builds_query = builds_logic.BuildsLogic.get_copr_builds_list(copr=copr) 82 return flask.Response(stream_with_context(helpers.stream_template("coprs/detail/builds.html", 83 copr=copr, 84 builds=list(builds_query))))
85
86 87 ################################ Url builds ################################ 88 89 @coprs_ns.route("/<username>/<coprname>/add_build/") 90 @login_required 91 @req_with_copr 92 -def copr_add_build(copr, form=None):
93 return render_add_build( 94 copr, form, view='coprs_ns.copr_new_build')
95
96 97 @coprs_ns.route("/g/<group_name>/<coprname>/add_build/") 98 @login_required 99 @req_with_copr 100 -def group_copr_add_build(copr, form=None):
101 return render_add_build( 102 copr, form, view='coprs_ns.copr_new_build')
103
104 105 -def render_add_build(copr, form, view):
106 if not form: 107 form = forms.BuildFormUrlFactory(copr.active_chroots)() 108 return flask.render_template("coprs/detail/add_build/url.html", 109 copr=copr, view=view, form=form)
110
111 112 @coprs_ns.route("/<username>/<coprname>/new_build/", methods=["POST"]) 113 @login_required 114 @req_with_copr 115 -def copr_new_build(copr):
116 return process_new_build_url( 117 copr, 118 "coprs_ns.copr_new_build", 119 url_on_success=url_for("coprs_ns.copr_builds", 120 username=copr.user.username, coprname=copr.name) 121 )
122
123 124 @coprs_ns.route("/g/<group_name>/<coprname>/new_build/", methods=["POST"]) 125 @login_required 126 @req_with_copr 127 -def group_copr_new_build(copr):
128 return process_new_build_url( 129 copr, 130 "coprs_ns.copr_new_build", 131 url_on_success=url_for("coprs_ns.group_copr_builds", 132 group_name=copr.group.name, coprname=copr.name) 133 )
134
135 136 -def process_new_build_url(copr, add_view, url_on_success):
137 def factory(**build_options): 138 pkgs = form.pkgs.data.split("\n") 139 for pkg in pkgs: 140 BuildsLogic.create_new_from_url( 141 flask.g.user, copr, pkg, 142 chroot_names=form.selected_chroots, 143 **build_options 144 ) 145 for pkg in pkgs: 146 flask.flash("New build has been created: {}".format(pkg), "success")
147 148 form = forms.BuildFormUrlFactory(copr.active_chroots)() 149 return process_new_build(copr, form, factory, render_add_build, 150 add_view, url_on_success, msg_on_success=False) 151
152 153 -def process_new_build(copr, form, create_new_build_factory, add_function, add_view, url_on_success, msg_on_success=True):
154 if form.validate_on_submit(): 155 build_options = { 156 "enable_net": form.enable_net.data, 157 "timeout": form.timeout.data, 158 } 159 160 try: 161 create_new_build_factory(**build_options) 162 db.session.commit() 163 except (ActionInProgressException, InsufficientRightsException, UnrepeatableBuildException) as e: 164 db.session.rollback() 165 flask.flash(str(e), "error") 166 else: 167 if msg_on_success: 168 flask.flash("New build has been created.", "success") 169 170 return flask.redirect(url_on_success) 171 else: 172 return add_function(copr, form, add_view)
173
174 175 ################################ SCM builds ######################################### 176 177 @coprs_ns.route("/<username>/<coprname>/add_build_scm/") 178 @login_required 179 @req_with_copr 180 -def copr_add_build_scm(copr, form=None):
181 return render_add_build_scm( 182 copr, form, view='coprs_ns.copr_new_build_scm')
183
184 185 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_scm/") 186 @login_required 187 @req_with_copr 188 -def group_copr_add_build_scm(copr, form=None):
189 return render_add_build_scm( 190 copr, form, view='coprs_ns.copr_new_build_scm')
191
192 193 -def render_add_build_scm(copr, form, view, package=None):
194 if not form: 195 form = forms.BuildFormScmFactory(copr.active_chroots)() 196 return flask.render_template("coprs/detail/add_build/scm.html", 197 copr=copr, form=form, view=view, package=package)
198
199 200 @coprs_ns.route("/<username>/<coprname>/new_build_scm/", methods=["POST"]) 201 @login_required 202 @req_with_copr 203 -def copr_new_build_scm(copr):
204 view = 'coprs_ns.copr_new_build_scm' 205 url_on_success = url_for("coprs_ns.copr_builds", 206 username=copr.user.username, coprname=copr.name) 207 return process_new_build_scm(copr, view, url_on_success)
208
209 210 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_scm/", methods=["POST"]) 211 @login_required 212 @req_with_copr 213 -def group_copr_new_build_scm(copr):
214 view = 'coprs_ns.copr_new_build_scm' 215 url_on_success = url_for("coprs_ns.group_copr_builds", 216 group_name=copr.group.name, coprname=copr.name) 217 return process_new_build_scm(copr, view, url_on_success)
218
219 220 -def process_new_build_scm(copr, add_view, url_on_success):
221 def factory(**build_options): 222 BuildsLogic.create_new_from_scm( 223 flask.g.user, 224 copr, 225 form.scm_type.data, 226 form.clone_url.data, 227 form.committish.data, 228 form.subdirectory.data, 229 form.spec.data, 230 form.srpm_build_method.data, 231 form.selected_chroots, 232 **build_options 233 )
234 form = forms.BuildFormScmFactory(copr.active_chroots)() 235 return process_new_build(copr, form, factory, render_add_build_scm, add_view, url_on_success) 236
237 238 ################################ PyPI builds ################################ 239 240 @coprs_ns.route("/<username>/<coprname>/add_build_pypi/") 241 @login_required 242 @req_with_copr 243 -def copr_add_build_pypi(copr, form=None):
244 return render_add_build_pypi( 245 copr, form, view='coprs_ns.copr_new_build_pypi')
246
247 248 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_pypi/") 249 @login_required 250 @req_with_copr 251 -def group_copr_add_build_pypi(copr, form=None):
252 return render_add_build_pypi( 253 copr, form, view='coprs_ns.copr_new_build_pypi')
254
255 256 -def render_add_build_pypi(copr, form, view, package=None):
257 if not form: 258 form = forms.BuildFormPyPIFactory(copr.active_chroots)() 259 return flask.render_template("coprs/detail/add_build/pypi.html", 260 copr=copr, form=form, view=view, package=package)
261
262 263 @coprs_ns.route("/<username>/<coprname>/new_build_pypi/", methods=["POST"]) 264 @login_required 265 @req_with_copr 266 -def copr_new_build_pypi(copr):
267 view = 'coprs_ns.copr_new_build_pypi' 268 url_on_success = url_for("coprs_ns.copr_builds", 269 username=copr.user.username, coprname=copr.name) 270 return process_new_build_pypi(copr, view, url_on_success)
271
272 273 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_pypi/", methods=["POST"]) 274 @login_required 275 @req_with_copr 276 -def group_copr_new_build_pypi(copr):
277 view = 'coprs_ns.copr_new_build_pypi' 278 url_on_success = url_for("coprs_ns.group_copr_builds", 279 group_name=copr.group.name, coprname=copr.name) 280 return process_new_build_pypi(copr, view, url_on_success)
281
282 283 -def process_new_build_pypi(copr, add_view, url_on_success):
284 def factory(**build_options): 285 BuildsLogic.create_new_from_pypi( 286 flask.g.user, 287 copr, 288 form.pypi_package_name.data, 289 form.pypi_package_version.data, 290 form.python_versions.data, 291 form.selected_chroots, 292 **build_options 293 )
294 form = forms.BuildFormPyPIFactory(copr.active_chroots)() 295 return process_new_build(copr, form, factory, render_add_build_pypi, add_view, url_on_success) 296
297 298 ############################### RubyGems builds ############################### 299 300 @coprs_ns.route("/<username>/<coprname>/add_build_rubygems/") 301 @login_required 302 @req_with_copr 303 -def copr_add_build_rubygems(copr, form=None):
304 return render_add_build_rubygems( 305 copr, form, view='coprs_ns.copr_new_build_rubygems')
306
307 308 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_rubygems/") 309 @login_required 310 @req_with_copr 311 -def group_copr_add_build_rubygems(copr, form=None):
312 return render_add_build_rubygems( 313 copr, form, view='coprs_ns.copr_new_build_rubygems')
314
315 316 -def render_add_build_rubygems(copr, form, view, package=None):
317 if not form: 318 form = forms.BuildFormRubyGemsFactory(copr.active_chroots)() 319 return flask.render_template("coprs/detail/add_build/rubygems.html", 320 copr=copr, form=form, view=view, package=package)
321
322 323 @coprs_ns.route("/<username>/<coprname>/new_build_rubygems/", methods=["POST"]) 324 @login_required 325 @req_with_copr 326 -def copr_new_build_rubygems(copr):
327 view = 'coprs_ns.copr_new_build_rubygems' 328 url_on_success = url_for("coprs_ns.copr_builds", 329 username=copr.user.username, coprname=copr.name) 330 return process_new_build_rubygems(copr, view, url_on_success)
331
332 333 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_rubygems/", methods=["POST"]) 334 @login_required 335 @req_with_copr 336 -def group_copr_new_build_rubygems(copr):
337 view = 'coprs_ns.copr_new_build_rubygems' 338 url_on_success = url_for("coprs_ns.group_copr_builds", 339 group_name=copr.group.name, coprname=copr.name) 340 return process_new_build_rubygems(copr, view, url_on_success)
341
342 343 -def process_new_build_rubygems(copr, add_view, url_on_success):
344 def factory(**build_options): 345 BuildsLogic.create_new_from_rubygems( 346 flask.g.user, 347 copr, 348 form.gem_name.data, 349 form.selected_chroots, 350 **build_options 351 )
352 form = forms.BuildFormRubyGemsFactory(copr.active_chroots)() 353 return process_new_build(copr, form, factory, render_add_build_rubygems, add_view, url_on_success) 354
355 ############################### Custom builds ############################### 356 357 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_custom/", methods=["POST"]) 358 @coprs_ns.route("/<username>/<coprname>/new_build_custom/", methods=["POST"]) 359 @login_required 360 @req_with_copr 361 -def copr_new_build_custom(copr):
362 """ Handle the build request and redirect back. """ 363 364 # TODO: parametric decorator for this view && url_on_success 365 view = 'coprs_ns.copr_new_build_custom' 366 url_on_success = helpers.copr_url('coprs_ns.copr_add_build_custom', copr) 367 368 def factory(**build_options): 369 BuildsLogic.create_new_from_custom( 370 flask.g.user, 371 copr, 372 form.script.data, 373 form.chroot.data, 374 form.builddeps.data, 375 form.resultdir.data, 376 chroot_names=form.selected_chroots, 377 **build_options 378 )
379 380 form = forms.BuildFormCustomFactory(copr.active_chroots)() 381 382 return process_new_build(copr, form, factory, render_add_build_custom, 383 view, url_on_success) 384
385 386 387 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_custom/") 388 @coprs_ns.route("/<username>/<coprname>/add_build_custom/") 389 @login_required 390 @req_with_copr 391 -def copr_add_build_custom(copr, form=None):
392 return render_add_build_custom(copr, form, 393 'coprs_ns.copr_new_build_custom')
394
395 -def render_add_build_custom(copr, form, view, package=None):
396 if not form: 397 form = forms.BuildFormCustomFactory(copr.active_chroots)() 398 return flask.render_template("coprs/detail/add_build/custom.html", 399 copr=copr, form=form, view=view)
400
401 402 ################################ Upload builds ################################ 403 404 @coprs_ns.route("/<username>/<coprname>/add_build_upload/") 405 @login_required 406 @req_with_copr 407 -def copr_add_build_upload(copr, form=None):
408 return render_add_build_upload( 409 copr, form, view='coprs_ns.copr_new_build_upload')
410
411 412 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_upload/") 413 @login_required 414 @req_with_copr 415 -def group_copr_add_build_upload(copr, form=None):
416 return render_add_build_upload( 417 copr, form, view='coprs_ns.copr_new_build_upload')
418
419 420 -def render_add_build_upload(copr, form, view):
421 if not form: 422 form = forms.BuildFormUploadFactory(copr.active_chroots)() 423 return flask.render_template("coprs/detail/add_build/upload.html", 424 copr=copr, form=form, view=view)
425
426 427 @coprs_ns.route("/<username>/<coprname>/new_build_upload/", methods=["POST"]) 428 @login_required 429 @req_with_copr 430 -def copr_new_build_upload(copr):
431 view = 'coprs_ns.copr_new_build_upload' 432 url_on_success = url_for("coprs_ns.copr_builds", 433 username=copr.user.username, coprname=copr.name) 434 return process_new_build_upload(copr, view, url_on_success)
435
436 437 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_upload/", methods=["POST"]) 438 @login_required 439 @req_with_copr 440 -def group_copr_new_build_upload(copr):
441 view = 'coprs_ns.copr_new_build_upload' 442 url_on_success = url_for("coprs_ns.group_copr_builds", 443 group_name=copr.group.name, coprname=copr.name) 444 return process_new_build_upload(copr, view, url_on_success)
445
446 447 -def process_new_build_upload(copr, add_view, url_on_success):
448 def factory(**build_options): 449 BuildsLogic.create_new_from_upload( 450 flask.g.user, copr, 451 f_uploader=lambda path: form.pkgs.data.save(path), 452 orig_filename=form.pkgs.data.filename, 453 chroot_names=form.selected_chroots, 454 **build_options 455 )
456 form = forms.BuildFormUploadFactory(copr.active_chroots)() 457 return process_new_build(copr, form, factory, render_add_build_upload, add_view, url_on_success) 458
459 460 ################################ Builds rebuilds ################################ 461 462 @coprs_ns.route("/<username>/<coprname>/new_build_rebuild/<int:build_id>/", methods=["POST"]) 463 @login_required 464 @req_with_copr 465 -def copr_new_build_rebuild(copr, build_id):
466 view='coprs_ns.copr_new_build' 467 url_on_success = url_for( 468 "coprs_ns.copr_builds", 469 username=copr.user.username, coprname=copr.name) 470 471 return process_rebuild(copr, build_id, view=view, url_on_success=url_on_success)
472
473 474 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_rebuild/<int:build_id>/", methods=["POST"]) 475 @login_required 476 @req_with_copr 477 -def group_copr_new_build_rebuild(copr, build_id):
478 view='coprs_ns.copr_new_build' 479 url_on_success = url_for( 480 "coprs_ns.group_copr_builds", 481 group_name=copr.group.name, coprname=copr.name) 482 483 return process_rebuild(copr, build_id, view=view, url_on_success=url_on_success)
484
485 486 -def process_rebuild(copr, build_id, view, url_on_success):
487 def factory(**build_options): 488 source_build = ComplexLogic.get_build_safe(build_id) 489 BuildsLogic.create_new_from_other_build( 490 flask.g.user, copr, source_build, 491 chroot_names=form.selected_chroots, 492 **build_options 493 )
494 form = forms.BuildFormRebuildFactory.create_form_cls(copr.active_chroots)() 495 return process_new_build(copr, form, factory, render_add_build, view, url_on_success) 496 497 498 ################################ Repeat ################################ 499 500 @coprs_ns.route("/<username>/<coprname>/repeat_build/<int:build_id>/", 501 methods=["GET", "POST"])
502 @login_required 503 @req_with_copr 504 -def copr_repeat_build(copr, build_id):
505 return process_copr_repeat_build(build_id, copr)
506 507 508 @coprs_ns.route("/g/<group_name>/<coprname>/repeat_build/<int:build_id>/", 509 methods=["GET", "POST"])
510 @login_required 511 @req_with_copr 512 -def group_copr_repeat_build(copr, build_id):
513 return process_copr_repeat_build(build_id, copr)
514
515 516 -def process_copr_repeat_build(build_id, copr):
517 build = ComplexLogic.get_build_safe(build_id) 518 if not flask.g.user.can_build_in(build.copr): 519 flask.flash("You are not allowed to repeat this build.") 520 521 if build.source_type == helpers.BuildSourceEnum('upload'): 522 # If the original build's source is 'upload', we will show only the 523 # original build's chroots and skip import. 524 available_chroots = build.chroots 525 526 else: 527 # For all other sources, we will show all chroots enabled in the project 528 # and proceed with import. 529 available_chroots = copr.active_chroots 530 531 form = forms.BuildFormRebuildFactory.create_form_cls(available_chroots)( 532 build_id=build_id, enable_net=build.enable_net) 533 534 # remove all checkboxes by default 535 for ch in available_chroots: 536 field = getattr(form, ch.name) 537 field.data = False 538 chroot_to_build = request.args.get("chroot") 539 app.logger.debug("got param chroot: {}".format(chroot_to_build)) 540 if chroot_to_build: 541 # set single checkbox if chroot query arg was provided 542 if hasattr(form, chroot_to_build): 543 getattr(form, chroot_to_build).data = True 544 else: 545 build_chroot_names = set(ch.name for ch in build.chroots) 546 build_failed_chroot_names = set(ch.name for ch in build.get_chroots_by_status([ 547 helpers.StatusEnum('failed'), helpers.StatusEnum('canceled'), 548 ])) 549 for ch in available_chroots: 550 # check checkbox on all the chroots that have not been (successfully) built before 551 if (ch.name not in build_chroot_names) or (ch.name in build_failed_chroot_names): 552 getattr(form, ch.name).data = True 553 return flask.render_template( 554 "coprs/detail/add_build/rebuild.html", 555 copr=copr, build=build, form=form)
556
557 558 ################################ Cancel ################################ 559 560 -def process_cancel_build(build):
561 try: 562 builds_logic.BuildsLogic.cancel_build(flask.g.user, build) 563 except InsufficientRightsException as e: 564 flask.flash(str(e), "error") 565 else: 566 db.session.commit() 567 flask.flash("Build {} has been canceled successfully.".format(build.id), "success") 568 return flask.redirect(helpers.url_for_copr_builds(build.copr))
569 570 571 @coprs_ns.route("/<username>/<coprname>/cancel_build/<int:build_id>/", 572 methods=["POST"])
573 @login_required 574 -def copr_cancel_build(username, coprname, build_id):
575 # only the user who ran the build can cancel it 576 build = ComplexLogic.get_build_safe(build_id) 577 return process_cancel_build(build)
578 579 580 @coprs_ns.route("/g/<group_name>/<coprname>/cancel_build/<int:build_id>/", 581 methods=["POST"])
582 @login_required 583 -def group_copr_cancel_build(group_name, coprname, build_id):
584 build = ComplexLogic.get_build_safe(build_id) 585 return process_cancel_build(build)
586 587 588 ################################ Delete ################################ 589 590 @coprs_ns.route("/<username>/<coprname>/delete_build/<int:build_id>/", 591 methods=["POST"])
592 @login_required 593 -def copr_delete_build(username, coprname, build_id):
594 build = ComplexLogic.get_build_safe(build_id) 595 596 try: 597 builds_logic.BuildsLogic.delete_build(flask.g.user, build) 598 except (InsufficientRightsException, ActionInProgressException) as e: 599 flask.flash(str(e), "error") 600 else: 601 db.session.commit() 602 flask.flash("Build has been deleted successfully.", "success") 603 604 return flask.redirect(helpers.url_for_copr_builds(build.copr))
605