@vizzly-testing/cli 0.35.3-beta.0 → 0.35.3-beta.2
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 +15 -7
- package/dist/api/client.js +20 -5
- package/dist/api/core.js +17 -3
- package/dist/cli.js +12 -52
- package/dist/commands/baselines.js +0 -7
- package/dist/commands/config-cmd.js +0 -7
- package/dist/commands/context.js +261 -308
- package/dist/commands/doctor.js +0 -8
- package/dist/commands/init.js +69 -25
- package/dist/commands/login.js +0 -13
- package/dist/commands/logout.js +0 -12
- package/dist/commands/orgs.js +0 -9
- package/dist/commands/whoami.js +0 -12
- package/dist/context/local-workspace-provider.js +276 -30
- package/dist/plugin-loader.js +1 -1
- package/dist/reporter/reporter-bundle.css +1 -1
- package/dist/reporter/reporter-bundle.iife.js +17 -17
- package/dist/server/routers/events.js +4 -4
- package/dist/tdd/services/comparison-service.js +32 -8
- package/dist/utils/visual-context-normalizers.js +12 -3
- package/package.json +13 -12
- package/skills/vizzly/SKILL.md +42 -52
- package/skills/vizzly/references/cli-context.md +50 -49
- package/skills/vizzly/references/dynamic-content.md +18 -29
- package/skills/vizzly/references/sdks.md +20 -28
- package/skills/vizzly/references/setup-ci.md +18 -42
- package/dist/config/index.js +0 -13
- package/dist/project/index.js +0 -13
- package/dist/tdd/index.js +0 -19
- package/dist/tdd/services/baseline-downloader.js +0 -151
- package/dist/tdd/services/hotspot-service.js +0 -58
- package/dist/utils/environment.js +0 -109
- package/skills/vizzly/agents/openai.yaml +0 -4
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Setup And CI
|
|
2
2
|
|
|
3
|
-
Use this reference only when the
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Use this reference only when the task includes initialization, CI changes, or
|
|
4
|
+
configuration troubleshooting. These workflows mutate files or external build
|
|
5
|
+
state.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Initialize
|
|
8
8
|
|
|
9
9
|
Initialize only with authorization:
|
|
10
10
|
|
|
@@ -12,57 +12,33 @@ Initialize only with authorization:
|
|
|
12
12
|
vizzly init
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
vizzly tdd run "<existing visual test command>" --no-open
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
or:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
vizzly tdd start --json
|
|
25
|
-
<existing visual test command>
|
|
26
|
-
vizzly tdd stop --json
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Do not run `tdd start` before `tdd run`; both own a local TDD server lifecycle.
|
|
15
|
+
Use [CLI context](cli-context.md) for local evidence and TDD lifecycle commands.
|
|
30
16
|
|
|
31
17
|
## Cloud CI
|
|
32
18
|
|
|
33
|
-
Use a project-scoped token
|
|
34
|
-
|
|
35
|
-
credentials while debugging.
|
|
36
|
-
|
|
37
|
-
Wrap the CI job's existing visual test command:
|
|
19
|
+
Use a project-scoped token from the repository's existing secret system. Never
|
|
20
|
+
print it or write it into the repository.
|
|
38
21
|
|
|
39
22
|
```bash
|
|
40
23
|
vizzly run "<existing visual test command>" --wait --json
|
|
41
24
|
```
|
|
42
25
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Give every shard in one build the same parallel ID, unique to that workflow
|
|
46
|
-
attempt. Run all shards without `--wait`, then finalize that shared ID once
|
|
47
|
-
after every shard finishes:
|
|
26
|
+
For parallel CI, give every shard the same workflow-specific parallel ID. Run
|
|
27
|
+
shards without `--wait`, then finalize once after all shards finish:
|
|
48
28
|
|
|
49
29
|
```bash
|
|
50
30
|
vizzly run "<shard test command>" --parallel-id "<shared-ci-run-id>" --json
|
|
51
31
|
vizzly finalize "<shared-ci-run-id>" --json
|
|
52
32
|
```
|
|
53
33
|
|
|
54
|
-
Do not create a different parallel ID per shard, and do not wait for a parallel
|
|
55
|
-
build to complete before it has been finalized. Use one finalizer rather than
|
|
56
|
-
having every shard race to finalize the build.
|
|
57
|
-
|
|
58
34
|
## Troubleshoot
|
|
59
35
|
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
evidence
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
36
|
+
- `vizzly doctor`: local configuration
|
|
37
|
+
- `vizzly tdd status --json`: a local daemon started by the task
|
|
38
|
+
- `vizzly status <build-id> --json`: cloud lifecycle
|
|
39
|
+
- `vizzly context build <build-id> --source cloud --agent --json`: visual
|
|
40
|
+
evidence
|
|
41
|
+
|
|
42
|
+
If screenshots are absent, verify the existing integration, the test path that
|
|
43
|
+
should capture them, and the active session. If authentication is absent,
|
|
44
|
+
report it rather than logging in unless setup is in scope.
|
package/dist/config/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Config Module - Public exports
|
|
3
|
-
*
|
|
4
|
-
* Provides functional configuration primitives:
|
|
5
|
-
* - core.js: Pure functions for merging, serialization, validation results
|
|
6
|
-
* - operations.js: Config operations with dependency injection
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// Core pure functions
|
|
10
|
-
export { buildGlobalConfigResult, buildMergedConfig, buildMergedConfigResult, buildProjectConfigResult, buildValidationFailure, buildValidationSuccess, CONFIG_DEFAULTS, deepMerge, extractCosmiconfigResult, extractEnvOverrides, getConfigFormat, READ_SCOPES, serializeConfig, serializeToJavaScript, serializeToJson, stringifyWithIndent, validateReadScope, validateWriteScope, WRITE_SCOPES } from './core.js';
|
|
11
|
-
|
|
12
|
-
// Config operations (take dependencies as parameters)
|
|
13
|
-
export { getConfig, getConfigSource, getGlobalConfig, getMergedConfig, getProjectConfig, updateConfig, updateGlobalConfig, updateProjectConfig, validateConfig, writeProjectConfigFile } from './operations.js';
|
package/dist/project/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project Module - Public exports
|
|
3
|
-
*
|
|
4
|
-
* Provides functional project management primitives:
|
|
5
|
-
* - core.js: Pure functions for validation, URL building, response extraction
|
|
6
|
-
* - operations.js: Project operations with dependency injection
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// Core pure functions
|
|
10
|
-
export { buildBuildsQueryParams, buildBuildsUrl, buildMappingResult, buildNoApiServiceError, buildNoAuthError, buildOrgHeader, buildProjectFetchError, buildProjectUrl, buildTokenCreateError, buildTokenRevokeError, buildTokensFetchError, buildTokensUrl, enrichProjectsWithOrg, extractBuilds, extractOrganizations, extractProject, extractProjects, extractToken, extractTokens, mappingsToArray, validateDirectory, validateProjectData } from './core.js';
|
|
11
|
-
|
|
12
|
-
// Project operations (take dependencies as parameters)
|
|
13
|
-
export { createMapping, createProjectToken, getMapping, getProject, getProjectWithApiToken, getProjectWithOAuth, getRecentBuilds, getRecentBuildsWithApiToken, getRecentBuildsWithOAuth, listMappings, listProjects, listProjectsWithApiToken, listProjectsWithOAuth, listProjectTokens, removeMapping, revokeProjectToken, switchProject } from './operations.js';
|
package/dist/tdd/index.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TDD Module Exports
|
|
3
|
-
*
|
|
4
|
-
* Re-exports all TDD functionality for clean imports.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export { calculateHotspotCoverage, shouldFilterAsHotspot } from './core/hotspot-coverage.js';
|
|
8
|
-
// Core pure functions
|
|
9
|
-
export { generateBaselineFilename, generateComparisonId, generateScreenshotSignature } from './core/signature.js';
|
|
10
|
-
|
|
11
|
-
// Metadata I/O
|
|
12
|
-
export { createEmptyBaselineMetadata, findScreenshotBySignature, loadBaselineMetadata, saveBaselineMetadata, upsertScreenshotInMetadata } from './metadata/baseline-metadata.js';
|
|
13
|
-
export { createHotspotCache, getHotspotForScreenshot, loadHotspotMetadata, saveHotspotMetadata } from './metadata/hotspot-metadata.js';
|
|
14
|
-
export { baselineMatchesSha, buildBaselineMetadataEntry, downloadBaselineImage, downloadBaselinesInBatches } from './services/baseline-downloader.js';
|
|
15
|
-
// Services
|
|
16
|
-
export { baselineExists, clearBaselineData, getBaselinePath, getCurrentPath, getDiffPath, initializeDirectories, promoteCurrentToBaseline, readBaseline, readCurrent, saveBaseline, saveCurrent } from './services/baseline-manager.js';
|
|
17
|
-
export { buildErrorComparison, buildFailedComparison, buildNewComparison, buildPassedComparison, compareImages, isDimensionMismatchError } from './services/comparison-service.js';
|
|
18
|
-
export { downloadHotspots } from './services/hotspot-service.js';
|
|
19
|
-
export { buildResults, calculateSummary, findComparison, findComparisonById, getErrorComparisons, getFailedComparisons, getNewComparisons, isSuccessful } from './services/result-service.js';
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Baseline Downloader
|
|
3
|
-
*
|
|
4
|
-
* Functions for downloading baseline images from the cloud API.
|
|
5
|
-
* These are lower-level utilities - orchestration happens in TddService.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { existsSync, writeFileSync } from 'node:fs';
|
|
9
|
-
import { fetchWithTimeout } from '../../utils/fetch-utils.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Download a single baseline image
|
|
13
|
-
*
|
|
14
|
-
* @param {string} url - URL to download from
|
|
15
|
-
* @param {string} destPath - Destination file path
|
|
16
|
-
* @param {Object} options - Options
|
|
17
|
-
* @param {number} options.timeout - Request timeout in ms (default: 30000)
|
|
18
|
-
* @returns {Promise<{ success: boolean, error?: string }>}
|
|
19
|
-
*/
|
|
20
|
-
export async function downloadBaselineImage(url, destPath, options = {}) {
|
|
21
|
-
let {
|
|
22
|
-
timeout = 30000
|
|
23
|
-
} = options;
|
|
24
|
-
try {
|
|
25
|
-
let response = await fetchWithTimeout(url, {
|
|
26
|
-
timeout
|
|
27
|
-
});
|
|
28
|
-
if (!response.ok) {
|
|
29
|
-
return {
|
|
30
|
-
success: false,
|
|
31
|
-
error: `HTTP ${response.status}: ${response.statusText}`
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
let buffer = Buffer.from(await response.arrayBuffer());
|
|
35
|
-
writeFileSync(destPath, buffer);
|
|
36
|
-
return {
|
|
37
|
-
success: true
|
|
38
|
-
};
|
|
39
|
-
} catch (error) {
|
|
40
|
-
return {
|
|
41
|
-
success: false,
|
|
42
|
-
error: error.message
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Check if a baseline already exists with matching SHA
|
|
49
|
-
*
|
|
50
|
-
* @param {string} filePath - Path to the baseline file
|
|
51
|
-
* @param {string} expectedSha - Expected SHA256 hash
|
|
52
|
-
* @param {Map<string, string>} shaMap - Map of filename -> sha256
|
|
53
|
-
* @returns {boolean}
|
|
54
|
-
*/
|
|
55
|
-
export function baselineMatchesSha(filePath, expectedSha, shaMap) {
|
|
56
|
-
if (!existsSync(filePath) || !expectedSha) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
let filename = filePath.split('/').pop();
|
|
60
|
-
let storedSha = shaMap.get(filename);
|
|
61
|
-
return storedSha === expectedSha;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Download multiple baselines in batches
|
|
66
|
-
*
|
|
67
|
-
* @param {Array} screenshots - Screenshots to download
|
|
68
|
-
* @param {Object} options - Options
|
|
69
|
-
* @param {string} options.baselinePath - Path to baselines directory
|
|
70
|
-
* @param {Map<string, string>} options.existingShaMap - Existing SHA map for skip logic
|
|
71
|
-
* @param {number} options.batchSize - Concurrent downloads (default: 5)
|
|
72
|
-
* @param {Function} options.onProgress - Progress callback (downloaded, skipped, errors, total)
|
|
73
|
-
* @param {Function} options.getFilePath - Function to get file path for a screenshot
|
|
74
|
-
* @returns {Promise<{ downloaded: number, skipped: number, errors: number }>}
|
|
75
|
-
*/
|
|
76
|
-
export async function downloadBaselinesInBatches(screenshots, options = {}) {
|
|
77
|
-
let {
|
|
78
|
-
existingShaMap = new Map(),
|
|
79
|
-
batchSize = 5,
|
|
80
|
-
onProgress,
|
|
81
|
-
getFilePath
|
|
82
|
-
} = options;
|
|
83
|
-
let downloaded = 0;
|
|
84
|
-
let skipped = 0;
|
|
85
|
-
let errors = 0;
|
|
86
|
-
let total = screenshots.length;
|
|
87
|
-
|
|
88
|
-
// Process in batches
|
|
89
|
-
for (let i = 0; i < screenshots.length; i += batchSize) {
|
|
90
|
-
let batch = screenshots.slice(i, i + batchSize);
|
|
91
|
-
let batchPromises = batch.map(async screenshot => {
|
|
92
|
-
let filePath = getFilePath(screenshot);
|
|
93
|
-
let url = screenshot.original_url;
|
|
94
|
-
if (!url) {
|
|
95
|
-
errors++;
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Skip if SHA matches
|
|
100
|
-
if (baselineMatchesSha(filePath, screenshot.sha256, existingShaMap)) {
|
|
101
|
-
skipped++;
|
|
102
|
-
downloaded++;
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
let result = await downloadBaselineImage(url, filePath);
|
|
106
|
-
if (result.success) {
|
|
107
|
-
downloaded++;
|
|
108
|
-
} else {
|
|
109
|
-
errors++;
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
await Promise.all(batchPromises);
|
|
113
|
-
if (onProgress) {
|
|
114
|
-
onProgress(downloaded, skipped, errors, total);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return {
|
|
118
|
-
downloaded,
|
|
119
|
-
skipped,
|
|
120
|
-
errors
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Build baseline metadata entry for a downloaded screenshot
|
|
126
|
-
*
|
|
127
|
-
* @param {Object} screenshot - Screenshot data from API
|
|
128
|
-
* @param {string} filename - Local filename
|
|
129
|
-
* @param {string} filePath - Full file path
|
|
130
|
-
* @param {Object} buildInfo - Build information
|
|
131
|
-
* @returns {Object} Metadata entry
|
|
132
|
-
*/
|
|
133
|
-
export function buildBaselineMetadataEntry(screenshot, filename, filePath, buildInfo = {}) {
|
|
134
|
-
return {
|
|
135
|
-
name: screenshot.name,
|
|
136
|
-
originalName: screenshot.name,
|
|
137
|
-
sha256: screenshot.sha256,
|
|
138
|
-
id: screenshot.id,
|
|
139
|
-
filename,
|
|
140
|
-
path: filePath,
|
|
141
|
-
browser: screenshot.browser || screenshot.metadata?.browser,
|
|
142
|
-
viewport_width: screenshot.viewport_width || screenshot.metadata?.viewport?.width || screenshot.properties?.viewport?.width,
|
|
143
|
-
originalUrl: screenshot.original_url,
|
|
144
|
-
fileSize: screenshot.file_size,
|
|
145
|
-
dimensions: screenshot.dimensions,
|
|
146
|
-
// Build info for tracking
|
|
147
|
-
buildId: buildInfo.buildId,
|
|
148
|
-
commitSha: buildInfo.commitSha,
|
|
149
|
-
approvalStatus: screenshot.approval_status
|
|
150
|
-
};
|
|
151
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hotspot Service
|
|
3
|
-
*
|
|
4
|
-
* Functions for downloading and managing hotspot data from the cloud.
|
|
5
|
-
* Hotspots identify regions that frequently change due to dynamic content.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { saveHotspotMetadata } from '../metadata/hotspot-metadata.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Download hotspots for screenshots from cloud API
|
|
12
|
-
*
|
|
13
|
-
* @param {Object} options
|
|
14
|
-
* @param {Object} options.api - ApiService instance
|
|
15
|
-
* @param {string} options.workingDir - Working directory
|
|
16
|
-
* @param {string[]} options.screenshotNames - Names of screenshots to get hotspots for
|
|
17
|
-
* @returns {Promise<{ success: boolean, count: number, regionCount: number, error?: string }>}
|
|
18
|
-
*/
|
|
19
|
-
export async function downloadHotspots(options) {
|
|
20
|
-
let {
|
|
21
|
-
api,
|
|
22
|
-
workingDir,
|
|
23
|
-
screenshotNames
|
|
24
|
-
} = options;
|
|
25
|
-
if (!screenshotNames || screenshotNames.length === 0) {
|
|
26
|
-
return {
|
|
27
|
-
success: true,
|
|
28
|
-
count: 0,
|
|
29
|
-
regionCount: 0
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
let response = await api.getHotspots(screenshotNames);
|
|
34
|
-
if (!response?.hotspots) {
|
|
35
|
-
return {
|
|
36
|
-
success: false,
|
|
37
|
-
error: 'API returned no hotspot data'
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Save hotspots to disk
|
|
42
|
-
saveHotspotMetadata(workingDir, response.hotspots, response.summary);
|
|
43
|
-
|
|
44
|
-
// Calculate stats
|
|
45
|
-
let count = Object.keys(response.hotspots).length;
|
|
46
|
-
let regionCount = Object.values(response.hotspots).reduce((sum, h) => sum + (h.regions?.length || 0), 0);
|
|
47
|
-
return {
|
|
48
|
-
success: true,
|
|
49
|
-
count,
|
|
50
|
-
regionCount
|
|
51
|
-
};
|
|
52
|
-
} catch (error) {
|
|
53
|
-
return {
|
|
54
|
-
success: false,
|
|
55
|
-
error: error.message
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Environment detection utilities for handling CI/interactive environments
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Check if running in a CI environment
|
|
7
|
-
* Based on common CI environment variables
|
|
8
|
-
* @returns {boolean} True if running in CI
|
|
9
|
-
*/
|
|
10
|
-
export function isCI() {
|
|
11
|
-
return Boolean(process.env.CI ||
|
|
12
|
-
// Generic CI flag
|
|
13
|
-
process.env.CONTINUOUS_INTEGRATION ||
|
|
14
|
-
// TravisCI, CircleCI
|
|
15
|
-
process.env.BUILD_NUMBER ||
|
|
16
|
-
// Jenkins
|
|
17
|
-
process.env.GITHUB_ACTIONS ||
|
|
18
|
-
// GitHub Actions
|
|
19
|
-
process.env.GITLAB_CI ||
|
|
20
|
-
// GitLab CI
|
|
21
|
-
process.env.CIRCLECI ||
|
|
22
|
-
// CircleCI
|
|
23
|
-
process.env.TRAVIS ||
|
|
24
|
-
// TravisCI
|
|
25
|
-
process.env.APPVEYOR ||
|
|
26
|
-
// AppVeyor
|
|
27
|
-
process.env.CODEBUILD_BUILD_ID ||
|
|
28
|
-
// AWS CodeBuild
|
|
29
|
-
process.env.TEAMCITY_VERSION ||
|
|
30
|
-
// TeamCity
|
|
31
|
-
process.env.TF_BUILD ||
|
|
32
|
-
// Azure DevOps
|
|
33
|
-
process.env.DRONE ||
|
|
34
|
-
// Drone CI
|
|
35
|
-
process.env.BITBUCKET_BUILD_NUMBER // Bitbucket Pipelines
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Check if stdout supports interactive features
|
|
41
|
-
* @returns {boolean} True if interactive features are supported
|
|
42
|
-
*/
|
|
43
|
-
export function isInteractiveTerminal() {
|
|
44
|
-
return Boolean(process.stdout.isTTY && process.stdin.isTTY && (!process.env.TERM || process.env.TERM !== 'dumb'));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Determine if interactive mode should be enabled
|
|
49
|
-
* Takes into account CI detection, TTY support, and explicit flags
|
|
50
|
-
* @param {Object} options
|
|
51
|
-
* @param {boolean} [options.noInteractive] - Explicit flag to disable interactive mode
|
|
52
|
-
* @param {boolean} [options.interactive] - Explicit flag to force interactive mode
|
|
53
|
-
* @returns {boolean} True if interactive mode should be enabled
|
|
54
|
-
*/
|
|
55
|
-
export function shouldUseInteractiveMode(options = {}) {
|
|
56
|
-
// Explicit flags take priority
|
|
57
|
-
// Commander.js sets interactive=false when --no-interactive is used
|
|
58
|
-
if (options.interactive === false) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
if (options.interactive === true) {
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Legacy support for explicit noInteractive flag
|
|
66
|
-
if (options.noInteractive === true) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Auto-detect based on environment
|
|
71
|
-
return !isCI() && isInteractiveTerminal();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Get environment type for logging/debugging
|
|
76
|
-
* @returns {string} Environment type description
|
|
77
|
-
*/
|
|
78
|
-
export function getEnvironmentType() {
|
|
79
|
-
if (isCI()) {
|
|
80
|
-
return 'CI';
|
|
81
|
-
}
|
|
82
|
-
if (!isInteractiveTerminal()) {
|
|
83
|
-
return 'non-interactive';
|
|
84
|
-
}
|
|
85
|
-
return 'interactive';
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Get detailed environment info for debugging
|
|
90
|
-
* @returns {Object} Environment details
|
|
91
|
-
*/
|
|
92
|
-
export function getEnvironmentDetails() {
|
|
93
|
-
return {
|
|
94
|
-
isCI: isCI(),
|
|
95
|
-
isInteractiveTerminal: isInteractiveTerminal(),
|
|
96
|
-
environmentType: getEnvironmentType(),
|
|
97
|
-
stdoutIsTTY: Boolean(process.stdout.isTTY),
|
|
98
|
-
stdinIsTTY: Boolean(process.stdin.isTTY),
|
|
99
|
-
ciVars: {
|
|
100
|
-
CI: process.env.CI,
|
|
101
|
-
CONTINUOUS_INTEGRATION: process.env.CONTINUOUS_INTEGRATION,
|
|
102
|
-
GITHUB_ACTIONS: process.env.GITHUB_ACTIONS,
|
|
103
|
-
GITLAB_CI: process.env.GITLAB_CI,
|
|
104
|
-
CIRCLECI: process.env.CIRCLECI,
|
|
105
|
-
TRAVIS: process.env.TRAVIS
|
|
106
|
-
},
|
|
107
|
-
termType: process.env.TERM
|
|
108
|
-
};
|
|
109
|
-
}
|