@devicecloud.dev/dcd 4.1.4 → 4.1.5
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/dist/commands/cloud.d.ts +30 -0
- package/dist/commands/cloud.js +30 -0
- package/dist/config/flags/execution.flags.js +2 -2
- package/dist/gateways/api-gateway.d.ts +2 -2
- package/dist/services/execution-plan.service.d.ts +23 -0
- package/dist/services/execution-plan.service.js +41 -0
- package/dist/types/generated/schema.types.d.ts +1086 -348
- package/oclif.manifest.json +4 -3
- package/package.json +1 -1
package/dist/commands/cloud.d.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
/**
|
|
3
|
+
* Primary CLI command for executing tests on DeviceCloud.
|
|
4
|
+
* Orchestrates the complete test workflow:
|
|
5
|
+
* - Binary upload with SHA deduplication
|
|
6
|
+
* - Flow file analysis and dependency resolution
|
|
7
|
+
* - Device compatibility validation
|
|
8
|
+
* - Test submission with parallel execution
|
|
9
|
+
* - Real-time result polling with 5-second intervals
|
|
10
|
+
* - Artifact download (reports, videos, logs)
|
|
11
|
+
*
|
|
12
|
+
* Replaces `maestro cloud` with DeviceCloud-specific functionality.
|
|
13
|
+
*/
|
|
2
14
|
export default class Cloud extends Command {
|
|
3
15
|
static args: {
|
|
4
16
|
firstFile: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -50,12 +62,30 @@ export default class Cloud extends Command {
|
|
|
50
62
|
apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
51
63
|
apiUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
52
64
|
};
|
|
65
|
+
/** Service for device/OS compatibility validation */
|
|
53
66
|
private deviceValidationService;
|
|
67
|
+
/** Service for Moropo test framework integration */
|
|
54
68
|
private moropoService;
|
|
69
|
+
/** Service for downloading test reports and artifacts */
|
|
55
70
|
private reportDownloadService;
|
|
71
|
+
/** Service for polling test results with 5-second intervals */
|
|
56
72
|
private resultsPollingService;
|
|
73
|
+
/** Service for submitting tests to the API */
|
|
57
74
|
private testSubmissionService;
|
|
75
|
+
/**
|
|
76
|
+
* Check for CLI updates and notify user if outdated
|
|
77
|
+
* Compares current version with latest npm release
|
|
78
|
+
* @returns Promise that resolves when version check is complete
|
|
79
|
+
*/
|
|
58
80
|
private versionCheck;
|
|
81
|
+
/** Service for CLI version checking */
|
|
59
82
|
private versionService;
|
|
83
|
+
/**
|
|
84
|
+
* Main command execution entry point
|
|
85
|
+
* Orchestrates the complete test submission and monitoring workflow
|
|
86
|
+
* @returns Promise that resolves when command execution is complete
|
|
87
|
+
* @throws RunFailedError if tests fail
|
|
88
|
+
* @throws Error for infrastructure or configuration errors
|
|
89
|
+
*/
|
|
60
90
|
run(): Promise<any>;
|
|
61
91
|
}
|
package/dist/commands/cloud.js
CHANGED
|
@@ -23,6 +23,18 @@ process.on('warning', (warning) => {
|
|
|
23
23
|
// Ignore punycode deprecation warnings
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
|
+
/**
|
|
27
|
+
* Primary CLI command for executing tests on DeviceCloud.
|
|
28
|
+
* Orchestrates the complete test workflow:
|
|
29
|
+
* - Binary upload with SHA deduplication
|
|
30
|
+
* - Flow file analysis and dependency resolution
|
|
31
|
+
* - Device compatibility validation
|
|
32
|
+
* - Test submission with parallel execution
|
|
33
|
+
* - Real-time result polling with 5-second intervals
|
|
34
|
+
* - Artifact download (reports, videos, logs)
|
|
35
|
+
*
|
|
36
|
+
* Replaces `maestro cloud` with DeviceCloud-specific functionality.
|
|
37
|
+
*/
|
|
26
38
|
class Cloud extends core_1.Command {
|
|
27
39
|
static args = {
|
|
28
40
|
firstFile: core_1.Args.string({
|
|
@@ -40,11 +52,21 @@ class Cloud extends core_1.Command {
|
|
|
40
52
|
static enableJsonFlag = true;
|
|
41
53
|
static examples = ['<%= config.bin %> <%= command.id %>'];
|
|
42
54
|
static flags = constants_1.flags;
|
|
55
|
+
/** Service for device/OS compatibility validation */
|
|
43
56
|
deviceValidationService = new device_validation_service_1.DeviceValidationService();
|
|
57
|
+
/** Service for Moropo test framework integration */
|
|
44
58
|
moropoService = new moropo_service_1.MoropoService();
|
|
59
|
+
/** Service for downloading test reports and artifacts */
|
|
45
60
|
reportDownloadService = new report_download_service_1.ReportDownloadService();
|
|
61
|
+
/** Service for polling test results with 5-second intervals */
|
|
46
62
|
resultsPollingService = new results_polling_service_1.ResultsPollingService();
|
|
63
|
+
/** Service for submitting tests to the API */
|
|
47
64
|
testSubmissionService = new test_submission_service_1.TestSubmissionService();
|
|
65
|
+
/**
|
|
66
|
+
* Check for CLI updates and notify user if outdated
|
|
67
|
+
* Compares current version with latest npm release
|
|
68
|
+
* @returns Promise that resolves when version check is complete
|
|
69
|
+
*/
|
|
48
70
|
versionCheck = async () => {
|
|
49
71
|
const latestVersion = await this.versionService.checkLatestCliVersion();
|
|
50
72
|
if (latestVersion &&
|
|
@@ -57,7 +79,15 @@ class Cloud extends core_1.Command {
|
|
|
57
79
|
`);
|
|
58
80
|
}
|
|
59
81
|
};
|
|
82
|
+
/** Service for CLI version checking */
|
|
60
83
|
versionService = new version_service_1.VersionService();
|
|
84
|
+
/**
|
|
85
|
+
* Main command execution entry point
|
|
86
|
+
* Orchestrates the complete test submission and monitoring workflow
|
|
87
|
+
* @returns Promise that resolves when command execution is complete
|
|
88
|
+
* @throws RunFailedError if tests fail
|
|
89
|
+
* @throws Error for infrastructure or configuration errors
|
|
90
|
+
*/
|
|
61
91
|
async run() {
|
|
62
92
|
let output = null;
|
|
63
93
|
// Store debug flag outside try/catch to access it in catch block
|
|
@@ -44,7 +44,7 @@ exports.executionFlags = {
|
|
|
44
44
|
}),
|
|
45
45
|
'runner-type': core_1.Flags.string({
|
|
46
46
|
default: 'default',
|
|
47
|
-
description: '[experimental] The type of runner to use - note: anything other than default will incur premium pricing tiers, see https://docs.devicecloud.dev/reference/runner-type for more information. gpu1
|
|
48
|
-
options: ['default', 'm4', 'm1', 'gpu1'],
|
|
47
|
+
description: '[experimental] The type of runner to use - note: anything other than default will incur premium pricing tiers, see https://docs.devicecloud.dev/reference/runner-type for more information. gpu1 and cpu1 are Android-only and require contacting support to enable, otherwise reverts to default.',
|
|
48
|
+
options: ['default', 'm4', 'm1', 'gpu1', 'cpu1'],
|
|
49
49
|
}),
|
|
50
50
|
};
|
|
@@ -14,14 +14,14 @@ export declare const ApiGateway: {
|
|
|
14
14
|
downloadArtifactsZip(baseUrl: string, apiKey: string, uploadId: string, results: "ALL" | "FAILED", artifactsPath?: string): Promise<void>;
|
|
15
15
|
finaliseUpload(baseUrl: string, apiKey: string, id: string, metadata: TAppMetadata, path: string, sha: string): Promise<Record<string, never>>;
|
|
16
16
|
getBinaryUploadUrl(baseUrl: string, apiKey: string, platform: "android" | "ios"): Promise<{
|
|
17
|
-
id: string;
|
|
18
17
|
message: string;
|
|
19
18
|
path: string;
|
|
20
19
|
token: string;
|
|
20
|
+
id: string;
|
|
21
21
|
}>;
|
|
22
22
|
getResultsForUpload(baseUrl: string, apiKey: string, uploadId: string): Promise<{
|
|
23
|
-
results?: import("../types/generated/schema.types").components["schemas"]["TResultResponse"][];
|
|
24
23
|
statusCode?: number;
|
|
24
|
+
results?: import("../types/generated/schema.types").components["schemas"]["TResultResponse"][];
|
|
25
25
|
}>;
|
|
26
26
|
getUploadStatus(baseUrl: string, apiKey: string, options: {
|
|
27
27
|
name?: string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Email notification configuration */
|
|
1
2
|
interface INotificationsConfig {
|
|
2
3
|
email?: {
|
|
3
4
|
enabled?: boolean;
|
|
@@ -5,6 +6,7 @@ interface INotificationsConfig {
|
|
|
5
6
|
recipients?: string[];
|
|
6
7
|
};
|
|
7
8
|
}
|
|
9
|
+
/** Workspace configuration from config.yaml */
|
|
8
10
|
interface IWorkspaceConfig {
|
|
9
11
|
excludeTags?: null | string[];
|
|
10
12
|
executionOrder?: IExecutionOrder | null;
|
|
@@ -13,13 +15,16 @@ interface IWorkspaceConfig {
|
|
|
13
15
|
local?: ILocal | null;
|
|
14
16
|
notifications?: INotificationsConfig;
|
|
15
17
|
}
|
|
18
|
+
/** Local execution configuration */
|
|
16
19
|
interface ILocal {
|
|
17
20
|
deterministicOrder: boolean | null;
|
|
18
21
|
}
|
|
22
|
+
/** Sequential execution configuration */
|
|
19
23
|
interface IExecutionOrder {
|
|
20
24
|
continueOnFailure: boolean;
|
|
21
25
|
flowsOrder: string[];
|
|
22
26
|
}
|
|
27
|
+
/** Options for execution plan generation */
|
|
23
28
|
export interface PlanOptions {
|
|
24
29
|
configFile?: string;
|
|
25
30
|
debug?: boolean;
|
|
@@ -28,6 +33,7 @@ export interface PlanOptions {
|
|
|
28
33
|
includeTags?: string[];
|
|
29
34
|
input: string;
|
|
30
35
|
}
|
|
36
|
+
/** Execution plan containing all flows to run with metadata and dependencies */
|
|
31
37
|
export interface IExecutionPlan {
|
|
32
38
|
allExcludeTags?: null | string[];
|
|
33
39
|
allIncludeTags?: null | string[];
|
|
@@ -39,9 +45,26 @@ export interface IExecutionPlan {
|
|
|
39
45
|
totalFlowFiles: number;
|
|
40
46
|
workspaceConfig?: IWorkspaceConfig;
|
|
41
47
|
}
|
|
48
|
+
/** Flow sequence configuration for ordered execution */
|
|
42
49
|
interface IFlowSequence {
|
|
43
50
|
continueOnFailure?: boolean;
|
|
44
51
|
flows: string[];
|
|
45
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Generate execution plan for test flows
|
|
55
|
+
*
|
|
56
|
+
* Handles:
|
|
57
|
+
* - Single file or directory input
|
|
58
|
+
* - Workspace configuration (config.yaml)
|
|
59
|
+
* - Flow inclusion/exclusion patterns
|
|
60
|
+
* - Tag-based filtering (include/exclude)
|
|
61
|
+
* - Dependency resolution (runFlow, scripts, media)
|
|
62
|
+
* - Sequential execution ordering
|
|
63
|
+
* - DeviceCloud-specific overrides
|
|
64
|
+
*
|
|
65
|
+
* @param options - Plan generation options
|
|
66
|
+
* @returns Complete execution plan with flows, dependencies, and metadata
|
|
67
|
+
* @throws Error if input path doesn't exist, no flows found, or dependencies missing
|
|
68
|
+
*/
|
|
46
69
|
export declare function plan(options: PlanOptions): Promise<IExecutionPlan>;
|
|
47
70
|
export {};
|
|
@@ -5,6 +5,13 @@ const glob_1 = require("glob");
|
|
|
5
5
|
const fs = require("node:fs");
|
|
6
6
|
const path = require("node:path");
|
|
7
7
|
const execution_plan_utils_1 = require("./execution-plan.utils");
|
|
8
|
+
/**
|
|
9
|
+
* Recursively check and resolve all dependencies for a flow file
|
|
10
|
+
* Includes runFlow references, JavaScript scripts, and media files
|
|
11
|
+
* @param input - Path to flow file to check
|
|
12
|
+
* @returns Array of all dependency file paths (deduplicated)
|
|
13
|
+
* @throws Error if any referenced files are missing
|
|
14
|
+
*/
|
|
8
15
|
async function checkDependencies(input) {
|
|
9
16
|
const checkedDependencies = [];
|
|
10
17
|
const uncheckedDependencies = [input];
|
|
@@ -35,12 +42,24 @@ async function checkDependencies(input) {
|
|
|
35
42
|
}
|
|
36
43
|
return checkedDependencies;
|
|
37
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Filter flow files based on exclude patterns
|
|
47
|
+
* @param unfilteredFlowFiles - All discovered flow files
|
|
48
|
+
* @param excludeFlows - Patterns to exclude
|
|
49
|
+
* @returns Filtered array of flow file paths
|
|
50
|
+
*/
|
|
38
51
|
function filterFlowFiles(unfilteredFlowFiles, excludeFlows) {
|
|
39
52
|
if (excludeFlows) {
|
|
40
53
|
return unfilteredFlowFiles.filter((file) => !excludeFlows.some((flow) => path.normalize(file).startsWith(path.normalize(path.resolve(flow)))));
|
|
41
54
|
}
|
|
42
55
|
return unfilteredFlowFiles;
|
|
43
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Load workspace configuration from config.yaml/yml if present
|
|
59
|
+
* @param input - Input directory path
|
|
60
|
+
* @param unfilteredFlowFiles - List of discovered flow files
|
|
61
|
+
* @returns Workspace configuration object (empty if no config file found)
|
|
62
|
+
*/
|
|
44
63
|
function getWorkspaceConfig(input, unfilteredFlowFiles) {
|
|
45
64
|
const possibleConfigPaths = new Set([path.join(input, 'config.yaml'), path.join(input, 'config.yml')].map((p) => path.normalize(p)));
|
|
46
65
|
const configFilePath = unfilteredFlowFiles.find((file) => possibleConfigPaths.has(path.normalize(file)));
|
|
@@ -49,6 +68,12 @@ function getWorkspaceConfig(input, unfilteredFlowFiles) {
|
|
|
49
68
|
: {};
|
|
50
69
|
return config;
|
|
51
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract DeviceCloud-specific override environment variables
|
|
73
|
+
* Looks for env vars prefixed with DEVICECLOUD_OVERRIDE_
|
|
74
|
+
* @param config - Flow configuration object
|
|
75
|
+
* @returns Object containing override key-value pairs
|
|
76
|
+
*/
|
|
52
77
|
function extractDeviceCloudOverrides(config) {
|
|
53
78
|
if (!config || !config.env || typeof config.env !== 'object') {
|
|
54
79
|
return {};
|
|
@@ -64,6 +89,22 @@ function extractDeviceCloudOverrides(config) {
|
|
|
64
89
|
}
|
|
65
90
|
return overrides;
|
|
66
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Generate execution plan for test flows
|
|
94
|
+
*
|
|
95
|
+
* Handles:
|
|
96
|
+
* - Single file or directory input
|
|
97
|
+
* - Workspace configuration (config.yaml)
|
|
98
|
+
* - Flow inclusion/exclusion patterns
|
|
99
|
+
* - Tag-based filtering (include/exclude)
|
|
100
|
+
* - Dependency resolution (runFlow, scripts, media)
|
|
101
|
+
* - Sequential execution ordering
|
|
102
|
+
* - DeviceCloud-specific overrides
|
|
103
|
+
*
|
|
104
|
+
* @param options - Plan generation options
|
|
105
|
+
* @returns Complete execution plan with flows, dependencies, and metadata
|
|
106
|
+
* @throws Error if input path doesn't exist, no flows found, or dependencies missing
|
|
107
|
+
*/
|
|
67
108
|
async function plan(options) {
|
|
68
109
|
const { input, includeTags = [], excludeTags = [], excludeFlows, configFile, debug = false, } = options;
|
|
69
110
|
const normalizedInput = path.normalize(input);
|