applications: mark element as in error on scan failure (#70981)
gitea-wip/hobo/pipeline/head There was a failure building this commit Details
gitea/hobo/pipeline/head Something is wrong with the build of this commit Details

This commit is contained in:
Lauréline Guérin 2022-11-04 09:54:55 +01:00
parent f699c76306
commit 25d01c5567
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
5 changed files with 82 additions and 2 deletions

View File

@ -0,0 +1,23 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0007_asyncjob'),
]
operations = [
migrations.AddField(
model_name='element',
name='error',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='element',
name='error_status',
field=models.CharField(
choices=[('notfound', 'Not Found'), ('error', 'Error')], max_length=100, null=True
),
),
]

View File

@ -98,12 +98,14 @@ class Application(models.Model):
continue
response = requests.get(dependencies_url)
if not response.ok:
el.set_error(response.status_code)
raise ScanError(
_(
'Failed to scan "%s" (type %s, slug %s) dependencies (%s)'
% (el.name, el.type, el.slug, response.status_code)
)
)
el.reset_error()
for dependency in response.json()['data']:
if (dependency['type'], dependency['id']) in elements:
continue
@ -127,6 +129,15 @@ class Element(models.Model):
slug = models.SlugField(max_length=500, verbose_name=_('Slug'))
name = models.CharField(max_length=500, verbose_name=_('Name'))
cache = JSONField(blank=True, default=dict)
error = models.BooleanField(default=False)
error_status = models.CharField(
max_length=100,
choices=[
('notfound', _('Not Found')),
('error', _('Error')),
],
null=True,
)
def __repr__(self):
return '<Element %s/%s>' % (self.type, self.slug)
@ -141,6 +152,16 @@ class Element(models.Model):
if self.cache['urls'].get('export'):
return '%sredirect/' % self.cache['urls']['export']
def set_error(self, http_status_code):
self.error = True
self.error_status = 'notfound' if http_status_code == 404 else 'error'
self.save()
def reset_error(self):
self.error = False
self.error_status = None
self.save()
class Relation(models.Model):
application = models.ForeignKey(Application, on_delete=models.CASCADE)

View File

@ -26,11 +26,14 @@
{% block content %}
<ul class="objects-list single-links">
<ul class="objects-list single-links application-content">
{% for relation in relations %}
{% if not relation.auto_dependency %}
<li>
<a {% if relation.element.get_redirect_url %}href="{{ relation.element.get_redirect_url }}"{% endif %}>{{ relation.element.name }} <span class="extra-info">- {{ relation.element.type_label }}</span></a>
<a {% if relation.element.get_redirect_url %}href="{{ relation.element.get_redirect_url }}"{% endif %}>
{% if relation.element.error %}<span class="tag tag-error">{{ relation.element.get_error_status_display }}</span>{% endif %}
{{ relation.element.name }} <span class="extra-info">- {{ relation.element.type_label }}</span>
</a>
{% if app.editable %}<a rel="popup" class="delete" href="{% url 'application-delete-element' app_slug=app.slug pk=relation.id %}">{% trans "remove" %}</a>{% endif %}
</li>
{% endif %}

View File

@ -343,6 +343,12 @@ h2.application-title {
}
}
ul.objects-list.application-content {
span.tag-error {
background: #CD2026;
}
}
#versions {
.version {
background: white;

View File

@ -382,6 +382,33 @@ def test_scandeps_on_unknown_element(app, admin_user, settings):
job = AsyncJob.objects.latest('pk')
assert job.status == 'failed'
assert job.exception == 'Failed to scan "Unknown" (type forms, slug unknown) dependencies (404)'
element.refresh_from_db()
assert element.error is True
assert element.error_status == 'notfound'
def response_content(url, request):
if url.path == '/api/export-import/forms/unknown/dependencies/':
return {'status_code': 500}
return mocked_http(url, request)
with HTTMock(response_content):
with pytest.raises(ScanError) as e:
app.get('/applications/manifest/test/scandeps/').follow()
assert str(e.value) == 'Failed to scan "Unknown" (type forms, slug unknown) dependencies (500)'
job = AsyncJob.objects.latest('pk')
assert job.status == 'failed'
assert job.exception == 'Failed to scan "Unknown" (type forms, slug unknown) dependencies (500)'
element.refresh_from_db()
assert element.error is True
assert element.error_status == 'error'
with HTTMock(mocked_http):
app.get('/applications/manifest/test/scandeps/').follow()
job = AsyncJob.objects.latest('pk')
assert job.status == 'completed'
element.refresh_from_db()
assert element.error is False
assert element.error_status is None
@pytest.mark.parametrize('editable', [True, False])