Skip to content
This repository has been archived by the owner on Oct 11, 2022. It is now read-only.

Commit

Permalink
Merge pull request #5017 from withspectrum/3.1.3
Browse files Browse the repository at this point in the history
3.1.3
  • Loading branch information
brianlovin authored Apr 3, 2019
2 parents 2bca8b1 + 735b2ae commit 182499b
Show file tree
Hide file tree
Showing 17 changed files with 226 additions and 126 deletions.
5 changes: 3 additions & 2 deletions api/apollo-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class ProtectedApolloServer extends ApolloServer {
}
}

let connections = 0;
const server = new ProtectedApolloServer({
schema,
formatError: createErrorFormatter(),
Expand Down Expand Up @@ -77,15 +78,15 @@ const server = new ProtectedApolloServer({
subscriptions: {
path: '/websocket',
onDisconnect: rawSocket => {
statsd.increment('websocket.connections', -1);
statsd.gauge('ws.connections', (connections -= 1));
return getUserIdFromReq(rawSocket.upgradeReq)
.then(id => id && setUserOnline(id, false))
.catch(err => {
console.error(err);
});
},
onConnect: (connectionParams, rawSocket) => {
statsd.increment('websocket.connections', 1);
statsd.gauge('ws.connections', (connections += 1));
return getUserIdFromReq(rawSocket.upgradeReq)
.then(id => (id ? setUserOnline(id, true) : null))
.then(user => {
Expand Down
2 changes: 2 additions & 0 deletions api/queries/user/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import totalReputation from './totalReputation';
import isAdmin from './isAdmin';
import contextPermissions from './contextPermissions';
import githubProfile from './githubProfile';
import isOnline from './isOnline';

// no-op resolvers to transition while removing payments
import type { DBUser } from 'shared/types';
Expand Down Expand Up @@ -48,5 +49,6 @@ module.exports = {
isPro,
recurringPayments,
invoices,
isOnline,
},
};
7 changes: 7 additions & 0 deletions api/queries/user/isOnline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// @flow
import type { GraphQLContext } from '../../';
import type { DBUser } from 'shared/types';

// Always return true for the current user
export default ({ isOnline, id }: DBUser, _: any, { user }: GraphQLContext) =>
user && user.id === id ? true : isOnline;
2 changes: 1 addition & 1 deletion config-overrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ module.exports = function override(config, env) {
config.plugins.unshift(
new webpack.optimize.CommonsChunkPlugin({
names: ['bootstrap'],
filename: 'static/js/[name].js',
filename: 'static/js/[name].[hash].js',
minChunks: Infinity,
})
);
Expand Down
4 changes: 4 additions & 0 deletions cypress/integration/channel/view/membership_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ const QUIET_USER_ID = constants.QUIET_USER_ID;
const leave = () => {
cy.get('[data-cy="channel-leave-button"]')
.last()
.scrollIntoView()
.should('be.visible')
.contains('Member');

cy.get('[data-cy="channel-leave-button"]')
.last()
.scrollIntoView()
.click();

cy.get('[data-cy="channel-join-button"]').contains(`Join`);
Expand All @@ -35,11 +37,13 @@ const leave = () => {
const join = () => {
cy.get('[data-cy="channel-join-button"]')
.last()
.scrollIntoView()
.should('be.visible')
.contains('Join');

cy.get('[data-cy="channel-join-button"]')
.last()
.scrollIntoView()
.click();

cy.get('[data-cy="channel-leave-button"]').contains(`Member`);
Expand Down
7 changes: 6 additions & 1 deletion cypress/integration/thread/action_bar_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,9 @@ describe('action bar renders', () => {
cy.auth(publicThreadAuthor.id);

openSettingsDropdown();

cy.get('[data-cy="thread-actions-dropdown-trigger"]').should(
'be.visible'
);
cy.get('[data-cy="thread-dropdown-edit"]').click();
cy.get('[data-cy="save-thread-edit-button"]').should('be.visible');
const title = 'Some new thread';
Expand All @@ -209,6 +211,9 @@ describe('action bar renders', () => {

// undo the edit
openSettingsDropdown();
cy.get('[data-cy="thread-actions-dropdown-trigger"]').should(
'be.visible'
);
cy.get('[data-cy="thread-dropdown-edit"]').click();
cy.get('[data-cy="save-thread-edit-button"]').should('be.visible');
const originalTitle = 'The first thread! 🎉';
Expand Down
37 changes: 21 additions & 16 deletions hyperion/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,27 @@ addSecurityMiddleware(app, { enableNonce: true, enableCSP: true });

// Serve static files from the build folder
app.use(
express.static(path.resolve(__dirname, '..', 'build'), {
index: false,
setHeaders: (res, path) => {
// Don't cache the serviceworker in the browser
if (path.indexOf('sw.js') > -1) {
res.setHeader('Cache-Control', 'no-store, no-cache');
return;
}

if (path.endsWith('.js')) {
// Cache static files in now CDN for seven days
// (the filename changes if the file content changes, so we can cache these forever)
res.setHeader('Cache-Control', `s-maxage=${ONE_HOUR}`);
}
},
})
express.static(
process.env.NODE_ENV === 'production'
? './build'
: path.join(__dirname, '../build/'),
{
index: false,
setHeaders: (res, path) => {
// Don't cache the serviceworker in the browser
if (path.indexOf('sw.js') > -1) {
res.setHeader('Cache-Control', 'no-store, no-cache');
return;
}

if (path.endsWith('.js')) {
// Cache static files in now CDN for seven days
// (the filename changes if the file content changes, so we can cache these forever)
res.setHeader('Cache-Control', `s-maxage=${ONE_HOUR}`);
}
},
}
)
);

// In dev the static files from the root public folder aren't moved to the build folder by create-react-app
Expand Down
110 changes: 60 additions & 50 deletions hyperion/renderer/html-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,28 @@ import serialize from 'serialize-javascript';

// Match main.asdf123.js in production mode or bundle.js in dev mode
const mainBundleRegex = /(main|bundle)\.(?:.*\.)?js$/;
const bootstrapBundleRegex = /(bootstrap)\.(?:.*\.)?js$/;

let bundles;
try {
bundles = fs.readdirSync(path.join(__dirname, '../../build/static/js'));
bundles = fs.readdirSync(
process.env.NODE_ENV === 'production'
? './build/static/js'
: path.join(__dirname, '../../build/static/js')
);
} catch (err) {
console.error(err);
throw new Error(
'It looks like you didn\'t run "yarn run dev:web" or "yarn run build:web" before starting hyperion. Please wait until either of them completes before starting hyperion.'
);
}

// Get the main bundle filename
const mainBundle = bundles.find(bundle => mainBundleRegex.test(bundle));
if (!mainBundle) {
const bootstrapBundle = bundles.find(bundle =>
bootstrapBundleRegex.test(bundle)
);
if (!mainBundle || !bootstrapBundle) {
throw new Error(
'It looks like you didn\'t run "yarn run dev:web" or "yarn run build:web" before starting hyperion. Please wait until either of them completes before starting hyperion.'
);
Expand All @@ -34,54 +43,55 @@ export const getHeader = ({
metaTags: string,
nonce: string,
}) => {
// prettier-ignore
return html`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="mask-icon" href="/img/pinned-tab.svg" color="#171A21">
<meta name="theme-color" content="#171A21">
<link rel="manifest" href="/manifest.json">
<meta property="og:site_name" content="Spectrum">
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@withspectrum">
<meta name="twitter:image:alt" content="Where communities are built">
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="/img/apple-icon-57x57-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/img/apple-icon-72x72-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/img/apple-icon-114x114-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/img/apple-icon-144x144-precomposed.png" />
${metaTags}
<script type="text/javascript" nonce="${nonce}">
!function(e,a,t,n,g,c,o){e.GoogleAnalyticsObject=g,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(t),o=a.getElementsByTagName(t)[0],c.defer=1,c.src="https://www.google-analytics.com/analytics.js",o.parentNode.insertBefore(c,o)}(window,document,"script",0,"ga"),ga("create","UA-92673909-1","auto"),ga("send","pageview"),ga('set', 'anonymizeIp', true)
</script>
<script nonce="${nonce}" type="text/javascript">
(function(e,t){var n=e.amplitude||{_q:[],_iq:{}};var r=t.createElement("script")
;r.type="text/javascript";r.async=true
;r.src="https://cdn.amplitude.com/libs/amplitude-4.2.1-min.gz.js"
;r.onload=function(){if(e.amplitude.runQueuedFunctions){
e.amplitude.runQueuedFunctions()}else{
console.error("[Amplitude] Error: could not load SDK")}}
;var i=t.getElementsByTagName("script")[0];i.parentNode.insertBefore(r,i)
;function s(e,t){e.prototype[t]=function(){
this._q.push([t].concat(Array.prototype.slice.call(arguments,0)));return this}}
var o=function(){this._q=[];return this}
;var a=["add","append","clearAll","prepend","set","setOnce","unset"]
;for(var u=0;u<a.length;u++){s(o,a[u])}n.Identify=o;var c=function(){this._q=[]
;return this}
;var l=["setProductId","setQuantity","setPrice","setRevenueType","setEventProperties"]
;for(var p=0;p<l.length;p++){s(c,l[p])}n.Revenue=c
;var d=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties","setGroup","logRevenueV2","regenerateDeviceId","logEventWithTimestamp","logEventWithGroups","setSessionId","resetSessionId"]
;function v(e){function t(t){e[t]=function(){
e._q.push([t].concat(Array.prototype.slice.call(arguments,0)))}}
for(var n=0;n<d.length;n++){t(d[n])}}v(n);n.getInstance=function(e){
e=(!e||e.length===0?"$default_instance":e).toLowerCase()
;if(!n._iq.hasOwnProperty(e)){n._iq[e]={_q:[]};v(n._iq[e])}return n._iq[e]}
;e.amplitude=n})(window,document);
</script>
</head>
<body>
<div id="root">`;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="mask-icon" href="/img/pinned-tab.svg" color="#171A21">
<meta name="theme-color" content="#171A21">
<link rel="manifest" href="/manifest.json">
<meta property="og:site_name" content="Spectrum">
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@withspectrum">
<meta name="twitter:image:alt" content="Where communities are built">
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="/img/apple-icon-57x57-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/img/apple-icon-72x72-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/img/apple-icon-114x114-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/img/apple-icon-144x144-precomposed.png" />
${metaTags}
<script type="text/javascript" nonce="${nonce}">
!function(e,a,t,n,g,c,o){e.GoogleAnalyticsObject=g,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(t),o=a.getElementsByTagName(t)[0],c.defer=1,c.src="https://www.google-analytics.com/analytics.js",o.parentNode.insertBefore(c,o)}(window,document,"script",0,"ga"),ga("create","UA-92673909-1","auto"),ga("send","pageview"),ga('set', 'anonymizeIp', true)
</script>
<script nonce="${nonce}" type="text/javascript">
(function(e,t){var n=e.amplitude||{_q:[],_iq:{}};var r=t.createElement("script")
;r.type="text/javascript";r.async=true
;r.src="https://cdn.amplitude.com/libs/amplitude-4.2.1-min.gz.js"
;r.onload=function(){if(e.amplitude.runQueuedFunctions){
e.amplitude.runQueuedFunctions()}else{
console.error("[Amplitude] Error: could not load SDK")}}
;var i=t.getElementsByTagName("script")[0];i.parentNode.insertBefore(r,i)
;function s(e,t){e.prototype[t]=function(){
this._q.push([t].concat(Array.prototype.slice.call(arguments,0)));return this}}
var o=function(){this._q=[];return this}
;var a=["add","append","clearAll","prepend","set","setOnce","unset"]
;for(var u=0;u<a.length;u++){s(o,a[u])}n.Identify=o;var c=function(){this._q=[]
;return this}
;var l=["setProductId","setQuantity","setPrice","setRevenueType","setEventProperties"]
;for(var p=0;p<l.length;p++){s(c,l[p])}n.Revenue=c
;var d=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties","setGroup","logRevenueV2","regenerateDeviceId","logEventWithTimestamp","logEventWithGroups","setSessionId","resetSessionId"]
;function v(e){function t(t){e[t]=function(){
e._q.push([t].concat(Array.prototype.slice.call(arguments,0)))}}
for(var n=0;n<d.length;n++){t(d[n])}}v(n);n.getInstance=function(e){
e=(!e||e.length===0?"$default_instance":e).toLowerCase()
;if(!n._iq.hasOwnProperty(e)){n._iq[e]={_q:[]};v(n._iq[e])}return n._iq[e]}
;e.amplitude=n})(window,document);
</script>
</head>
<body>
<div id="root">`;
};

export const getFooter = ({
Expand All @@ -103,7 +113,7 @@ export const getFooter = ({
)}</script>
<script nonce="${nonce}">window.__DATA__=${serialize(data)}</script>
<script defer="defer" type="text/javascript" src="https://cdn.polyfill.io/v2/polyfill.min.js?features=default,Array.prototype.find,Symbol.iterator"></script>
<script type="text/javascript" src="/static/js/bootstrap.js"></script>
${createScriptTag({ src: `/static/js/${bootstrapBundle}` })}
${bundles.map(src => createScriptTag({ src }))}
${createScriptTag({ src: `/static/js/${mainBundle}` })}
</body>
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Spectrum",
"version": "3.1.2",
"version": "3.1.3",
"license": "BSD-3-Clause",
"devDependencies": {
"@babel/preset-flow": "^7.0.0",
Expand Down Expand Up @@ -222,7 +222,7 @@
"event-stream": "3.3.4"
},
"scripts": {
"start": "cross-env NODE_ENV=production node build-hyperion/main.js",
"start": "NODE_ENV=production node main.js",
"start:athena": "cross-env NODE_ENV=production node build-athena/main.js",
"start:hermes": "cross-env NODE_ENV=production node build-hermes/main.js",
"start:chronos": "cross-env NODE_ENV=production node build-chronos/main.js",
Expand All @@ -241,7 +241,6 @@
"dev:hyperion": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=build*,hyperion*,-hyperion:resolvers cross-env DIR=hyperion backpack",
"dev:analytics": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=build*,analytics*,-analytics:resolvers cross-env DIR=analytics backpack",
"dev:desktop": "(cd desktop && yarn run dev)",
"build": "npm run build:web && npm run build:hyperion",
"prebuild:api": "rimraf build-api",
"build:api": "cross-env NODE_PATH=./ cross-env DIR=api backpack build",
"postbuild:api": "cp api/package.json build-api/package.json && cp now.json build-api/now.json && cpy cacert build-api",
Expand All @@ -263,8 +262,9 @@
"prebuild:analytics": "rimraf build-analytics",
"build:analytics": "cross-env NODE_PATH=./ cross-env DIR=analytics backpack build",
"postbuild:analytics": "cp analytics/package.json build-analytics/package.json && cp now.json build-analytics/now.json && cpy cacert build-analytics",
"prebuild:hyperion": "rimraf build-hyperion",
"prebuild:hyperion": "rimraf build && yarn run build:web && rimraf build-hyperion",
"build:hyperion": "cross-env NODE_PATH=./ cross-env DIR=hyperion backpack build",
"postbuild:hyperion": "cp -r build build-hyperion && cp now.json build-hyperion && cp yarn.lock build-hyperion && cp package.json build-hyperion && cp cacert build-hyperion",
"build:web": "cross-env NODE_PATH=./ react-app-rewired build",
"build:desktop": "(cd desktop && yarn run package:all)",
"test:desktop": "(cd desktop && yarn run package:test)",
Expand Down
44 changes: 15 additions & 29 deletions scripts/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,35 +67,6 @@ if (!flags.prod) {

console.log(`\nDeploying to ${flags.prod ? 'production' : 'alpha'}!\n`);

// Hyperion needs to be deployed especially
if (servers.indexOf('hyperion') > -1) {
servers = servers.filter(w => w !== 'hyperion');
console.log(`\n---hyperion---`);
console.log(`Deploying hyperion`);
exec(now(), {
stdio: 'inherit',
});
console.log('Aliasing to hyperion.workers.spectrum.chat');
exec(
now(`alias hyperion.${flags.prod ? 'workers' : 'alpha'}.spectrum.chat`),
{
stdio: 'inherit',
}
);
console.log('Clearing cache');
exec(
now(
`alias -r rules${!flags.prod ? '-alpha' : ''}.json ${
!flags.prod ? 'alpha.' : ''
}spectrum.chat`
),
{
stdio: 'inherit',
}
);
console.log('hyperion is live!\n');
}

if (servers.length > 0) {
console.log('Installing fresh dependencies...');
exec('yarn');
Expand Down Expand Up @@ -127,6 +98,21 @@ if (servers.length > 0) {
});

console.log(`${server} is live!`);

if (server === 'hyperion') {
console.log('Clearing hyperion cache...');
exec(
now(
`alias -r rules${!flags.prod ? '-alpha' : ''}.json ${
!flags.prod ? 'alpha.' : ''
}spectrum.chat`
),
{
stdio: 'inherit',
}
);
console.log('Cache cleared!');
}
console.log('Deleting old deploy(s)...');
exec(now(`rm --safe --yes build-${server}`), {
stdio: 'inherit',
Expand Down
Loading

0 comments on commit 182499b

Please sign in to comment.