@qawolf/cli 1.20.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/cli.js +92 -36
- package/dist/runner-sdk.js +191013 -0
- package/dist/types/runnerSdk/index.d.ts +24 -0
- package/dist/types/runnerSdk/types.d.ts +120 -0
- package/package.json +14 -3
- package/skills/qawolf-cli/SKILL.md +5 -2
- package/skills/qawolf-cli/references/runner.md +2 -5
package/README.md
CHANGED
|
@@ -93,6 +93,28 @@ Omit `--global` to install the skill only for the current project. The skill als
|
|
|
93
93
|
|
|
94
94
|
The skill is generated from its [source template](src/commands/qawolfCliSkill.template.md) and the command tree (`bun run generate`), and kept in sync by the test suite.
|
|
95
95
|
|
|
96
|
+
## Runner SDK
|
|
97
|
+
|
|
98
|
+
Drive interactive runners from TypeScript instead of spawning commands. Every verb names the runner it addresses, so nothing is launched or billed implicitly.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { createRunnerSdk } from "@qawolf/cli/runner-sdk";
|
|
102
|
+
|
|
103
|
+
const runner = createRunnerSdk({ apiKey: process.env.QAWOLF_API_KEY });
|
|
104
|
+
|
|
105
|
+
await runner.launch({ id: "agent-1", runnerFamily: "default" });
|
|
106
|
+
|
|
107
|
+
const submitted = await runner.run({
|
|
108
|
+
entryPointPath: "src/flows/smoke.flow.ts",
|
|
109
|
+
environment: "ambient",
|
|
110
|
+
runnerId: "agent-1",
|
|
111
|
+
selection: "whole-flow",
|
|
112
|
+
});
|
|
113
|
+
if (submitted.ok) console.log(submitted.value.runId, submitted.value.fileSync);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`ok: false` is a transport or auth failure. A runner that refused the request comes back as `ok: true` with `value.outcome === "failure"` and a `failureReason` from the published contract, so a caller can switch on it exhaustively.
|
|
117
|
+
|
|
96
118
|
## Reference
|
|
97
119
|
|
|
98
120
|
- [Commands](https://docs.qawolf.com/qawolf/libraries/cli/api-reference/commands) — full command and flag reference
|
package/dist/cli.js
CHANGED
|
@@ -325968,6 +325968,7 @@ var flowsMessages = {
|
|
|
325968
325968
|
flowCount: (count) => pluralize(count, "flow"),
|
|
325969
325969
|
list: {
|
|
325970
325970
|
remoteRequiresEnv: "--remote requires an environment. Pass --env <env> or set QAWOLF_ENVIRONMENT.",
|
|
325971
|
+
aiTaskIdRequiresRemote: "--ai-task-id requires --remote",
|
|
325971
325972
|
draftsRequireRemote: "--include-drafts requires --remote"
|
|
325972
325973
|
},
|
|
325973
325974
|
selectors: {
|
|
@@ -326122,7 +326123,6 @@ var interactMessages = {
|
|
|
326122
326123
|
actionAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`,
|
|
326123
326124
|
screenshotAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`,
|
|
326124
326125
|
runnerHasNoScreen: "This runner does not run a browser on a virtual desktop, so there is nothing about it to see or drive. Retrying will never help: launch a playwright runner instead.",
|
|
326125
|
-
runnerHasNoScreenToEvaluate: "The runner could not evaluate the snippet. This covers a runner that is still starting or busy, and also one with no live page to evaluate against: a freshly launched runner has no page until a run opens one, so run a flow on it with qawolf runner run first. If it is not a runner that runs a browser at all, this will never clear. It is not proof the snippet did not run, so do not resubmit one that mutates the page without reading qawolf runner events console first.",
|
|
326126
326126
|
inspectNeedsABrowserRunner: "This runner is a mobile device, and element and page HTML are a browser's shapes. Retrying will never help. Launch a playwright runner to inspect one.",
|
|
326127
326127
|
nothingToInspect: (errorMessage2) => `The runner had nothing to inspect${errorMessage2 === undefined ? "" : `: ${errorMessage2}`}. There is no live page, nothing matched the selector, or no variable has that name; a runner cannot tell those apart. Run a flow on it first, or check the selector or name.`,
|
|
326128
326128
|
inspectAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`,
|
|
@@ -326137,7 +326137,10 @@ var interactMessages = {
|
|
|
326137
326137
|
snippetErrored: (errorMessage2) => errorMessage2 === undefined ? "The snippet threw and reported no message." : `The snippet threw: ${errorMessage2}`,
|
|
326138
326138
|
snippetFileUnreadable: (path) => `Could not read "${path}". Name a readable file, or "-" to read the snippet from stdin.`,
|
|
326139
326139
|
snippetRan: "The snippet ran. Its value is not returned: read anything it printed with qawolf runner events console.",
|
|
326140
|
+
snippetRunnerUnreachable: "The runner could not be reached. It may still be starting, or it may have terminated after inactivity. It is not proof the snippet did not run: a snippet that outlives the answer window is still executing when you read this, so do not blindly resubmit one that mutates the page without reading qawolf runner events console first.",
|
|
326140
326141
|
snippetStopped: "The snippet was interrupted before it finished. Anything it printed first is in qawolf runner events console.",
|
|
326142
|
+
runnerCannotEvaluateSnippets: "This runner has no snippet evaluator attached, so there is nothing to run code against. Retrying will never help: launch a playwright, android, ios, or windows runner instead.",
|
|
326143
|
+
snippetAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`,
|
|
326141
326144
|
stdinEmptyAction: 'Nothing arrived on stdin. Pipe the action in, or name the action type instead of "-".',
|
|
326142
326145
|
stdinEmptySnippet: 'Nothing arrived on stdin. Pipe the snippet in, or name a file instead of "-".',
|
|
326143
326146
|
missingPackageJsonForImport: "No package.json in the current directory. The install resolves against the run's own dependencies, which are read from one.",
|
|
@@ -326153,7 +326156,7 @@ var interactMessages = {
|
|
|
326153
326156
|
runnerCannotHighlightSelectors: "This runner has no browser to draw on, so there is nothing to highlight. Retrying will never help: launch a playwright runner instead.",
|
|
326154
326157
|
highlightAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`,
|
|
326155
326158
|
snapshotPromoted: (screenshotPath, baselinePath) => `Promoted ${screenshotPath} to the baseline at ${baselinePath}.`,
|
|
326156
|
-
snapshotNotFound: (screenshotPath) => `The run wrote no screenshot at "${screenshotPath}", so nothing was changed. The two paths have to be the ones an image diff reported: read them from the
|
|
326159
|
+
snapshotNotFound: (screenshotPath) => `The run wrote no screenshot at "${screenshotPath}", so nothing was changed. The two paths have to be the ones an image diff reported: read them from the imageDiffArtifact entry on qawolf runner events run-events.`,
|
|
326157
326160
|
runnerCannotPromoteSnapshots: "This runner stores no screenshots, so it holds no baseline to replace. Retrying will never help.",
|
|
326158
326161
|
promoteSnapshotAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`
|
|
326159
326162
|
};
|
|
@@ -342694,8 +342697,9 @@ var runSelectionSchema = exports_external.object({
|
|
|
342694
342697
|
// node_modules/@qawolf/api-contracts/dist/v1/automate/index.js
|
|
342695
342698
|
var makeAutomateContract = (ids) => {
|
|
342696
342699
|
const input = exports_external.object({
|
|
342700
|
+
aiTaskId: ids.aiTask.describe("The AI task to build the automation on: drafts are read from and the automation branches off the task's branch instead of the environment's.").optional(),
|
|
342697
342701
|
environmentId: ids.environmentRef,
|
|
342698
|
-
flowIds: exports_external.array(ids.flow).min(1).max(300).refine((flowIds) => new Set(flowIds).size === flowIds.length, "flowIds must be unique").describe("IDs of every requested draft flow the automation builds. Reuse an existing draft only when its name matches the requested journey; a generic starter or placeholder is not a match. After publishing, resolve the IDs with `qawolf --json flows list --remote --env <environment-id-or-alias> --include-drafts
|
|
342702
|
+
flowIds: exports_external.array(ids.flow).min(1).max(300).refine((flowIds) => new Set(flowIds).size === flowIds.length, "flowIds must be unique").describe("IDs of every requested draft flow the automation builds. Reuse an existing draft only when its name matches the requested journey; a generic starter or placeholder is not a match. After publishing, resolve the IDs with `qawolf --json flows list --remote --env <environment-id-or-alias> --include-drafts`, adding `--ai-task-id` when the drafts live on an AI task's branch."),
|
|
342699
342703
|
patch: exports_external.string().min(1).max(1e6).optional().describe("Unified diff applied to the automation's working branch before it runs. It cannot create or rename a selected flow; publish selected flows with Git first.")
|
|
342700
342704
|
});
|
|
342701
342705
|
const output = resource({ automationId: ids.automation }, { urlFieldDescription: "Absolute URL of the automation review page." });
|
|
@@ -342926,6 +342930,7 @@ var flowReadinessSchema = exports_external.enum(["draft", "active"]);
|
|
|
342926
342930
|
// node_modules/@qawolf/api-contracts/dist/v1/flow/index.js
|
|
342927
342931
|
var makeListFlowsContract = (ids) => {
|
|
342928
342932
|
const input = exports_external.object({
|
|
342933
|
+
aiTaskId: ids.aiTask.describe("List the flows on this AI task's branch, including drafts, instead of the ones in the environment. The task must belong to the environment.").optional(),
|
|
342929
342934
|
environmentId: ids.environmentRef,
|
|
342930
342935
|
includeDrafts: exports_external.boolean().default(false).describe("Include draft flows in the listing.")
|
|
342931
342936
|
});
|
|
@@ -342943,7 +342948,7 @@ var makeListFlowsContract = (ids) => {
|
|
|
342943
342948
|
}))
|
|
342944
342949
|
});
|
|
342945
342950
|
return {
|
|
342946
|
-
description: "List the flows of an environment at its latest reconciled commit.",
|
|
342951
|
+
description: "List the flows of an environment at its latest reconciled commit, or, when an AI task is given, the flows on that task's branch.",
|
|
342947
342952
|
input,
|
|
342948
342953
|
kind: "read",
|
|
342949
342954
|
name: "flow.list",
|
|
@@ -343269,10 +343274,13 @@ var makeEvaluateSnippetOnRunnerContract = () => {
|
|
|
343269
343274
|
outcome: exports_external.literal("success"),
|
|
343270
343275
|
result: exports_external.enum(["success", "stopped", "error"]).describe("`success` if the snippet ran to completion, `stopped` if it was interrupted, `error` if it threw. Whether it ran, not what it evaluated to.")
|
|
343271
343276
|
}),
|
|
343272
|
-
makeRunnerFailureSchema([
|
|
343277
|
+
makeRunnerFailureSchema([
|
|
343278
|
+
"runner-cannot-evaluate-snippets",
|
|
343279
|
+
runnerUnreachableFailureReason
|
|
343280
|
+
])
|
|
343273
343281
|
]);
|
|
343274
343282
|
return {
|
|
343275
|
-
description: "Evaluate a snippet against whatever the runner's browser is showing right now. Answers whether the snippet ran, and its error if it threw — not the value it evaluated to, so read anything you want back out of the runner's journal (a snippet's `console.log` lands in the `console` stream). A snippet starts no run and leaves no run-scoped journal entries of its own. `runner-
|
|
343283
|
+
description: "Evaluate a snippet against whatever the runner's browser is showing right now. Answers whether the snippet ran, and its error if it threw — not the value it evaluated to, so read anything you want back out of the runner's journal (a snippet's `console.log` lands in the `console` stream). A snippet starts no run and leaves no run-scoped journal entries of its own. `runner-cannot-evaluate-snippets` on a runner with nothing attached to serve one — which will never clear, so check that the runner you launched is one that runs a browser or app before retrying. `runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may be too busy to answer. Neither is proof the snippet did not run: a snippet that outlives the answer window is still executing when you read this, so do not blindly resubmit one that mutates what the page is looking at.",
|
|
343276
343284
|
input,
|
|
343277
343285
|
kind: "write",
|
|
343278
343286
|
name: "runner.evaluateSnippet",
|
|
@@ -346156,7 +346164,7 @@ function startUpdateCheck(deps) {
|
|
|
346156
346164
|
// package.json
|
|
346157
346165
|
var package_default = {
|
|
346158
346166
|
name: "@qawolf/cli",
|
|
346159
|
-
version: "1.
|
|
346167
|
+
version: "1.21.0",
|
|
346160
346168
|
description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
|
|
346161
346169
|
keywords: [
|
|
346162
346170
|
"automation",
|
|
@@ -346184,16 +346192,27 @@ var package_default = {
|
|
|
346184
346192
|
"LICENSE",
|
|
346185
346193
|
"README.md",
|
|
346186
346194
|
"dist/cli.js",
|
|
346195
|
+
"dist/runner-sdk.js",
|
|
346196
|
+
"dist/types/runnerSdk/index.d.ts",
|
|
346197
|
+
"dist/types/runnerSdk/types.d.ts",
|
|
346187
346198
|
"skills"
|
|
346188
346199
|
],
|
|
346189
346200
|
type: "module",
|
|
346201
|
+
exports: {
|
|
346202
|
+
"./runner-sdk": {
|
|
346203
|
+
types: "./dist/types/runnerSdk/index.d.ts",
|
|
346204
|
+
import: "./dist/runner-sdk.js"
|
|
346205
|
+
},
|
|
346206
|
+
"./package.json": "./package.json"
|
|
346207
|
+
},
|
|
346190
346208
|
publishConfig: {
|
|
346191
346209
|
access: "public"
|
|
346192
346210
|
},
|
|
346193
346211
|
scripts: {
|
|
346194
346212
|
build: "bun run build:bundle",
|
|
346195
|
-
"build:bundle": "bun run generate && bun scripts/build.ts",
|
|
346196
346213
|
"build:binary": "bun run build && bun scripts/buildBinary.ts",
|
|
346214
|
+
"build:bundle": "bun run generate && bun scripts/build.ts",
|
|
346215
|
+
"build:types-gate": "bun scripts/checkSdkTypes.ts",
|
|
346197
346216
|
dev: "bun run src/main.ts",
|
|
346198
346217
|
format: "oxfmt .",
|
|
346199
346218
|
"format:check": "oxfmt --check .",
|
|
@@ -346216,7 +346235,7 @@ var package_default = {
|
|
|
346216
346235
|
"@clack/prompts": "1.5.1",
|
|
346217
346236
|
"@napi-rs/keyring": "1.3.0",
|
|
346218
346237
|
"@oxc-node/core": "0.1.0",
|
|
346219
|
-
"@qawolf/api-contracts": "0.
|
|
346238
|
+
"@qawolf/api-contracts": "0.37.0",
|
|
346220
346239
|
"@qawolf/emails": "1.1.1",
|
|
346221
346240
|
"@qawolf/flow-targets": "1.0.0",
|
|
346222
346241
|
"@qawolf/flows": "0.1.4",
|
|
@@ -349119,6 +349138,7 @@ async function fetchKnownTags(ctx) {
|
|
|
349119
349138
|
// src/domains/flows/listRemote.ts
|
|
349120
349139
|
async function flowsListRemote(ctx, pattern, options) {
|
|
349121
349140
|
const result = await ctx.platformClient.callPublicApi(publicContractsV1.flow.list, {
|
|
349141
|
+
aiTaskId: options.aiTaskId,
|
|
349122
349142
|
environmentId: options.env,
|
|
349123
349143
|
includeDrafts: options.includeDrafts
|
|
349124
349144
|
});
|
|
@@ -356431,25 +356451,32 @@ Examples:
|
|
|
356431
356451
|
$ qawolf flows list --tag auth
|
|
356432
356452
|
$ qawolf flows list --env staging --tag auth
|
|
356433
356453
|
$ qawolf flows list --remote --env staging --tag auth --tag smoke
|
|
356434
|
-
$ qawolf flows list "**/checkout/**" --remote --env staging --include-drafts
|
|
356435
|
-
|
|
356454
|
+
$ qawolf flows list "**/checkout/**" --remote --env staging --include-drafts
|
|
356455
|
+
$ qawolf flows list --remote --env staging --ai-task-id ait_123`;
|
|
356456
|
+
function registerFlowsCommand(program2, signals, deps = { withResolvedEnv }) {
|
|
356436
356457
|
const flows = program2.command("flows").description("Manage and run QA Wolf flows");
|
|
356437
356458
|
registerFlowsRunCommand(flows, signals);
|
|
356438
356459
|
registerRunWorkerCommand(flows, signals);
|
|
356439
356460
|
declareCommandKind(flows.command("list [pattern]"), "local", {
|
|
356440
356461
|
kindNote: "read with --remote"
|
|
356441
|
-
}).description("List flows matching [pattern] from the local project, or from a QA Wolf environment with --remote").option("--remote", "List flows from the QA Wolf platform instead of the local project", false).option("--env <env>", "Environment to list flows from: a QA Wolf environment with --remote, otherwise a pulled one by slug or id").option("--include-drafts", "Include draft flows in the listing (requires --remote)", false).option("--tag <name>", "Only list flows carrying this tag; repeat for several. Without --remote, matches against tags cached by the last pull", collectValue, []).addHelpText("after", listExamples).action((pattern, opts, command) => {
|
|
356462
|
+
}).description("List flows matching [pattern] from the local project, or from a QA Wolf environment with --remote").option("--remote", "List flows from the QA Wolf platform instead of the local project", false).option("--env <env>", "Environment to list flows from: a QA Wolf environment with --remote, otherwise a pulled one by slug or id").option("--include-drafts", "Include draft flows in the listing (requires --remote)", false).option("--tag <name>", "Only list flows carrying this tag; repeat for several. Without --remote, matches against tags cached by the last pull", collectValue, []).addOption(new Option("--ai-task-id <aiTaskId>", "List the flows on this AI task's branch, including drafts, instead of the ones in the environment (requires --remote)").env("QAWOLF_AI_TASK_ID")).addHelpText("after", listExamples).action((pattern, opts, command) => {
|
|
356442
356463
|
const tags = opts.tag;
|
|
356443
356464
|
if (opts.remote) {
|
|
356444
|
-
return withResolvedEnv(signals, {
|
|
356465
|
+
return deps.withResolvedEnv(signals, {
|
|
356445
356466
|
explicit: opts.env,
|
|
356446
356467
|
requiredMessage: flowsMessages.list.remoteRequiresEnv
|
|
356447
356468
|
}, (ctx, env3) => flowsListRemote(ctx, pattern, {
|
|
356448
356469
|
env: env3,
|
|
356449
356470
|
includeDrafts: opts.includeDrafts,
|
|
356471
|
+
aiTaskId: opts.aiTaskId,
|
|
356450
356472
|
tags
|
|
356451
356473
|
}))(opts, command);
|
|
356452
356474
|
}
|
|
356475
|
+
if (command.getOptionValueSource("aiTaskId") === "cli") {
|
|
356476
|
+
return withContext(signals, async () => ({
|
|
356477
|
+
error: flowsMessages.list.aiTaskIdRequiresRemote
|
|
356478
|
+
}))(opts, command);
|
|
356479
|
+
}
|
|
356453
356480
|
if (opts.includeDrafts) {
|
|
356454
356481
|
return withContext(signals, async () => ({
|
|
356455
356482
|
error: flowsMessages.list.draftsRequireRemote
|
|
@@ -358322,6 +358349,28 @@ function registerRunnerInspectCommands(runner, signals) {
|
|
|
358322
358349
|
registerRunnerInspectMobileCommands(inspect, signals);
|
|
358323
358350
|
}
|
|
358324
358351
|
|
|
358352
|
+
// src/domains/interactiveRunner/evaluateSnippetFailure.ts
|
|
358353
|
+
function describeEvaluateSnippetFailure(failure) {
|
|
358354
|
+
const { failureReason } = failure;
|
|
358355
|
+
switch (failureReason) {
|
|
358356
|
+
case "runner-cannot-evaluate-snippets":
|
|
358357
|
+
return {
|
|
358358
|
+
error: interactiveRunnerMessages.runnerCannotEvaluateSnippets,
|
|
358359
|
+
exitCode: exitCodes.invalidArgs
|
|
358360
|
+
};
|
|
358361
|
+
case "runner-unreachable":
|
|
358362
|
+
return {
|
|
358363
|
+
error: interactiveRunnerMessages.snippetRunnerUnreachable,
|
|
358364
|
+
exitCode: exitCodes.network
|
|
358365
|
+
};
|
|
358366
|
+
default:
|
|
358367
|
+
return {
|
|
358368
|
+
error: interactiveRunnerMessages.snippetAnsweredUnknown(failureReason),
|
|
358369
|
+
exitCode: exitCodes.network
|
|
358370
|
+
};
|
|
358371
|
+
}
|
|
358372
|
+
}
|
|
358373
|
+
|
|
358325
358374
|
// src/core/interactiveRunner/runFiles.ts
|
|
358326
358375
|
import { isAbsolute as isAbsolute5, relative as relative10, resolve as resolve11, sep as sep5 } from "node:path";
|
|
358327
358376
|
function toCollectedPath(cwd, path9) {
|
|
@@ -358383,9 +358432,8 @@ function describeRunFilesCheck(check2) {
|
|
|
358383
358432
|
}
|
|
358384
358433
|
}
|
|
358385
358434
|
|
|
358386
|
-
// src/domains/interactiveRunner/
|
|
358387
|
-
|
|
358388
|
-
async function resolveScope(contextFile, deps) {
|
|
358435
|
+
// src/domains/interactiveRunner/snippetScope.ts
|
|
358436
|
+
async function resolveSnippetScope(contextFile, deps) {
|
|
358389
358437
|
if (contextFile === undefined) {
|
|
358390
358438
|
return { filePath: undefined, files: undefined, ok: true };
|
|
358391
358439
|
}
|
|
@@ -358397,6 +358445,9 @@ async function resolveScope(contextFile, deps) {
|
|
|
358397
358445
|
}
|
|
358398
358446
|
return { filePath, files, ok: true };
|
|
358399
358447
|
}
|
|
358448
|
+
|
|
358449
|
+
// src/domains/interactiveRunner/evaluateSnippet.ts
|
|
358450
|
+
var stdinArgument = "-";
|
|
358400
358451
|
async function readCode(source, deps) {
|
|
358401
358452
|
const code = source === stdinArgument ? await deps.readStdin() : await deps.readFile(source).catch(() => {
|
|
358402
358453
|
return;
|
|
@@ -358416,7 +358467,7 @@ async function handleRunnerExec(ctx, options, deps) {
|
|
|
358416
358467
|
const code = await readCode(options.source, deps);
|
|
358417
358468
|
if (!code.ok)
|
|
358418
358469
|
return { error: code.error, exitCode: exitCodes.invalidArgs };
|
|
358419
|
-
const scope = await
|
|
358470
|
+
const scope = await resolveSnippetScope(options.contextFile, deps);
|
|
358420
358471
|
if (!scope.ok)
|
|
358421
358472
|
return { error: scope.error, exitCode: exitCodes.invalidArgs };
|
|
358422
358473
|
const resolved = await resolveRunner(ctx, { autoLaunch: true, runner: options.runner }, deps);
|
|
@@ -358437,11 +358488,7 @@ async function handleRunnerExec(ctx, options, deps) {
|
|
|
358437
358488
|
};
|
|
358438
358489
|
}
|
|
358439
358490
|
if (result.value.outcome === "failure") {
|
|
358440
|
-
result.value
|
|
358441
|
-
return {
|
|
358442
|
-
error: interactiveRunnerMessages.runnerHasNoScreenToEvaluate,
|
|
358443
|
-
exitCode: exitCodes.network
|
|
358444
|
-
};
|
|
358491
|
+
return describeEvaluateSnippetFailure(result.value);
|
|
358445
358492
|
}
|
|
358446
358493
|
switch (result.value.result) {
|
|
358447
358494
|
case "success":
|
|
@@ -358792,14 +358839,13 @@ async function probeRunner(ctx, runner) {
|
|
|
358792
358839
|
return { ...failureFields(result), ok: false };
|
|
358793
358840
|
return { ok: true, runner, running: result.value.running };
|
|
358794
358841
|
}
|
|
358795
|
-
async function
|
|
358842
|
+
async function listRunners(ctx, deps) {
|
|
358796
358843
|
const { candidates, defaultRunnerId } = await readCandidates(deps);
|
|
358797
358844
|
const running = [];
|
|
358798
358845
|
const gone = [];
|
|
358799
358846
|
for await (const probe of batchMap(candidates, (runner) => probeRunner(ctx, runner), probeBatchSize)) {
|
|
358800
|
-
if (!probe.ok)
|
|
358801
|
-
return { ...failureFields(probe),
|
|
358802
|
-
}
|
|
358847
|
+
if (!probe.ok)
|
|
358848
|
+
return { ...failureFields(probe), ok: false };
|
|
358803
358849
|
if (probe.running)
|
|
358804
358850
|
running.push(probe.runner);
|
|
358805
358851
|
else
|
|
@@ -358808,14 +358854,24 @@ async function handleRunnerList(ctx, deps) {
|
|
|
358808
358854
|
await deps.store.dropRunners(gone).catch(() => {
|
|
358809
358855
|
return;
|
|
358810
358856
|
});
|
|
358811
|
-
|
|
358812
|
-
|
|
358813
|
-
|
|
358814
|
-
|
|
358815
|
-
|
|
358816
|
-
|
|
358817
|
-
|
|
358818
|
-
|
|
358857
|
+
return {
|
|
358858
|
+
items: [
|
|
358859
|
+
...running.filter((runner) => runner.id === defaultRunnerId),
|
|
358860
|
+
...running.filter((runner) => runner.id !== defaultRunnerId)
|
|
358861
|
+
].map((runner) => ({
|
|
358862
|
+
id: runner.id,
|
|
358863
|
+
isDefault: runner.id === defaultRunnerId,
|
|
358864
|
+
runnerName: runner.runnerName
|
|
358865
|
+
})),
|
|
358866
|
+
ok: true
|
|
358867
|
+
};
|
|
358868
|
+
}
|
|
358869
|
+
async function handleRunnerList(ctx, deps) {
|
|
358870
|
+
const listed = await listRunners(ctx, deps);
|
|
358871
|
+
if (!listed.ok) {
|
|
358872
|
+
return { ...failureFields(listed), exitCode: exitCodes.network };
|
|
358873
|
+
}
|
|
358874
|
+
const items = listed.items;
|
|
358819
358875
|
if (ctx.ui.mode === "json") {
|
|
358820
358876
|
ctx.ui.json(items);
|
|
358821
358877
|
return;
|
|
@@ -358948,7 +359004,7 @@ async function handleRunnerPromoteSnapshot(ctx, options, deps) {
|
|
|
358948
359004
|
var promoteSnapshotExamples = `
|
|
358949
359005
|
Examples:
|
|
358950
359006
|
$ qawolf runner promote-snapshot --screenshot checkout-1-actual.png --baseline checkout-1.png
|
|
358951
|
-
$ qawolf runner events run-events --tail 20 | jq 'select(.type == "
|
|
359007
|
+
$ qawolf runner events run-events --tail 20 | jq 'select(.type == "imageDiffArtifact")'`;
|
|
358952
359008
|
function registerRunnerPromoteSnapshotCommand(runner, signals) {
|
|
358953
359009
|
declareCommandKind(runner.command("promote-snapshot"), "write").description("Accept a run's screenshot as the new baseline for an image diff, on the runner that produced it").requiredOption("--screenshot <path>", "The screenshot to promote, as the image diff named it").requiredOption("--baseline <path>", "The baseline to replace, as the image diff named it").option("--runner <id>", runnerFlagDescription).addHelpText("after", promoteSnapshotExamples).action((opts, command) => withAuthContext(signals, (ctx) => handleRunnerPromoteSnapshot(ctx, {
|
|
358954
359010
|
baselinePath: opts.baseline,
|
|
@@ -359691,4 +359747,4 @@ createProgram({ signals }).parseAsync().catch(() => {
|
|
|
359691
359747
|
process.exitCode = 1;
|
|
359692
359748
|
}).finally(() => flushAndExit(typeof process.exitCode === "number" ? process.exitCode : 0));
|
|
359693
359749
|
|
|
359694
|
-
//# debugId=
|
|
359750
|
+
//# debugId=65DBB9A4D5E4AFCD64756E2164756E21
|