@pushpalsdev/cli 1.0.97 → 1.0.98

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushpalsdev/cli",
3
- "version": "1.0.97",
3
+ "version": "1.0.98",
4
4
  "description": "PushPals terminal CLI for LocalBuddy -> RemoteBuddy orchestration",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -883,13 +883,69 @@ export function shouldEnsurePlaywrightBrowserRuntime(repo: string, command: stri
883
883
  );
884
884
  }
885
885
 
886
- export function playwrightBrowserInstallArgv(): string[] {
887
- return ["bunx", "playwright", "install", "chromium"];
886
+ const PLAYWRIGHT_BROWSER_INSTALL_TARGETS = new Set([
887
+ "chromium",
888
+ "chrome",
889
+ "chrome-beta",
890
+ "chrome-dev",
891
+ "chrome-canary",
892
+ "msedge",
893
+ "msedge-beta",
894
+ "msedge-dev",
895
+ "msedge-canary",
896
+ "firefox",
897
+ "webkit",
898
+ ]);
899
+
900
+ function addPlaywrightInstallTarget(targets: Set<string>, rawValue: string): void {
901
+ const value = rawValue.trim().toLowerCase();
902
+ if (!value) return;
903
+ const normalized = value === "edge" ? "msedge" : value;
904
+ if (PLAYWRIGHT_BROWSER_INSTALL_TARGETS.has(normalized)) {
905
+ targets.add(normalized);
906
+ }
907
+ }
908
+
909
+ export function inferPlaywrightBrowserInstallTargets(repo: string, command: string): string[] {
910
+ const targets = new Set<string>(["chromium"]);
911
+ const script = resolvePackageScriptForValidationCommand(repo, command);
912
+ const scriptText = script
913
+ ? `${script.script}\n${readReferencedValidationScriptText(script.cwd, script.script)}`
914
+ : "";
915
+ const text = `${command}\n${scriptText}`;
916
+
917
+ for (const match of text.matchAll(/\bchannel\s*:\s*["'`]([^"'`]+)["'`]/gi)) {
918
+ addPlaywrightInstallTarget(targets, match[1] ?? "");
919
+ }
920
+ for (const match of text.matchAll(/\bbrowserName\s*:\s*["'`]([^"'`]+)["'`]/gi)) {
921
+ addPlaywrightInstallTarget(targets, match[1] ?? "");
922
+ }
923
+ for (const match of text.matchAll(/(?:^|\s)(?:--browser|--browser-name|--channel)[=\s]+["'`]?([A-Za-z0-9_-]+)/gi)) {
924
+ addPlaywrightInstallTarget(targets, match[1] ?? "");
925
+ }
926
+ for (const target of PLAYWRIGHT_BROWSER_INSTALL_TARGETS) {
927
+ const escaped = target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
928
+ if (new RegExp(`\\b${escaped}\\s*\\.\\s*launch\\b`, "i").test(text)) {
929
+ addPlaywrightInstallTarget(targets, target);
930
+ }
931
+ }
932
+
933
+ return Array.from(targets).sort((a, b) => {
934
+ if (a === "chromium") return -1;
935
+ if (b === "chromium") return 1;
936
+ return a.localeCompare(b);
937
+ });
938
+ }
939
+
940
+ export function playwrightBrowserInstallArgv(targets: string[] = ["chromium"]): string[] {
941
+ const installTargets = Array.from(new Set(targets.map((target) => target.trim()).filter(Boolean)));
942
+ return ["bunx", "playwright", "install", ...(installTargets.length > 0 ? installTargets : ["chromium"])];
888
943
  }
889
944
 
890
945
  async function runPlaywrightBrowserRuntimePreflight(
891
946
  repo: string,
892
947
  command: string,
948
+ targets: string[],
893
949
  timeoutMs: number,
894
950
  outputPolicy: Partial<OutputCompactionPolicy>,
895
951
  ): Promise<ValidationExecutionResult> {
@@ -898,11 +954,11 @@ async function runPlaywrightBrowserRuntimePreflight(
898
954
  return runValidationArgv(
899
955
  repo,
900
956
  command,
901
- playwrightBrowserInstallArgv(),
957
+ playwrightBrowserInstallArgv(targets),
902
958
  env,
903
959
  timeout,
904
960
  outputPolicy,
905
- `Browser runtime preflight timed out after ${timeout}ms while ensuring Playwright Chromium. Captured output is the process output emitted before PushPals terminated the installer process tree.`,
961
+ `Browser runtime preflight timed out after ${timeout}ms while ensuring Playwright browser target(s): ${targets.join(", ")}. Captured output is the process output emitted before PushPals terminated the installer process tree.`,
906
962
  );
907
963
  }
908
964
 
@@ -1772,7 +1828,7 @@ async function runDeterministicQualityGate(
1772
1828
  )}`,
1773
1829
  );
1774
1830
  }
1775
- let playwrightBrowserRuntimeReady = false;
1831
+ const playwrightBrowserRuntimeReadyTargets = new Set<string>();
1776
1832
  for (const command of commandsToRun) {
1777
1833
  const commandMissingTools = requirementsForValidationCommand(toolchainPlan, command).filter(
1778
1834
  (requirement) =>
@@ -1801,17 +1857,25 @@ async function runDeterministicQualityGate(
1801
1857
  repo,
1802
1858
  command,
1803
1859
  );
1860
+ const playwrightBrowserTargets = commandNeedsPlaywrightBrowserRuntime
1861
+ ? inferPlaywrightBrowserInstallTargets(repo, command)
1862
+ : [];
1863
+ const missingPlaywrightBrowserTargets = playwrightBrowserTargets.filter(
1864
+ (target) => !playwrightBrowserRuntimeReadyTargets.has(target),
1865
+ );
1804
1866
  let commandBrowserRuntimeEnsured =
1805
- playwrightBrowserRuntimeReady && commandNeedsPlaywrightBrowserRuntime;
1806
- if (!playwrightBrowserRuntimeReady && commandNeedsPlaywrightBrowserRuntime) {
1867
+ commandNeedsPlaywrightBrowserRuntime &&
1868
+ missingPlaywrightBrowserTargets.length === 0;
1869
+ if (missingPlaywrightBrowserTargets.length > 0) {
1807
1870
  const browserEnv = buildWorkerSandboxWritableEnv(repo);
1808
1871
  onLog?.(
1809
1872
  "stdout",
1810
- `[ValidationGate] Browser runtime preflight: ensuring Playwright Chromium for "${command}" at ${browserEnv.PLAYWRIGHT_BROWSERS_PATH ?? "(default browser cache)"}`,
1873
+ `[ValidationGate] Browser runtime preflight: ensuring Playwright browser target(s) ${missingPlaywrightBrowserTargets.join(", ")} for "${command}" at ${browserEnv.PLAYWRIGHT_BROWSERS_PATH ?? "(default browser cache)"}`,
1811
1874
  );
1812
1875
  const browserPreflight = await runPlaywrightBrowserRuntimePreflight(
1813
1876
  repo,
1814
1877
  command,
1878
+ missingPlaywrightBrowserTargets,
1815
1879
  resolveValidationCommandTimeoutMs(command, qualityValidationStepTimeoutMs),
1816
1880
  outputPolicy,
1817
1881
  );
@@ -1820,7 +1884,7 @@ async function runDeterministicQualityGate(
1820
1884
  validationRuns.push({
1821
1885
  ...browserPreflight,
1822
1886
  stderr: [
1823
- `Browser runtime preflight failed before validation command "${command}". WorkerPals could not ensure Playwright Chromium in PLAYWRIGHT_BROWSERS_PATH=${browserEnv.PLAYWRIGHT_BROWSERS_PATH ?? "(default)"}.`,
1887
+ `Browser runtime preflight failed before validation command "${command}". WorkerPals could not ensure Playwright browser target(s) ${missingPlaywrightBrowserTargets.join(", ")} in PLAYWRIGHT_BROWSERS_PATH=${browserEnv.PLAYWRIGHT_BROWSERS_PATH ?? "(default)"}.`,
1824
1888
  browserPreflight.stderr,
1825
1889
  ]
1826
1890
  .filter(Boolean)
@@ -1832,10 +1896,12 @@ async function runDeterministicQualityGate(
1832
1896
  );
1833
1897
  continue;
1834
1898
  }
1835
- playwrightBrowserRuntimeReady = true;
1899
+ for (const target of missingPlaywrightBrowserTargets) {
1900
+ playwrightBrowserRuntimeReadyTargets.add(target);
1901
+ }
1836
1902
  onLog?.(
1837
1903
  "stdout",
1838
- `[ValidationGate] Browser runtime preflight passed for "${command}"`,
1904
+ `[ValidationGate] Browser runtime preflight passed for "${command}" (${missingPlaywrightBrowserTargets.join(", ")})`,
1839
1905
  );
1840
1906
  commandBrowserRuntimeEnsured = true;
1841
1907
  }