Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: coderoad/coderoad-vscode
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4a9e9ccb4650a220e3b8f586d0f70184260a6077
Choose a base ref
...
head repository: coderoad/coderoad-vscode
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 37ed10baa19040fd6a3cae3183e23066f4b440fa
Choose a head ref
  • 7 commits
  • 9 files changed
  • 1 contributor

Commits on Apr 11, 2020

  1. Move min requirement to Node 12 -> Node 10

    As of v0.2.0
    ShMcK authored Apr 11, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f8d57f4 View commit details
  2. Merge pull request #246 from coderoad/remove-node-12-min-req

    Move min requirement to Node 12 -> Node 10
    ShMcK authored Apr 11, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    cf6a7a5 View commit details
  3. add schema

    Signed-off-by: shmck <shawn.j.mckay@gmail.com>
    ShMcK committed Apr 11, 2020
    Copy the full SHA
    c4d2e35 View commit details
  4. create getVersion fn

    Signed-off-by: shmck <shawn.j.mckay@gmail.com>
    ShMcK committed Apr 11, 2020
    Copy the full SHA
    5513a1d View commit details
  5. compare versions fn

    Signed-off-by: shmck <shawn.j.mckay@gmail.com>
    ShMcK committed Apr 11, 2020
    Copy the full SHA
    21a0ff0 View commit details
  6. have git use version fn

    Signed-off-by: shmck <shawn.j.mckay@gmail.com>
    ShMcK committed Apr 11, 2020
    Copy the full SHA
    176d24a View commit details
  7. add tutorial missing and unmet dependency checks

    Signed-off-by: shmck <shawn.j.mckay@gmail.com>
    ShMcK committed Apr 11, 2020
    Copy the full SHA
    37ed10b View commit details
