git-shots-cli 0.6.2 → 0.7.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/dist/index.js +21 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -85,11 +85,15 @@ async function upload(config, options) {
|
|
|
85
85
|
});
|
|
86
86
|
const localSlugs = files.map((f) => f.fileName.replace(/\.png$/, ""));
|
|
87
87
|
const allSlugs = [.../* @__PURE__ */ new Set([...options.baseManifest ?? [], ...localSlugs])];
|
|
88
|
+
if (options.force) {
|
|
89
|
+
console.log(chalk2.yellow("Force mode: bypassing content hash dedup"));
|
|
90
|
+
}
|
|
88
91
|
console.log(chalk2.dim(`Found ${files.length} screenshots`));
|
|
89
92
|
const url = `${config.server}/api/upload`;
|
|
90
93
|
const batches = chunk(files, BATCH_SIZE);
|
|
91
94
|
let totalUploaded = 0;
|
|
92
95
|
let totalSkipped = 0;
|
|
96
|
+
const totalSkippedScreens = [];
|
|
93
97
|
for (let i = 0; i < batches.length; i++) {
|
|
94
98
|
const batch = batches[i];
|
|
95
99
|
const isLastBatch = i === batches.length - 1;
|
|
@@ -98,6 +102,7 @@ async function upload(config, options) {
|
|
|
98
102
|
formData.append("branch", branch);
|
|
99
103
|
formData.append("gitSha", sha);
|
|
100
104
|
if (config.platform) formData.append("platform", config.platform);
|
|
105
|
+
if (options.force) formData.append("forceUpload", "true");
|
|
101
106
|
if (isLastBatch) {
|
|
102
107
|
formData.append("allSlugs", JSON.stringify(allSlugs));
|
|
103
108
|
}
|
|
@@ -121,6 +126,7 @@ async function upload(config, options) {
|
|
|
121
126
|
}
|
|
122
127
|
totalUploaded += data.uploaded ?? 0;
|
|
123
128
|
totalSkipped += data.skipped ?? 0;
|
|
129
|
+
if (data.skippedScreens) totalSkippedScreens.push(...data.skippedScreens);
|
|
124
130
|
if (batches.length > 1) {
|
|
125
131
|
const parts2 = [];
|
|
126
132
|
if (data.uploaded > 0) parts2.push(chalk2.green(`${data.uploaded} uploaded`));
|
|
@@ -137,6 +143,15 @@ async function upload(config, options) {
|
|
|
137
143
|
if (totalSkipped > 0) parts.push(chalk2.dim(`${totalSkipped} unchanged`));
|
|
138
144
|
console.log(`
|
|
139
145
|
${parts.join(", ") || chalk2.dim("nothing to do")}`);
|
|
146
|
+
if (totalSkippedScreens.length > 0) {
|
|
147
|
+
const MAX_DISPLAY = 20;
|
|
148
|
+
if (totalSkippedScreens.length <= MAX_DISPLAY) {
|
|
149
|
+
console.log(chalk2.dim(`Skipped: ${totalSkippedScreens.join(", ")}`));
|
|
150
|
+
} else {
|
|
151
|
+
const shown = totalSkippedScreens.slice(0, MAX_DISPLAY).join(", ");
|
|
152
|
+
console.log(chalk2.dim(`Skipped: ${shown} ... and ${totalSkippedScreens.length - MAX_DISPLAY} more`));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
140
155
|
}
|
|
141
156
|
|
|
142
157
|
// src/compare.ts
|
|
@@ -333,7 +348,7 @@ async function review(config, options) {
|
|
|
333
348
|
} catch {
|
|
334
349
|
}
|
|
335
350
|
console.log(chalk6.dim("Uploading screenshots..."));
|
|
336
|
-
await upload(config, { branch, sha, baseManifest });
|
|
351
|
+
await upload(config, { branch, sha, baseManifest, force: options.force });
|
|
337
352
|
console.log();
|
|
338
353
|
console.log(chalk6.dim("Creating review session..."));
|
|
339
354
|
const reviewUrl = `${config.server}/api/reviews`;
|
|
@@ -687,7 +702,7 @@ var require2 = createRequire(import.meta.url);
|
|
|
687
702
|
var { version } = require2("../package.json");
|
|
688
703
|
var program = new Command();
|
|
689
704
|
program.name("git-shots").description("CLI for git-shots visual regression platform").version(version);
|
|
690
|
-
program.command("upload").description("Upload screenshots to git-shots").option("-p, --project <slug>", "Project slug").option("-s, --server <url>", "Server URL").option("-d, --directory <path>", "Screenshots directory").option("-b, --branch <name>", "Git branch (auto-detected)").option("--sha <hash>", "Git SHA (auto-detected)").option("--platform <name>", "Platform tag (e.g., android, web)").action(async (options) => {
|
|
705
|
+
program.command("upload").description("Upload screenshots to git-shots").option("-p, --project <slug>", "Project slug").option("-s, --server <url>", "Server URL").option("-d, --directory <path>", "Screenshots directory").option("-b, --branch <name>", "Git branch (auto-detected)").option("--sha <hash>", "Git SHA (auto-detected)").option("--platform <name>", "Platform tag (e.g., android, web)").option("-f, --force", "Re-upload all files, bypassing content hash dedup").action(async (options) => {
|
|
691
706
|
const config = loadConfig();
|
|
692
707
|
if (options.project) config.project = options.project;
|
|
693
708
|
if (options.server) config.server = options.server;
|
|
@@ -697,7 +712,7 @@ program.command("upload").description("Upload screenshots to git-shots").option(
|
|
|
697
712
|
console.error("Error: project slug required. Use --project or .git-shots.json");
|
|
698
713
|
process.exit(1);
|
|
699
714
|
}
|
|
700
|
-
await upload(config, { branch: options.branch, sha: options.sha });
|
|
715
|
+
await upload(config, { branch: options.branch, sha: options.sha, force: options.force });
|
|
701
716
|
if (config.flows && config.flows.length > 0) {
|
|
702
717
|
await syncFlows(config);
|
|
703
718
|
}
|
|
@@ -734,7 +749,7 @@ program.command("pull-baselines").description("Download baseline screenshots fro
|
|
|
734
749
|
}
|
|
735
750
|
await pullBaselines(config, { branch: options.branch, output: options.output });
|
|
736
751
|
});
|
|
737
|
-
program.command("review").description("Upload screenshots, create review session, and poll for verdict").option("-p, --project <slug>", "Project slug").option("-s, --server <url>", "Server URL").option("-d, --directory <path>", "Screenshots directory").option("-b, --branch <name>", "Git branch (auto-detected)").option("--sha <hash>", "Git SHA (auto-detected)").option("--platform <name>", "Platform tag (e.g., android, web)").option("--open", "Open review URL in browser", true).option("--no-open", "Do not open review URL in browser").option("--poll", "Poll for verdict and exit with code", true).option("--no-poll", "Do not poll for verdict").option("--timeout <seconds>", "Polling timeout in seconds", parseInt, 300).option("--screens <patterns>", "Screen slug patterns to compare (comma-separated, supports *)").action(async (options) => {
|
|
752
|
+
program.command("review").description("Upload screenshots, create review session, and poll for verdict").option("-p, --project <slug>", "Project slug").option("-s, --server <url>", "Server URL").option("-d, --directory <path>", "Screenshots directory").option("-b, --branch <name>", "Git branch (auto-detected)").option("--sha <hash>", "Git SHA (auto-detected)").option("--platform <name>", "Platform tag (e.g., android, web)").option("--open", "Open review URL in browser", true).option("--no-open", "Do not open review URL in browser").option("--poll", "Poll for verdict and exit with code", true).option("--no-poll", "Do not poll for verdict").option("--timeout <seconds>", "Polling timeout in seconds", parseInt, 300).option("--screens <patterns>", "Screen slug patterns to compare (comma-separated, supports *)").option("-f, --force", "Re-upload all files, bypassing content hash dedup").action(async (options) => {
|
|
738
753
|
const config = loadConfig();
|
|
739
754
|
if (options.project) config.project = options.project;
|
|
740
755
|
if (options.server) config.server = options.server;
|
|
@@ -751,7 +766,8 @@ program.command("review").description("Upload screenshots, create review session
|
|
|
751
766
|
open: options.open,
|
|
752
767
|
poll: options.poll,
|
|
753
768
|
timeout: options.timeout,
|
|
754
|
-
screens
|
|
769
|
+
screens,
|
|
770
|
+
force: options.force
|
|
755
771
|
});
|
|
756
772
|
});
|
|
757
773
|
program.command("rename <old-slug> <new-slug>").description("Rename a screen slug (moves R2 objects server-side)").option("-p, --project <slug>", "Project slug").option("-s, --server <url>", "Server URL").option("--platform <name>", "Platform to disambiguate (e.g., android, web)").option("--category <value>", "Set new category (use empty string to clear)").action(async (oldSlug, newSlug, options) => {
|