Skip to content

Feature/hooks #417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 2, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
breaking - init setup actions moved in config
Signed-off-by: shmck <shawn.j.mckay@gmail.com>
  • Loading branch information
ShMcK committed Aug 2, 2020
commit d3cd169e32c98526c0a98e49f580efc6a335e380
1 change: 0 additions & 1 deletion src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ export { default as onValidateSetup } from './onValidateSetup'
export { default as onRunReset } from './onRunReset'
export { default as onErrorPage } from './onErrorPage'
export { onRunTest, onTestPass } from './onTest'
export { onSetupActions, onSolutionActions } from './onActions'
export { onOpenLogs } from './onOpenLogs'
55 changes: 0 additions & 55 deletions src/actions/onActions.ts

This file was deleted.

7 changes: 3 additions & 4 deletions src/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Context from './services/context/context'
import logger from './services/logger'
import { openWorkspace } from './services/workspace'
import * as actions from './actions'
import * as hooks from './services/hooks'

interface Channel {
receive(action: T.Action): Promise<void>
Expand Down Expand Up @@ -56,14 +57,12 @@ class Channel implements Channel {
// load step actions (git commits, commands, open files)
case 'SETUP_ACTIONS':
await vscode.commands.executeCommand(COMMANDS.SET_CURRENT_POSITION, action.payload.position)
actions.onSetupActions({ actions: action.payload.actions, send: this.send })
hooks.onSetupEnter(action.payload.actions)
return
// load solution step actions (git commits, commands, open files)
case 'SOLUTION_ACTIONS':
await vscode.commands.executeCommand(COMMANDS.SET_CURRENT_POSITION, action.payload.position)
await actions.onSolutionActions({ actions: action.payload.actions, send: this.send })
// run test following solution to update position
actions.onRunTest()
hooks.onSolutionEnter(action.payload.actions)
return
case 'EDITOR_SYNC_POSITION':
// update progress when a level is deemed complete in the client
Expand Down
39 changes: 22 additions & 17 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import * as T from 'typings'
import * as TT from 'typings/tutorial'
import * as vscode from 'vscode'
import createTestRunner from './services/testRunner'
import { onSetupActions } from './actions/onActions'
import createWebView from './services/webview'
import logger from './services/logger'
import * as hooks from './services/hooks'

export const COMMANDS = {
START: 'coderoad.start',
Expand All @@ -19,6 +19,14 @@ interface CreateCommandProps {
workspaceState: vscode.Memento
}

let sendToClient = (action: T.Action): void => {
/* */
}

export const send = (action: T.Action): void => {
sendToClient(action)
}

export const createCommands = ({ extensionPath, workspaceState }: CreateCommandProps): { [key: string]: any } => {
// React panel webview
let webview: any
Expand All @@ -30,6 +38,10 @@ export const createCommands = ({ extensionPath, workspaceState }: CreateCommandP
[COMMANDS.START]: async () => {
if (webview && webview.state.loaded) {
webview.createOrShow()
// make send to client function exportable
// as "send". This makes it easier to pass the send
// function throughout the codebase
sendToClient = webview.send
} else {
// activate machine
webview = createWebView({
Expand All @@ -39,38 +51,31 @@ export const createCommands = ({ extensionPath, workspaceState }: CreateCommandP
}
},
[COMMANDS.CONFIG_TEST_RUNNER]: async (data: TT.Tutorial) => {
const testRunnerConfig = data.config.testRunner
const setup = testRunnerConfig.setup || testRunnerConfig.actions // TODO: deprecate and remove config.actions
if (setup) {
// setup tutorial test runner commits
// assumes git already exists
await onSetupActions({
actions: setup,
send: webview.send,
dir: testRunnerConfig.directory || testRunnerConfig.path,
}) // TODO: deprecate and remove config.path
const setupActions = data.config.setup
if (setupActions) {
hooks.onInit(setupActions)
}
testRunner = createTestRunner(data, {
onSuccess: (position: T.Position) => {
logger('test pass position', position)
// send test pass message back to client
webview.send({ type: 'TEST_PASS', payload: { position: { ...position, complete: true } } })
send({ type: 'TEST_PASS', payload: { position: { ...position, complete: true } } })
},
onFail: (position: T.Position, failSummary: T.TestFail): void => {
// send test fail message back to client with failure message
webview.send({ type: 'TEST_FAIL', payload: { position, fail: failSummary } })
send({ type: 'TEST_FAIL', payload: { position, fail: failSummary } })
},
onError: (position: T.Position) => {
// TODO: send test error message back to client
const message = 'Error with test runner'
webview.send({ type: 'TEST_ERROR', payload: { position, message } })
send({ type: 'TEST_ERROR', payload: { position, message } })
},
onRun: (position: T.Position) => {
// send test run message back to client
webview.send({ type: 'TEST_RUNNING', payload: { position } })
send({ type: 'TEST_RUNNING', payload: { position } })
},
onLoadSubtasks: ({ summary }) => {
webview.send({ type: 'LOAD_SUBTASK_RESULTS', payload: { summary } })
send({ type: 'LOAD_SUBTASK_RESULTS', payload: { summary } })
},
})
},
Expand All @@ -85,7 +90,7 @@ export const createCommands = ({ extensionPath, workspaceState }: CreateCommandP
testRunner({ position: currentPosition, onSuccess: callbacks?.onSuccess, subtasks })
},
[COMMANDS.ENTER]: () => {
webview.send({ type: 'KEY_PRESS_ENTER' })
send({ type: 'KEY_PRESS_ENTER' })
},
}
}
39 changes: 39 additions & 0 deletions src/services/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as TT from 'typings/tutorial'
import * as git from '../git'
import loadCommits from './utils/loadCommits'
import loadWatchers from './utils/loadWatchers'
import openFiles from './utils/openFiles'
import runCommands from './utils/runCommands'
import { onError as telemetryOnError } from '../telemetry'
import { onRunTest } from '../../actions/onTest'

export const onInit = async (actions: TT.StepActions): Promise<void> => {
await loadCommits(actions.commits)
await runCommands(actions.commands)
}

export const onLevelEnter = async (actions: TT.StepActions): Promise<void> => {
await loadCommits(actions.commits)
await runCommands(actions.commands)
}

export const onSetupEnter = async (actions: TT.StepActions): Promise<void> => {
// TODO: set position
await loadCommits(actions.commits)
await openFiles(actions.files)
await loadWatchers(actions.watchers)
await runCommands(actions.commands)
}

export const onSolutionEnter = async (actions: TT.StepActions): Promise<void> => {
// TODO: set position
await git.clear()
await loadCommits(actions.commits)
await openFiles(actions.files)
await runCommands(actions.commands)
await onRunTest()
}

export const onError = async (error: Error): Promise<void> => {
telemetryOnError(error)
}
13 changes: 13 additions & 0 deletions src/services/hooks/utils/loadCommits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as git from '../../git'

const loadCommits = async (commits: string[]): Promise<void> => {
if (commits) {
// load the current list of commits for validation
const currentCommits: string[] = await git.loadCommitHistory()
for (const commit of commits) {
await git.loadCommit(commit)
}
}
}

export default loadCommits
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as chokidar from 'chokidar'
import * as vscode from 'vscode'
import { COMMANDS } from '../../commands'
import { WORKSPACE_ROOT } from '../../environment'
import { COMMANDS } from '../../../commands'
import { WORKSPACE_ROOT } from '../../../environment'

// NOTE: vscode createFileWatcher doesn't seem to detect changes outside of vscode
// such as `npm install` of a package. Went with chokidar instead
Expand All @@ -14,7 +14,7 @@ const disposeWatcher = (watcher: string) => {
delete watcherObject[watcher]
}

const loadWatchers = (watchers: string[]): void => {
const loadWatchers = (watchers: string[] = []): void => {
if (!watchers.length) {
// remove all watchers
for (const watcher of Object.keys(watcherObject)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { join } from 'path'
import * as vscode from 'vscode'
import { COMMANDS } from '../../commands'
import { COMMANDS } from '../../../commands'

const openFiles = async (files: string[]): Promise<void> => {
const openFiles = async (files: string[] = []): Promise<void> => {
if (!files.length) {
return
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import * as T from 'typings'
import { exec } from '../../services/node'
import { exec } from '../../node'
import { send } from '../../../commands'

interface RunCommands {
commands: string[]
send: (action: T.Action) => void
dir?: string
}

const runCommands = async ({ commands, send, dir }: RunCommands): Promise<void> => {
const runCommands = async (commands: string[] = []): Promise<void> => {
if (!commands.length) {
return
}
Expand All @@ -19,10 +14,10 @@ const runCommands = async ({ commands, send, dir }: RunCommands): Promise<void>
send({ type: 'COMMAND_START', payload: { process: { ...process, status: 'RUNNING' } } })
let result: { stdout: string; stderr: string }
try {
result = await exec({ command, dir })
result = await exec({ command })
console.log(result)
} catch (error) {
console.log(`Test failed: ${error.message}`)
console.error(`Test failed: ${error.message}`)
send({ type: 'COMMAND_FAIL', payload: { process: { ...process, status: 'FAIL' } } })
return
}
Expand Down
7 changes: 3 additions & 4 deletions src/services/reset/lastHash.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,9 @@ describe('lastHash', () => {
const tutorial: TT.Tutorial = {
config: {
// @ts-ignore
testRunner: {
setup: {
commits: ['abcdef2', 'abcdef3'],
},
testRunner: {},
setup: {
commits: ['abcdef2', 'abcdef3'],
},
},
levels: [
Expand Down
2 changes: 1 addition & 1 deletion src/services/reset/lastHash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const getLastCommitHash = (position: T.Position, tutorial: TT.Tutorial | null):
level = levels[levelIndex - 1]
} else {
// use init commit
const configCommits = tutorial.config.testRunner.setup?.commits
const configCommits = tutorial.config.setup?.commits
if (!configCommits) {
throw new Error('No commits found to reset back to')
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/testRunner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks): ((params: an
}
}
logger('COMMAND', command)
result = await exec({ command, dir: testRunnerConfig.directory || testRunnerConfig.path }) // TODO: remove config.path later
result = await exec({ command, dir: testRunnerConfig.directory })
} catch (err) {
result = { stdout: err.stdout, stderr: err.stack }
}
Expand Down
4 changes: 1 addition & 3 deletions typings/tutorial.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type TutorialConfig = {
testRunner: TestRunnerConfig
repo: TutorialRepo
dependencies?: TutorialDependency[]
setup?: StepActions
reset?: ConfigReset
}

Expand Down Expand Up @@ -70,10 +71,7 @@ export interface TestRunnerArgs {
export interface TestRunnerConfig {
command: string
args: TestRunnerArgs
path?: string // deprecated
directory?: string
actions?: StepActions // deprecated
setup?: StepActions
}

export interface TutorialRepo {
Expand Down