Skip to content

Commit df33cad

Browse files
committed
TST: trigger travis OSX tests if Linux tests pass
Use travis_after_all to wait for all Linux tests to pass, before triggering the OSX tests at MacPython/matplotlib-wheels. Uses: * https://github.com/dmakhno/travis_after_all * https://github.com/ajdm/travis-build-children following model at: python-pillow/Pillow#1067 Authorization token to allow trigger of OSX build comes from: travis login travis token # My (Matthew Brett's) github token travis encrypt AUTH_TOKEN=<my_travis_token> The output becomes: env: global: - secure: "dfjNqGKzQG5bu3FnDNwLG8H/C4QoieFo4PfFmZPdM2RY7WIzukwKFNT6kiDfOrpwt+2bR7FhzjOGlDECGtlGOtYPN8XuXGjhcP4a4IfakdbDfF+D3NPIpf5VlE6776k0VpvcZBTMYJKNFIMc7QPkOwjvNJ2aXyfe3hBuGlKJzQU=" in .travis.yml
1 parent 1fe5b9c commit df33cad

File tree

3 files changed

+148
-13
lines changed

3 files changed

+148
-13
lines changed

.travis.yml

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ env:
44
- ARTIFACTS_S3_BUCKET=matplotlib-test-results
55
- secure: RgJI7BBL8aX5FTOQe7xiXqWHMxWokd6GNUWp1NUV2mRLXPb9dI0RXqZt3UJwKTAzf1z/OtlHDmEkBoTVK81E9iUxK5npwyyjhJ8yTJmwfQtQF2n51Q1Ww9p+XSLORrOzZc7kAo6Kw6FIXN1pfctgYq2bQkrwJPRx/oPR8f6hcbY=
66
- secure: E7OCdqhZ+PlwJcn+Hd6ns9TDJgEUXiUNEI0wu7xjxB2vBRRIKtZMbuaZjd+iKDqCKuVOJKu0ClBUYxmgmpLicTwi34CfTUYt6D4uhrU+8hBBOn1iiK51cl/aBvlUUrqaRLVhukNEBGZcyqAjXSA/Qsnp2iELEmAfOUa92ZYo1sk=
7+
- secure: "dfjNqGKzQG5bu3FnDNwLG8H/C4QoieFo4PfFmZPdM2RY7WIzukwKFNT6kiDfOrpwt+2bR7FhzjOGlDECGtlGOtYPN8XuXGjhcP4a4IfakdbDfF+D3NPIpf5VlE6776k0VpvcZBTMYJKNFIMc7QPkOwjvNJ2aXyfe3hBuGlKJzQU="
78
- BUILD_DOCS=false
89
- TEST_ARGS=--no-pep8
910
- NUMPY=numpy
@@ -51,26 +52,35 @@ script:
5152
# multiple processes
5253
- gcc --version
5354
- python -c "from matplotlib import font_manager"
54-
- if [[ $BUILD_DOCS == false ]]; then export MPL_REPO_DIR=$PWD; fi # pep8-conformance test of the examples
55-
- if [[ $BUILD_DOCS == false ]]; then mkdir ../tmp_test_dir; fi
56-
- if [[ $BUILD_DOCS == false ]]; then cd ../tmp_test_dir; fi
57-
- if [[ $BUILD_DOCS == false ]]; then gdb -return-child-result -batch -ex r -ex bt --args python ../matplotlib/tests.py -sv --processes=8 --process-timeout=300 $TEST_ARGS; fi
58-
- if [[ $BUILD_DOCS == true ]]; then cd doc; python make.py html --small --warningsaserrors; fi
59-
# We don't build the LaTeX docs here, so linkchecker will complain
60-
- if [[ $BUILD_DOCS == true ]]; then touch build/html/Matplotlib.pdf; fi
61-
- if [[ $BUILD_DOCS == true ]]; then linkchecker build/html/index.html; fi
55+
- |
56+
if [[ $BUILD_DOCS == false ]]; then
57+
export MPL_REPO_DIR=$PWD # pep8-conformance test of the examples
58+
mkdir ../tmp_test_dir
59+
cd ../tmp_test_dir
60+
gdb -return-child-result -batch -ex r -ex bt --args python ../matplotlib/tests.py -sv --processes=8 --process-timeout=300 $TEST_ARGS
61+
else
62+
cd doc
63+
python make.py html --small --warningsaserrors
64+
# We don't build the LaTeX docs here, so linkchecker will complain
65+
touch build/html/Matplotlib.pdf
66+
linkchecker build/html/index.html
67+
fi
6268
6369
after_failure:
64-
- tar cjf result_images.tar.bz2 result_images
65-
- if [[ $TRAVIS_PULL_REQUEST == false ]]; then gem install travis-artifacts; fi
66-
- if [[ $TRAVIS_PULL_REQUEST == false ]]; then travis-artifacts upload --path result_images.tar.bz2; fi
67-
- if [[ $TRAVIS_PULL_REQUEST != false ]]; then echo "The result images will only be uploaded if they are on the matplotlib/matplotlib repo - this is for security reasons to prevent arbitrary PRs echoing security details." else echo https://s3.amazonaws.com/matplotlib-test-results/artifacts/${TRAVIS_BUILD_NUMBER}/${TRAVIS_JOB_NUMBER}/result_images.tar.bz2; fi
70+
|
71+
if [[ $BUILD_DOCS == false && $TRAVIS_PULL_REQUEST == false && $TRAVIS_REPO_SLUG == 'matplotlib/matplotlib' ]]; then
72+
gem install travis-artifacts
73+
cd $MPL_REPO_DIR/../tmp_test_dir
74+
tar cjf result_images.tar.bz2 result_images
75+
travis-artifacts upload --path result_images.tar.bz2
76+
echo "The result images will only be uploaded if they are on the matplotlib/matplotlib repo - this is for security reasons to prevent arbitrary PRs echoing security details." else echo https://s3.amazonaws.com/matplotlib-test-results/artifacts/${TRAVIS_BUILD_NUMBER}/${TRAVIS_JOB_NUMBER}/result_images.tar.bz2
77+
fi
6878

