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