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