diff --git a/.gitignore b/.gitignore index 4415a5c02c..2af112bfb3 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ coverage # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release +# build folder for automated releases +latest + # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules diff --git a/.travis.yml b/.travis.yml index b202d643e3..3ac0b259fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,9 +15,9 @@ env: global: - COVERAGE_OPTION='./node_modules/.bin/istanbul cover' matrix: - - PARSE_SERVER_TEST_DB=postgres - MONGODB_VERSION=3.0.8 - MONGODB_VERSION=3.2.6 + - PARSE_SERVER_TEST_DB=postgres matrix: fast_finish: true branches: @@ -30,14 +30,25 @@ cache: - "$HOME/.mongodb/versions" after_script: - bash <(curl -s https://codecov.io/bash) +after_failure: + - (cd resources; python travis_after_all.py) +after_success: + - (cd resources; python travis_after_all.py) + deploy: - provider: npm - email: - secure: T3LwSJFcu632SDfCoavcKL39NktWLEOOFzonAjeHAglmMyDp9hvU8xHwQ4JJy2CRA03c+ezAe2gH3Va+jfxvh1JtFUan+p88vaCHHKuNwPSp4WZBPt1ZTDmG+ACG6j+ZWHK+eP7hLvtlCi/M9/v4/bVojpm7v01LLiM+MRhnE9E7eLemQC4zb6RVtf2oGQ3mX51kMeya218kEm5bsQPpRJElI9jwletFa8qYK5AFgaCHpll059RRHQTTE9MTNcN58P/Kf6Qb3KGpKNoaHTXoOD4U6LcXLWvdHONVB6AzGefxg2b/dvtaO4nd5lDooMBR3u9kWpopXkyAuf+fO/8je9JTxO6CDUtDjHRcR2mCEXWX6rculIAbNXOv1ccRYCTQ8aFtYnFlMSb1+QIAdyT6HHmeT5ktk3+XJRuEv0PJJvqHTo+j7tPngjiv5sPNutgGFlOFO90omTbzEkIT/D/LsgXbWm2QKYWejbLiuSINg+FiFiZN90doCf4aCpm2y1Q/9GzvK+eXcpqzPCGxOykE7EuPZK3+S/ZU2oaWL2uSpbKPtC0qxebrneR307aVEa7C85HCkTMMBzE4tjUr8h5HhLqtWvqmDcnBo3PfQhf9cEO6jQLd3qhEVJmcwKz/yOCfgPXlCbRqiKk7j94perpNCIalXtMI9ySYjJNjHsB4600= - api_key: - secure: WLjhHVAdUkDy6UdNWveTpZqphw9olN0alCpyPpU0cJjlN/hk7YxPP+YHOSVnMZaRZoHM0LL11jPKLf970nymBfvJHDWxKk71c/5xyTX8pBtSxmGmGy23a5g2VrHVMd2JxsI7NEAH500tlFz+01t4E3Steo0NpAkHR3Q51kj01gQy8IumsksfhRc9uvjZ7zjm99Yk4L+cxyei79v4esfpx7Bgm0HTfAAAG/19F+r0hvvFiV517SREDU/YtcX/rIjVepEy1uiLKEohnmYtVIRSA3Hjh6VlHVhdj2WDd/dYrxi/Ioysq2zOM9pZVLamO9asB1e6JrTEipWE9jSZXxsbnfFzuNLxcOjKv1wd3OzQKF/7pGKGiWRTv5Xm19D/FrXoE/ULs6bHcC/Ke8Gs2RxPlOCdvAFehCkyf5P4HOPCQdR7o8Yiuvt+5JWKBflElNbSd4nWgwUOo3Yv8vC4Vj53fwmM+Uqfu3IgYFWktYxCm4RWIKMfB/gtmjcF6QYFfjvEMwAvRfBV81kuynCsnubXWzQeBE/b3JOhBfpGciKCjKfy+tS6bZfFjCtQV98hMMiCPre8Y7PahHDYc65wU9Ake+ZE+dDaSbeV3DZ5JeifLJHzKW2J2dWeRANkOaiSwO9VBC9/rht5ulK5qQ1pB2+sKDToAaiKy6RMlB/HgIoYqsU= - on: - tags: true - all_branches: true - condition: "$MONGODB_VERSION = '3.0.8'" - repo: ParsePlatform/parse-server + - provider: script + skip_cleanup: true + script: ./resources/npm-git.sh + on: + branch: master + condition: "$BUILD_LEADER$BUILD_AGGREGATE_STATUS = YESothers_succeeded" + - provider: npm + email: + secure: T3LwSJFcu632SDfCoavcKL39NktWLEOOFzonAjeHAglmMyDp9hvU8xHwQ4JJy2CRA03c+ezAe2gH3Va+jfxvh1JtFUan+p88vaCHHKuNwPSp4WZBPt1ZTDmG+ACG6j+ZWHK+eP7hLvtlCi/M9/v4/bVojpm7v01LLiM+MRhnE9E7eLemQC4zb6RVtf2oGQ3mX51kMeya218kEm5bsQPpRJElI9jwletFa8qYK5AFgaCHpll059RRHQTTE9MTNcN58P/Kf6Qb3KGpKNoaHTXoOD4U6LcXLWvdHONVB6AzGefxg2b/dvtaO4nd5lDooMBR3u9kWpopXkyAuf+fO/8je9JTxO6CDUtDjHRcR2mCEXWX6rculIAbNXOv1ccRYCTQ8aFtYnFlMSb1+QIAdyT6HHmeT5ktk3+XJRuEv0PJJvqHTo+j7tPngjiv5sPNutgGFlOFO90omTbzEkIT/D/LsgXbWm2QKYWejbLiuSINg+FiFiZN90doCf4aCpm2y1Q/9GzvK+eXcpqzPCGxOykE7EuPZK3+S/ZU2oaWL2uSpbKPtC0qxebrneR307aVEa7C85HCkTMMBzE4tjUr8h5HhLqtWvqmDcnBo3PfQhf9cEO6jQLd3qhEVJmcwKz/yOCfgPXlCbRqiKk7j94perpNCIalXtMI9ySYjJNjHsB4600= + api_key: + secure: WLjhHVAdUkDy6UdNWveTpZqphw9olN0alCpyPpU0cJjlN/hk7YxPP+YHOSVnMZaRZoHM0LL11jPKLf970nymBfvJHDWxKk71c/5xyTX8pBtSxmGmGy23a5g2VrHVMd2JxsI7NEAH500tlFz+01t4E3Steo0NpAkHR3Q51kj01gQy8IumsksfhRc9uvjZ7zjm99Yk4L+cxyei79v4esfpx7Bgm0HTfAAAG/19F+r0hvvFiV517SREDU/YtcX/rIjVepEy1uiLKEohnmYtVIRSA3Hjh6VlHVhdj2WDd/dYrxi/Ioysq2zOM9pZVLamO9asB1e6JrTEipWE9jSZXxsbnfFzuNLxcOjKv1wd3OzQKF/7pGKGiWRTv5Xm19D/FrXoE/ULs6bHcC/Ke8Gs2RxPlOCdvAFehCkyf5P4HOPCQdR7o8Yiuvt+5JWKBflElNbSd4nWgwUOo3Yv8vC4Vj53fwmM+Uqfu3IgYFWktYxCm4RWIKMfB/gtmjcF6QYFfjvEMwAvRfBV81kuynCsnubXWzQeBE/b3JOhBfpGciKCjKfy+tS6bZfFjCtQV98hMMiCPre8Y7PahHDYc65wU9Ake+ZE+dDaSbeV3DZ5JeifLJHzKW2J2dWeRANkOaiSwO9VBC9/rht5ulK5qQ1pB2+sKDToAaiKy6RMlB/HgIoYqsU= + on: + tags: true + all_branches: true + condition: "$MONGODB_VERSION = '3.0.8'" + repo: ParsePlatform/parse-server diff --git a/README.md b/README.md index 7897e7ba67..b3c4b297fa 100644 --- a/README.md +++ b/README.md @@ -325,6 +325,18 @@ If you believe you've found an issue with Parse Server, make sure these boxes ar - [ ] You've searched through [existing issues](https://github.com/ParsePlatform/parse-server/issues?utf8=%E2%9C%93&q=). Chances are that your issue has been reported or resolved before. +# Want to ride the bleeding edge? + +The `latest` branch in this repository is automatically maintained to be the last +commit to `master` to pass all tests, in the same form found on npm. It is +recommend to use builds deployed npm for many reasons, but if you want to use +the latest not-yet-released version of parse-server, you can do so by depending +directly on this branch: + +``` +npm install parseplatform/parse-server.git#latest +``` + # Contributing We really want Parse to be yours, to see it grow and thrive in the open source community. Please see the [Contributing to Parse Server guide](CONTRIBUTING.md). diff --git a/resources/npm-git.sh b/resources/npm-git.sh new file mode 100755 index 0000000000..07c156db1f --- /dev/null +++ b/resources/npm-git.sh @@ -0,0 +1,33 @@ +#!/bin/sh -e + +# This script maintains a git branch which mirrors master but in a form that +# what will eventually be deployed to npm, allowing npm dependencies to use: +# +# "parse-server": "parseplatform/parse-server#latest" +# + +# From: https://github.com/graphql/graphql-js/blob/master/resources/npm-git.sh + +BUILD_DIR=latest + +npm run build + +mkdir -p $BUILD_DIR + +cp package.json $BUILD_DIR/ +cp README.md $BUILD_DIR/ +cp LICENSE $BUILD_DIR/ +cp PATENTS $BUILD_DIR/ +cp CHANGELOG.md $BUILD_DIR/ +cp -R lib $BUILD_DIR +cp -R bin $BUILD_DIR +cp -R public_html $BUILD_DIR +cp -R views $BUILD_DIR + +cd $BUILD_DIR +git init +git config user.name "Travis CI" +git config user.email "github@fb.com" +git add . +git commit -m "Deploy master to LATEST branch" +git push --force --quiet "https://${GH_TOKEN}@github.com/parseplatform/parse-server.git" master:latest \ No newline at end of file diff --git a/resources/travis_after_all.py b/resources/travis_after_all.py new file mode 100644 index 0000000000..08a1503628 --- /dev/null +++ b/resources/travis_after_all.py @@ -0,0 +1,102 @@ +""" +https://github.com/dmakhno/travis_after_all/blob/master/travis_after_all.py +https://github.com/graphql/graphql-js/blob/master/resources/travis_after_all.py +""" + +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) \ No newline at end of file