squad 1.87__py3-none-any.whl → 1.89__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- squad/api/rest.py +7 -1
- squad/ci/backend/lava.py +10 -7
- squad/ci/backend/tuxsuite.py +8 -1
- squad/ci/tasks.py +6 -2
- squad/core/callback.py +10 -4
- squad/core/history.py +4 -1
- squad/core/models.py +15 -3
- squad/core/utils.py +1 -1
- squad/frontend/comparison.py +6 -1
- squad/frontend/templates/squad/tests.jinja2 +1 -1
- squad/frontend/tests.py +2 -2
- squad/plugins/linux_log_parser.py +79 -32
- squad/version.py +1 -1
- {squad-1.87.dist-info → squad-1.89.dist-info}/METADATA +1 -1
- {squad-1.87.dist-info → squad-1.89.dist-info}/RECORD +19 -19
- {squad-1.87.dist-info → squad-1.89.dist-info}/WHEEL +1 -1
- {squad-1.87.dist-info → squad-1.89.dist-info}/COPYING +0 -0
- {squad-1.87.dist-info → squad-1.89.dist-info}/entry_points.txt +0 -0
- {squad-1.87.dist-info → squad-1.89.dist-info}/top_level.txt +0 -0
squad/api/rest.py
CHANGED
@@ -1190,7 +1190,13 @@ class BuildViewSet(NestedViewSetMixin, ModelViewSet):
|
|
1190
1190
|
raise ValidationError('url is required.')
|
1191
1191
|
return Response({'message': 'OK'}, status=status.HTTP_202_ACCEPTED)
|
1192
1192
|
except (ValidationError, IntegrityError) as e:
|
1193
|
-
|
1193
|
+
message = ""
|
1194
|
+
if hasattr(e, "messages"):
|
1195
|
+
message = ', '.join(e.messages)
|
1196
|
+
else:
|
1197
|
+
message = str(e)
|
1198
|
+
|
1199
|
+
return Response({'message': message}, status=status.HTTP_400_BAD_REQUEST)
|
1194
1200
|
|
1195
1201
|
@action(detail=True, methods=['get'], suffix='compare')
|
1196
1202
|
def compare(self, request, pk=None):
|
squad/ci/backend/lava.py
CHANGED
@@ -396,9 +396,10 @@ class Backend(BaseBackend):
|
|
396
396
|
|
397
397
|
def __lava_job_name(self, definition):
|
398
398
|
yaml_definition = yaml.safe_load(definition)
|
399
|
-
if 'job_name' in yaml_definition.keys():
|
399
|
+
if type(yaml_definition) is dict and 'job_name' in yaml_definition.keys():
|
400
|
+
job_name = yaml_definition['job_name']
|
400
401
|
# only return first 255 characters
|
401
|
-
return
|
402
|
+
return job_name[:255] if job_name else ''
|
402
403
|
return None
|
403
404
|
|
404
405
|
def __resubmit__(self, job_id):
|
@@ -659,11 +660,13 @@ class Backend(BaseBackend):
|
|
659
660
|
suite = result['suite'].split("_", 1)[-1]
|
660
661
|
res_name = "%s/%s" % (suite, result['name'])
|
661
662
|
res_log = None
|
662
|
-
if 'log_start_line' in result.keys()
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
663
|
+
if 'log_start_line' in result.keys():
|
664
|
+
log_url = f"{self.job_url(test_job)}#L{result['log_start_line']}"
|
665
|
+
res_log = f"Testcase log: <a href='{log_url}'>{log_url}</a>\n"
|
666
|
+
if 'log_end_line' in result.keys() and \
|
667
|
+
result['log_start_line'] is not None and \
|
668
|
+
result['log_end_line'] is not None:
|
669
|
+
res_log += self.__download_test_log__(raw_logs, result['log_start_line'], result['log_end_line'])
|
667
670
|
# YAML from LAVA has all values serialized to strings
|
668
671
|
if result['measurement'] == 'None' or result['measurement'] is None:
|
669
672
|
res_value = result['result']
|
squad/ci/backend/tuxsuite.py
CHANGED
@@ -332,7 +332,14 @@ class Backend(BaseBackend):
|
|
332
332
|
test_job.name = ','.join(results['tests'])
|
333
333
|
|
334
334
|
if results['results'] == {}:
|
335
|
-
|
335
|
+
waiting_for = results.get('waiting_for')
|
336
|
+
if waiting_for is None:
|
337
|
+
test_job.failure = 'no results'
|
338
|
+
elif 'BUILD' in waiting_for:
|
339
|
+
test_job.failure = 'build failed'
|
340
|
+
else:
|
341
|
+
test_job.failure = 'sanity test failed'
|
342
|
+
|
336
343
|
return status, completed, metadata, tests, metrics, logs
|
337
344
|
|
338
345
|
# Fetch results even if the job fails, but has results
|
squad/ci/tasks.py
CHANGED
@@ -27,8 +27,12 @@ def poll(backend_id=None):
|
|
27
27
|
@celery.task
|
28
28
|
def fetch(job_id):
|
29
29
|
logger.info("fetching %s" % job_id)
|
30
|
-
|
31
|
-
|
30
|
+
try:
|
31
|
+
testjob = TestJob.objects.get(pk=job_id)
|
32
|
+
if testjob.job_id:
|
33
|
+
testjob.backend.fetch(testjob.id)
|
34
|
+
except TestJob.DoesNotExist:
|
35
|
+
return
|
32
36
|
|
33
37
|
|
34
38
|
@celery.task
|
squad/core/callback.py
CHANGED
@@ -56,12 +56,18 @@ def dispatch_callback(callback_object):
|
|
56
56
|
else:
|
57
57
|
args['data'] = json.loads(callback_object.payload)
|
58
58
|
|
59
|
-
|
60
|
-
|
59
|
+
try:
|
60
|
+
request = getattr(requests, callback_object.method)
|
61
|
+
response = request(callback_object.url, **args)
|
62
|
+
response_code = response.status_code
|
63
|
+
response_content = response.content
|
64
|
+
except requests.exceptions.RequestException as e:
|
65
|
+
response_code = None
|
66
|
+
response_content = str(e)
|
61
67
|
|
62
68
|
if callback_object.record_response:
|
63
|
-
callback_object.response_code =
|
64
|
-
callback_object.response_content =
|
69
|
+
callback_object.response_code = response_code
|
70
|
+
callback_object.response_content = response_content
|
65
71
|
|
66
72
|
callback_object.is_sent = True
|
67
73
|
callback_object.save()
|
squad/core/history.py
CHANGED
@@ -3,7 +3,7 @@ from django.core.paginator import Paginator
|
|
3
3
|
|
4
4
|
from squad.core.queries import test_confidence
|
5
5
|
from squad.core.utils import parse_name
|
6
|
-
from squad.core.models import SuiteMetadata, KnownIssue, Environment
|
6
|
+
from squad.core.models import SuiteMetadata, KnownIssue, Environment, Build
|
7
7
|
|
8
8
|
|
9
9
|
class TestResult(object):
|
@@ -49,6 +49,9 @@ class TestHistory(object):
|
|
49
49
|
self.number = page
|
50
50
|
builds = self.paginator.page(page)
|
51
51
|
|
52
|
+
if len(builds) == 0:
|
53
|
+
raise Build.DoesNotExist
|
54
|
+
|
52
55
|
self.top = builds[0]
|
53
56
|
|
54
57
|
issues_by_env = {}
|
squad/core/models.py
CHANGED
@@ -16,7 +16,7 @@ from django.db.models.query import prefetch_related_objects
|
|
16
16
|
from django.contrib.auth.models import User, AnonymousUser, Group as auth_group
|
17
17
|
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
18
18
|
from django.contrib.contenttypes.models import ContentType
|
19
|
-
from django.db.models.signals import post_save, pre_delete
|
19
|
+
from django.db.models.signals import post_save, pre_delete, pre_save
|
20
20
|
from django.dispatch import receiver
|
21
21
|
|
22
22
|
from django.conf import settings
|
@@ -1428,9 +1428,13 @@ class ProjectStatus(models.Model, TestSummaryBase):
|
|
1428
1428
|
return None
|
1429
1429
|
|
1430
1430
|
def __get_yaml_field__(self, field_value):
|
1431
|
-
if field_value is
|
1431
|
+
if field_value is None:
|
1432
|
+
return {}
|
1433
|
+
|
1434
|
+
try:
|
1432
1435
|
return yaml.load(field_value, Loader=yaml.Loader)
|
1433
|
-
|
1436
|
+
except yaml.YAMLError:
|
1437
|
+
return {}
|
1434
1438
|
|
1435
1439
|
def get_regressions(self):
|
1436
1440
|
return self.__get_yaml_field__(self.regressions)
|
@@ -1467,6 +1471,14 @@ class ProjectStatus(models.Model, TestSummaryBase):
|
|
1467
1471
|
return thresholds_exceeded
|
1468
1472
|
|
1469
1473
|
|
1474
|
+
@receiver(pre_save, sender=ProjectStatus)
|
1475
|
+
def validate_project_status(sender, instance, *args, **kwargs):
|
1476
|
+
yaml_validator(instance.regressions)
|
1477
|
+
yaml_validator(instance.fixes)
|
1478
|
+
yaml_validator(instance.metric_regressions)
|
1479
|
+
yaml_validator(instance.metric_fixes)
|
1480
|
+
|
1481
|
+
|
1470
1482
|
class NotificationDelivery(models.Model):
|
1471
1483
|
|
1472
1484
|
status = models.ForeignKey('ProjectStatus', related_name='deliveries', on_delete=models.CASCADE)
|
squad/core/utils.py
CHANGED
@@ -67,7 +67,7 @@ def yaml_validator(value):
|
|
67
67
|
if len(value) == 0:
|
68
68
|
return
|
69
69
|
try:
|
70
|
-
if not isinstance(yaml.
|
70
|
+
if not isinstance(yaml.load(value, Loader=yaml.Loader), dict):
|
71
71
|
raise ValidationError("Dictionary object expected")
|
72
72
|
except yaml.YAMLError as e:
|
73
73
|
raise ValidationError(e)
|
squad/frontend/comparison.py
CHANGED
@@ -3,6 +3,7 @@ from functools import reduce
|
|
3
3
|
from django.shortcuts import render, get_object_or_404
|
4
4
|
from django.core.paginator import Paginator
|
5
5
|
from django.db.models import Q, Prefetch
|
6
|
+
from django.http import HttpResponseNotFound
|
6
7
|
|
7
8
|
from squad.core.models import Project, Group, Build
|
8
9
|
from squad.core.comparison import TestComparison, MetricComparison
|
@@ -107,7 +108,11 @@ def compare_builds(request):
|
|
107
108
|
comparison = None
|
108
109
|
project = None
|
109
110
|
if project_slug:
|
110
|
-
|
111
|
+
group_and_project = project_slug.split('/')
|
112
|
+
if len(group_and_project) != 2:
|
113
|
+
return HttpResponseNotFound()
|
114
|
+
|
115
|
+
group_slug, project_slug = group_and_project
|
111
116
|
project = get_object_or_404(Project, group__slug=group_slug, slug=project_slug)
|
112
117
|
|
113
118
|
baseline_build = request.GET.get('baseline')
|
@@ -37,7 +37,7 @@
|
|
37
37
|
{% for status in test %}
|
38
38
|
<td class="{{status[0]}}"><a href="{{ test_history_url }}">{{status[0]}}{% if status[1] %} ({{status[1]}} %){% endif %}</a>
|
39
39
|
{% if status[2] %}
|
40
|
-
<a href='#' data-toggle="modal" data-target="#info_modal" data-status="{{ status[
|
40
|
+
<a href='#' data-toggle="modal" data-target="#info_modal" data-status="{{ status[2] }}"><span data-toggle="tooltip" data-placement="right" title="{{ _('Show info') }}" class='fa fa-info-circle'></span></a>
|
41
41
|
{% endif %}
|
42
42
|
</td>
|
43
43
|
{% endfor %}
|
squad/frontend/tests.py
CHANGED
@@ -6,7 +6,7 @@ from django.shortcuts import render, get_object_or_404
|
|
6
6
|
from django.http import Http404
|
7
7
|
|
8
8
|
from squad.http import auth
|
9
|
-
from squad.core.models import Test, Suite, SuiteMetadata, Environment
|
9
|
+
from squad.core.models import Build, Test, Suite, SuiteMetadata, Environment
|
10
10
|
from squad.core.history import TestHistory
|
11
11
|
from squad.core.queries import test_confidence
|
12
12
|
from squad.frontend.views import get_build
|
@@ -234,5 +234,5 @@ def test_history(request, group_slug, project_slug, build_version=None, testrun_
|
|
234
234
|
history = TestHistory(project, full_test_name, top=top, page=page)
|
235
235
|
context.update({"history": history})
|
236
236
|
return render(request, 'squad/test_history.jinja2', context)
|
237
|
-
except (Suite.DoesNotExist, SuiteMetadata.DoesNotExist) as e:
|
237
|
+
except (Suite.DoesNotExist, SuiteMetadata.DoesNotExist, Build.DoesNotExist) as e:
|
238
238
|
raise Http404(f"Test not found: {e}")
|
@@ -4,26 +4,28 @@ import re
|
|
4
4
|
from collections import defaultdict
|
5
5
|
from squad.plugins import Plugin as BasePlugin
|
6
6
|
from squad.core.models import SuiteMetadata
|
7
|
+
from django.template.defaultfilters import slugify
|
7
8
|
|
8
9
|
|
9
10
|
logger = logging.getLogger()
|
10
11
|
|
11
12
|
REGEX_NAME = 0
|
12
13
|
REGEX_BODY = 1
|
14
|
+
REGEX_EXTRACT_NAME = 2
|
13
15
|
|
14
16
|
MULTILINERS = [
|
15
|
-
('check-kernel-exception', r'-+\[? cut here \]?-+.*?-+\[? end trace \w* \]?-+'),
|
16
|
-
('check-kernel-kasan', r'=+\n\[[\s\.\d]+\]\s+BUG: KASAN:.*?=+'),
|
17
|
-
('check-kernel-kfence', r'=+\n\[[\s\.\d]+\]\s+BUG: KFENCE:.*?=+'),
|
17
|
+
('check-kernel-exception', r'-+\[? cut here \]?-+.*?-+\[? end trace \w* \]?-+', r"\d][^\+\n]*"),
|
18
|
+
('check-kernel-kasan', r'=+\n\[[\s\.\d]+\]\s+BUG: KASAN:.*?=+', r"BUG: KASAN:[^\+\n]*"),
|
19
|
+
('check-kernel-kfence', r'=+\n\[[\s\.\d]+\]\s+BUG: KFENCE:.*?=+', r"BUG: KFENCE:[^\+\n]*"),
|
18
20
|
]
|
19
21
|
|
20
22
|
ONELINERS = [
|
21
|
-
('check-kernel-oops', r'^[^\n]+Oops(?: -|:).*?$'),
|
22
|
-
('check-kernel-fault', r'^[^\n]+Unhandled fault.*?$'),
|
23
|
-
('check-kernel-warning', r'^[^\n]+WARNING:.*?$'),
|
24
|
-
('check-kernel-bug', r'^[^\n]+(?: kernel BUG at|BUG:).*?$'),
|
25
|
-
('check-kernel-invalid-opcode', r'^[^\n]+invalid opcode:.*?$'),
|
26
|
-
('check-kernel-panic', r'Kernel panic - not syncing.*?$'),
|
23
|
+
('check-kernel-oops', r'^[^\n]+Oops(?: -|:).*?$', r"Oops[^\+\n]*"),
|
24
|
+
('check-kernel-fault', r'^[^\n]+Unhandled fault.*?$', r"Unhandled [^\+\n]*"),
|
25
|
+
('check-kernel-warning', r'^[^\n]+WARNING:.*?$', r"WARNING: [^\+\n]*"),
|
26
|
+
('check-kernel-bug', r'^[^\n]+(?: kernel BUG at|BUG:).*?$', r"BUG[^\+\n]*"),
|
27
|
+
('check-kernel-invalid-opcode', r'^[^\n]+invalid opcode:.*?$', r"invalid opcode: [^\+\n]*"),
|
28
|
+
('check-kernel-panic', r'Kernel panic - not syncing.*?$', r"Kernel [^\+\n]*"),
|
27
29
|
]
|
28
30
|
|
29
31
|
# Tip: broader regexes should come first
|
@@ -70,33 +72,55 @@ class Plugin(BasePlugin):
|
|
70
72
|
snippets[regex_id].append(match[regex_id])
|
71
73
|
return snippets
|
72
74
|
|
73
|
-
def __create_tests(self, testrun, suite, test_name, lines):
|
75
|
+
def __create_tests(self, testrun, suite, test_name, lines, test_regex=None):
|
74
76
|
"""
|
75
77
|
There will be at least one test per regex. If there were any match for a given
|
76
78
|
regex, then a new test will be generated using test_name + shasum. This helps
|
77
79
|
comparing kernel logs accross different builds
|
78
80
|
"""
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
metadata=metadata,
|
85
|
-
build=testrun.build,
|
86
|
-
environment=testrun.environment,
|
87
|
-
)
|
88
|
-
|
89
|
-
# Some lines of the matched regex might be the same, and we don't want to create
|
90
|
-
# multiple tests like test1-sha1, test1-sha1, etc, so we'll create a set of sha1sums
|
91
|
-
# then create only new tests for unique sha's
|
81
|
+
# Run the REGEX_EXTRACT_NAME regex over the log lines to sort them by
|
82
|
+
# extracted name. If no name is extracted or the log parser did not
|
83
|
+
# have any output for a particular regex, just use the default name
|
84
|
+
# (for example "check-kernel-oops").
|
85
|
+
tests_to_create = defaultdict(set)
|
92
86
|
shas = defaultdict(set)
|
93
|
-
for line in lines:
|
94
|
-
sha = self.__create_shasum(line)
|
95
|
-
shas[sha].add(line)
|
96
87
|
|
97
|
-
|
98
|
-
|
88
|
+
# If there are no lines, use the default name and create a passing
|
89
|
+
# test. For example "check-kernel-oops"
|
90
|
+
if not lines:
|
91
|
+
tests_to_create[test_name] = []
|
92
|
+
|
93
|
+
# If there are lines, then create the tests for these.
|
94
|
+
for line in lines:
|
95
|
+
extracted_name = self.__create_name(line, test_regex)
|
96
|
+
if extracted_name:
|
97
|
+
extended_test_name = f"{test_name}-{extracted_name}"
|
98
|
+
else:
|
99
|
+
extended_test_name = test_name
|
100
|
+
tests_to_create[extended_test_name].add(line)
|
101
|
+
|
102
|
+
for name, lines in tests_to_create.items():
|
99
103
|
metadata, _ = SuiteMetadata.objects.get_or_create(suite=suite.slug, name=name, kind='test')
|
104
|
+
testrun.tests.create(
|
105
|
+
suite=suite,
|
106
|
+
result=(len(lines) == 0),
|
107
|
+
log='\n'.join(lines),
|
108
|
+
metadata=metadata,
|
109
|
+
build=testrun.build,
|
110
|
+
environment=testrun.environment,
|
111
|
+
)
|
112
|
+
|
113
|
+
# Some lines of the matched regex might be the same, and we don't want to create
|
114
|
+
# multiple tests like test1-sha1, test1-sha1, etc, so we'll create a set of sha1sums
|
115
|
+
# then create only new tests for unique sha's
|
116
|
+
|
117
|
+
for line in lines:
|
118
|
+
sha = self.__create_shasum(line)
|
119
|
+
name_with_sha = f"{name}-{sha}"
|
120
|
+
shas[name_with_sha].add(line)
|
121
|
+
|
122
|
+
for name_with_sha, lines in shas.items():
|
123
|
+
metadata, _ = SuiteMetadata.objects.get_or_create(suite=suite.slug, name=name_with_sha, kind='test')
|
100
124
|
testrun.tests.create(
|
101
125
|
suite=suite,
|
102
126
|
result=False,
|
@@ -106,11 +130,30 @@ class Plugin(BasePlugin):
|
|
106
130
|
environment=testrun.environment,
|
107
131
|
)
|
108
132
|
|
133
|
+
def __remove_numbers_and_time(self, snippet):
|
134
|
+
without_numbers = re.sub(r"(0x[a-f0-9]+|[<\[][0-9a-f]+?[>\]]|\d+)", "", snippet)
|
135
|
+
without_time = re.sub(r"^\[[^\]]+\]", "", without_numbers)
|
136
|
+
|
137
|
+
return without_time
|
138
|
+
|
139
|
+
def __create_name(self, snippet, regex=None):
|
140
|
+
matches = None
|
141
|
+
if regex:
|
142
|
+
matches = regex.findall(snippet)
|
143
|
+
if not matches:
|
144
|
+
return None
|
145
|
+
snippet = matches[0]
|
146
|
+
without_numbers_and_time = self.__remove_numbers_and_time(snippet)
|
147
|
+
|
148
|
+
# Limit the name length to 191 characters, since the max name length
|
149
|
+
# for SuiteMetadata in SQUAD is 256 characters. The SHA and "-" take 65
|
150
|
+
# characters: 256-65=191
|
151
|
+
return slugify(without_numbers_and_time)[:191]
|
152
|
+
|
109
153
|
def __create_shasum(self, snippet):
|
110
154
|
sha = hashlib.sha256()
|
111
|
-
|
112
|
-
|
113
|
-
sha.update(without_time.encode())
|
155
|
+
without_numbers_and_time = self.__remove_numbers_and_time(snippet)
|
156
|
+
sha.update(without_numbers_and_time.encode())
|
114
157
|
return sha.hexdigest()
|
115
158
|
|
116
159
|
def postprocess_testrun(self, testrun):
|
@@ -133,4 +176,8 @@ class Plugin(BasePlugin):
|
|
133
176
|
|
134
177
|
for regex_id in range(len(REGEXES)):
|
135
178
|
test_name = REGEXES[regex_id][REGEX_NAME]
|
136
|
-
|
179
|
+
regex_pattern = REGEXES[regex_id][REGEX_EXTRACT_NAME]
|
180
|
+
test_name_regex = None
|
181
|
+
if regex_pattern:
|
182
|
+
test_name_regex = re.compile(regex_pattern, re.S | re.M)
|
183
|
+
self.__create_tests(testrun, suite, test_name, snippets[regex_id], test_name_regex)
|
squad/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '1.
|
1
|
+
__version__ = '1.89'
|
@@ -10,14 +10,14 @@ squad/manage.py,sha256=Z-LXT67p0R-IzwJ9fLIAacEZmU0VUjqDOSg7j2ZSxJ4,1437
|
|
10
10
|
squad/settings.py,sha256=CRmnXFDrfdspzXGUIlffRcKMQizJ4Wzyyg1cIRu-h-M,14535
|
11
11
|
squad/socialaccount.py,sha256=vySqPwQ3qVVpahuJ-Snln8K--yzRL3bw4Nx27AsB39A,789
|
12
12
|
squad/urls.py,sha256=JiEfVW8YlzLPE52c2aHzdn5kVVKK4o22w8h5KOA6QhQ,2776
|
13
|
-
squad/version.py,sha256=
|
13
|
+
squad/version.py,sha256=DHemnt4WEI99t3epDIiaS6j6mPKaFVroxzlr9RNdMCU,21
|
14
14
|
squad/wsgi.py,sha256=SF8T0cQ0OPVyuYjO5YXBIQzvSXQHV0M2BTmd4gP1rPs,387
|
15
15
|
squad/api/__init__.py,sha256=CJiVakfAlHVN5mIFRVQYZQfuNUhUgWVbsdYTME4tq7U,1349
|
16
16
|
squad/api/apps.py,sha256=Trk72p-iV1uGn0o5mdJn5HARUoHGbfgO49jwXvpkmdQ,141
|
17
17
|
squad/api/ci.py,sha256=ymG-eMKXpJgrVUiZcqJW-dYZQKvm1LkdR3TUMe4OSoM,6943
|
18
18
|
squad/api/data.py,sha256=obKDV0-neEvj5lPF9VED2gy_hpfhGtLJABYvSY38ing,2379
|
19
19
|
squad/api/filters.py,sha256=Zvp8DCJmiNquFWqvfVseEAAMYYPiT95RUjqKdzcqSnw,6917
|
20
|
-
squad/api/rest.py,sha256=
|
20
|
+
squad/api/rest.py,sha256=ZtbK0c1BLPPnsX79XlKFVYONM_VJ0vacWZ2JsdCd4l0,77342
|
21
21
|
squad/api/urls.py,sha256=rmsdaL1uOCVSZ5x1redup9RliICmijaBjRK5ObsTkG8,1343
|
22
22
|
squad/api/utils.py,sha256=Sa8QFId3_oSqD2UOoY3Kuh54LLDLPNMq2sub5ktd6Fs,1160
|
23
23
|
squad/api/views.py,sha256=kuFlbiyZiD0i9jwwmkL3Y22LwJ3bx2oJs28d1g2DPA0,3898
|
@@ -26,13 +26,13 @@ squad/ci/admin.py,sha256=7yB-6F0cvt0NVvzGOTlZCyGPV_YHarmbKJZTTzataT4,2255
|
|
26
26
|
squad/ci/apps.py,sha256=6OVnzTdJkxdqEJnKWYE9dZgUcc29_T1LrDw41cK4EQk,139
|
27
27
|
squad/ci/exceptions.py,sha256=a1sccygniTYDSQi7FRn_6doapddFFiMf55AwGUh5Y80,227
|
28
28
|
squad/ci/models.py,sha256=Fm-4b3SDgMh9HXzqjOd4iZDRMJ1D9AnZ2cg7i2OR248,16018
|
29
|
-
squad/ci/tasks.py,sha256=
|
29
|
+
squad/ci/tasks.py,sha256=P0NYjLuyUViTpO1jZMuRVREbFDCccrMCZDw5E4pt928,3882
|
30
30
|
squad/ci/utils.py,sha256=38zHpw8xkZDSFlkG-2BwSK6AkcddK9OkN9LXuQ3SHR0,97
|
31
31
|
squad/ci/backend/__init__.py,sha256=yhpotXT9F4IdAOXvGQ3-17eOHAFwoaqf9SnMX17ab30,534
|
32
32
|
squad/ci/backend/fake.py,sha256=9sPKndsGd5GDNPp35v-zfJWXZCbge-yXH3RBQGgTlPk,2340
|
33
|
-
squad/ci/backend/lava.py,sha256=
|
33
|
+
squad/ci/backend/lava.py,sha256=E4QE0XtAiqArzzx3YSv7_2qYUBs4aSw8JOz0AV0z9W8,33877
|
34
34
|
squad/ci/backend/null.py,sha256=0CVylWELIZw3JyzCROB4XXAjgQUi15YjQz5caRfTNBo,5434
|
35
|
-
squad/ci/backend/tuxsuite.py,sha256
|
35
|
+
squad/ci/backend/tuxsuite.py,sha256=-A4p5HpUWnIC-61os0vdJOfAGoO81szoLkSgzyaUt6c,17901
|
36
36
|
squad/ci/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
37
|
squad/ci/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
38
|
squad/ci/management/commands/create_tuxsuite_boot_tests.py,sha256=JvjNusebLX71eyz9d-kaeCyekYSpzc1eXoeIqWK9ygo,4045
|
@@ -76,17 +76,17 @@ squad/ci/templatetags/filter_jobs.py,sha256=IkWjfSJSeImWlpHk2Tz_aiqalJvprStl5h2J
|
|
76
76
|
squad/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
77
77
|
squad/core/admin.py,sha256=tFyRu_rhHN-ABJkEApaT4YtRYa4qxNe-8jou2H3Q0P4,7897
|
78
78
|
squad/core/apps.py,sha256=Bl-4Yg0joKjygdifQG0ROIz4m5bHiPqytQ3G82uyzWc,143
|
79
|
-
squad/core/callback.py,sha256=
|
79
|
+
squad/core/callback.py,sha256=tzj5PFQFiambicGikUg4yjYJ9WW6hDbO2e1jRCgAhVQ,3282
|
80
80
|
squad/core/comparison.py,sha256=LR3-Unv0CTmakFCDzF_h8fm2peTJzkv79mQWNau1iwI,24429
|
81
81
|
squad/core/data.py,sha256=2zw56v7iYRTUc7wlhuUNgwIIMmK2w84hi-amR9J7EPU,2236
|
82
82
|
squad/core/failures.py,sha256=X6lJVghM2fOrd-RfuHeLlezW2pt7owDZ8eX-Kn_Qrt0,918
|
83
|
-
squad/core/history.py,sha256=
|
84
|
-
squad/core/models.py,sha256=
|
83
|
+
squad/core/history.py,sha256=QRSIoDOw6R6vUWMtsPMknsHGM7FaCAeuCYqASCayHTk,3541
|
84
|
+
squad/core/models.py,sha256=jAQpsCo4uNPF2f93LI-_Wfpu5TjUhHFf6LfwXA8grU0,60859
|
85
85
|
squad/core/notification.py,sha256=rOpO6F63w7_5l9gQgWBBEk-MFBjp7x_hVzoVIVyDze0,10030
|
86
86
|
squad/core/plugins.py,sha256=FLgyoXXKnPBYEf2MgHup9M017rHuADHivLhgzmx_cJE,6354
|
87
87
|
squad/core/queries.py,sha256=78fhIJZWXIlDryewYAt96beK1VJad66Ufu8cg3dHh4w,7698
|
88
88
|
squad/core/statistics.py,sha256=xyTHuhdBjcJ4AozZESjTzSD3dBmmCDgLpbg5XpeyO_M,1056
|
89
|
-
squad/core/utils.py,sha256=
|
89
|
+
squad/core/utils.py,sha256=jinGlLEnr8nL84OzBvm0VFGt6EzWWR0r4dOabDrbXfM,4908
|
90
90
|
squad/core/locale/django.pot,sha256=XycSJyEaEpozGBS9zu7QTNQbffZC0D9eSJ-AwXaVZx4,2282
|
91
91
|
squad/core/locale/es_MX/LC_MESSAGES/django.po,sha256=bwvTWHK2KOT6zFqbIYh61_xYqRnMaQECZsMsOvNdMNw,3071
|
92
92
|
squad/core/locale/pl/LC_MESSAGES/django.po,sha256=mI-Vo8OKWCcx4PrsoB6GiPY3lYU55tSqh0sO6fUeK2Y,3111
|
@@ -296,7 +296,7 @@ squad/frontend/apps.py,sha256=lKMd_HrIna5OZrfeWXndcGoIDR2KFmBFnMoGHtCGE4E,151
|
|
296
296
|
squad/frontend/badges.py,sha256=rEgjkJQKZQT1mL9j9s47okTQO-J55eU8mDNHShijovY,5878
|
297
297
|
squad/frontend/build_settings.py,sha256=_Hqw5npczuU01Zi6FGAiSbrtMMzK9eAXv-cX5U5btto,909
|
298
298
|
squad/frontend/ci.py,sha256=lfglUArCj5iYRLZgC6mDgEN_k-dDqfCezXW3j2Fn_Uc,2244
|
299
|
-
squad/frontend/comparison.py,sha256=
|
299
|
+
squad/frontend/comparison.py,sha256=Oy3Cffphy5qPsEGVAzICkCszb9JqHwaj-0RNMNxISLA,4721
|
300
300
|
squad/frontend/extract.py,sha256=p88JGuBvaC4AMDkJi7lqzbj5ZGh6h2LSlV7tcXbmxDc,8491
|
301
301
|
squad/frontend/forms.py,sha256=StPdrHsFsEoBKEOF6bBampLXbVXrZcEDkbuI4II1dCA,753
|
302
302
|
squad/frontend/group_settings.py,sha256=mV0kJEfRo41AEbOZMxWXY1MpYNqSgWVqac0dUdwkGyk,6232
|
@@ -304,7 +304,7 @@ squad/frontend/metrics.py,sha256=nGrfFHLG6g_DUYVJCIDlFLvLWhMrqJxX1Z0cckPBJlg,114
|
|
304
304
|
squad/frontend/project_settings.py,sha256=TtWz8h8Goeb3pccLy9jLUibeHqyqkdK8phL7_Vh_d0I,5045
|
305
305
|
squad/frontend/queries.py,sha256=NxQF2woAf9A4Wk_ozHzZXOGmr2as-j7hqfvmsfJ-ojc,967
|
306
306
|
squad/frontend/setup.py,sha256=NF9VunY1HJGB2HsHJss-go7EGmqr__JASddxiBCvmeQ,169
|
307
|
-
squad/frontend/tests.py,sha256=
|
307
|
+
squad/frontend/tests.py,sha256=PidrjaToK_Cks0s9Mc4i3Vh4UXOWoXTZlpnxQ2wWjHY,8740
|
308
308
|
squad/frontend/urls.py,sha256=biWauxwXR5j9kOfrSUqkv1Iqz-elB2aNViS9_UFoLzQ,4882
|
309
309
|
squad/frontend/user_settings.py,sha256=U_i59iuylg98uH98K4ezPa2NY56idslBhn7MS6FguHQ,4976
|
310
310
|
squad/frontend/utils.py,sha256=DeH58CJUI1dovpQrj3a-DcxNzM0cxsnBDOF0mrC4Qws,1364
|
@@ -397,7 +397,7 @@ squad/frontend/templates/squad/testjob.jinja2,sha256=hQLavgkYJ3qAKJMG7cHnmJGC1jd
|
|
397
397
|
squad/frontend/templates/squad/testjobs.jinja2,sha256=a90ltfoIWORB4i1mubA3cfQzX1IoSMqhYpAUc38RZSk,9632
|
398
398
|
squad/frontend/templates/squad/testjobs_progress.jinja2,sha256=4_o53GOdcClRdiNQxPHwvXPI9Ia07gTJRu5SGrCJ7s4,2638
|
399
399
|
squad/frontend/templates/squad/tests-details-nav.jinja2,sha256=WDi4vf0ctRK1dK1Z3IirBuyn5Dq9_qg_9A1P3GrB31U,664
|
400
|
-
squad/frontend/templates/squad/tests.jinja2,sha256=
|
400
|
+
squad/frontend/templates/squad/tests.jinja2,sha256=8JvKe8GwLMGvoTSkofbl6aT-QBKDodMYN7RfKTzWF6U,4970
|
401
401
|
squad/frontend/templates/squad/group_settings/advanced.jinja2,sha256=TbvNpZHK7fH3zx4Z_zwdmuhr8nev-jK8DhZ7_qQ7Osg,373
|
402
402
|
squad/frontend/templates/squad/group_settings/base.jinja2,sha256=Mywqt3uLMNT7NyaUXiG4nDvdJULLuVX9sb6vYkgR1nQ,1437
|
403
403
|
squad/frontend/templates/squad/group_settings/delete.jinja2,sha256=hO4mnNSph2D3qcAPUbffNgEdb-GsouSGxDRjcJ7NN8A,669
|
@@ -425,15 +425,15 @@ squad/plugins/__init__.py,sha256=9BSzy2jFIoDpWlhD7odPPrLdW4CC3btBhdFCvB651dM,152
|
|
425
425
|
squad/plugins/example.py,sha256=BKpwd315lHRIuNXJPteibpwfnI6C5eXYHYdFYBtVmsI,89
|
426
426
|
squad/plugins/gerrit.py,sha256=CqO2KnFQzu9utr_TQ-sGr1wg3ln0B-bS2-c0_i8T5-c,7009
|
427
427
|
squad/plugins/github.py,sha256=pdtLZw_7xNuzkaFvY_zWi0f2rsMlalXjKm7sz0eADz4,2429
|
428
|
-
squad/plugins/linux_log_parser.py,sha256=
|
428
|
+
squad/plugins/linux_log_parser.py,sha256=8GgIM4skM06uZX1d-15nZ0D4lxg5jOp9XYRvMtUtjA0,7195
|
429
429
|
squad/run/__init__.py,sha256=ssE8GPAGFiK6V0WpZYowav6Zqsd63dfDMMYasNa1sQg,1410
|
430
430
|
squad/run/__main__.py,sha256=DOl8JOi4Yg7DdtwnUeGqtYBJ6P2k-D2psAEuYOjWr8w,66
|
431
431
|
squad/run/listener.py,sha256=jBeOQhPGb4EdIREB1QsCzYuumsfJ-TqJPd3nR-0m59g,200
|
432
432
|
squad/run/scheduler.py,sha256=CDJG3q5C0GuQuxwlMOfWTSSJpDdwbR6rzpbJfuA0xuw,277
|
433
433
|
squad/run/worker.py,sha256=jtML0h5qKDuSbpJ6_rpWP4MT_rsGA7a24AhwGxBquzk,594
|
434
|
-
squad-1.
|
435
|
-
squad-1.
|
436
|
-
squad-1.
|
437
|
-
squad-1.
|
438
|
-
squad-1.
|
439
|
-
squad-1.
|
434
|
+
squad-1.89.dist-info/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
435
|
+
squad-1.89.dist-info/METADATA,sha256=Kb687CzcwB57kqLaoR1vJ9H6ESKXgDx5UToU4yOcZFg,1281
|
436
|
+
squad-1.89.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
|
437
|
+
squad-1.89.dist-info/entry_points.txt,sha256=apCDQydHZtvqV334ql6NhTJUAJeZRdtAm0TVcbbAi5Q,194
|
438
|
+
squad-1.89.dist-info/top_level.txt,sha256=_x9uqE1XppiiytmVTl_qNgpnXus6Gsef69HqfliE7WI,6
|
439
|
+
squad-1.89.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|