Skip to content

Commit 09fddfb

Browse files
ning-yremo5000
authored andcommitted
Add deploy to staging with terraform (#120)
* Add terraform and deployment scripts * Hotfix errors due to minifying js assets 1. It seems that using shorthand generator function definitions in objects (for src/slang/interpreter.ts) will result in a minified file where the generator method replaced by a function. `yield` calls in this generator therefore raise an uncaught syntax error in the browser. See: webpack/webpack#7566 2. A known issue with causes reuse of const variables in the same scope. See: mishoo/UglifyJS#2842 * Fix workspace-green css * Add profile variable to terraform config * Fix runInContext not finishing in minified js * Fix more instances of method shorthand bugs * Use dynamic class name for greenscreen * Format playground component * Add console.log to report version
1 parent 25d5ddc commit 09fddfb

File tree

18 files changed

+343
-163
lines changed

18 files changed

+343
-163
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
REACT_APP_IVLE_KEY=your_ivle_key_here
2+
REACT_APP_VERSION=$npm_package_version

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
/build
1111
src/styles/*.css
1212

13+
# deployment
14+
terraform*
15+
1316
# misc
1417
.DS_Store
1518
.env.local

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": true,
33
"name": "cadet-frontend",
4-
"version": "0.0.0",
4+
"version": "0.1.0",
55
"scripts-info": {
66
"format": "Format source code",
77
"start": "Start the Webpack development server",
@@ -10,7 +10,7 @@
1010
"update-ui-snapshots": "Update UI test snapshots"
1111
},
1212
"scripts": {
13-
"build": "build-css && build-js",
13+
"build": "node-sass-chokidar src/ -o src/ && react-scripts-ts build",
1414
"build-css": "node-sass-chokidar src/ -o src/",
1515
"build-js": "react-scripts-ts build",
1616
"coverage": "./scripts/coverage-fix.sh do && react-scripts-ts test --env=jsdom --coverage && ./scripts/coverage-fix.sh undo",
@@ -83,12 +83,14 @@
8383
"@types/react-router-redux": "^5.0.13",
8484
"@types/react-test-renderer": "^16.0.1",
8585
"@types/redux-mock-store": "^0.0.13",
86+
"babel-core": "6",
87+
"babel-runtime": "^6.23.0",
8688
"coveralls": "^3.0.1",
8789
"enzyme": "^3.3.0",
8890
"enzyme-adapter-react-16": "^1.1.1",
8991
"husky": "^1.0.0-rc.6",
9092
"prettier": "^1.12.0",
91-
"react-scripts-ts": "^2.15.1",
93+
"react-scripts-ts": "^2.16.0",
9294
"react-test-renderer": "^16.3.1",
9395
"typescript": "^2.8.1"
9496
}

src/components/Playground.tsx

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,40 @@ import { SideContentTab } from './workspace/side-content'
1111

1212
export type PlaygroundProps = RouteComponentProps<{}>
1313

14-
const Playground: React.SFC<PlaygroundProps> = props => {
15-
return (
16-
<HotKeys className="Playground pt-dark" keyMap={keyMap}>
17-
<WorkspaceContainer
18-
libQuery={parseLibrary(props)}
19-
prgrmQuery={parsePrgrm(props)}
20-
sideContentTabs={[playgroundIntroduction]}
21-
/>
22-
</HotKeys>
23-
)
14+
type PlaygroundState = {
15+
isGreen: boolean
16+
}
17+
18+
class Playground extends React.Component<PlaygroundProps, PlaygroundState> {
19+
private keyMap = { goGreen: 'h u l k' }
20+
21+
private handlers = { goGreen: () => {} }
22+
23+
constructor(props: PlaygroundProps) {
24+
super(props)
25+
this.state = { isGreen: false }
26+
this.handlers.goGreen = this.toggleIsGreen.bind(this)
27+
}
28+
29+
public render() {
30+
return (
31+
<HotKeys
32+
className={'Playground pt-dark' + (this.state.isGreen ? ' GreenScreen' : '')}
33+
keyMap={this.keyMap}
34+
handlers={this.handlers}
35+
>
36+
<WorkspaceContainer
37+
libQuery={parseLibrary(this.props)}
38+
prgrmQuery={parsePrgrm(this.props)}
39+
sideContentTabs={[playgroundIntroduction]}
40+
/>
41+
</HotKeys>
42+
)
43+
}
44+
45+
private toggleIsGreen() {
46+
this.setState({ isGreen: !this.state.isGreen })
47+
}
2448
}
2549

2650
const parsePrgrm = (props: PlaygroundProps) => {
@@ -35,10 +59,6 @@ const parseLibrary = (props: PlaygroundProps) => {
3559
return sourceChapters.includes(lib) ? lib : undefined
3660
}
3761

38-
const keyMap = {
39-
goGreen: 'h u l k'
40-
}
41-
4262
const SICP_SITE = 'http://www.comp.nus.edu.sg/~henz/sicp_js/'
4363
const CHAP = '\xa7'
4464
const playgroundIntroduction: SideContentTab = {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

33
exports[`Playground renders correctly 1`] = `
4-
"<HotKeys className=\\"Playground pt-dark\\" keyMap={{...}}>
4+
"<HotKeys className=\\"Playground pt-dark\\" keyMap={{...}} handlers={{...}}>
55
<Connect(Workspace) libQuery={[undefined]} prgrmQuery={[undefined]} sideContentTabs={{...}} />
66
</HotKeys>"
77
`;

src/components/workspace/index.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { decompressFromEncodedURIComponent } from 'lz-string'
22
import Resizable, { ResizableProps, ResizeCallback } from 're-resizable'
33
import * as React from 'react'
4-
import { HotKeys } from 'react-hotkeys'
54

65
import ControlBarContainer from '../../containers/workspace/ControlBarContainer'
76
import EditorContainer from '../../containers/workspace/EditorContainer'
@@ -60,7 +59,7 @@ class Workspace extends React.Component<WorkspaceProps, {}> {
6059
*/
6160
public render() {
6261
return (
63-
<HotKeys className="workspace" handlers={handlers}>
62+
<div className="workspace">
6463
<ControlBarContainer {...this.props.controlBarOptions} />
6564
<div className="row workspace-parent">
6665
<div className="editor-divider" ref={e => (this.editorDividerDiv = e!)} />
@@ -75,7 +74,7 @@ class Workspace extends React.Component<WorkspaceProps, {}> {
7574
<ReplContainer />
7675
</div>
7776
</div>
78-
</HotKeys>
77+
</div>
7978
)
8079
}
8180

@@ -154,10 +153,6 @@ class Workspace extends React.Component<WorkspaceProps, {}> {
154153
}
155154
}
156155

157-
const handlers = {
158-
goGreen: () => require('../../styles/workspace-green.css')
159-
}
160-
161156
const rightResizeOnly = {
162157
top: false,
163158
right: true,

src/index.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@ import { ConnectedRouter } from 'react-router-redux'
66

77
import ApplicationContainer from './containers/ApplicationContainer'
88
import { store } from './createStore'
9+
import { VERSION } from './utils/constants'
910
import { history } from './utils/history'
1011
import registerServiceWorker from './utils/registerServiceWorker'
1112

1213
import './styles/index.css'
1314

1415
const rootContainer = document.getElementById('root') as HTMLElement
1516
;(window as any).__REDUX_STORE__ = store // need this for slang's display
17+
// tslint:disable-next-line
18+
console.log(
19+
`%c Source Academy v${VERSION}; ` +
20+
'Please visit https://github.com/source-academy/cadet-frontend/issues to report bugs or issues.',
21+
'font-weight: bold;'
22+
)
1623

1724
render(
1825
<Provider store={store}>

src/sagas/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import * as actionTypes from '../actions/actionTypes'
88
import { mockAssessmentOverviews, mockAssessments } from '../mocks/api'
99
import { IState } from '../reducers/states'
1010
import { Context, interrupt, runInContext } from '../slang'
11+
import { IVLE_KEY } from '../utils/constants'
1112
import { showSuccessMessage, showWarningMessage } from '../utils/notification'
12-
import { IVLE_KEY } from '../utils/secrets'
1313

1414
function* mainSaga() {
1515
yield* apiFetchSaga()
@@ -105,7 +105,7 @@ function* workspaceSaga(): SagaIterator {
105105

106106
function* evalCode(code: string, context: Context) {
107107
const { result, interrupted } = yield race({
108-
result: call(runInContext, code, context),
108+
result: call(runInContext, code, context, { scheduler: 'async' }),
109109
interrupted: take(actionTypes.INTERRUPT_EXECUTION)
110110
})
111111
if (result) {

src/slang/interpreter.ts

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* tslint:disable: max-classes-per-file */
2+
/* tslint:disable: object-literal-shorthand*/
23
import * as es from 'estree'
34
import * as constants from './constants'
45
import { toJS } from './interop'
@@ -124,31 +125,41 @@ function* getArgs(context: Context, call: es.CallExpression) {
124125

125126
export type Evaluator<T extends es.Node> = (node: T, context: Context) => IterableIterator<Value>
126127

128+
/**
129+
* WARNING: Do not use object literal shorthands, e.g.
130+
* {
131+
* *Literal(node: es.Literal, ...) {...},
132+
* *ThisExpression(node: es.ThisExpression, ..._ {...},
133+
* ...
134+
* }
135+
* They do not minify well, raising uncaught syntax errors in production.
136+
* See: https://github.com/webpack/webpack/issues/7566
137+
*/
127138
export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
128139
/** Simple Values */
129-
*Literal(node: es.Literal, context: Context) {
140+
Literal: function*(node: es.Literal, context: Context) {
130141
return node.value
131142
},
132-
*ThisExpression(node: es.ThisExpression, context: Context) {
143+
ThisExpression: function*(node: es.ThisExpression, context: Context) {
133144
return context.runtime.frames[0].thisContext
134145
},
135-
*ArrayExpression(node: es.ArrayExpression, context: Context) {
146+
ArrayExpression: function*(node: es.ArrayExpression, context: Context) {
136147
const res = []
137148
for (const n of node.elements) {
138149
res.push(yield* evaluate(n, context))
139150
}
140151
return res
141152
},
142-
*FunctionExpression(node: es.FunctionExpression, context: Context) {
153+
FunctionExpression: function*(node: es.FunctionExpression, context: Context) {
143154
return new Closure(node, currentFrame(context), context)
144155
},
145-
*ArrowFunctionExpression(node: es.Function, context: Context) {
156+
ArrowFunctionExpression: function*(node: es.Function, context: Context) {
146157
return new ArrowClosure(node, currentFrame(context), context)
147158
},
148-
*Identifier(node: es.Identifier, context: Context) {
159+
Identifier: function*(node: es.Identifier, context: Context) {
149160
return getVariable(context, node.name)
150161
},
151-
*CallExpression(node: es.CallExpression, context: Context) {
162+
CallExpression: function*(node: es.CallExpression, context: Context) {
152163
const callee = yield* evaluate(node.callee, context)
153164
const args = yield* getArgs(context, node)
154165
let thisContext
@@ -158,7 +169,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
158169
const result = yield* apply(context, callee, args, node, thisContext)
159170
return result
160171
},
161-
*NewExpression(node: es.NewExpression, context: Context) {
172+
NewExpression: function*(node: es.NewExpression, context: Context) {
162173
const callee = yield* evaluate(node.callee, context)
163174
const args = []
164175
for (const arg of node.arguments) {
@@ -174,7 +185,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
174185
}
175186
return obj
176187
},
177-
*UnaryExpression(node: es.UnaryExpression, context: Context) {
188+
UnaryExpression: function*(node: es.UnaryExpression, context: Context) {
178189
const value = yield* evaluate(node.argument, context)
179190

180191
const error = rttc.checkUnaryExpression(context, node.operator, value)
@@ -191,7 +202,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
191202
return +value
192203
}
193204
},
194-
*BinaryExpression(node: es.BinaryExpression, context: Context) {
205+
BinaryExpression: function*(node: es.BinaryExpression, context: Context) {
195206
const left = yield* evaluate(node.left, context)
196207
const right = yield* evaluate(node.right, context)
197208

@@ -241,10 +252,10 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
241252
}
242253
return result
243254
},
244-
*ConditionalExpression(node: es.ConditionalExpression, context: Context) {
255+
ConditionalExpression: function*(node: es.ConditionalExpression, context: Context) {
245256
return yield* this.IfStatement(node, context)
246257
},
247-
*LogicalExpression(node: es.LogicalExpression, context: Context) {
258+
LogicalExpression: function*(node: es.LogicalExpression, context: Context) {
248259
const left = yield* evaluate(node.left, context)
249260
let error = rttc.checkLogicalExpression(context, left, true)
250261
if (error) {
@@ -264,20 +275,20 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
264275
return left
265276
}
266277
},
267-
*VariableDeclaration(node: es.VariableDeclaration, context: Context) {
278+
VariableDeclaration: function*(node: es.VariableDeclaration, context: Context) {
268279
const declaration = node.declarations[0]
269280
const id = declaration.id as es.Identifier
270281
const value = yield* evaluate(declaration.init!, context)
271282
defineVariable(context, id.name, value)
272283
return undefined
273284
},
274-
*ContinueStatement(node: es.ContinueStatement, context: Context) {
285+
ContinueStatement: function*(node: es.ContinueStatement, context: Context) {
275286
return new ContinueValue()
276287
},
277-
*BreakStatement(node: es.BreakStatement, context: Context) {
288+
BreakStatement: function*(node: es.BreakStatement, context: Context) {
278289
return new BreakValue()
279290
},
280-
*ForStatement(node: es.ForStatement, context: Context) {
291+
ForStatement: function*(node: es.ForStatement, context: Context) {
281292
if (node.init) {
282293
yield* evaluate(node.init, context)
283294
}
@@ -305,7 +316,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
305316
}
306317
return value
307318
},
308-
*MemberExpression(node: es.MemberExpression, context: Context) {
319+
MemberExpression: function*(node: es.MemberExpression, context: Context) {
309320
let obj = yield* evaluate(node.object, context)
310321
if (obj instanceof Closure) {
311322
obj = obj.fun
@@ -322,7 +333,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
322333
}
323334
}
324335
},
325-
*AssignmentExpression(node: es.AssignmentExpression, context: Context) {
336+
AssignmentExpression: function*(node: es.AssignmentExpression, context: Context) {
326337
if (node.left.type === 'MemberExpression') {
327338
const left = node.left
328339
const obj = yield* evaluate(left.object, context)
@@ -342,7 +353,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
342353
setVariable(context, id.name, value)
343354
return value
344355
},
345-
*FunctionDeclaration(node: es.FunctionDeclaration, context: Context) {
356+
FunctionDeclaration: function*(node: es.FunctionDeclaration, context: Context) {
346357
const id = node.id as es.Identifier
347358
// tslint:disable-next-line:no-any
348359
const closure = new Closure(node as any, currentFrame(context), context)
@@ -366,7 +377,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
366377
return undefined
367378
}
368379
},
369-
*ExpressionStatement(node: es.ExpressionStatement, context: Context) {
380+
ExpressionStatement: function*(node: es.ExpressionStatement, context: Context) {
370381
return yield* evaluate(node.expression, context)
371382
},
372383
*ReturnStatement(node: es.ReturnStatement, context: Context) {
@@ -382,7 +393,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
382393
return new ReturnValue(undefined)
383394
}
384395
},
385-
*WhileStatement(node: es.WhileStatement, context: Context) {
396+
WhileStatement: function*(node: es.WhileStatement, context: Context) {
386397
let value: any // tslint:disable-line
387398
let test
388399
while (
@@ -399,7 +410,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
399410
}
400411
return value
401412
},
402-
*ObjectExpression(node: es.ObjectExpression, context: Context) {
413+
ObjectExpression: function*(node: es.ObjectExpression, context: Context) {
403414
const obj = {}
404415
for (const prop of node.properties) {
405416
let key
@@ -412,7 +423,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
412423
}
413424
return obj
414425
},
415-
*BlockStatement(node: es.BlockStatement, context: Context) {
426+
BlockStatement: function*(node: es.BlockStatement, context: Context) {
416427
let result: Value
417428
for (const statement of node.body) {
418429
result = yield* evaluate(statement, context)
@@ -426,7 +437,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
426437
}
427438
return result
428439
},
429-
*Program(node: es.BlockStatement, context: Context) {
440+
Program: function*(node: es.BlockStatement, context: Context) {
430441
let result: Value
431442
for (const statement of node.body) {
432443
result = yield* evaluate(statement, context)

0 commit comments

Comments
 (0)