Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clients/static-site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"registry": "https://registry.npmjs.org/"
},
"peerDependencies": {
"@vizzly-testing/cli": ">=0.9.0"
"@vizzly-testing/cli": ">=0.24.0"
},
"dependencies": {
"cosmiconfig": "^9.0.0",
Expand Down
60 changes: 25 additions & 35 deletions clients/static-site/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,43 +166,33 @@ export async function run(buildPath, options = {}, context = {}) {
}
});

// Detect git info - use dynamic import to access internal utils
let gitUtils;
try {
// Try to import from the installed CLI package
let cliPath = await import.meta.resolve?.('@vizzly-testing/cli');
if (cliPath) {
gitUtils = await import(
'@vizzly-testing/cli/dist/utils/git.js'
).catch(() => null);
}
} catch {
// Fallback: try relative path if in monorepo
try {
gitUtils = await import('../../../src/utils/git.js').catch(
() => null
);
} catch {
gitUtils = null;
}
// Detect git info using CLI's plugin API (preferred) or fallback to env vars
let branch, commit, message, buildName, pullRequestNumber;

if (services.git?.detect) {
// Use CLI's git detection (correct handling of CI environments)
let gitInfo = await services.git.detect({
buildPrefix: 'Static Site',
});
branch = gitInfo.branch;
commit = gitInfo.commit;
message = gitInfo.message;
buildName = gitInfo.buildName;
pullRequestNumber = gitInfo.prNumber;
} else {
// Fallback for older CLI versions - use environment variables
logger.warn(
'⚠️ Upgrade to @vizzly-testing/cli@>=0.25.0 for improved git detection'
);
branch = process.env.VIZZLY_BRANCH || 'main';
commit = process.env.VIZZLY_COMMIT_SHA || undefined;
message = process.env.VIZZLY_COMMIT_MESSAGE || undefined;
buildName = `Static Site ${new Date().toISOString()}`;
pullRequestNumber = process.env.VIZZLY_PR_NUMBER
? parseInt(process.env.VIZZLY_PR_NUMBER, 10)
: undefined;
}

let branch = gitUtils
? await gitUtils.detectBranch()
: process.env.VIZZLY_BRANCH || 'main';
let commit = gitUtils
? await gitUtils.detectCommit()
: process.env.VIZZLY_COMMIT_SHA || undefined;
let message = gitUtils
? await gitUtils.detectCommitMessage()
: process.env.VIZZLY_COMMIT_MESSAGE || undefined;
let buildName = gitUtils
? await gitUtils.generateBuildNameWithGit('Static Site')
: `Static Site ${new Date().toISOString()}`;
let pullRequestNumber = gitUtils
? gitUtils.detectPullRequestNumber()
: process.env.VIZZLY_PR_NUMBER || undefined;

// Build options for API
let runOptions = {
port: vizzlyConfig?.server?.port || 47392,
Expand Down
2 changes: 1 addition & 1 deletion clients/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"registry": "https://registry.npmjs.org/"
},
"peerDependencies": {
"@vizzly-testing/cli": ">=0.9.0"
"@vizzly-testing/cli": ">=0.24.0"
},
"dependencies": {
"playwright-core": "^1.50.0",
Expand Down
58 changes: 23 additions & 35 deletions clients/storybook/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,43 +112,31 @@ export async function run(storybookPath, options = {}, context = {}) {
}
});

