MT#61875 build: support failed BuildRelease

In order to allow to keep information of failed builds. Before
we had to remove the info from a failed build in order to trigger
another full build.

Change-Id: I7cfcbedecdfed81951391fcdd84bb5be3c1b9e24
master
Victor Seva 4 months ago
parent bc9d1820e3
commit 37b7994091

@ -0,0 +1,17 @@
# Generated by Django 3.2.18 on 2025-01-14 16:05
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("build", "0006_alter_buildrelease_options"),
]
operations = [
migrations.AddField(
model_name="buildrelease",
name="failed",
field=models.BooleanField(default=False),
),
]

@ -151,6 +151,7 @@ class BuildRelease(models.Model):
failed_projects = models.TextField(null=True, editable=False)
pool_size = models.SmallIntegerField(default=0, editable=False)
triggered_jobs = models.TextField(null=True, editable=False)
failed = models.BooleanField(default=False, editable=True)
objects = BuildReleaseManager()
class Meta:
@ -197,6 +198,8 @@ class BuildRelease(models.Model):
@property
def done(self):
if self.failed:
return True
if self.built_projects is None:
return False
built_len = len(self.built_projects)

@ -88,6 +88,11 @@ class BuildReleaseDetail(generics.RetrieveDestroyAPIView):
instance.resume()
serializer = self.get_serializer(instance)
return Response(serializer.data)
elif action == "failed":
instance.failed = True
instance.save()
serializer = self.get_serializer(instance)
return Response(serializer.data)
return JsonResponse({"error": "Action unknown"}, status=400)

@ -58,6 +58,46 @@ function resume_build( id ) {
} );
}
/* eslint-disable-next-line no-unused-vars*/ // used at onClick
function click_failed( e, id ) {
mark_build_failed( id );
e.preventDefault();
}
function mark_build_failed( id ) {
function successFunc( _data, _textStatus, _jqXHR ) {
$( "#failed" ).prop( "disabled", true );
$( "#resume" ).prop( "disabled", true );
}
function errorFunc( _jqXHR, _status, error ) {
$( "#release_error" ).html( error );
}
var csrftoken = jQuery( "[name=csrfmiddlewaretoken]" ).val();
function csrfSafeMethod( method ) {
// these HTTP methods do not require CSRF protection
return ( /^(GET|HEAD|OPTIONS|TRACE)$/.test( method ) );
}
$.ajaxSetup( {
beforeSend: function( xhr, settings ) {
if ( !csrfSafeMethod( settings.type ) && !this.crossDomain ) {
xhr.setRequestHeader( "X-CSRFToken", csrftoken );
}
}
} );
$.ajax( {
url: "/build/" + id + "/?format=json",
data: JSON.stringify( { action: "failed" } ),
method: "PATCH",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: successFunc,
error: errorFunc
} );
}
function clean_all_uuids( project ) {
for ( var uuid of $.release[ project ].uuids ) {
$( "#" + project + "-" + uuid ).remove();

@ -23,6 +23,10 @@
disabled="disabled"
onclick="click_resume(event, '{{ build_release.id }}')"
class="btn btn-primary">Resume</button>
<button type="button" id="failed"
{% if build_release.failed %}disabled="disabled"{% endif %}
onclick="click_failed(event, '{{ build_release.id }}')"
class="btn btn-danger">Mark Failed</button>
{% endif %}
</td>
</tr>

@ -41,14 +41,17 @@
<th>Action</th>
</tr>
{% for br in build_releases %}
<tr class="success build_release" id="br_{{ br.id }}">
<tr class="{% if br.failed %}warning{% else %}success{% endif %} build_release" id="br_{{ br.id }}">
<td><a href="{% url 'panel:release-uuid' _uuid=br.uuid %}">{{ br.uuid }}</a></td>
<td>{{ br.start_date }}</td>
<td>{{ br.last_update }}</td>
<td>
<button type="button" id="refresh_{{ br.id }}"
{% if perms.build.can_trigger %}onclick="click_refresh_projects(event, '{{ br.id }}')"{% endif %}
class="btn btn-primary" {% if not perms.build.can_trigger %}disabled="disabled"{% endif %}>Refresh projects</button>
class="btn btn-primary" {% if not perms.build.can_trigger or br.done %}disabled="disabled"{% endif %}>Refresh projects</button>
<button type="button" id="failed_{{ br.id }}"
{% if perms.build.can_trigger %}onclick="click_failed(event, '{{ br.id }}')"{% endif %}
class="btn btn-danger" {% if br.failed %}disabled="disabled"{% endif %}>Mark failed</button>
<button type="button"
{% if perms.build.can_trigger %}onclick="click_delete(event, '{{ br.id }}')"{% endif %}
class="btn btn-danger" {% if not perms.build.can_trigger %}disabled="disabled"{% endif %}>Delete</button>
@ -172,5 +175,48 @@ function refresh_release_projects( id ) {
error: errorFunc
} );
}
/* eslint-disable-next-line no-unused-vars*/ // used at onClick
function click_failed( e, id ) {
mark_build_failed( id );
e.preventDefault();
}
function mark_build_failed( id ) {
function successFunc( _data, _textStatus, _jqXHR ) {
$("#br_" + id).removeClass("success");
$("#br_" + id).addClass("warning");
$("#build_button" ).removeAttr("disabled");
$("#failed_" + id ).attr("disabled", "disabled");
$("#refresh_" + id).attr("disabled", "disabled");
}
function errorFunc( _jqXHR, _status, error ) {
$( "#error" ).html( error );
}
var csrftoken = jQuery( "[name=csrfmiddlewaretoken]" ).val();
function csrfSafeMethod( method ) {
// these HTTP methods do not require CSRF protection
return ( /^(GET|HEAD|OPTIONS|TRACE)$/.test( method ) );
}
$.ajaxSetup( {
beforeSend: function( xhr, settings ) {
if ( !csrfSafeMethod( settings.type ) && !this.crossDomain ) {
xhr.setRequestHeader( "X-CSRFToken", csrftoken );
}
}
} );
$.ajax( {
url: "/build/" + id + "/?format=json",
data: JSON.stringify( { action: "failed" } ),
method: "PATCH",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: successFunc,
error: errorFunc
} );
}
</script>
{% endblock %}
Loading…
Cancel
Save