Skip to content

Commit

Permalink
Merge pull request #71 from SalesforceFoundation/issue-47
Browse files Browse the repository at this point in the history
Add some fields to Rebuild instead of overwriting info on Build
  • Loading branch information
jlantz authored Aug 11, 2017
2 parents a9eefcd + 26dd445 commit bd8da98
Show file tree
Hide file tree
Showing 19 changed files with 230 additions and 128 deletions.
32 changes: 32 additions & 0 deletions mrbelvedereci/build/migrations/0010_auto_20170810_2356.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-08-10 23:56
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('cumulusci', '0005_scratchorginstance_delete_error'),
('build', '0009_auto_20170809_1723'),
]

operations = [
migrations.AddField(
model_name='rebuild',
name='error_message',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='rebuild',
name='exception',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='rebuild',
name='org_instance',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rebuilds', to='cumulusci.ScratchOrgInstance'),
),
]
156 changes: 94 additions & 62 deletions mrbelvedereci/build/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import requests

from mrbelvedereci.build.utils import format_log
from mrbelvedereci.build.utils import set_build_info
from mrbelvedereci.cumulusci.config import MrbelvedereGlobalConfig
from mrbelvedereci.cumulusci.config import MrbelvedereProjectConfig
from mrbelvedereci.cumulusci.keychain import MrbelvedereProjectKeychain
Expand Down Expand Up @@ -96,13 +97,39 @@ def get_external_url(self):
url = '{}{}'.format(settings.SITE_URL, self.get_absolute_url())
return url

def get_build_attr(self, attr):
# get an attribute from the most recent build/rebuild
build = self.current_rebuild if self.current_rebuild else self
return getattr(build, attr)

def get_status(self):
return self.get_build_attr('status')

def get_exception(self):
return self.get_build_attr('exception')

def get_error_message(self):
return self.get_build_attr('error_message')

def get_time_queue(self):
return self.get_build_attr('time_queue')

def get_time_start(self):
return self.get_build_attr('time_start')

def get_time_end(self):
return self.get_build_attr('time_end')

def flush_log(self):
for handler in self.logger.handlers:
handler.stream.flush(force=True)

def run(self):
self.logger = init_logger(self)
self.set_running_status()
self.logger.info('-- Building commit {}'.format(self.commit))
self.flush_log()
build = self.current_rebuild if self.current_rebuild else self
set_build_info(build, status='running', time_start=timezone.now())

if self.schedule:
self.logger.info('Build triggered by {} schedule #{}'.format(
Expand All @@ -127,15 +154,9 @@ def run(self):

except Exception as e:
self.logger.error(unicode(e))
self.status = 'error'
self.time_end = timezone.now()
self.save()
set_build_info(build, status='error', time_end=timezone.now())
self.delete_build_dir()
self.flush_log()
if self.current_rebuild:
self.current_rebuild.status = self.status
self.current_rebuild.time_end = timezone.now()
self.current_rebuild.save()
return

# Run flows
Expand All @@ -161,17 +182,16 @@ def run(self):
flow, build_flow.status))
self.logger.error(' {}: {}'.format(build_flow.exception,
build_flow.error_message))
self.status = build_flow.status
self.exception = build_flow.exception
self.error_message = build_flow.error_message
self.time_end = timezone.now()
self.save()
set_build_info(
build,
status=build_flow.status,
exception=build_flow.exception,
error_message=build_flow.error_message,
time_end=timezone.now(),
)
self.flush_log()
if org_config.created:
self.delete_org(org_config)
if self.current_rebuild:
self.current_rebuild.status = self.status
self.current_rebuild.time_end = timezone.now()
self.current_rebuild.save()
return
else:
self.logger = init_logger(self)
Expand All @@ -182,45 +202,21 @@ def run(self):
self.save()

except Exception as e:
set_build_info(build, status='error', time_end=timezone.now())
if org_config.created:
self.delete_org(org_config)
self.logger = init_logger(self)
self.logger.error(unicode(e))
self.status = 'error'
self.time_end = timezone.now()
self.save()
self.delete_build_dir()
self.flush_log()
if self.current_rebuild:
self.current_rebuild.status = self.status
self.current_rebuild.time_end = timezone.now()
self.current_rebuild.save()
return

if org_config.created:
self.delete_org(org_config)

self.delete_build_dir()
self.flush_log()

