Skip to content

Commit fb222b1

Browse files
authored
fix: yaml scripts issue in windows (#251)
1 parent 4fd9303 commit fb222b1

File tree

4 files changed

+26
-134
lines changed

4 files changed

+26
-134
lines changed

packages/cli/src/cli-utils.ts

Lines changed: 1 addition & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,9 @@
1-
import assert from 'node:assert';
21
import { glob } from 'glob';
3-
import minimist from 'minimist';
4-
import { findOnlyItemInArgs, orderMattersParse } from './args';
52
import 'dotenv/config';
63
import { statSync } from 'node:fs';
74
import { existsSync } from 'node:fs';
85
import { join } from 'node:path';
9-
import { dump } from 'js-yaml';
106
import yargs from 'yargs/yargs';
11-
import type {
12-
MidsceneYamlFlowItemAIAction,
13-
MidsceneYamlFlowItemAIAssert,
14-
MidsceneYamlFlowItemAIQuery,
15-
MidsceneYamlFlowItemAIWaitFor,
16-
MidsceneYamlFlowItemSleep,
17-
MidsceneYamlScript,
18-
} from './types';
19-
20-
const preferenceArgs = {
21-
url: 'url',
22-
serve: 'serve',
23-
headed: 'headed',
24-
viewportWidth: 'viewport-width',
25-
viewportHeight: 'viewport-height',
26-
viewportScale: 'viewport-scale',
27-
useragent: 'user-agent',
28-
output: 'output',
29-
cookie: 'cookie',
30-
};
31-
32-
const removedArgs = {
33-
action: 'action',
34-
assert: 'assert',
35-
query: 'query',
36-
waitFor: 'wait-for',
37-
};
38-
39-
const actionArgs = {
40-
ai: 'ai',
41-
aiAction: 'aiAction',
42-
aiAssert: 'aiAssert',
43-
aiQuery: 'aiQuery',
44-
aiWaitFor: 'aiWaitFor',
45-
sleep: 'sleep',
46-
};
477

488
export const parseProcessArgs = async (): Promise<{
499
path?: string;
@@ -85,93 +45,14 @@ Usage: $0 [options] <path-to-yaml-script-file-or-directory>`,
8545
};
8646
};
8747

88-
export const parseArgsIntoYamlScript = async (
89-
input?: string[],
90-
): Promise<string> => {
91-
const args = minimist(input || process.argv);
92-
93-
if (findOnlyItemInArgs(args, 'version')) {
94-
const versionFromPkgJson = require('../package.json').version;
95-
console.log(`@midscene/cli version ${versionFromPkgJson}`);
96-
process.exit(0);
97-
}
98-
99-
// check if any deprecated args are used
100-
Object.keys(removedArgs).forEach((arg) => {
101-
if (findOnlyItemInArgs(args, arg)) {
102-
throw new Error(
103-
`Parameter ${arg} has been removed, use --aiAction --aiAssert --aiQuery --aiWaitFor instead.`,
104-
);
105-
}
106-
});
107-
108-
// check each arg is either in the preferenceArgs or actionArgs
109-
Object.keys(args).forEach((arg) => {
110-
if (arg === '_') return;
111-
assert(
112-
Object.values(preferenceArgs).includes(arg) ||
113-
Object.values(actionArgs).includes(arg),
114-
`Unknown argument: ${arg}`,
115-
);
116-
});
117-
118-
const url = findOnlyItemInArgs(args, preferenceArgs.url) as
119-
| string
120-
| undefined;
121-
122-
assert(url, 'url is required');
123-
const script: MidsceneYamlScript = {
124-
target: { url },
125-
flow: [],
126-
};
127-
128-
Object.entries(preferenceArgs).forEach(([key, value]) => {
129-
const argValue = findOnlyItemInArgs(args, value);
130-
if (argValue) {
131-
Object.assign(script.target, {
132-
[key]: argValue,
133-
});
134-
}
135-
});
136-
137-
const orderedArgs = orderMattersParse(process.argv);
138-
for (const arg of orderedArgs) {
139-
const argName = arg.name;
140-
const argValue = arg.value;
141-
if (argName === actionArgs.ai || argName === actionArgs.aiAction) {
142-
script.flow.push({
143-
aiAction: argValue,
144-
} as MidsceneYamlFlowItemAIAction);
145-
} else if (argName === actionArgs.aiAssert) {
146-
script.flow.push({
147-
aiAssert: argValue,
148-
} as MidsceneYamlFlowItemAIAssert);
149-
} else if (argName === actionArgs.aiQuery) {
150-
script.flow.push({
151-
aiQuery: argValue,
152-
} as MidsceneYamlFlowItemAIQuery);
153-
} else if (argName === actionArgs.aiWaitFor) {
154-
script.flow.push({
155-
aiWaitFor: argValue,
156-
} as MidsceneYamlFlowItemAIWaitFor);
157-
} else if (argName === actionArgs.sleep) {
158-
script.flow.push({
159-
sleep: argValue,
160-
} as MidsceneYamlFlowItemSleep);
161-
}
162-
}
163-
164-
const yaml = dump(script);
165-
return yaml;
166-
};
167-
16848
// match yml or yaml files
16949
export async function matchYamlFiles(fileGlob: string) {
17050
if (existsSync(fileGlob) && statSync(fileGlob).isDirectory()) {
17151
fileGlob = join(fileGlob, '**/*.{yml,yaml}');
17252
}
17353
const files = await glob(fileGlob, {
17454
nodir: true,
55+
windowsPathsNoEscape: true,
17556
});
17657
return files
17758
.filter((file) => file.endsWith('.yml') || file.endsWith('.yaml'))

packages/cli/src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,8 @@ Promise.resolve(
3535
process.exit(1);
3636
}
3737
process.exit(0);
38-
})(),
38+
})().catch((e) => {
39+
console.error(e);
40+
process.exit(1);
41+
}),
3942
);

packages/cli/src/printer.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ export const contextInfo = (context: MidsceneYamlFileContext) => {
5151
? chalk.gray('(navigating)')
5252
: '';
5353

54+
// error: ...
55+
const errorText = context.player.errorInSetup
56+
? `\n${indent}${chalk.red('error:')} ${context.player.errorInSetup?.message}\n${indent}${indent}${context.player.errorInSetup?.stack}`
57+
: '';
58+
5459
// output: ...
5560
const outputFile = context.player.output;
5661
const outputText =
@@ -66,7 +71,7 @@ export const contextInfo = (context: MidsceneYamlFileContext) => {
6671
: '';
6772

6873
const mergedText =
69-
`${fileStatusText} ${fileNameToPrint} ${contextActionText}${outputText}${reportText}`.trim();
74+
`${fileStatusText} ${fileNameToPrint} ${contextActionText}${outputText}${reportText}${errorText}`.trim();
7075

7176
return {
7277
fileNameToPrint,
@@ -127,17 +132,19 @@ export const contextTaskListSummary = (
127132
const currentLine: string[] = [];
128133
const suffixText: string[] = [];
129134
const { mergedText: fileInfo } = contextInfo(context);
130-
for (const task of taskStatusArray) {
131-
const { mergedLine } = singleTaskInfo(task);
135+
if (!context.player.errorInSetup) {
136+
for (const task of taskStatusArray) {
137+
const { mergedLine } = singleTaskInfo(task);
132138

133-
if (context.player.status === 'init') {
134-
suffixText.push(mergedLine);
135-
} else if (context.player.status === 'running') {
136-
currentLine.push(mergedLine);
137-
} else if (context.player.status === 'done') {
138-
prefixLines.push(mergedLine);
139-
} else if (context.player.status === 'error') {
140-
prefixLines.push(mergedLine);
139+
if (context.player.status === 'init') {
140+
suffixText.push(mergedLine);
141+
} else if (context.player.status === 'running') {
142+
currentLine.push(mergedLine);
143+
} else if (context.player.status === 'done') {
144+
prefixLines.push(mergedLine);
145+
} else if (context.player.status === 'error') {
146+
prefixLines.push(mergedLine);
147+
}
141148
}
142149
}
143150
const currentLineText =

packages/web-integration/src/puppeteer/agent-launcher.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@ export async function puppeteerAgentForTarget(
7272
);
7373
}
7474
const puppeteer = await import('puppeteer');
75+
// do not use 'no-sandbox' on windows https://www.perplexity.ai/search/how-to-solve-this-with-nodejs-dMHpdCypRa..JA8TkQzbeQ
76+
const isWindows = process.platform === 'win32';
7577
const browser = await puppeteer.launch({
7678
headless: !headed,
7779
args: [
78-
'--no-sandbox',
79-
'--disable-setuid-sandbox',
80+
...(isWindows ? [] : ['--no-sandbox', '--disable-setuid-sandbox']),
8081
'--disable-features=PasswordLeakDetection',
8182
'--disable-save-password-bubble',
8283
],

0 commit comments

Comments
 (0)