@qoretechnologies/qlip 0.1.3-beta.20260622084321 → 0.1.3-beta.20260709111133

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.
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/runtime/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,qBAAqB,EACrB,gBAAgB,EAEjB,MAAM,aAAa,CAAC;AA0BrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAypB1C,eAAO,MAAM,UAAU,GACrB,KAAK,gBAAgB,EACrB,gBAAgB,MAAM,GAAG,qBAAqB,EAC9C,UAAU,qBAAqB,kBA0BhC,CAAC;AAEF,KAAK,eAAe,GAAG,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAwBlE,eAAO,MAAM,qBAAqB,GAAU,KAAK,eAAe,kBAiD/D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAU,KAAK,eAAe,kBA8DhE,CAAC"}
1
+ {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/runtime/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,qBAAqB,EACrB,gBAAgB,EAEjB,MAAM,aAAa,CAAC;AA0BrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAgqB1C,eAAO,MAAM,UAAU,GACrB,KAAK,gBAAgB,EACrB,gBAAgB,MAAM,GAAG,qBAAqB,EAC9C,UAAU,qBAAqB,kBA0BhC,CAAC;AAEF,KAAK,eAAe,GAAG,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAwBlE,eAAO,MAAM,qBAAqB,GAAU,KAAK,eAAe,kBAiD/D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAU,KAAK,eAAe,kBA8DhE,CAAC"}
@@ -12,7 +12,14 @@ const ensureBrowserContext = async () => {
12
12
  // Vitest 4 deprecated '@vitest/browser/context' in favour of
13
13
  // 'vitest/browser'. Try the new module first and fall back for the
14
14
  // Vitest 2/3 consumers we still support (see VITEST_2_COMPAT).
15
- const browserModule = await import('vitest/browser').catch(() => import('@vitest/browser/context'));
15
+ // NOTE: on Vitest 2 the 'vitest/browser' specifier RESOLVES — it is the
16
+ // internal browser runner entry (startTests etc.), not the user context —
17
+ // so the import succeeds without `page`/`commands` and a catch-only
18
+ // fallback never fires, which broke every capture on Vitest 2 consumers.
19
+ // Fall back on missing exports as well as on resolution failure.
20
+ const browserModule = await import('vitest/browser')
21
+ .then((mod) => mod.page && mod.commands ? mod : import('@vitest/browser/context'))
22
+ .catch(() => import('@vitest/browser/context'));
16
23
  const { page, commands } = browserModule;
17
24
  if (!page || !commands) {
18
25
  throw new Error('[qlip] Playwright page is unavailable. Ensure Storybook Vitest addon is enabled.');
@@ -1 +1 @@
1
- {"version":3,"file":"autodetect.d.ts","sourceRoot":"","sources":["../../src/upload/autodetect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAoBH,eAAO,MAAM,gBAAgB,QAAO,MAAM,GAAG,SAW5C,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,MAAM,GAAG,SAI5C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAAO,MAAM,GAAG,SAGhD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAAO,MAAM,GAAG,SAcpD,CAAC;AA0BF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,QAAO,MAAM,EAAE,GAAG,SAgBvD,CAAC"}
1
+ {"version":3,"file":"autodetect.d.ts","sourceRoot":"","sources":["../../src/upload/autodetect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAqBH,eAAO,MAAM,gBAAgB,QAAO,MAAM,GAAG,SAW5C,CAAC;AAkCF,eAAO,MAAM,gBAAgB,QAAO,MAAM,GAAG,SAS5C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAAO,MAAM,GAAG,SAGhD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAAO,MAAM,GAAG,SAcpD,CAAC;AA0BF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,QAAO,MAAM,EAAE,GAAG,SAgBvD,CAAC"}
@@ -14,6 +14,7 @@
14
14
  * `qlip-server/design/UPLOAD.md`.
15
15
  */
16
16
  import { execFileSync } from 'node:child_process';
17
+ import { readFileSync } from 'node:fs';
17
18
  /** Server-side cap on the ancestry list (`qlip-server/design/UPLOAD.md`). */
18
19
  const MAX_ANCESTOR_COMMITS = 100;
19
20
  const gitCommand = (args) => {
@@ -43,7 +44,44 @@ export const autodetectBranch = () => {
43
44
  // Detached HEAD reports "HEAD" which isn't useful as a branch name.
44
45
  return branch === 'HEAD' ? undefined : branch;
45
46
  };
47
+ /**
48
+ * The PR head SHA from the GitHub Actions event payload, on
49
+ * `pull_request` / `pull_request_target` events only.
50
+ *
51
+ * Why this exists: on those events `GITHUB_SHA` is the EPHEMERAL merge
52
+ * commit GitHub synthesizes (`refs/pull/N/merge`), which exists in NO
53
+ * branch's history. qlip-server resolves baselines by walking git
54
+ * ancestry (`builds.commit IN <rev-list HEAD>`), so a build whose
55
+ * recorded commit is a merge SHA can never be found as an ancestor of a
56
+ * later build — the ancestry tier silently never matches PR-built
57
+ * baselines. The real branch head SHA (`pull_request.head.sha`) is the
58
+ * commit that actually produced the screenshots and the one that DOES
59
+ * appear in later ancestry. See qlip-server/design/UPLOAD.md §6.
60
+ */
61
+ const pullRequestHeadSha = () => {
62
+ const eventName = process.env['GITHUB_EVENT_NAME'];
63
+ if (eventName !== 'pull_request' && eventName !== 'pull_request_target') {
64
+ return undefined;
65
+ }
66
+ const eventPath = process.env['GITHUB_EVENT_PATH'];
67
+ if (!eventPath || eventPath.length === 0)
68
+ return undefined;
69
+ try {
70
+ const payload = JSON.parse(readFileSync(eventPath, 'utf-8'));
71
+ const sha = payload.pull_request?.head?.sha;
72
+ return sha && sha.length > 0 ? sha : undefined;
73
+ }
74
+ catch {
75
+ return undefined;
76
+ }
77
+ };
46
78
  export const autodetectCommit = () => {
79
+ // Prefer the PR head SHA over GITHUB_SHA: on pull_request events the
80
+ // latter is the ephemeral merge commit, useless for the server's
81
+ // ancestry-based baseline resolution (see pullRequestHeadSha).
82
+ const headSha = pullRequestHeadSha();
83
+ if (headSha)
84
+ return headSha;
47
85
  const sha = process.env['GITHUB_SHA'];
48
86
  if (sha && sha.length > 0)
49
87
  return sha;
@@ -17,6 +17,7 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.autodetectAncestorCommits = exports.autodetectPullRequestUrl = exports.autodetectBaseBranch = exports.autodetectCommit = exports.autodetectBranch = void 0;
19
19
  const node_child_process_1 = require("node:child_process");
20
+ const node_fs_1 = require("node:fs");
20
21
  /** Server-side cap on the ancestry list (`qlip-server/design/UPLOAD.md`). */
21
22
  const MAX_ANCESTOR_COMMITS = 100;
22
23
  const gitCommand = (args) => {
@@ -47,7 +48,44 @@ const autodetectBranch = () => {
47
48
  return branch === 'HEAD' ? undefined : branch;
48
49
  };
49
50
  exports.autodetectBranch = autodetectBranch;
51
+ /**
52
+ * The PR head SHA from the GitHub Actions event payload, on
53
+ * `pull_request` / `pull_request_target` events only.
54
+ *
55
+ * Why this exists: on those events `GITHUB_SHA` is the EPHEMERAL merge
56
+ * commit GitHub synthesizes (`refs/pull/N/merge`), which exists in NO
57
+ * branch's history. qlip-server resolves baselines by walking git
58
+ * ancestry (`builds.commit IN <rev-list HEAD>`), so a build whose
59
+ * recorded commit is a merge SHA can never be found as an ancestor of a
60
+ * later build — the ancestry tier silently never matches PR-built
61
+ * baselines. The real branch head SHA (`pull_request.head.sha`) is the
62
+ * commit that actually produced the screenshots and the one that DOES
63
+ * appear in later ancestry. See qlip-server/design/UPLOAD.md §6.
64
+ */
65
+ const pullRequestHeadSha = () => {
66
+ const eventName = process.env['GITHUB_EVENT_NAME'];
67
+ if (eventName !== 'pull_request' && eventName !== 'pull_request_target') {
68
+ return undefined;
69
+ }
70
+ const eventPath = process.env['GITHUB_EVENT_PATH'];
71
+ if (!eventPath || eventPath.length === 0)
72
+ return undefined;
73
+ try {
74
+ const payload = JSON.parse((0, node_fs_1.readFileSync)(eventPath, 'utf-8'));
75
+ const sha = payload.pull_request?.head?.sha;
76
+ return sha && sha.length > 0 ? sha : undefined;
77
+ }
78
+ catch {
79
+ return undefined;
80
+ }
81
+ };
50
82
  const autodetectCommit = () => {
83
+ // Prefer the PR head SHA over GITHUB_SHA: on pull_request events the
84
+ // latter is the ephemeral merge commit, useless for the server's
85
+ // ancestry-based baseline resolution (see pullRequestHeadSha).
86
+ const headSha = pullRequestHeadSha();
87
+ if (headSha)
88
+ return headSha;
51
89
  const sha = process.env['GITHUB_SHA'];
52
90
  if (sha && sha.length > 0)
53
91
  return sha;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qoretechnologies/qlip",
3
- "version": "0.1.3-beta.20260622084321",
3
+ "version": "0.1.3-beta.20260709111133",
4
4
  "description": "Storybook screenshot capture for the Vitest addon",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",