Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd68f702

Browse files
authored
Merge pull request#245 from coderoad/feature/validate-tutorial-deps
Validate tutorial dependencies
2 parentscf6a7a5 +21d2799 commitd68f702

File tree

8 files changed

+131
-19
lines changed

8 files changed

+131
-19
lines changed

‎errors/MissingTutorialDependency.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
###Missing Tutorial Dependency
2+
3+
The tutorial cannot run because it a dependency is not yet installed. Install the dependency and click "Check Again".

‎errors/UnmetTutorialDependency.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
###Unmet Tutorial Dependency
2+
3+
###Unmet Tutorial Dependency
4+
5+
Tutorial cannot reun because a dependency version doesn't match. Install the correct dependency and click "Check Again".

‎package-lock.json

Lines changed: 29 additions & 3 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"@types/jest":"^25.2.1",
4040
"@types/jsdom":"^16.2.0",
4141
"@types/node":"^13.11.0",
42+
"@types/semver":"^7.1.0",
4243
"@typescript-eslint/eslint-plugin":"^2.26.0",
4344
"@typescript-eslint/parser":"^2.26.0",
4445
"chokidar":"^3.3.0",
@@ -49,6 +50,7 @@
4950
"jest":"^25.2.7",
5051
"jsdom":"^16.2.2",
5152
"prettier":"^2.0.2",
53+
"semver":"^7.2.2",
5254
"ts-jest":"^25.3.1",
5355
"typescript":"^3.8.3"
5456
},

‎src/channel/index.ts

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import tutorialConfig from '../actions/tutorialConfig'
99
import{COMMANDS}from'../editor/commands'
1010
importloggerfrom'../services/logger'
1111
importContextfrom'./context'
12-
import{versionasgitVersion}from'../services/git'
12+
import{version,compareVersions}from'../services/dependencies'
1313
import{openWorkspace,checkWorkspaceEmpty}from'../services/workspace'
1414
import{readFile}from'fs'
1515
import{join}from'path'
1616
import{promisify}from'util'
17+
import{compare}from'semver'
1718

1819
constreadFileAsync=promisify(readFile)
1920

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

98+
// validate dependencies
99+
constdependencies=data.config.dependencies
100+
if(dependencies&&dependencies.length){
101+
for(constdepofdependencies){
102+
// check dependency is installed
103+
constcurrentVersion:string|null=awaitversion(dep.name)
104+
if(!currentVersion){
105+
// use a custom error message
106+
consterror={
107+
type:'MissingTutorialDependency',
108+
message:dep.message||`Process "${dep.name}" is required but not found. It may need to be installed`,
109+
actions:[
110+
{
111+
label:'Check Again',
112+
transition:'TRY_AGAIN',
113+
},
114+
],
115+
}
116+
this.send({type:'TUTORIAL_CONFIGURE_FAIL',payload:{ error}})
117+
return
118+
}
119+
120+
// check dependency version
121+
constsatisfiedDependency=awaitcompareVersions(currentVersion,dep.version)
122+
123+
if(!satisfiedDependency){
124+
consterror={
125+
type:'UnmetTutorialDependency',
126+
message:`Expected${dep.name} to have version${dep.version}, but found version${currentVersion}`,
127+
actions:[
128+
{
129+
label:'Check Again',
130+
transition:'TRY_AGAIN',
131+
},
132+
],
133+
}
134+
this.send({type:'TUTORIAL_CONFIGURE_FAIL',payload:{ error}})
135+
return
136+
}
137+
138+
if(satisfiedDependency!==true){
139+
consterror=satisfiedDependency||{
140+
type:'UnknownError',
141+
message:`Something went wrong comparing dependency for${name}`,
142+
actions:[
143+
{
144+
label:'Try Again',
145+
transition:'TRY_AGAIN',
146+
},
147+
],
148+
}
149+
this.send({type:'TUTORIAL_CONFIGURE_FAIL',payload:{ error}})
150+
return
151+
}
152+
}
153+
}
154+
97155
consterror:E.ErrorMessage|void=awaittutorialConfig({config:data.config}).catch((error:Error)=>({
98156
type:'UnknownError',
99157
message:`Location: tutorial config.\n\n${error.message}`,
@@ -144,7 +202,7 @@ class Channel implements Channel {
144202
}
145203
// 2. check Git is installed.
146204
// Should wait for workspace before running otherwise requires access to root folder
147-
constisGitInstalled=awaitgitVersion()
205+
constisGitInstalled=awaitversion('git')
148206
if(!isGitInstalled){
149207
consterror:E.ErrorMessage={
150208
type:'GitNotFound',
@@ -197,7 +255,7 @@ class Channel implements Channel {
197255

198256
if(errorMarkdown){
199257
// add a clearer error message for the user
200-
error.message=`${errorMarkdown}\n${error.message}`
258+
error.message=`${errorMarkdown}\n\n${error.message}`
201259
}
202260
}
203261

‎src/services/dependencies/index.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import{satisfies}from'semver'
2+
importnodefrom'../node'
3+
4+
constsemverRegex=/(?<=^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
5+
6+
exportconstversion=async(name:string):Promise<string|null>=>{
7+
try{
8+
const{ stdout, stderr}=awaitnode.exec(`${name} --version`)
9+
if(!stderr){
10+
constmatch=stdout.match(semverRegex)
11+
if(match){
12+
returnmatch[0]
13+
}
14+
}
15+
returnnull
16+
}catch(error){
17+
returnnull
18+
}
19+
}
20+
21+
exportconstcompareVersions=async(currentVersion:string,expectedVersion:string):Promise<never|boolean>=>{
22+
// see node-semver docs: https://github.com/npm/node-semver
23+
returnsatisfies(currentVersion,expectedVersion)
24+
}

‎src/services/git/index.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,6 @@ export async function clear(): Promise<Error | void> {
6969
thrownewError('Error cleaning up current unsaved work')
7070
}
7171

72-
exportasyncfunctionversion():Promise<string|null>{
73-
const{ stdout, stderr}=awaitnode.exec('git --version')
74-
if(!stderr){
75-
constmatch=stdout.match(/^gitversion(\d+\.)?(\d+\.)?(\*|\d+)/)
76-
if(match){
77-
// eslint-disable-next-line
78-
const[_,major,minor,patch]=match
79-
return`${major}${minor}${patch}`
80-
}
81-
}
82-
returnnull
83-
}
84-
8572
asyncfunctioninit():Promise<Error|void>{
8673
const{ stderr}=awaitnode.exec('git init')
8774
if(stderr){

‎typings/tutorial.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export type Maybe<T> = T | null
33
exporttypeTutorialConfig={
44
testRunner:TutorialTestRunner
55
repo:TutorialRepo
6+
dependencies?:TutorialDependency[]
67
}
78

89
/** Logical groupings of tasks */
@@ -57,3 +58,9 @@ export interface TutorialRepo {
5758
uri:string
5859
branch:string
5960
}
61+
62+
exportinterfaceTutorialDependency{
63+
name:string
64+
version:string
65+
message?:string
66+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp