diff --git a/Jenkinsfile b/Jenkinsfile index 18a2532f8236797c5f074eadcd9b6c160a9ef22a..bf031771306c10109afbc40a165d66b40b27e698 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,3 +1,19 @@ +import groovy.json.JsonOutput + +// From https://issues.jenkins-ci.org/browse/JENKINS-44231 + +// Given arbitrary string returns a strongly escaped shell string literal. +// I.e. it will be in single quotes which turns off interpolation of $(...), etc. +// E.g.: 1'2\3\'4 5"6 (groovy string) -> '1'\''2\3\'\''4 5"6' (groovy string which can be safely pasted into shell command). +def shellString(s) { + // Replace ' with '\'' (https://unix.stackexchange.com/a/187654/260156). Then enclose with '...'. + // 1) Why not replace \ with \\? Because '...' does not treat backslashes in a special way. + // 2) And why not use ANSI-C quoting? I.e. we could replace ' with \' + // and enclose using $'...' (https://stackoverflow.com/a/8254156/4839573). + // Because ANSI-C quoting is not yet supported by Dash (default shell in Ubuntu & Debian) (https://unix.stackexchange.com/a/371873). + '\'' + s.replace('\'', '\'\\\'\'') + '\'' +} + pipeline { agent any @@ -6,9 +22,41 @@ pipeline { } stages { + stage('pre-build') { + steps { + sh 'rm -rf ./build ./tmp' + } + } + stage('build') { steps { - build 'reticulum' + script { + def baseAssetsPath = env.BASE_ASSETS_PATH + def assetBundleServer = env.ASSET_BUNDLE_SERVER + def targetS3Url = env.TARGET_S3_URL + def smokeURL = env.SMOKE_URL + def slackURL = env.SLACK_URL + + def habCommand = "sudo /usr/bin/hab-docker-studio -k mozillareality run /bin/bash scripts/hab-build-and-push.sh ${baseAssetsPath} ${assetBundleServer} ${targetS3Url} ${env.BUILD_NUMBER}" + sh "/usr/bin/script --return -c ${shellString(habCommand)} /dev/null" + + def gitMessage = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'[%an] %s'").trim() + def gitSha = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim() + def text = ( + "*<http://localhost:8080/job/${env.JOB_NAME}/${env.BUILD_NUMBER}|#${env.BUILD_NUMBER}>* *${env.JOB_NAME}* " + + "<https://github.com/mozilla/hubs/commit/$gitSha|$gitSha> " + + "Hubs: ```${gitSha} ${gitMessage}```\n" + + "<${smokeURL}?require_version=${env.BUILD_NUMBER}|Smoke Test> - to push:\n" + + "`/mr hubs deploy ${targetS3Url}`" + ) + def payload = 'payload=' + JsonOutput.toJson([ + text : text, + channel : "#mr-builds", + username : "buildbot", + icon_emoji: ":gift:" + ]) + sh "curl -X POST --data-urlencode ${shellString(payload)} ${slackURL}" + } } } } diff --git a/scripts/build_local_reticulum.sh b/scripts/build_local_reticulum.sh deleted file mode 100755 index 9a19f9f202b688b27213b0478f9e1a14e67d2620..0000000000000000000000000000000000000000 --- a/scripts/build_local_reticulum.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -if [ ! -e ../reticulum ]; then - echo "This script assumes reticulum is checked out in a sibling to this folder." -fi - -rm -rf ../reticulum/priv/static ; GENERATE_SMOKE_TESTS=true BASE_ASSETS_PATH=https://hubs.local:4000/ yarn build -- --output-path ../reticulum/priv/static diff --git a/scripts/hab-build-and-push.sh b/scripts/hab-build-and-push.sh new file mode 100755 index 0000000000000000000000000000000000000000..2f04c0a26fd57505bfd508de05b56e920e947b37 --- /dev/null +++ b/scripts/hab-build-and-push.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +export BASE_ASSETS_PATH=$1 +export ASSET_BUNDLE_SERVER=$2 +export TARGET_S3_URL=$3 +export BUILD_VERSION=$4 + +# To build + push to S3 run: +# hab studio run "bash scripts/hab-build-and-push.sh" + +# On exit, need to make all files writable so CI can clean on next build +trap 'chmod -R a+rw .' EXIT + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +pushd "$DIR/.." + +mkdir -p .yarn +mkdir -p node_modules +mkdir -p build + +# Yarn expects /usr/local/share +# https://github.com/yarnpkg/yarn/issues/4628 +mkdir -p /usr/local/share + +rm /usr/bin/env +ln -s "$(hab pkg path core/coreutils)/bin/env" /usr/bin/env +hab pkg install -b core/coreutils core/bash core/node core/yarn core/git core/aws-cli + +yarn install --cache-folder .yarn +GENERATE_SMOKE_TESTS=true yarn build --output-path build +mkdir build/pages +mv build/*.html build/pages + +aws s3 sync --acl public-read --cache-control "max-age=31556926" build/assets "$TARGET_S3_URL/assets" +aws s3 sync --acl public-read --cache-control "no-cache" --delete build/pages "$TARGET_S3_URL/pages/latest" diff --git a/scripts/run-local-reticulum.sh b/scripts/run-local-reticulum.sh new file mode 100644 index 0000000000000000000000000000000000000000..976d858cd8dd7adea49ae587995759c431420182 --- /dev/null +++ b/scripts/run-local-reticulum.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +BASE_ASSETS_PATH=https://hubs.local:8080/ DEV_RETICULUM_SERVER=hubs.local:4000 yarn start diff --git a/src/assets/translations.data.json b/src/assets/translations.data.json index 79d11599544849a83f9982617dafddd3bb6c268a..1f8ae6a1b0986b0576ad3dd567b1fc8bb96c1d86 100644 --- a/src/assets/translations.data.json +++ b/src/assets/translations.data.json @@ -40,6 +40,7 @@ "exit.subtitle.closed": "This room is no longer available.", "exit.subtitle.full": "This room is full, please try again later.", "exit.subtitle.connect_error": "Unable to connect to this room, please try again later.", + "exit.subtitle.version_mismatch": "The version you deployed is not available yet. Your browser will refresh in 5 seconds.", "autoexit.title": "Auto-ending session in ", "autoexit.title_units": " seconds", "autoexit.subtitle": "You have started another session.", diff --git a/src/hub.js b/src/hub.js index fa21149111a673f2390b7acc6b33eaeb3dbfa840..d66de1f4ffae134ee535e1bc6b38a4baf562f9e7 100644 --- a/src/hub.js +++ b/src/hub.js @@ -432,6 +432,13 @@ const onReady = async () => { return; } + if (qs.required_version && qs.required_version !== process.env.BUILD_VERSION) { + remountUI({ roomUnavailableReason: "version_mismatch" }); + setTimeout(() => document.location.reload(), 5000); + exitScene(); + return; + } + getAvailableVREntryTypes().then(availableVREntryTypes => { if (availableVREntryTypes.gearvr === VR_DEVICE_AVAILABILITY.yes) { remountUI({ availableVREntryTypes, forcedVREntryType: "gearvr" }); diff --git a/src/index.js b/src/index.js index 2383019035144bc82277e15baa01b034f6244754..32558cd4ec93844c558ce5d45fed8d54824ac01a 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,6 @@ import InfoDialog from "./react-components/info-dialog.js"; import queryString from "query-string"; const qs = queryString.parse(location.search); - registerTelemetry(); ReactDOM.render( diff --git a/src/react-components/hub-create-panel.js b/src/react-components/hub-create-panel.js index 7e44ce63093ad5ad3df772807794140cab9af2b9..dc10b99ac217609b07bda59422c805c5ea4f1581 100644 --- a/src/react-components/hub-create-panel.js +++ b/src/react-components/hub-create-panel.js @@ -85,7 +85,7 @@ class HubCreatePanel extends Component { const hub = await res.json(); - if (process.env.NODE_ENV === "production") { + if (process.env.NODE_ENV === "production" || document.location.host === process.env.DEV_RETICULUM_SERVER) { document.location = hub.url; } else { document.location = `/hub.html?hub_id=${hub.hub_id}`; diff --git a/webpack.config.js b/webpack.config.js index 3c92d1b38b746d1646696d0eb93d7b3f00fadd2b..5f688d9bfa687d8cc517eb0b98e9d70b74fd71d2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -99,6 +99,7 @@ const config = { useLocalIp: true, public: "hubs.local:8080", port: 8080, + headers: { "Access-Control-Allow-Origin": "*" }, before: function(app) { // networked-aframe makes HEAD requests to the server for time syncing. Respond with an empty body. app.head("*", function(req, res, next) { @@ -266,7 +267,8 @@ const config = { NODE_ENV: process.env.NODE_ENV, JANUS_SERVER: process.env.JANUS_SERVER, DEV_RETICULUM_SERVER: process.env.DEV_RETICULUM_SERVER, - ASSET_BUNDLE_SERVER: process.env.ASSET_BUNDLE_SERVER + ASSET_BUNDLE_SERVER: process.env.ASSET_BUNDLE_SERVER, + BUILD_VERSION: process.env.BUILD_VERSION }) }) ]