diff --git a/.travis-github.enc b/.travis-github.enc index 39bb04f8..381fb565 100644 Binary files a/.travis-github.enc and b/.travis-github.enc differ diff --git a/.travis.yml b/.travis.yml index ed6e3c1f..011e29e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ env: matrix: - CFGFLAGS= MYCXXFLAGS= MYLDFLAGS= global: - - secure: "Rfoqtksz9rPuC2MszbwYRFarHGQuD2rrRV+cxNLwU9fBaWRfdhoJZKt+LqIUv/w84/Oz24gp1ulfW4jSwrfIjfG1ER/glkV5TcQOKjlhRVwjSFW8/9lZiZgqHVX5QiEqdrIeVOBLGQucQWcUb/vxxEZua4qIAiescBCi9s7AfkA=" + - secure: "i2f2UVDnyHT/9z0U3XvgTj8eDERvnc1Wk7HpseEjb75JwGzqn/2R+RKHmoSrwK3hFgij2IMxZL19XtHFwMz9t5A/huAAKD74KMMI/QpeZEJ/sjT3CTLcE9HEVDdJOjc7dfLRxb2hZtgvx8clZIMrpeUdPhci8openff30KvXVbg=" matrix: include: - compiler: clang @@ -20,7 +20,6 @@ before_install: - ( cd ~ && wget http://prdownloads.sourceforge.net/swig/swig-2.0.8.tar.gz && tar xvf swig-2.0.8.tar.gz && cd swig-2.0.8 && ./configure && make && sudo make install ) - sudo apt-get install doxygen graphviz script: - - curl -o travis_after_all.py https://raw.github.com/dmakhno/travis_after_all/master/travis_after_all.py - ./bootstrap.sh - mkdir build - cd build @@ -31,14 +30,16 @@ script: - sudo make install - cd .. after_success: - - python travis_after_all.py - - cat .to_export_back - - export $(cat .to_export_back) + - test -r .travis_after_all_.py && python .travis_after_all.py || echo No .travis_after_all.py found + - test -r .to_export_back && cat .to_export_back || echo No .to_export_back found + - export DUMMY_VAR=dummy-value $(cat .to_export_back) - | if [ "$BUILD_LEADER" == "YES" ] && [ "$BUILD_AGGREGATE_STATUS" == "others_succeeded" ] && [ "$TRAVIS_REPO_SLUG" == "znc/znc" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then echo "All builds passed!" openssl aes-256-cbc -d -in .travis-github.enc -out ~/znc-docs-key -k ${SECRET_KEY} ./.travis-generate-docs.sh + else + echo "Not leader" fi notifications: irc: diff --git a/.travis_after_all.py b/.travis_after_all.py new file mode 100644 index 00000000..f20e53ee --- /dev/null +++ b/.travis_after_all.py @@ -0,0 +1,120 @@ +# https://github.com/dmakhno/travis_after_all/tree/b7172bca92d6dcfcec2a0eacdf14eb5f3a1ad627 + +# The MIT License (MIT) +# +# Copyright (c) 2014 Dmytro Makhno +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import os +import json +import time +import logging + +try: + import urllib.request as urllib2 +except ImportError: + import urllib2 + +log = logging.getLogger("travis.leader") +log.addHandler(logging.StreamHandler()) +log.setLevel(logging.INFO) + +TRAVIS_JOB_NUMBER = 'TRAVIS_JOB_NUMBER' +TRAVIS_BUILD_ID = 'TRAVIS_BUILD_ID' +POLLING_INTERVAL = 'LEADER_POLLING_INTERVAL' + +build_id = os.getenv(TRAVIS_BUILD_ID) +polling_interval = int(os.getenv(POLLING_INTERVAL, '5')) + +#assume, first job is the leader +is_leader = lambda job_number: job_number.endswith('.1') + +if not os.getenv(TRAVIS_JOB_NUMBER): + # seems even for builds with only one job, this won't get here + log.fatal("Don't use defining leader for build without matrix") + exit(1) +elif is_leader(os.getenv(TRAVIS_JOB_NUMBER)): + log.info("This is a leader") +else: + #since python is subprocess, env variables are exported back via file + with open(".to_export_back", "w") as export_var: + export_var.write("BUILD_MINION=YES") + log.info("This is a minion") + exit(0) + + +class MatrixElement(object): + def __init__(self, json_raw): + self.is_finished = json_raw['finished_at'] is not None + self.is_succeeded = json_raw['result'] == 0 + self.number = json_raw['number'] + self.is_leader = is_leader(self.number) + + +def matrix_snapshot(): + """ + :return: Matrix List + """ + response = urllib2.build_opener().open("https://api.travis-ci.org/builds/{0}".format(build_id)).read() + raw_json = json.loads(response) + matrix_without_leader = [MatrixElement(element) for element in raw_json["matrix"]] + return matrix_without_leader + + +def wait_others_to_finish(): + def others_finished(): + """ + Dumps others to finish + Leader cannot finish, it is working now + :return: tuple(True or False, List of not finished jobs) + """ + snapshot = matrix_snapshot() + finished = [el.is_finished for el in snapshot if not el.is_leader] + return reduce(lambda a, b: a and b, finished), [el.number for el in snapshot if + not el.is_leader and not el.is_finished] + + while True: + finished, waiting_list = others_finished() + if finished: break + log.info("Leader waits for minions {0}...".format(waiting_list)) # just in case do not get "silence timeout" + time.sleep(polling_interval) + + +try: + wait_others_to_finish() + + final_snapshot = matrix_snapshot() + log.info("Final Results: {0}".format([(e.number, e.is_succeeded) for e in final_snapshot])) + + BUILD_AGGREGATE_STATUS = 'BUILD_AGGREGATE_STATUS' + others_snapshot = [el for el in final_snapshot if not el.is_leader] + if reduce(lambda a, b: a and b, [e.is_succeeded for e in others_snapshot]): + os.environ[BUILD_AGGREGATE_STATUS] = "others_succeeded" + elif reduce(lambda a, b: a and b, [not e.is_succeeded for e in others_snapshot]): + log.error("Others Failed") + os.environ[BUILD_AGGREGATE_STATUS] = "others_failed" + else: + log.warn("Others Unknown") + os.environ[BUILD_AGGREGATE_STATUS] = "unknown" + #since python is subprocess, env variables are exported back via file + with open(".to_export_back", "w") as export_var: + export_var.write("BUILD_LEADER=YES {0}={1}".format(BUILD_AGGREGATE_STATUS, os.environ[BUILD_AGGREGATE_STATUS])) + +except Exception as e: + log.fatal(e)