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.
Files changed (2) hide show
  1. package/dist/index.js +21 -5
  2. 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) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-shots-cli",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "description": "CLI for git-shots visual regression platform",
5
5
  "type": "module",
6
6
  "bin": {