Showing with 124 additions and 19 deletions.
  1. +1 −1 README.md
  2. +3 −0 errors/MissingTutorialDependency.md
  3. +5 −0 errors/UnmetTutorialDependency.md
  4. +29 −3 package-lock.json
  5. +2 −0 package.json
  6. +52 −2 src/channel/index.ts
  7. +25 −0 src/services/dependencies/index.ts
  8. +0 −13 src/services/git/index.ts
  9. +7 −0 typings/tutorial.d.ts
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ Install CodeRoad from [this link in the VSCode Marketplace](https://marketplace.

- OS: MacOS, Linux (Windows coming soon #227)
- VSCode 1.40+
- Node.js 12+ (10+ soon #237)
- Node.js 10+
- Git

## Creating Tutorials
3 changes: 3 additions & 0 deletions errors/MissingTutorialDependency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Missing Tutorial Dependency

The tutorial cannot run because it a dependency is not yet installed. Install the dependency and click "Check Again".
5 changes: 5 additions & 0 deletions errors/UnmetTutorialDependency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Unmet Tutorial Dependency

### Unmet Tutorial Dependency

Tutorial cannot reun because a dependency version doesn't match. Install the correct dependency and click "Check Again".
32 changes: 29 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@
"@types/jest": "^25.2.1",
"@types/jsdom": "^16.2.0",
"@types/node": "^13.11.0",
"@types/semver": "^7.1.0",
"@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/parser": "^2.26.0",
"chokidar": "^3.3.0",
@@ -49,6 +50,7 @@
"jest": "^25.2.7",
"jsdom": "^16.2.2",
"prettier": "^2.0.2",
"semver": "^7.2.2",
"ts-jest": "^25.3.1",
"typescript": "^3.8.3"
},
54 changes: 52 additions & 2 deletions src/channel/index.ts
Original file line number Diff line number Diff line change
@@ -9,11 +9,12 @@ import tutorialConfig from '../actions/tutorialConfig'
import { COMMANDS } from '../editor/commands'
import logger from '../services/logger'
import Context from './context'
import { version as gitVersion } from '../services/git'
import { version, compareVersions } from '../services/dependencies'
import { openWorkspace, checkWorkspaceEmpty } from '../services/workspace'
import { readFile } from 'fs'
import { join } from 'path'
import { promisify } from 'util'
import { compare } from 'semver'

const readFileAsync = promisify(readFile)

@@ -94,6 +95,55 @@ class Channel implements Channel {
// setup tutorial config (save watcher, test runner, etc)
await this.context.setTutorial(this.workspaceState, data)

// validate dependencies
if (data.config.dependencies) {
for (const dep of data.config.dependencies) {
// check dependency is installed
const currentVersion: string | null = await version(name)
if (!currentVersion) {
// use a custom error message
const error = {
type: 'MissingTutorialDependency',
message: dep.message || `Process ${name} is required but not found. It may need to be installed`,
actions: [
{
label: 'Check Again',
transition: 'TRY_AGAIN',
},
],
}
this.send({ type: 'TUTORIAL_CONFIGURE_FAIL', payload: { error } })
return
}

// check dependency version
const satisfiedDependency = await compareVersions(currentVersion, dep.version).catch((error: Error) => ({
type: 'UnmetTutorialDependency',
message: error.message,
actions: [
{
label: 'Check Again',
transition: 'TRY_AGAIN',
},
],
}))
if (satisfiedDependency !== true) {
const error = satisfiedDependency || {
type: 'UnknownError',
message: `Something went wrong comparing dependency for ${name}`,
actions: [
{
label: 'Try Again',
transition: 'TRY_AGAIN',
},
],
}
this.send({ type: 'TUTORIAL_CONFIGURE_FAIL', payload: { error } })
return
}
}
}

const error: E.ErrorMessage | void = await tutorialConfig({ config: data.config }).catch((error: Error) => ({
type: 'UnknownError',
message: `Location: tutorial config.\n\n${error.message}`,
@@ -144,7 +194,7 @@ class Channel implements Channel {
}
// 2. check Git is installed.
// Should wait for workspace before running otherwise requires access to root folder
const isGitInstalled = await gitVersion()
const isGitInstalled = await version('git')
if (!isGitInstalled) {
const error: E.ErrorMessage = {
type: 'GitNotFound',
25 changes: 25 additions & 0 deletions src/services/dependencies/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as TT from 'typings/tutorial'
import { satisfies } from 'semver'
import node from '../node'

const semverRegex = /(?<=^v?|\sv?)(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[\da-z-]*[a-z-][\da-z-]*)(?:\.(?:0|[1-9]\d*|[\da-z-]*[a-z-][\da-z-]*))*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?(?=$|\s)/gi

export const version = async (name: string): Promise<string | null> => {
const { stdout, stderr } = await node.exec(`${name} --version`)
if (!stderr) {
const match = stdout.match(semverRegex)
if (match) {
return match[0]
}
}
return null
}

export const compareVersions = async (currentVersion: string, expectedVersion: string): Promise<never | boolean> => {
// see node-semver docs: https://github.com/npm/node-semver
const satisfied: boolean = satisfies(currentVersion, expectedVersion)
if (!satisfied) {
throw new Error(`Expected ${name} to have version ${expectedVersion}, but found version ${currentVersion}`)
}
return true
}
13 changes: 0 additions & 13 deletions src/services/git/index.ts
Original file line number Diff line number Diff line change
@@ -69,19 +69,6 @@ export async function clear(): Promise<Error | void> {
throw new Error('Error cleaning up current unsaved work')
}

export async function version(): Promise<string | null> {
const { stdout, stderr } = await node.exec('git --version')
if (!stderr) {
const match = stdout.match(/^git version (\d+\.)?(\d+\.)?(\*|\d+)/)
if (match) {
// eslint-disable-next-line
const [_, major, minor, patch] = match
return `${major}${minor}${patch}`
}
}
return null
}

async function init(): Promise<Error | void> {
const { stderr } = await node.exec('git init')
if (stderr) {
7 changes: 7 additions & 0 deletions typings/tutorial.d.ts
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ export type Maybe<T> = T | null
export type TutorialConfig = {
testRunner: TutorialTestRunner
repo: TutorialRepo
dependencies?: TutorialDependency[]
}

/** Logical groupings of tasks */
@@ -57,3 +58,9 @@ export interface TutorialRepo {
uri: string
branch: string
}

export interface TutorialDependency {
name: string
version: string
message?: string
}