# Set success status
self.status = 'success'
self.time_end = timezone.now()
self.save()
if self.current_rebuild:
self.current_rebuild.status = self.status
self.current_rebuild.time_end = timezone.now()
self.current_rebuild.save()

def set_running_status(self):
self.status = 'running'
self.time_start = timezone.now()
self.logger.info('-- Building commit {}'.format(self.commit))
self.save()
if self.current_rebuild:
self.current_rebuild.status = self.status
self.current_rebuild.time_start = timezone.now()
self.current_rebuild.save()
set_build_status(build, status='success', time_end=timezone.now())

def checkout(self):
zip_url = '{}/archive/{}.zip'.format(
Expand Down Expand Up @@ -261,10 +257,43 @@ def get_project_config(self):
def get_org(self, project_config):
org_config = project_config.keychain.get_org(self.plan.org)
self.org = org_config.org
self.org_instance = org_config.org_instance
if self.current_rebuild:
self.current_rebuild.org_instance = org_config.org_instance
self.current_rebuild.save()
else:
self.org_instance = org_config.org_instance
self.save()
return org_config

def get_org_instance(self):
if self.current_rebuild:
return self.current_rebuild.org_instance
else:
return self.org_instance

def get_org_attr(self, attr):
org_instance = self.get_org_instance()
obj = getattr(org_instance, attr, '')
return obj() if callable(obj) else obj

def get_org_deleted(self):
return self.get_org_attr('deleted')

def get_org_sf_org_id(self):
return self.get_org_attr('sf_org_id')

def get_org_name(self):
return self.get_org_attr('__unicode__')

def get_org_time_deleted(self):
return self.get_org_attr('time_deleted')

def get_org_url(self):
return self.get_org_attr('get_absolute_url')

def get_org_username(self):
return self.get_org_attr('username')

def delete_org(self, org_config):
self.logger = init_logger(self)
if not org_config.scratch:
Expand All @@ -274,7 +303,8 @@ def delete_org(self, org_config):
'Skipping scratch org deletion since keep_org was requested')
return
try:
self.org_instance.delete_org(org_config)
org_instance = self.get_org_instance()
org_instance.delete_org(org_config)
except Exception as e:
self.logger.error(e.message)
self.save()
Expand Down Expand Up @@ -317,12 +347,11 @@ def get_log_html(self):

def run(self, project_config, org_config):
# Record the start
self.set_running_status()
set_build_info(self, status='running', time_start=timezone.now())

# Set up logger
self.logger = init_logger(self)

exception = None
try:
# Run the flow
result = self.run_flow(project_config, org_config)
Expand All @@ -331,38 +360,37 @@ def run(self, project_config, org_config):
self.load_test_results()

# Record result
self.record_result()
exception = None
status = 'success'

except MetadataComponentFailure as e:
exception = e
self.status = 'fail'
status = 'fail'

except ApexTestException as e:
exception = e
self.load_test_results()
self.status = 'fail'
status = 'fail'

except BrowserTestFailure as e:
exception = e
self.load_test_results()
self.status = 'fail'
status = 'fail'

except Exception as e:
exception = e
self.status = 'error'
status = 'error'

kwargs = {
'status': status,
'time_end': timezone.now(),
}
if exception:
if self.status == 'error':
if status == 'error':
self.logger.error(unicode(e))
self.exception = e.__class__.__name__
self.error_message = unicode(e)
self.time_end = timezone.now()
self.save()

def set_running_status(self):
self.status = 'running'
self.time_start = timezone.now()
self.save()
kwargs['error_message'] = unicode(e)
kwargs['exception'] = e.__class__.__name__
set_build_info(self, **kwargs)

