summaryrefslogtreecommitdiff
path: root/test/utils
diff options
context:
space:
mode:
authorMatt Clay <matt@mystile.com>2019-08-05 11:27:37 -0700
committerGitHub <noreply@github.com>2019-08-05 11:27:37 -0700
commitd3da8e4a5b7c87ea6bb4f1345300ddb0a833a6b2 (patch)
tree7ba508da69df460058f5fa9bf07ffb7b01aa644b /test/utils
parent41235ac05a7a52f102422da17d40b5952e722095 (diff)
downloadansible-d3da8e4a5b7c87ea6bb4f1345300ddb0a833a6b2.tar.gz
Replace old shippable.py with new check_matrix.py. (#60022)
This new script does not depend on ansible-test and provides much more robust job matrix testing. It is also run on every job in the matrix now, to detect issues with jobs being re-run after matrix changes are made.
Diffstat (limited to 'test/utils')
-rwxr-xr-xtest/utils/shippable/check_matrix.py107
-rwxr-xr-xtest/utils/shippable/sanity.sh2
-rwxr-xr-xtest/utils/shippable/shippable.sh1
3 files changed, 108 insertions, 2 deletions
diff --git a/test/utils/shippable/check_matrix.py b/test/utils/shippable/check_matrix.py
new file mode 100755
index 0000000000..99e4ea88ff
--- /dev/null
+++ b/test/utils/shippable/check_matrix.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+"""Verify the currently executing Shippable test matrix matches the one defined in the "shippable.yml" file."""
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import datetime
+import json
+import os
+import re
+import sys
+import time
+
+try:
+ from typing import NoReturn
+except ImportError:
+ NoReturn = None
+
+try:
+ # noinspection PyCompatibility
+ from urllib2 import urlopen # pylint: disable=ansible-bad-import-from
+except ImportError:
+ # noinspection PyCompatibility
+ from urllib.request import urlopen
+
+
+def main(): # type: () -> None
+ """Main entry point."""
+ with open('shippable.yml', 'rb') as yaml_file:
+ yaml = yaml_file.read().decode('utf-8').splitlines()
+
+ defined_matrix = [match.group(1) for match in [re.search(r'^ *- env: T=(.*)$', line) for line in yaml] if match and match.group(1) != 'none']
+
+ if not defined_matrix:
+ fail('No matrix entries found in the "shippable.yml" file.',
+ 'Did you modify the "shippable.yml" file?')
+
+ run_id = os.environ['SHIPPABLE_BUILD_ID']
+ sleep = 1
+ jobs = []
+
+ for attempts_remaining in range(4, -1, -1):
+ try:
+ jobs = json.loads(urlopen('https://api.shippable.com/jobs?runIds=%s' % run_id).read())
+
+ if not isinstance(jobs, list):
+ raise Exception('Shippable run %s data is not a list.' % run_id)
+
+ break
+ except Exception as ex:
+ if not attempts_remaining:
+ fail('Unable to retrieve Shippable run %s matrix.' % run_id,
+ str(ex))
+
+ sys.stderr.write('Unable to retrieve Shippable run %s matrix: %s\n' % (run_id, ex))
+ sys.stderr.write('Trying again in %d seconds...\n' % sleep)
+ time.sleep(sleep)
+ sleep *= 2
+
+ if len(jobs) != len(defined_matrix):
+ if len(jobs) == 1:
+ hint = '\n\nMake sure you do not use the "Rebuild with SSH" option.'
+ else:
+ hint = ''
+
+ fail('Shippable run %s has %d jobs instead of the expected %d jobs.' % (run_id, len(jobs), len(defined_matrix)),
+ 'Try re-running the entire matrix.%s' % hint)
+
+ actual_matrix = dict((job.get('jobNumber'), dict(tuple(line.split('=', 1)) for line in job.get('env', [])).get('T', '')) for job in jobs)
+ errors = [(job_number, test, actual_matrix.get(job_number)) for job_number, test in enumerate(defined_matrix, 1) if actual_matrix.get(job_number) != test]
+
+ if len(errors):
+ error_summary = '\n'.join('Job %s expected "%s" but found "%s" instead.' % (job_number, expected, actual) for job_number, expected, actual in errors)
+
+ fail('Shippable run %s has a job matrix mismatch.' % run_id,
+ 'Try re-running the entire matrix.\n\n%s' % error_summary)
+
+
+def fail(message, output): # type: (str, str) -> NoReturn
+ # Include a leading newline to improve readability on Shippable "Tests" tab.
+ # Without this, the first line becomes indented.
+ output = '\n' + output.strip()
+
+ timestamp = datetime.datetime.utcnow().replace(microsecond=0).isoformat()
+
+ # hack to avoid requiring junit-xml, which isn't pre-installed on Shippable outside our test containers
+ xml = '''
+<?xml version="1.0" encoding="utf-8"?>
+<testsuites disabled="0" errors="1" failures="0" tests="1" time="0.0">
+\t<testsuite disabled="0" errors="1" failures="0" file="None" log="None" name="ansible-test" skipped="0" tests="1" time="0" timestamp="%s" url="None">
+\t\t<testcase classname="timeout" name="timeout">
+\t\t\t<error message="%s" type="error">%s</error>
+\t\t</testcase>
+\t</testsuite>
+</testsuites>
+''' % (timestamp, message, output)
+
+ with open('test/results/junit/check-matrix.xml', 'w') as junit_fd:
+ junit_fd.write(xml.lstrip())
+
+ sys.stderr.write(message + '\n')
+ sys.stderr.write(output + '\n')
+
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/utils/shippable/sanity.sh b/test/utils/shippable/sanity.sh
index 09d859b363..8a05ee2096 100755
--- a/test/utils/shippable/sanity.sh
+++ b/test/utils/shippable/sanity.sh
@@ -7,8 +7,6 @@ IFS='/:' read -ra args <<< "$1"
group="${args[1]}"
-shippable.py
-
if [ "${BASE_BRANCH:-}" ]; then
base_branch="origin/${BASE_BRANCH}"
else
diff --git a/test/utils/shippable/shippable.sh b/test/utils/shippable/shippable.sh
index 3571d3de4a..79aa5d08e9 100755
--- a/test/utils/shippable/shippable.sh
+++ b/test/utils/shippable/shippable.sh
@@ -133,4 +133,5 @@ fi
ansible-test env --dump --show --timeout "${timeout}" --color -v
+"test/utils/shippable/check_matrix.py"
"test/utils/shippable/${script}.sh" "${test}"