diff --git a/CHANGELOG.md b/CHANGELOG.md index 49661c22..34df7985 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +0.15.1 Release notes (2016-11-22) +============================================================= +### Breaking changes +* None + +### Enhancements +* None + +### Bugfixes +* Fix compile error for collection notification in chrome debug mode + 0.15.0 Release notes (2016-11-15) ============================================================= ### Breaking changes diff --git a/README.md b/README.md index 4bc70c95..048e25fc 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Prerequisites: First clone this repository: ``` -git clone https://github.com/realm/realm-js-private.git +git clone https://github.com/realm/realm-js.git ``` Then in the cloned directory: diff --git a/dependencies.list b/dependencies.list index 6e4c7a6b..c6e9e123 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=0.14.3-6 +VERSION=0.15.1-rc REALM_CORE_VERSION=2.1.4 REALM_SYNC_VERSION=1.0.0-BETA-3.3 REALM_OBJECT_SERVER_VERSION=1.0.0-BETA-2.1 diff --git a/docs/sync.js b/docs/sync.js index 5ba015d2..0bb9d9be 100644 --- a/docs/sync.js +++ b/docs/sync.js @@ -107,11 +107,10 @@ class User { /** * Create an admin user for the given authentication server with an existing token - * @param {string} server - authentication server * @param {string} adminToken - existing admin token * @return {User} - admin user populated with the given token and server */ - adminUser(server, adminToken) {} + adminUser(adminToken) {} /** * A dictionary containing users that are currently logged in. diff --git a/examples/NodeInterprocess/index.js b/examples/NodeInterprocess/index.js index 9570a3eb..ec1e1454 100644 --- a/examples/NodeInterprocess/index.js +++ b/examples/NodeInterprocess/index.js @@ -1,6 +1,25 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +'use strict'; + var express = require('express'), - util = require('util'), - winston = require('winston'); + winston = require('winston'), RealmWinston = require('./winston-realm').Realm; var app = express(); @@ -14,12 +33,13 @@ app.get('/', function (req, res) { winston.info('Handled Hello World'); }); -app.use(function (req, res, next) { +app.use(function (req, res) { res.status(404).send('Sorry can not find that!'); winston.error('404 Error at: ' + req.url); }) app.listen(3000, function () { + // eslint-disable-next-line no-console console.log('Example app listening on port 3000!'); }); diff --git a/examples/NodeInterprocess/listener.js b/examples/NodeInterprocess/listener.js index e901df94..dea6e764 100644 --- a/examples/NodeInterprocess/listener.js +++ b/examples/NodeInterprocess/listener.js @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + 'use strict'; var Realm = require('realm'); @@ -10,6 +28,8 @@ let winstonRealm = new Realm({ winstonRealm.objects('Log').filtered('level = "error"').addListener((logs, changes) => { changes.insertions.map((index) => { let log = logs[index]; + + // eslint-disable-next-line no-console console.log(log.message); }) }); diff --git a/lib/browser/lists.js b/lib/browser/lists.js index af90250e..df4e63c7 100644 --- a/lib/browser/lists.js +++ b/lib/browser/lists.js @@ -30,7 +30,10 @@ createMethods(List.prototype, objectTypes.LIST, [ 'filtered', 'sorted', 'snapshot', - 'isValid', + 'isValid', + 'addListener', + 'removeListener', + 'removeAllListeners', ]); // Mutating methods: diff --git a/lib/browser/results.js b/lib/browser/results.js index 887a7dd1..6dd4e6b0 100644 --- a/lib/browser/results.js +++ b/lib/browser/results.js @@ -30,6 +30,9 @@ createMethods(Results.prototype, objectTypes.RESULTS, [ 'sorted', 'snapshot', 'isValid', + 'addListener', + 'removeListener', + 'removeAllListeners', ]); export function createResults(realmId, info) { diff --git a/lib/extensions.js b/lib/extensions.js index 83cb05bd..c2443149 100644 --- a/lib/extensions.js +++ b/lib/extensions.js @@ -30,6 +30,16 @@ module.exports = function(realmConstructor) { if (realmConstructor.Sync.cleanup) { // FIXME: DOES THIS WORK ON BOTH NODE AND REACT NATIVE? process.on('exit', realmConstructor.Sync.cleanup); + process.on('SIGINT', function () { + realmConstructor.Sync.cleanup(); + process.exit(2); + }); + process.on('uncaughtException', function(e) { + realmConstructor.Sync.cleanup(); + /* eslint-disable no-console */ + console.log(e.stack); + process.exit(99); + }); } } diff --git a/lib/index.js b/lib/index.js index cef11a10..549a363a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -22,24 +22,38 @@ function node_require(module) { return require(module); } -var realmConstructor; +// If process is defined, we're running in node. +function isNode() { + return typeof process == 'object' && (('' + process) == '[object process]' || typeof jest == 'object') +} + +// function isElectronRenderer() { +// return isNode() && process.type === 'renderer' +// } + +var realmConstructor; +if (isNode()) { + node_require('./submit-analytics')('Run'); -if (typeof Realm != 'undefined') { - // The global Realm constructor should be available on device (using JavaScriptCore). - realmConstructor = Realm; // eslint-disable-line no-undef -// eslint-disable-next-line -} else if (typeof window != 'undefined') { - // The userAgent will be defined when running in a browser (such as Chrome debugging mode). - realmConstructor = require('./browser').default; // (exported as ES6 module) -// eslint-disable-next-line -} else if (typeof process == 'object' && (('' + process) == '[object process]' || typeof jest == 'object')) { - // If process is defined, we're running in node. // Prevent React Native packager from seeing this module. var binary = node_require('node-pre-gyp'); var path = node_require('path'); - var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json'))); + var pkg = path.resolve(path.join(__dirname,'../package.json')); + var binding_path = binary.find(pkg); realmConstructor = require(binding_path).Realm; } else { + if (typeof Realm != 'undefined') { + // The global Realm constructor should be available on device (using JavaScriptCore). + realmConstructor = Realm; // eslint-disable-line no-undef + // eslint-disable-next-line + } else if (typeof window != 'undefined') { + // The userAgent will be defined when running in a browser (such as Chrome debugging mode). + realmConstructor = require('./browser').default; // (exported as ES6 module) + // eslint-disable-next-line + } +} + +if (!realmConstructor) { throw new Error('Missing Realm constructor - please ensure RealmReact framework is included!'); } diff --git a/lib/submit-analytics.js b/lib/submit-analytics.js new file mode 100644 index 00000000..02f3cede --- /dev/null +++ b/lib/submit-analytics.js @@ -0,0 +1,97 @@ +#!/usr/bin/env node + +// Asynchronously submits install information to Realm. +// +// Why are we doing this? In short, because it helps us build a better product +// for you. None of the data personally identifies you, your employer or your +// app, but it *will* help us understand what language you use, what Node.js +// versions you target, etc. Having this info will help prioritizing our time, +// adding new features and deprecating old features. Collecting an anonymized +// application path & anonymized machine identifier is the only way for us to +// count actual usage of the other metrics accurately. If we don’t have a way to +// deduplicate the info reported, it will be useless, as a single developer +// `npm install`-ing the same app 10 times would report 10 times more than another +// developer that only installs once, making the data all but useless. +// No one likes sharing data unless it’s necessary, we get it, and we’ve +// debated adding this for a long long time. If you truly, absolutely +// feel compelled to not send this data back to Realm, then you can set an env +// variable named REALM_DISABLE_ANALYTICS. +// +// Currently the following information is reported: +// - What version of Realm is being installed. +// - The OS platform and version which is being used. +// - Node.js, v8, libuv, OpenSSL version numbers. +// - An anonymous machine identifier and hashed application path to aggregate the other information on. + +'use strict'; + +const os = require('os'); +const crypto = require('crypto'); +const fs = require('fs'); +const request = require('request'); + +function sha256(data) { + let hash = crypto.createHash('sha256'); + hash.update(data); + return hash.digest('hex'); +} + +function getDarwinIdentifier() { + const interfaces = os.networkInterfaces(); + const iface = interfaces["en0"] || interfaces["en1"]; + if (!iface) { + return Buffer.from('unknown', 'utf8'); + } + + const mac = iface[0].mac.replace(/:/g, ''); + return Buffer.from(mac, 'hex'); +} + +function getLinuxIdentifier() { + if (fs.existsSync('/var/lib/dbus/machine-id')) { + return fs.readFileSync('/var/lib/dbus/machine-id'); + } else if (fs.existsSync('/etc/machine-id')) { + return fs.readFileSync('/etc/machine-id'); + } else { + return Buffer.from('unknown', 'utf8'); + } +} + +function getAnonymizedMachineIdentifier() { + switch (os.platform()) { + case 'darwin': + return sha256(getDarwinIdentifier()); + case 'linux': + return sha256(getLinuxIdentifier()); + default: + return null; + } +} + +module.exports = function(eventName) { + if ('REALM_DISABLE_ANALYTICS' in process.env) + return; + + const identifier = getAnonymizedMachineIdentifier(); + const payload = { + 'event': eventName, + 'properties': { + 'token': 'aab85907a13e1ff44a95be539d9942a9', + 'distinct_id': identifier, + 'Anonymized Machine Identifier': identifier, + 'Anonymized Application ID': sha256(__dirname), + 'Binding': 'node.js', + 'Version': require('../package.json').version, + 'Language': 'javascript', + 'OS Type': os.platform(), + 'OS Version': os.release(), + 'Node.js versions': process.versions + } + }; + + request(`https://api.mixpanel.com/track/?data=${Buffer.from(JSON.stringify(payload), 'utf8').toString('base64')}&ip=1`); +} + +if (require.main === module) { + module.exports('Install'); +} diff --git a/package.json b/package.json index 31dde586..8a68eaff 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "0.15.0", + "version": "0.15.1-rc", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ @@ -55,6 +55,7 @@ "nan": "^2.3.3", "needle": "^1.3.0", "node-pre-gyp": "^0.6.30", + "request": "^2.78.0", "sync-request": "^3.0.1", "url-parse": "^1.1.7" }, diff --git a/packaging/.gitignore b/packaging/.gitignore new file mode 100644 index 00000000..28a0d4d0 --- /dev/null +++ b/packaging/.gitignore @@ -0,0 +1,3 @@ +/out +/test-logs + diff --git a/packaging/Jenkinsfile.node-pre-gyp b/packaging/Jenkinsfile.node-pre-gyp new file mode 100644 index 00000000..3bf75eec --- /dev/null +++ b/packaging/Jenkinsfile.node-pre-gyp @@ -0,0 +1,140 @@ +#!groovy + +// parameter: PUBLISH +repoName = 'realm-js' // This is a global variable + +def setBuildName(newBuildName) { + currentBuild.displayName = "${currentBuild.displayName} - ${newBuildName}" +} + +def unstashSources() { + sshagent(['realm-ci-ssh']) { + sh 'rm -rf * .git' + checkout scm + sh 'git clean -ffdx -e .????????' + sh 'git submodule update --init --recursive' + } +} + +def readGitTag() { + sh "git describe --exact-match --tags HEAD | tail -n 1 > tag.txt 2>&1 || true" + def tag = readFile('tag.txt').trim() + return tag +} + +def readGitSha() { + sh "git rev-parse HEAD | cut -b1-8 > sha.txt" + def sha = readFile('sha.txt').readLines().last().trim() + return sha +} + +def getVersion(){ + def dependencies = readProperties file: 'dependencies.list' + def gitTag = readGitTag() + def gitSha = readGitSha() + if (gitTag == "") { + return "${dependencies.VERSION}-g${gitSha}" + } + else { + return dependencies.VERSION + } +} + +def doBuildLinux(dependencies) { + return { + node('docker') { + unstashSources() + + docker.withRegistry("https://${env.DOCKER_REGISTRY}", "ecr:eu-west-1:aws-ci-user") { + withCredentials([[$class: 'StringBinding', credentialsId: 'packagecloud-sync-devel-master-token', variable: 'PACKAGECLOUD_MASTER_TOKEN']]) { + withEnv(["EXTRA_NPM_ARGUMENTS=--realm_download_binaries=0"]) { + sh 'sh packaging/package.sh node-pre-gyp' + } + } + } + + dir('packaging/out/node-pre-gyp') { + stash includes: "realm-*", name: "compiled-linux" + archiveArtifacts "realm-*" + } + } + } +} + +def doBuildMac(dependencies) { + return { + node('osx_vegas') { + unstashSources() + sh ''' + ./scripts/build-node-pre-gyp.sh + tar cvfz darwin-compiled.tgz compiled/ + ''' + dir('out') { + stash includes: 'realm-*', name: "compiled-mac" + archiveArtifacts "realm-*" + } + + } + } +} + +def doBuild(dependencies) { + parallel( + "build_mac": doBuildMac(dependencies), + "build_linux": doBuildLinux(dependencies) + ) +} + +def doPublish() { + node('aws') { + sh 'rm -rf *' + unstash 'compiled-mac' + unstash 'compiled-linux' + withCredentials([[$class: 'FileBinding', credentialsId: 'c0cc8f9e-c3f1-4e22-b22f-6568392e26ae', variable: 's3cfg_config_file']]) { + sh """ + s3cmd -c \$s3cfg_config_file put realm-* 's3://static.realm.io/node-pre-gyp/' + rm -rf * + """ + } + } +} + +def gitTag +def gitSha +def dependencies +def version + +stage 'check' +node('docker') { + unstashSources() + dependencies = readProperties file: 'dependencies.list' + echo "VERSION: ${dependencies.VERSION}" + echo "NODEJS_REALM_VERSION: ${dependencies.NODEJS_REALM_VERSION}" + echo "NODEJS_REALM_SERVER_VERSION: ${dependencies.NODEJS_REALM_SERVER_VERSION}" + + gitTag = readGitTag() + gitSha = readGitSha() + version = getVersion() + echo "tag: ${gitTag}" + if (gitTag == "") { + echo "No tag given for this build" + setBuildName("${gitSha}") + } else { + if (gitTag != "v${dependencies.VERSION}") { + echo "Git tag '${gitTag}' does not match v${dependencies.VERSION}" + } else { + echo "Building release: '${gitTag}'" + setBuildName("Tag ${gitTag}") + } + } + + echo "version: ${version}" +} + +stage 'build' +doBuild(dependencies) + +if (PUBLISH == 'true') { + stage 'publish' + doPublish() +} diff --git a/packaging/functions.sh b/packaging/functions.sh new file mode 100755 index 00000000..6be864e0 --- /dev/null +++ b/packaging/functions.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +die() { echo "$@" 1>&2 ; exit 1; } +info() { echo "===> $*"; } +apply_shell_expansion() { + declare file="$1" + declare data=$(< "$file") + declare delimiter="__apply_shell_expansion_delimiter__" + declare command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter" + eval "$command" +} + +docker_build() { + declare name="$1"; shift + declare path="$1"; shift + declare args="$*" + + if [ "${DOCKER_REGISTRY}" != "" ]; then + remote_name="${DOCKER_REGISTRY}/${name}" + fi + + info "Building ${name} image..." + if [ "${DOCKER_REGISTRY}" != "" ]; then + docker_pull "${remote_name}" && docker tag "${remote_name}" "${name}" || true + fi + + old_id=$(docker images -q "${name}") + info "Old ${name} image id: ${old_id}" + + if [ "${DOCKERFILE}" != "" ]; then + docker build ${args} -t "${name}" -f "${DOCKERFILE}" "${path}" || \ + die "Building ${name} image failed" + else + docker build ${args} -t "${name}" "${path}" || \ + die "Building ${name} image failed" + fi + + new_id=$(docker images -q "${name}") + info "New ${name} image id: ${new_id}" + + if [ "${DEBUG}" ] && [ "${new_id}" != "${old_id}" ]; then + info "History for old id $old_id:" + if [ "${old_id}" != "" ]; then + docker history "$old_id" + fi + + info "History for new id $new_id:" + docker history "$new_id" + fi + + if [ "${NOPUSH:-0}" != "1" ] && [ "${DOCKER_REGISTRY}" != "" ]; then + docker tag "${name}" "${remote_name}" + docker_push "${remote_name}" + fi +} + +# Due to https://github.com/docker/docker/issues/20316, we use +# https://github.com/tonistiigi/buildcache to generate a cache of the layer +# metadata for later builds. +my_buildcache() { + if [ "$DOCKER_REGISTRY" != "" ]; then + + docker_path="/var/lib/docker" + + # Stupid hack for our AWS nodes, which have docker data on another volume + if [ -d "/mnt/docker" ]; then + docker_path="/mnt/docker" + fi + + docker pull "${DOCKER_REGISTRY}/ci/buildcache" >/dev/null && \ + docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v ${docker_path}:/var/lib/docker \ + "${DOCKER_REGISTRY}/ci/buildcache" "$@" + fi +} + +docker_pull() { + info "Attempting to pull '$1' image from registry..." + ( + tmpdir=$(mktemp -d) + docker pull "$1" + ( + # In addition, pull the cached metadata and load it (buildcache) + cd "${tmpdir}" && docker pull "$1-cache" && docker save "$1-cache" | \ + tar -xf - && docker load -i ./*/layer.tar + ) + rm -rf "${tmpdir}" + ) || true +} + +docker_push() { + info "Pushing '$1' image to registry..." + docker push "$1" + # Create a cache of the layer metdata we need and push it as an image + #docker rmi $1-cache 2>/dev/null || true + my_buildcache save -g /var/lib/docker "$1" | gunzip -c | \ + docker import - "$1-cache" && \ + docker push "$1-cache" +} diff --git a/packaging/node-pre-gyp/base-image/Dockerfile b/packaging/node-pre-gyp/base-image/Dockerfile new file mode 100644 index 00000000..03bf127c --- /dev/null +++ b/packaging/node-pre-gyp/base-image/Dockerfile @@ -0,0 +1,37 @@ +FROM alanfranz/fwd-centos-6:latest + +ARG PACKAGECLOUD_URL + +ENV NPM_CONFIG_UNSAFE_PERM true + +# Install EPEL & devtoolset +# On CentOS6, there is a bug with OverlayFS and Docker. It is needed to touch +# /var/lib/rpm/* in order to work around this issue. +# Link: https://github.com/docker/docker/issues/10180 + +RUN touch /var/lib/rpm/* \ + && yum -y install \ + epel-release \ + centos-release-scl-rh \ + && yum-config-manager --enable rhel-server-rhscl-6-rpms \ + && curl -s $PACKAGECLOUD_URL/script.rpm.sh | bash \ + && yum -y install \ + python27 \ + which \ + chrpath \ + openssl-devel \ + devtoolset-3-gcc \ + devtoolset-3-gcc-c++ \ + devtoolset-3-binutils \ + libconfig-devel \ + jq \ + && yum remove -y g++ gcc \ + && yum clean all + +ENV NVM_DIR /root/.nvm +RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.31.4/install.sh | bash +RUN . $NVM_DIR/nvm.sh && \ + nvm install 4.4.7 && \ + nvm install 5.12.0 && \ + nvm install 6.5.0 && \ + nvm install 7.0.0 diff --git a/packaging/node-pre-gyp/build-image/Dockerfile b/packaging/node-pre-gyp/build-image/Dockerfile new file mode 100644 index 00000000..7ea13bf6 --- /dev/null +++ b/packaging/node-pre-gyp/build-image/Dockerfile @@ -0,0 +1,4 @@ +FROM ci/realm-js:node-pre-gyp-base + +ENTRYPOINT ["/bin/bash", "/inside/docker-entrypoint.sh"] +CMD ["/bin/bash", "/inside/build-package"] diff --git a/packaging/node-pre-gyp/build-image/inside/build-package b/packaging/node-pre-gyp/build-image/inside/build-package new file mode 100755 index 00000000..aee4ef23 --- /dev/null +++ b/packaging/node-pre-gyp/build-image/inside/build-package @@ -0,0 +1,34 @@ +#!/bin/bash + +set -e + +# we should always set proper ownership before exiting, otherwise +# the created packages will have root:root ownership and we'll be unable +# to delete them from our host. +trap 'chown -R --reference /inside/build-package /out/' EXIT + +. $NVM_DIR/nvm.sh + +REALM_CORE_VERSION=$(echo ${REALM_CORE_VERSION} | sed 's/-\([^g]\)/_\1/g') + +yum install -y \ + realm-devel-${REALM_CORE_VERSION} \ + realm-node-devel-${REALM_CORE_VERSION} + +export NPM_CONFIG_UNSAFE_PERM=true # because we're running as root + +setup_source() { + path=$1 + cp -a /source $path + cd $path + json=$(jq ".version = \"${VERSION}\"" package.json) + echo $json > package.json + rm -rf compiled node_modules .nvm +} + +setup_source "/tmp/build" +./scripts/build-node-pre-gyp.sh + +nvm use 4.4.7 + +cp out/* /out/ diff --git a/packaging/node-pre-gyp/build-image/inside/docker-entrypoint.sh b/packaging/node-pre-gyp/build-image/inside/docker-entrypoint.sh new file mode 100755 index 00000000..3d0ece23 --- /dev/null +++ b/packaging/node-pre-gyp/build-image/inside/docker-entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +scl enable devtoolset-3 -- "$@" diff --git a/packaging/node-pre-gyp/test-image/Dockerfile b/packaging/node-pre-gyp/test-image/Dockerfile new file mode 100644 index 00000000..3b4c58db --- /dev/null +++ b/packaging/node-pre-gyp/test-image/Dockerfile @@ -0,0 +1,3 @@ +FROM ci/realm-js:node-pre-gyp-base + +CMD ["/bin/bash", "/inside/test"] diff --git a/packaging/node-pre-gyp/test-image/inside/test b/packaging/node-pre-gyp/test-image/inside/test new file mode 100755 index 00000000..0f546bfe --- /dev/null +++ b/packaging/node-pre-gyp/test-image/inside/test @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +# we should always set proper ownership before exiting, otherwise +# the created logs will have root:root ownership and we'll be unable +# to delete them from our host. +trap 'chown -R --reference $0 /test-logs/' EXIT + +. $NVM_DIR/nvm.sh + +ls -la /out + +nvm use 4.4.7 diff --git a/packaging/package.sh b/packaging/package.sh new file mode 100755 index 00000000..9c307c7a --- /dev/null +++ b/packaging/package.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +set -e + +script_path="$(pushd "$(dirname "$0")" >/dev/null; pwd)" +src_path="$(pushd "${script_path}/.." >/dev/null; pwd)" + +. "${script_path}/functions.sh" + + +git_tag=$(git describe --exact-match --tags HEAD 2>/dev/null || true) + +. "${src_path}/dependencies.list" + +export PACKAGECLOUD_URL="https://${PACKAGECLOUD_MASTER_TOKEN}:@packagecloud.io/install/repositories/realm/sync-devel" + +if [ -z "$git_tag" ]; then + info "No git tag exists. Triggering -devel build" + sha=$(git rev-parse HEAD | cut -b1-8) + ITERATION="0.$sha" +elif [ "$git_tag" != "v${VERSION}" ]; then + die "Git tag '$git_tag' does not match VERSION: '$VERSION'" +else + info "Found git tag: '$git_tag'. Triggering release build" + ITERATION="${BUILD_NUMBER:-1}" +fi + +rm -rf "${src_path}/packaging/out"; mkdir -p "${src_path}/packaging/out" + +cp "${src_path}/dependencies.list" "${src_path}/packaging/out/packaging.list" +cat <<-EOD >> "${src_path}/packaging/out/packaging.list" +ITERATION=$ITERATION +EXTRA_NPM_ARGUMENTS=$EXTRA_NPM_ARGUMENTS +EOD + +env_file="${src_path}/packaging/out/packaging.list" + +default="centos-6 centos-7 ubuntu-1604" +for distro in ${*:-$default}; do + distro_path="${src_path}/packaging/${distro}" + image_name="ci/${PACKAGE_NAME}:${distro}" + + mkdir -p "${src_path}/packaging/out/$distro" + rm -f "${src_path}/packaging/out/$distro/*" + + mkdir -p "${src_path}/packaging/test-logs/$distro" + rm -f "${src_path}/packaging/test-logs/$distro/*" + + docker_build "${image_name}-base" "${distro_path}/base-image" \ + --build-arg "PACKAGECLOUD_URL=$PACKAGECLOUD_URL" + + docker_build "${image_name}-build" "${distro_path}/build-image" + + info "Running '$distro' build..." + docker run \ + --env-file "${env_file}" \ + --rm \ + -v "${src_path}/packaging/${distro}/files:/files:ro,z" \ + -v "${src_path}/packaging/${distro}/build-image/inside:/inside:ro,z" \ + -v "${src_path}:/source:ro,z" \ + -v "${src_path}/packaging/common:/common:ro,z" \ + -v "${src_path}/packaging/out/${distro}:/out:z" \ + -w /inside "${image_name}-build" \ + || die "Build phase for '$distro' failed." + + docker_build "${image_name}-test" "${distro_path}/test-image" + + info "Running '$distro' tests..." + docker run \ + --env-file "${env_file}" \ + --rm \ + -v "${src_path}/packaging/${distro}/test-image/inside:/inside:ro,z" \ + -v "${src_path}/packaging/out/${distro}:/out:z" \ + -v "${src_path}/packaging/test-logs/${distro}:/test-logs:z" \ + -v "${src_path}/packaging/common:/common:ro,z" \ + -w /inside "${image_name}-test" \ + || die "Test phase for '$distro' failed." + + info "Test phase for '$distro' succeeded." +done diff --git a/scripts/build-node-pre-gyp.sh b/scripts/build-node-pre-gyp.sh index ba0998b7..bd7bdd2e 100755 --- a/scripts/build-node-pre-gyp.sh +++ b/scripts/build-node-pre-gyp.sh @@ -1,6 +1,6 @@ #!/bin/bash -node_versions=${@:-4.4.7 5.12.0 6.5.0} +node_versions=${@:-4.4.7 5.12.0 6.5.0 7.0.0} topdir=$(cd $(dirname "$0")/..; pwd) diff --git a/scripts/test.sh b/scripts/test.sh index 814a6365..e0528ae9 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -11,7 +11,7 @@ CONFIGURATION="${2:-"Release"}" DESTINATION= PATH="/opt/android-sdk-linux/platform-tools:$PATH" SRCROOT=$(cd "$(dirname "$0")/.." && pwd) -XCPRETTY=true +XCPRETTY=`which xcpretty || true` # Start current working directory at the root of the project. cd "$SRCROOT" @@ -83,13 +83,21 @@ start_packager() { xctest() { local dest="$(xcrun simctl list devices | grep -v unavailable | grep -m 1 -o '[0-9A-F\-]\{36\}')" if [ -n "$XCPRETTY" ]; then - mkdir -p build - xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$dest" build test | tee build/build.log | xcpretty -c --no-utf --report junit --output build/reports/junit.xml || { - echo "The raw xcodebuild output is available in build/build.log" - exit 1 + LOGTEMP=`mktemp build.log.XXXXXX` + trap "rm $LOGTEMP" EXIT + xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$dest" build test 2>&1 | tee "$LOGTEMP" | "$XCPRETTY" -c --no-utf --report junit --output build/reports/junit.xml || { + EXITCODE=$? + printf "*** Xcode Failure (exit code $EXITCODE). The full xcode log follows: ***\n\n" + cat "$LOGTEMP" + printf "\n\n*** End Xcode Failure ***\n" + exit $EXITCODE } else - xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$dest" build test + xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$dest" build test || { + EXITCODE=$? + echo "*** Failure (exit code $EXITCODE). ***" + exit $EXITCODE + } fi } @@ -100,7 +108,7 @@ trap cleanup EXIT # Use a consistent version of Node if possible. if [ -s "${HOME}/.nvm/nvm.sh" ]; then . "${HOME}/.nvm/nvm.sh" - nvm use 4.4.7 || true + nvm use 5.12 || true fi # Remove cached packages @@ -156,7 +164,7 @@ case "$TARGET" in ;; "react-tests-android") [[ $CONFIGURATION == 'Debug' ]] && exit 0 - XCPRETTY=false + XCPRETTY='' pushd tests/react-test-app diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 60cd5354..a1a1b3fb 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -903,7 +903,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.15.0; + CURRENT_PROJECT_VERSION = 0.15.1; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -966,7 +966,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.15.0; + CURRENT_PROJECT_VERSION = 0.15.1; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; diff --git a/src/object-store b/src/object-store index 1c2f3a76..aa6b8ee6 160000 --- a/src/object-store +++ b/src/object-store @@ -1 +1 @@ -Subproject commit 1c2f3a7607467ed904a81a4824d0cbda33cc0ebb +Subproject commit aa6b8ee613e79c664bc59717ac84de8b33619594 diff --git a/tests/spec/sync_integration_tests.js b/tests/spec/sync_integration_tests.js index 925ec1aa..6bfd2d35 100644 --- a/tests/spec/sync_integration_tests.js +++ b/tests/spec/sync_integration_tests.js @@ -21,8 +21,7 @@ describe('Sync Integration', () => { this.rl.on("line", (line) => { var match; if ((match = line.match(/Connection\[1\]: Session\[1\]: Received: BIND\(server_path='\/(.+)',/))) { - var adminUser = Realm.Sync.User.adminUser('http://127.0.0.1:9080/', - fs.readFileSync("sync-bundle/admin_token.base64", "utf-8")); + var adminUser = Realm.Sync.User.adminUser(fs.readFileSync("sync-bundle/admin_token.base64", "utf-8")); this.adminRealmPath = match[1]; this.adminRealm = new Realm({ path: "__admin.realm",