6979
after_success:
7080
|
7181
if [[ $TRAVIS_PULL_REQUEST == false && $BUILD_DOCS == true && $TRAVIS_BRANCH == 'master' ]]; then
82+
cd $MPL_REPO_DIR
7283
echo "Uploading documentation"
73-
cd ..
7484
openssl aes-256-cbc -K $encrypted_cc802e084cd0_key -iv $encrypted_cc802e084cd0_iv -in .travis/matplotlibDeployKey.enc -out .travis/matplotlibDeployKey -d
7585
eval `ssh-agent -s`
7686
chmod 600 .travis/matplotlibDeployKey
@@ -90,3 +100,19 @@ after_success:
90100
else
91101
echo "Will only deploy docs build from matplotlib master branch"
92102
fi
103+
if [[ $TRAVIS_PULL_REQUEST == false ]] && \
104+
[[ $TRAVIS_REPO_SLUG == 'matplotlib/matplotlib' ]] && \
105+
[[ $TRAVIS_BRANCH == 'master' ]]; then
106+
cd $MPL_REPO_DIR
107+
python .travis/travis_after_all.py
108+
export $(cat .to_export_back)
109+
if [ "$BUILD_LEADER" = "YES" ]; then
110+
if [ "$BUILD_AGGREGATE_STATUS" = "others_succeeded" ]; then
111+
echo "All Succeeded! Triggering OSX build..."
112+
./.travis/build_children.sh
113+
else
114+
echo "Some Failed; no OSX build"
115+
fi
116+
fi
117+
fi
118+
fi

.travis/build_children.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
# Modified from:
3+
# https://github.com/ajdm/travis-build-children/blob/master/build_children.sh
4+
5+
# Get last child project build number from branch named "latest"
6+
BUILD_NUM=$(curl -s 'https://api.travis-ci.org/repos/MacPython/matplotlib-wheels/branches/latest' | grep -o '^{"branch":{"id":[0-9]*,' | grep -o '[0-9]' | tr -d '\n')
7+
8+
# Restart last child project build
9+
curl -X POST https://api.travis-ci.org/builds/$BUILD_NUM/restart --header "Authorization: token "$AUTH_TOKEN