// Detect git info - use dynamic import to access internal utils
let gitUtils;
try {
// Try to import from the installed CLI package
let cliPath = await import.meta.resolve?.('@vizzly-testing/cli');
if (cliPath) {
gitUtils = await import(
'@vizzly-testing/cli/dist/utils/git.js'
).catch(() => null);
}
} catch {
// Fallback: try relative path if in monorepo
try {
gitUtils = await import('../../../src/utils/git.js').catch(
() => null
);
} catch {
gitUtils = null;
}
// Detect git info using CLI's plugin API (preferred) or fallback to env vars
let branch, commit, message, buildName, pullRequestNumber;

if (services.git?.detect) {
// Use CLI's git detection (correct handling of CI environments)
let gitInfo = await services.git.detect({ buildPrefix: 'Storybook' });
branch = gitInfo.branch;
commit = gitInfo.commit;
message = gitInfo.message;
buildName = gitInfo.buildName;
pullRequestNumber = gitInfo.prNumber;
} else {
// Fallback for older CLI versions - use environment variables
logger.warn(
'⚠️ Upgrade to @vizzly-testing/cli@>=0.25.0 for improved git detection'
);
branch = process.env.VIZZLY_BRANCH || 'main';
commit = process.env.VIZZLY_COMMIT_SHA || undefined;
message = process.env.VIZZLY_COMMIT_MESSAGE || undefined;
buildName = `Storybook ${new Date().toISOString()}`;
pullRequestNumber = process.env.VIZZLY_PR_NUMBER
? parseInt(process.env.VIZZLY_PR_NUMBER, 10)
: undefined;
}

let branch = gitUtils
? await gitUtils.detectBranch()
: process.env.VIZZLY_BRANCH || 'main';
let commit = gitUtils
? await gitUtils.detectCommit()
: process.env.VIZZLY_COMMIT_SHA || undefined;
let message = gitUtils
? await gitUtils.detectCommitMessage()
: process.env.VIZZLY_COMMIT_MESSAGE || undefined;
let buildName = gitUtils
? await gitUtils.generateBuildNameWithGit('Storybook')
: `Storybook ${new Date().toISOString()}`;
let pullRequestNumber = gitUtils
? gitUtils.detectPullRequestNumber()
: process.env.VIZZLY_PR_NUMBER || undefined;

// Build options for API
let runOptions = {
port: vizzlyConfig?.server?.port || 47392,
Expand Down
24 changes: 22 additions & 2 deletions examples/custom-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,28 @@ The `register` function receives:
1. **`program`** - Commander.js program instance for adding commands
2. **`context`** - Object containing:
- `config` - Merged Vizzly configuration
- `logger` - Component logger for consistent output
- `services` - Service container with API client, uploader, etc.
- `output` - Output utilities for consistent CLI output
- `services` - Service container (see below)

### Services API

The `services` object provides stable APIs for plugins:

```javascript
let { git, testRunner, serverManager } = services;

// Git detection (v0.25.0+) - handles CI environments correctly
let gitInfo = await git.detect({ buildPrefix: 'MyPlugin' });
// Returns: { branch, commit, message, prNumber, buildName }

// Build lifecycle
let buildId = await testRunner.createBuild(options);
await testRunner.finalizeBuild(buildId, wait, success, executionTime);

// Server control
await serverManager.start(buildId, tddMode, setBaseline);
await serverManager.stop();
```

## Creating Your Own Plugin

Expand Down
13 changes: 12 additions & 1 deletion examples/custom-plugin/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,18 @@ export default {
output.info('Checking Vizzly services...');

// Access services from the stable API
let { testRunner, serverManager } = services;
let { git, testRunner, serverManager } = services;

// Verify git detection is available (v0.25.0+)
if (git?.detect) {
output.success('git.detect is available');
let gitInfo = await git.detect({ buildPrefix: 'Example' });
output.info(` Branch: ${gitInfo.branch}`);
output.info(` Commit: ${gitInfo.commit?.slice(0, 7) || 'unknown'}`);
output.info(` PR: ${gitInfo.prNumber || 'none'}`);
} else {
output.warn('git.detect not available (requires CLI v0.25.0+)');
}

// Verify testRunner is available
if (typeof testRunner.createBuild === 'function') {
Expand Down
38 changes: 38 additions & 0 deletions src/plugin-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@
* exposed to plugins to prevent coupling to implementation details.
*/

import {
detectBranch,
detectCommit,
detectCommitMessage,
detectPullRequestNumber,
generateBuildNameWithGit,
} from './utils/git.js';

/**
* Creates a stable plugin services object from the internal services
*
* Only exposes:
* - git: Git information detection (branch, commit, PR number, etc.)
* - testRunner: Build lifecycle management (createBuild, finalizeBuild, events)
* - serverManager: Screenshot server control (start, stop)
*
Expand All @@ -23,6 +32,35 @@ export function createPluginServices(services) {
let { testRunner, serverManager } = services;

return Object.freeze({
// Git detection utilities - provides correct git info from CI environments
git: Object.freeze({
/**
* Detect git information for build creation
* Handles CI environment variables correctly (GitHub Actions, GitLab, etc.)
*
* @param {Object} [options] - Detection options
* @param {string} [options.buildPrefix] - Prefix for generated build name
* @returns {Promise<Object>} Git info: { branch, commit, message, prNumber, buildName }
*/
async detect(options = {}) {
let [branch, commit, message] = await Promise.all([
detectBranch(),
detectCommit(),
detectCommitMessage(),
]);
let prNumber = detectPullRequestNumber();
let buildName = await generateBuildNameWithGit(options.buildPrefix);

return {
branch,
commit,
message,
prNumber,
buildName,
};
},
}),

testRunner: Object.freeze({
// EventEmitter methods for build lifecycle events
once: testRunner.once.bind(testRunner),
Expand Down
Loading