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

Commit 182499b

Browse files
authored
Merge pull request #5017 from withspectrum/3.1.3
3.1.3
2 parents 2bca8b1 + 735b2ae commit 182499b

File tree

17 files changed

+226
-126
lines changed

17 files changed

+226
-126
lines changed

api/apollo-server.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class ProtectedApolloServer extends ApolloServer {
4545
}
4646
}
4747

48+
let connections = 0;
4849
const server = new ProtectedApolloServer({
4950
schema,
5051
formatError: createErrorFormatter(),
@@ -77,15 +78,15 @@ const server = new ProtectedApolloServer({
7778
subscriptions: {
7879
path: '/websocket',
7980
onDisconnect: rawSocket => {
80-
statsd.increment('websocket.connections', -1);
81+
statsd.gauge('ws.connections', (connections -= 1));
8182
return getUserIdFromReq(rawSocket.upgradeReq)
8283
.then(id => id && setUserOnline(id, false))
8384
.catch(err => {
8485
console.error(err);
8586
});
8687
},
8788
onConnect: (connectionParams, rawSocket) => {
88-
statsd.increment('websocket.connections', 1);
89+
statsd.gauge('ws.connections', (connections += 1));
8990
return getUserIdFromReq(rawSocket.upgradeReq)
9091
.then(id => (id ? setUserOnline(id, true) : null))
9192
.then(user => {

api/queries/user/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import totalReputation from './totalReputation';
1717
import isAdmin from './isAdmin';
1818
import contextPermissions from './contextPermissions';
1919
import githubProfile from './githubProfile';
20+
import isOnline from './isOnline';
2021

2122
// no-op resolvers to transition while removing payments
2223
import type { DBUser } from 'shared/types';
@@ -48,5 +49,6 @@ module.exports = {
4849
isPro,
4950
recurringPayments,
5051
invoices,
52+
isOnline,
5153
},
5254
};

api/queries/user/isOnline.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @flow
2+
import type { GraphQLContext } from '../../';
3+
import type { DBUser } from 'shared/types';
4+
5+
// Always return true for the current user
6+
export default ({ isOnline, id }: DBUser, _: any, { user }: GraphQLContext) =>
7+
user && user.id === id ? true : isOnline;

config-overrides.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ module.exports = function override(config, env) {
149149
config.plugins.unshift(
150150
new webpack.optimize.CommonsChunkPlugin({
151151
names: ['bootstrap'],
152-
filename: 'static/js/[name].js',
152+
filename: 'static/js/[name].[hash].js',
153153
minChunks: Infinity,
154154
})
155155
);

cypress/integration/channel/view/membership_spec.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ const QUIET_USER_ID = constants.QUIET_USER_ID;
2222
const leave = () => {
2323
cy.get('[data-cy="channel-leave-button"]')
2424
.last()
25+
.scrollIntoView()
2526
.should('be.visible')
2627
.contains('Member');
2728

2829
cy.get('[data-cy="channel-leave-button"]')
2930
.last()
31+
.scrollIntoView()
3032
.click();
3133

3234
cy.get('[data-cy="channel-join-button"]').contains(`Join`);
@@ -35,11 +37,13 @@ const leave = () => {
3537
const join = () => {
3638
cy.get('[data-cy="channel-join-button"]')
3739
.last()
40+
.scrollIntoView()
3841
.should('be.visible')
3942
.contains('Join');
4043

4144
cy.get('[data-cy="channel-join-button"]')
4245
.last()
46+
.scrollIntoView()
4347
.click();
4448

4549
cy.get('[data-cy="channel-leave-button"]').contains(`Member`);

cypress/integration/thread/action_bar_spec.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,9 @@ describe('action bar renders', () => {
195195
cy.auth(publicThreadAuthor.id);
196196

197197
openSettingsDropdown();
198-
198+
cy.get('[data-cy="thread-actions-dropdown-trigger"]').should(
199+
'be.visible'
200+
);
199201
cy.get('[data-cy="thread-dropdown-edit"]').click();
200202
cy.get('[data-cy="save-thread-edit-button"]').should('be.visible');
201203
const title = 'Some new thread';
@@ -209,6 +211,9 @@ describe('action bar renders', () => {
209211

210212
// undo the edit
211213
openSettingsDropdown();
214+
cy.get('[data-cy="thread-actions-dropdown-trigger"]').should(
215+
'be.visible'
216+
);
212217
cy.get('[data-cy="thread-dropdown-edit"]').click();
213218
cy.get('[data-cy="save-thread-edit-button"]').should('be.visible');
214219
const originalTitle = 'The first thread! 🎉';

hyperion/index.js

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,27 @@ addSecurityMiddleware(app, { enableNonce: true, enableCSP: true });
3535

3636
// Serve static files from the build folder
3737
app.use(
38-
express.static(path.resolve(__dirname, '..', 'build'), {
39-
index: false,
40-
setHeaders: (res, path) => {
41-
// Don't cache the serviceworker in the browser
42-
if (path.indexOf('sw.js') > -1) {
43-
res.setHeader('Cache-Control', 'no-store, no-cache');
44-
return;
45-
}
46-
47-
if (path.endsWith('.js')) {
48-
// Cache static files in now CDN for seven days
49-
// (the filename changes if the file content changes, so we can cache these forever)
50-
res.setHeader('Cache-Control', `s-maxage=${ONE_HOUR}`);
51-
}
52-
},
53-
})
38+
express.static(
39+
process.env.NODE_ENV === 'production'
40+
? './build'
41+
: path.join(__dirname, '../build/'),
42+
{
43+
index: false,
44+
setHeaders: (res, path) => {
45+
// Don't cache the serviceworker in the browser
46+
if (path.indexOf('sw.js') > -1) {
47+
res.setHeader('Cache-Control', 'no-store, no-cache');
48+
return;
49+
}
50+
51+
if (path.endsWith('.js')) {
52+
// Cache static files in now CDN for seven days
53+
// (the filename changes if the file content changes, so we can cache these forever)
54+
res.setHeader('Cache-Control', `s-maxage=${ONE_HOUR}`);
55+
}
56+
},
57+
}
58+
)
5459
);
5560

5661
// In dev the static files from the root public folder aren't moved to the build folder by create-react-app

hyperion/renderer/html-template.js

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,28 @@ import serialize from 'serialize-javascript';
66

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

1011
let bundles;
1112
try {
12-
bundles = fs.readdirSync(path.join(__dirname, '../../build/static/js'));
13+
bundles = fs.readdirSync(
14+
process.env.NODE_ENV === 'production'
15+
? './build/static/js'
16+
: path.join(__dirname, '../../build/static/js')
17+
);
1318
} catch (err) {
19+
console.error(err);
1420
throw new Error(
1521
'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.'
1622
);
1723
}
1824

1925
// Get the main bundle filename
2026
const mainBundle = bundles.find(bundle => mainBundleRegex.test(bundle));
21-
if (!mainBundle) {
27+
const bootstrapBundle = bundles.find(bundle =>
28+
bootstrapBundleRegex.test(bundle)
29+
);
30+
if (!mainBundle || !bootstrapBundle) {
2231
throw new Error(
2332
'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.'
2433
);
@@ -34,54 +43,55 @@ export const getHeader = ({
3443
metaTags: string,
3544
nonce: string,
3645
}) => {
46+
// prettier-ignore
3747
return html`
38-
<!DOCTYPE html>
39-
<html lang="en">
40-
<head>
41-
<meta charset="utf-8">
42-
<meta name="viewport" content="width=device-width,initial-scale=1">
43-
<link rel="mask-icon" href="/img/pinned-tab.svg" color="#171A21">
44-
<meta name="theme-color" content="#171A21">
45-
<link rel="manifest" href="/manifest.json">
46-
<meta property="og:site_name" content="Spectrum">
47-
<meta name="twitter:card" content="summary">
48-
<meta name="twitter:site" content="@withspectrum">
49-
<meta name="twitter:image:alt" content="Where communities are built">
50-
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="/img/apple-icon-57x57-precomposed.png" />
51-
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/img/apple-icon-72x72-precomposed.png" />
52-
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/img/apple-icon-114x114-precomposed.png" />
53-
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/img/apple-icon-144x144-precomposed.png" />
54-
${metaTags}
55-
<script type="text/javascript" nonce="${nonce}">
56-
!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)
57-
</script>
58-
<script nonce="${nonce}" type="text/javascript">
59-
(function(e,t){var n=e.amplitude||{_q:[],_iq:{}};var r=t.createElement("script")
60-
;r.type="text/javascript";r.async=true
61-
;r.src="https://cdn.amplitude.com/libs/amplitude-4.2.1-min.gz.js"
62-
;r.onload=function(){if(e.amplitude.runQueuedFunctions){
63-
e.amplitude.runQueuedFunctions()}else{
64-
console.error("[Amplitude] Error: could not load SDK")}}
65-
;var i=t.getElementsByTagName("script")[0];i.parentNode.insertBefore(r,i)
66-
;function s(e,t){e.prototype[t]=function(){
67-
this._q.push([t].concat(Array.prototype.slice.call(arguments,0)));return this}}
68-
var o=function(){this._q=[];return this}
69-
;var a=["add","append","clearAll","prepend","set","setOnce","unset"]
70-
;for(var u=0;u<a.length;u++){s(o,a[u])}n.Identify=o;var c=function(){this._q=[]
71-
;return this}
72-
;var l=["setProductId","setQuantity","setPrice","setRevenueType","setEventProperties"]
73-
;for(var p=0;p<l.length;p++){s(c,l[p])}n.Revenue=c
74-
;var d=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties","setGroup","logRevenueV2","regenerateDeviceId","logEventWithTimestamp","logEventWithGroups","setSessionId","resetSessionId"]
75-
;function v(e){function t(t){e[t]=function(){
76-
e._q.push([t].concat(Array.prototype.slice.call(arguments,0)))}}
77-
for(var n=0;n<d.length;n++){t(d[n])}}v(n);n.getInstance=function(e){
78-
e=(!e||e.length===0?"$default_instance":e).toLowerCase()
79-
;if(!n._iq.hasOwnProperty(e)){n._iq[e]={_q:[]};v(n._iq[e])}return n._iq[e]}
80-
;e.amplitude=n})(window,document);
81-
</script>
82-
</head>
83-
<body>
84-
<div id="root">`;
48+
<!DOCTYPE html>
49+
<html lang="en">
50+
<head>
51+
<meta charset="utf-8">
52+
<meta name="viewport" content="width=device-width,initial-scale=1">
53+
<link rel="mask-icon" href="/img/pinned-tab.svg" color="#171A21">
54+
<meta name="theme-color" content="#171A21">
55+
<link rel="manifest" href="/manifest.json">
56+
<meta property="og:site_name" content="Spectrum">
57+
<meta name="twitter:card" content="summary">
58+
<meta name="twitter:site" content="@withspectrum">
59+
<meta name="twitter:image:alt" content="Where communities are built">
60+
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="/img/apple-icon-57x57-precomposed.png" />
61+
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/img/apple-icon-72x72-precomposed.png" />
62+
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/img/apple-icon-114x114-precomposed.png" />
63+
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/img/apple-icon-144x144-precomposed.png" />
64+
${metaTags}
65+
<script type="text/javascript" nonce="${nonce}">
66+
!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)
67+
</script>
68+
<script nonce="${nonce}" type="text/javascript">
69+
(function(e,t){var n=e.amplitude||{_q:[],_iq:{}};var r=t.createElement("script")
70+
;r.type="text/javascript";r.async=true
71+
;r.src="https://cdn.amplitude.com/libs/amplitude-4.2.1-min.gz.js"
72+
;r.onload=function(){if(e.amplitude.runQueuedFunctions){
73+
e.amplitude.runQueuedFunctions()}else{
74+
console.error("[Amplitude] Error: could not load SDK")}}
75+
;var i=t.getElementsByTagName("script")[0];i.parentNode.insertBefore(r,i)
76+
;function s(e,t){e.prototype[t]=function(){
77+
this._q.push([t].concat(Array.prototype.slice.call(arguments,0)));return this}}
78+
var o=function(){this._q=[];return this}
79+
;var a=["add","append","clearAll","prepend","set","setOnce","unset"]
80+
;for(var u=0;u<a.length;u++){s(o,a[u])}n.Identify=o;var c=function(){this._q=[]
81+
;return this}
82+
;var l=["setProductId","setQuantity","setPrice","setRevenueType","setEventProperties"]
83+
;for(var p=0;p<l.length;p++){s(c,l[p])}n.Revenue=c
84+
;var d=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties","setGroup","logRevenueV2","regenerateDeviceId","logEventWithTimestamp","logEventWithGroups","setSessionId","resetSessionId"]
85+
;function v(e){function t(t){e[t]=function(){
86+
e._q.push([t].concat(Array.prototype.slice.call(arguments,0)))}}
87+
for(var n=0;n<d.length;n++){t(d[n])}}v(n);n.getInstance=function(e){
88+
e=(!e||e.length===0?"$default_instance":e).toLowerCase()
89+
;if(!n._iq.hasOwnProperty(e)){n._iq[e]={_q:[]};v(n._iq[e])}return n._iq[e]}
90+
;e.amplitude=n})(window,document);
91+
</script>
92+
</head>
93+
<body>
94+
<div id="root">`;
8595
};
8696

8797
export const getFooter = ({
@@ -103,7 +113,7 @@ export const getFooter = ({
103113
)}</script>
104114
<script nonce="${nonce}">window.__DATA__=${serialize(data)}</script>
105115
<script defer="defer" type="text/javascript" src="https://cdn.polyfill.io/v2/polyfill.min.js?features=default,Array.prototype.find,Symbol.iterator"></script>
106-
<script type="text/javascript" src="/static/js/bootstrap.js"></script>
116+
${createScriptTag({ src: `/static/js/${bootstrapBundle}` })}
107117
${bundles.map(src => createScriptTag({ src }))}
108118
${createScriptTag({ src: `/static/js/${mainBundle}` })}
109119
</body>

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Spectrum",
3-
"version": "3.1.2",
3+
"version": "3.1.3",
44
"license": "BSD-3-Clause",
55
"devDependencies": {
66
"@babel/preset-flow": "^7.0.0",
@@ -222,7 +222,7 @@
222222
"event-stream": "3.3.4"
223223
},
224224
"scripts": {
225-
"start": "cross-env NODE_ENV=production node build-hyperion/main.js",
225+
"start": "NODE_ENV=production node main.js",
226226
"start:athena": "cross-env NODE_ENV=production node build-athena/main.js",
227227
"start:hermes": "cross-env NODE_ENV=production node build-hermes/main.js",
228228
"start:chronos": "cross-env NODE_ENV=production node build-chronos/main.js",
@@ -241,7 +241,6 @@
241241
"dev:hyperion": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=build*,hyperion*,-hyperion:resolvers cross-env DIR=hyperion backpack",
242242
"dev:analytics": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=build*,analytics*,-analytics:resolvers cross-env DIR=analytics backpack",
243243
"dev:desktop": "(cd desktop && yarn run dev)",
244-
"build": "npm run build:web && npm run build:hyperion",
245244
"prebuild:api": "rimraf build-api",
246245
"build:api": "cross-env NODE_PATH=./ cross-env DIR=api backpack build",
247246
"postbuild:api": "cp api/package.json build-api/package.json && cp now.json build-api/now.json && cpy cacert build-api",
@@ -263,8 +262,9 @@
263262
"prebuild:analytics": "rimraf build-analytics",
264263
"build:analytics": "cross-env NODE_PATH=./ cross-env DIR=analytics backpack build",
265264
"postbuild:analytics": "cp analytics/package.json build-analytics/package.json && cp now.json build-analytics/now.json && cpy cacert build-analytics",
266-
"prebuild:hyperion": "rimraf build-hyperion",
265+
"prebuild:hyperion": "rimraf build && yarn run build:web && rimraf build-hyperion",
267266
"build:hyperion": "cross-env NODE_PATH=./ cross-env DIR=hyperion backpack build",
267+
"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",
268268
"build:web": "cross-env NODE_PATH=./ react-app-rewired build",
269269
"build:desktop": "(cd desktop && yarn run package:all)",
270270
"test:desktop": "(cd desktop && yarn run package:test)",

scripts/deploy.js

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -67,35 +67,6 @@ if (!flags.prod) {
6767

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

70-
// Hyperion needs to be deployed especially
71-
if (servers.indexOf('hyperion') > -1) {
72-
servers = servers.filter(w => w !== 'hyperion');
73-
console.log(`\n---hyperion---`);
74-
console.log(`Deploying hyperion`);
75-
exec(now(), {
76-
stdio: 'inherit',
77-
});
78-
console.log('Aliasing to hyperion.workers.spectrum.chat');
79-
exec(
80-
now(`alias hyperion.${flags.prod ? 'workers' : 'alpha'}.spectrum.chat`),
81-
{
82-
stdio: 'inherit',
83-
}
84-
);
85-
console.log('Clearing cache');
86-
exec(
87-
now(
88-
`alias -r rules${!flags.prod ? '-alpha' : ''}.json ${
89-
!flags.prod ? 'alpha.' : ''
90-
}spectrum.chat`
91-
),
92-
{
93-
stdio: 'inherit',
94-
}
95-
);
96-
console.log('hyperion is live!\n');
97-
}
98-
9970
if (servers.length > 0) {
10071
console.log('Installing fresh dependencies...');
10172
exec('yarn');
@@ -127,6 +98,21 @@ if (servers.length > 0) {
12798
});
12899

129100
console.log(`${server} is live!`);
101+
102+
if (server === 'hyperion') {
103+
console.log('Clearing hyperion cache...');
104+
exec(
105+
now(
106+
`alias -r rules${!flags.prod ? '-alpha' : ''}.json ${
107+
!flags.prod ? 'alpha.' : ''
108+
}spectrum.chat`
109+
),
110+
{
111+
stdio: 'inherit',
112+
}
113+
);
114+
console.log('Cache cleared!');
115+
}
130116
console.log('Deleting old deploy(s)...');
131117
exec(now(`rm --safe --yes build-${server}`), {
132118
stdio: 'inherit',

0 commit comments

Comments
 (0)