.travis/travis_after_all.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Copied from:
2+
# https://github.com/dmakhno/travis_after_all
3+
# commit b7172bca9
4+
import os
5+
import json
6+
import time
7+
import logging
8+
9+
try:
10+
import urllib.request as urllib2
11+
except ImportError:
12+
import urllib2
13+
14+
log = logging.getLogger("travis.leader")
15+
log.addHandler(logging.StreamHandler())
16+
log.setLevel(logging.INFO)
17+
18+
TRAVIS_JOB_NUMBER = 'TRAVIS_JOB_NUMBER'
19+
TRAVIS_BUILD_ID = 'TRAVIS_BUILD_ID'
20+
POLLING_INTERVAL = 'LEADER_POLLING_INTERVAL'
21+
22+
build_id = os.getenv(TRAVIS_BUILD_ID)
23+
polling_interval = int(os.getenv(POLLING_INTERVAL, '5'))
24+
25+
#assume, first job is the leader
26+
is_leader = lambda job_number: job_number.endswith('.1')
27+
28+
if not os.getenv(TRAVIS_JOB_NUMBER):
29+
# seems even for builds with only one job, this won't get here
30+
log.fatal("Don't use defining leader for build without matrix")
31+
exit(1)
32+
elif is_leader(os.getenv(TRAVIS_JOB_NUMBER)):
33+
log.info("This is a leader")
34+
else:
35+
#since python is subprocess, env variables are exported back via file
36+
with open(".to_export_back", "w") as export_var:
37+
export_var.write("BUILD_MINION=YES")
38+
log.info("This is a minion")
39+
exit(0)
40+
41+
42+
class MatrixElement(object):
43+
def __init__(self, json_raw):
44+
self.is_finished = json_raw['finished_at'] is not None
45+
self.is_succeeded = json_raw['result'] == 0
46+
self.number = json_raw['number']
47+
self.is_leader = is_leader(self.number)
48+
49+
50+
def matrix_snapshot():
51+
"""
52+
:return: Matrix List
53+
"""
54+
response = urllib2.build_opener().open("https://api.travis-ci.org/builds/{0}".format(build_id)).read()
55+
raw_json = json.loads(response)
56+
matrix_without_leader = [MatrixElement(element) for element in raw_json["matrix"]]
57+
return matrix_without_leader
58+
59+
60+
def wait_others_to_finish():
61+
def others_finished():
62+
"""
63+
Dumps others to finish
64+
Leader cannot finish, it is working now
65+
:return: tuple(True or False, List of not finished jobs)
66+
"""
67+
snapshot = matrix_snapshot()
68+
finished = [el.is_finished for el in snapshot if not el.is_leader]
69+
return reduce(lambda a, b: a and b, finished), [el.number for el in snapshot if
70+
not el.is_leader and not el.is_finished]
71+
72+
while True:
73+
finished, waiting_list = others_finished()
74+
if finished: break
75+
log.info("Leader waits for minions {0}...".format(waiting_list)) # just in case do not get "silence timeout"
76+
time.sleep(polling_interval)
77+
78+
79+
try:
80+
wait_others_to_finish()
81+
82+
final_snapshot = matrix_snapshot()
83+
log.info("Final Results: {0}".format([(e.number, e.is_succeeded) for e in final_snapshot]))
84+
85+
BUILD_AGGREGATE_STATUS = 'BUILD_AGGREGATE_STATUS'
86+
others_snapshot = [el for el in final_snapshot if not el.is_leader]
87+
if reduce(lambda a, b: a and b, [e.is_succeeded for e in others_snapshot]):
88+
os.environ[BUILD_AGGREGATE_STATUS] = "others_succeeded"
89+
elif reduce(lambda a, b: a and b, [not e.is_succeeded for e in others_snapshot]):
90+
log.error("Others Failed")
91+
os.environ[BUILD_AGGREGATE_STATUS] = "others_failed"
92+
else:
93+
log.warn("Others Unknown")
94+
os.environ[BUILD_AGGREGATE_STATUS] = "unknown"
95+
#since python is subprocess, env variables are exported back via file
96+
with open(".to_export_back", "w") as export_var:
97+
export_var.write("BUILD_LEADER=YES {0}={1}".format(BUILD_AGGREGATE_STATUS, os.environ[BUILD_AGGREGATE_STATUS]))
98+
99+
except Exception as e:
100+
log.fatal(e)

0 commit comments

Comments
 (0)