def run_flow(self, project_config, org_config):
# Add the repo root to syspath to allow for custom tasks and flows in
Expand Down Expand Up @@ -456,8 +484,12 @@ def load_junit(self, filename):
class Rebuild(models.Model):
build = models.ForeignKey('build.Build', related_name='rebuilds')
user = models.ForeignKey('users.User', related_name='rebuilds')
org_instance = models.ForeignKey('cumulusci.ScratchOrgInstance',
related_name='rebuilds', null=True, blank=True)
status = models.CharField(max_length=16, choices=BUILD_STATUSES,
default='queued')
exception = models.TextField(null=True, blank=True)
error_message = models.TextField(null=True, blank=True)
time_queue = models.DateTimeField(auto_now_add=True)
time_start = models.DateTimeField(null=True, blank=True)
time_end = models.DateTimeField(null=True, blank=True)
Expand Down
10 changes: 7 additions & 3 deletions mrbelvedereci/build/templates/build/build_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@
<div class="slds-truncate" title="{{ build.id }}"><a href="/builds/{{ build.id }}">{{ build.id }}</a></div>
</th>
<td data-label="Status">
<div class="slds-truncate slds-badge {% if build.status == 'fail' or build.status == 'error' %}slds-theme--error{% elif build.status == 'success' %}slds-theme--success{% endif %}" title="{{ build.status }}">{{ build.status }}</div>
<div
class="slds-truncate slds-badge {% if build.get_status == 'fail' or build.get_status == 'error' %}slds-theme--error{% elif build.get_status == 'success' %}slds-theme--success{% endif %}"
title="{{ build.get_status }}">
{{ build.get_status }}
</div>
</td>
<td data-label="Repository">
<div class="slds-truncate" title="{{ build.repo.name }}">{{ build.repo.name }}</div>
Expand All @@ -59,10 +63,10 @@
<div class="slds-truncate" title="{{ build.commit }}">{{ build.commit }}</div>
</td>
<td data-label="Start Date">
<div class="slds-truncate" title="{{ build.time_start }}">{{ build.time_start }}</div>
<div class="slds-truncate" title="{{ build.get_time_start }}">{{ build.get_time_start }}</div>
</td>
<td data-label="End Date">
<div class="slds-truncate" title="{{ build.time_end }}">{{ build.time_end }}</div>
<div class="slds-truncate" title="{{ build.get_time_end }}">{{ build.get_time_end }}</div>
</td>
</tr>
{% endfor %}
Expand Down
6 changes: 3 additions & 3 deletions mrbelvedereci/build/templates/build/detail.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{% extends "build/detail_layout.html" %}
{% block tab_content %}
{% if build.status == 'fail' or build.status == 'error' %}
{% if build.get_status == 'fail' or build.get_status == 'error' %}
<div class="slds-box slds-theme--warning slds-m-bottom--large">
<h3 class="slds-text-heading--large">Build Exception: {{ build.exception }}</h3>
<p>{{ build.error_message|linebreaks }}</p>
<h3 class="slds-text-heading--large">Build Exception: {{ build.get_exception }}</h3>
<p>{{ build.get_error_message|linebreaks }}</p>
</div>
{% endif %}
<div class="slds-box">
Expand Down
11 changes: 7 additions & 4 deletions mrbelvedereci/build/templates/build/detail_layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{% endblock %}

{% block layout_header_buttons %}
{% if request.user.is_staff and build.status != 'success' %}
{% if request.user.is_staff and build.get_status != 'success' %}
<div class="slds-button-group" role="group">
<a href="{{ build.get_absolute_url }}/rebuild">
<button class="slds-button slds-button--neutral">
Expand All @@ -28,8 +28,11 @@
<ul class="slds-grid slds-page-header__detail-row">
<li class="slds-page-header__detail-block">
<p class="slds-text-title slds-truncate slds-m-bottom--xx-small" title="Status">Status</p>
<p class="slds-text-body--regular slds-truncate" title="{{ build.status }}">
<div class="slds-badge {% if build.status == 'fail' or build.status == 'error' %}slds-theme--error{% elif build.status == 'success' %}slds-theme--success{% endif %}">{{ build.status }}</div>
<p class="slds-text-body--regular slds-truncate" title="{{ build.get_status }}">
<div
class="slds-badge {% if build.get_status == 'fail' or build.get_status == 'error' %}slds-theme--error{% elif build.get_status == 'success' %}slds-theme--success{% endif %}">
{{ build.get_status }}
</div>
</p>
</li>
<li class="slds-page-header__detail-block">
Expand Down Expand Up @@ -68,7 +71,7 @@
{% endblock %}

{% block layout_body %}
{% if build.status == 'queued' %}
{% if build.get_status == 'queued' %}
<div class="slds-box slds-theme--info">
<h3 class="slds-text-heading--medium">Waiting for a worker</h3>
<p>The build is currently queued and will start as soon as a worker is available.</p>
Expand Down
Loading

0 comments on commit bd8da98

Please sign in to comment.