happo 6.0.0 → 6.0.1

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 (31) hide show
  1. package/dist/cli/{cancelJob-D6TPCMA5.js → cancelJob-WJENZG2D.js} +3 -3
  2. package/dist/cli/{chunk-MGX62D4H.js → chunk-5TMGUI7R.js} +2 -2
  3. package/dist/cli/{chunk-HM2REEUJ.js → chunk-FJEU3Q5K.js} +3 -3
  4. package/dist/cli/{chunk-HM2REEUJ.js.map → chunk-FJEU3Q5K.js.map} +1 -1
  5. package/dist/cli/{chunk-LCJMFFCO.js → chunk-TN4ETT64.js} +2 -2
  6. package/dist/cli/createAsyncComparison-M67S4LND.js +9 -0
  7. package/dist/cli/{createAsyncReport-BCUCIDBQ.js → createAsyncReport-4JQLIRC3.js} +3 -3
  8. package/dist/cli/index.js +31 -12
  9. package/dist/cli/index.js.map +2 -2
  10. package/dist/cli/package-46H7ER65.js +7 -0
  11. package/dist/cli/{prepareSnapRequests-JY6YQY7D.js → prepareSnapRequests-3QY7GDSP.js} +3 -3
  12. package/dist/cli/{startJob-L7MU4ZEI.js → startJob-F6F63N2M.js} +3 -3
  13. package/dist/cli/{wrapper-TZQSSHAC.js → wrapper-4HPTAS7H.js} +4 -4
  14. package/dist/config/loadConfig.d.ts.map +1 -1
  15. package/dist/cypress/task.js +17 -3
  16. package/dist/cypress/task.js.map +2 -2
  17. package/dist/environment/index.d.ts.map +1 -1
  18. package/dist/playwright/index.js +17 -3
  19. package/dist/playwright/index.js.map +2 -2
  20. package/package.json +2 -2
  21. package/dist/cli/createAsyncComparison-VJ4CBNBI.js +0 -9
  22. package/dist/cli/package-SP4QZDNI.js +0 -7
  23. /package/dist/cli/{cancelJob-D6TPCMA5.js.map → cancelJob-WJENZG2D.js.map} +0 -0
  24. /package/dist/cli/{chunk-MGX62D4H.js.map → chunk-5TMGUI7R.js.map} +0 -0
  25. /package/dist/cli/{chunk-LCJMFFCO.js.map → chunk-TN4ETT64.js.map} +0 -0
  26. /package/dist/cli/{createAsyncComparison-VJ4CBNBI.js.map → createAsyncComparison-M67S4LND.js.map} +0 -0
  27. /package/dist/cli/{createAsyncReport-BCUCIDBQ.js.map → createAsyncReport-4JQLIRC3.js.map} +0 -0
  28. /package/dist/cli/{package-SP4QZDNI.js.map → package-46H7ER65.js.map} +0 -0
  29. /package/dist/cli/{prepareSnapRequests-JY6YQY7D.js.map → prepareSnapRequests-3QY7GDSP.js.map} +0 -0
  30. /package/dist/cli/{startJob-L7MU4ZEI.js.map → startJob-F6F63N2M.js.map} +0 -0
  31. /package/dist/cli/{wrapper-TZQSSHAC.js.map → wrapper-4HPTAS7H.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-MGX62D4H.js";
4
- import "./chunk-HM2REEUJ.js";
3
+ } from "./chunk-5TMGUI7R.js";
4
+ import "./chunk-FJEU3Q5K.js";
5
5
 
6
6
  // src/network/cancelJob.ts
7
7
  async function cancelJob(status, config, { beforeSha, afterSha, link, message }, logger) {
@@ -24,4 +24,4 @@ async function cancelJob(status, config, { beforeSha, afterSha, link, message },
24
24
  export {
25
25
  cancelJob as default
26
26
  };
27
- //# sourceMappingURL=cancelJob-D6TPCMA5.js.map
27
+ //# sourceMappingURL=cancelJob-WJENZG2D.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./chunk-HM2REEUJ.js";
3
+ } from "./chunk-FJEU3Q5K.js";
4
4
 
5
5
  // src/network/makeHappoAPIRequest.ts
6
6
  import { SignJWT } from "jose";
@@ -138,4 +138,4 @@ async function makeHappoAPIRequest({ url, path, method = "GET", formData, body }
138
138
  export {
139
139
  makeHappoAPIRequest
140
140
  };
141
- //# sourceMappingURL=chunk-MGX62D4H.js.map
141
+ //# sourceMappingURL=chunk-5TMGUI7R.js.map
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "happo",
4
- version: "6.0.0",
4
+ version: "6.0.1",
5
5
  description: "Visual regression testing and accessibility testing",
6
6
  license: "MIT",
7
7
  repository: {
@@ -117,7 +117,7 @@ var package_default = {
117
117
  "@types/react-dom": "^19.2.0",
118
118
  "@types/serve-handler": "^6.1.4",
119
119
  cypress: "^15.5.0",
120
- esbuild: "^0.25.10",
120
+ esbuild: "^0.27.0",
121
121
  eslint: "^9.36.0",
122
122
  "eslint-config-prettier": "^10.1.8",
123
123
  "eslint-plugin-compat": "^6.0.2",
@@ -165,4 +165,4 @@ var package_default = {
165
165
  export {
166
166
  package_default
167
167
  };
168
- //# sourceMappingURL=chunk-HM2REEUJ.js.map
168
+ //# sourceMappingURL=chunk-FJEU3Q5K.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../package.json"],
4
- "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.0.0\",\n \"description\": \"Visual regression testing and accessibility testing\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/happo/happo.git\"\n },\n \"bugs\": \"https://github.com/happo/happo/issues\",\n \"homepage\": \"https://happo.io\",\n \"bin\": {\n \"happo\": \"dist/cli/index.js\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/config/index.js\",\n \"types\": \"./dist/config/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/config/index.d.ts\",\n \"default\": \"./dist/config/index.js\"\n },\n \"./cypress\": {\n \"types\": \"./dist/cypress/index.d.ts\",\n \"default\": \"./dist/cypress/index.js\"\n },\n \"./cypress/task\": {\n \"types\": \"./dist/cypress/task.d.ts\",\n \"default\": \"./dist/cypress/task.js\"\n },\n \"./playwright\": {\n \"types\": \"./dist/playwright/index.d.ts\",\n \"default\": \"./dist/playwright/index.js\"\n },\n \"./custom\": {\n \"types\": \"./dist/custom/index.d.ts\",\n \"default\": \"./dist/custom/index.js\"\n },\n \"./storybook/addon\": {\n \"types\": \"./dist/storybook/browser/addon.d.ts\",\n \"default\": \"./dist/storybook/browser/addon.js\"\n },\n \"./storybook/decorator\": {\n \"types\": \"./dist/storybook/browser/decorator.d.ts\",\n \"default\": \"./dist/storybook/browser/decorator.js\"\n },\n \"./storybook/preset\": {\n \"types\": \"./dist/storybook/preset.d.ts\",\n \"default\": \"./dist/storybook/preset.js\"\n },\n \"./storybook/register\": {\n \"types\": \"./dist/storybook/browser/register.d.ts\",\n \"default\": \"./dist/storybook/browser/register.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"all\": \"node ./scripts/allchecks.ts\",\n \"build\": \"pnpm build:types && pnpm build:dist\",\n \"build:custom\": \"esbuild src/custom/__happo__/index.ts --bundle --format=iife --global-name=happoCustom --outfile=tmp/happo-custom/bundle.js --platform=browser --target=esnext\",\n \"build:dist\": \"./scripts/build.ts\",\n \"build:types\": \"pnpm tsc --pretty\",\n \"build:watch\": \"tsc --build --watch\",\n \"clean\": \"rm -rf dist tmp/tsc tmp/happo-custom\",\n \"lint\": \"eslint .\",\n \"prepublishOnly\": \"pnpm clean && pnpm build\",\n \"storybook:dev\": \"storybook dev --config-dir src/storybook/__tests__/storybook-app -p ${PORT:-6007}\",\n \"test\": \"node --env-file-if-exists=.env.local ./scripts/test.ts\",\n \"test:custom\": \"pnpm build:dist && pnpm build:custom && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.custom.config.ts\",\n \"test:cypress\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.cypress.config.ts e2e -- cypress run -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:cypress:open\": \"cypress open -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:playwright\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.playwright.config.ts e2e -- playwright test\",\n \"test:storybook\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.storybook.config.ts\",\n \"test:pages\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.pages.config.ts\",\n \"tsc\": \"tsc --build tsconfig.json\"\n },\n \"browserslist\": {\n \"node\": [\n \"node 22\"\n ],\n \"browser\": [\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ],\n \"isomorphic\": [\n \"node 22\",\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ]\n },\n \"prettier\": {\n \"printWidth\": 85,\n \"singleQuote\": true,\n \"trailingComma\": \"all\",\n \"arrowParens\": \"always\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.36.0\",\n \"@playwright/test\": \"^1.55.1\",\n \"@reporters/github\": \"^1.11.0\",\n \"@storybook/builder-vite\": \"^10.0.1\",\n \"@storybook/react-vite\": \"^10.0.1\",\n \"@types/async-retry\": \"^1.4.9\",\n \"@types/base64-stream\": \"^1.0.5\",\n \"@types/jsdom\": \"^27.0.0\",\n \"@types/mime-types\": \"^3.0.1\",\n \"@types/multiparty\": \"^4.2.1\",\n \"@types/node\": \"^24.9.1\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@types/serve-handler\": \"^6.1.4\",\n \"cypress\": \"^15.5.0\",\n \"esbuild\": \"^0.25.10\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-compat\": \"^6.0.2\",\n \"eslint-plugin-depend\": \"^1.3.1\",\n \"eslint-plugin-simple-import-sort\": \"^12.1.1\",\n \"eslint-plugin-unicorn\": \"^62.0.0\",\n \"jiti\": \"^2.6.0\",\n \"jsdom\": \"^27.0.0\",\n \"multiparty\": \"^4.2.3\",\n \"prettier\": \"^3.6.2\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"react-error-boundary\": \"^6.0.0\",\n \"serve-handler\": \"^6.1.6\",\n \"storybook\": \"^10.0.1\",\n \"typescript\": \"^5.9.2\",\n \"typescript-eslint\": \"^8.44.1\"\n },\n \"dependencies\": {\n \"async-retry\": \"^1.3.3\",\n \"base64-stream\": \"^1.0.0\",\n \"empathic\": \"^2.0.0\",\n \"fflate\": \"^0.8.2\",\n \"jose\": \"^6.1.0\",\n \"limit-concur\": \"^4.0.0\",\n \"mime-types\": \"^3.0.1\",\n \"srcset\": \"^5.0.2\"\n },\n \"keywords\": [\n \"accessibility\",\n \"cypress\",\n \"playwright\",\n \"regression\",\n \"storybook\",\n \"testing\",\n \"ui\",\n \"visual regression\",\n \"visual\"\n ],\n \"engines\": {\n \"node\": \">=22\"\n }\n}\n"],
4
+ "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.0.1\",\n \"description\": \"Visual regression testing and accessibility testing\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/happo/happo.git\"\n },\n \"bugs\": \"https://github.com/happo/happo/issues\",\n \"homepage\": \"https://happo.io\",\n \"bin\": {\n \"happo\": \"dist/cli/index.js\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/config/index.js\",\n \"types\": \"./dist/config/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/config/index.d.ts\",\n \"default\": \"./dist/config/index.js\"\n },\n \"./cypress\": {\n \"types\": \"./dist/cypress/index.d.ts\",\n \"default\": \"./dist/cypress/index.js\"\n },\n \"./cypress/task\": {\n \"types\": \"./dist/cypress/task.d.ts\",\n \"default\": \"./dist/cypress/task.js\"\n },\n \"./playwright\": {\n \"types\": \"./dist/playwright/index.d.ts\",\n \"default\": \"./dist/playwright/index.js\"\n },\n \"./custom\": {\n \"types\": \"./dist/custom/index.d.ts\",\n \"default\": \"./dist/custom/index.js\"\n },\n \"./storybook/addon\": {\n \"types\": \"./dist/storybook/browser/addon.d.ts\",\n \"default\": \"./dist/storybook/browser/addon.js\"\n },\n \"./storybook/decorator\": {\n \"types\": \"./dist/storybook/browser/decorator.d.ts\",\n \"default\": \"./dist/storybook/browser/decorator.js\"\n },\n \"./storybook/preset\": {\n \"types\": \"./dist/storybook/preset.d.ts\",\n \"default\": \"./dist/storybook/preset.js\"\n },\n \"./storybook/register\": {\n \"types\": \"./dist/storybook/browser/register.d.ts\",\n \"default\": \"./dist/storybook/browser/register.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"all\": \"node ./scripts/allchecks.ts\",\n \"build\": \"pnpm build:types && pnpm build:dist\",\n \"build:custom\": \"esbuild src/custom/__happo__/index.ts --bundle --format=iife --global-name=happoCustom --outfile=tmp/happo-custom/bundle.js --platform=browser --target=esnext\",\n \"build:dist\": \"./scripts/build.ts\",\n \"build:types\": \"pnpm tsc --pretty\",\n \"build:watch\": \"tsc --build --watch\",\n \"clean\": \"rm -rf dist tmp/tsc tmp/happo-custom\",\n \"lint\": \"eslint .\",\n \"prepublishOnly\": \"pnpm clean && pnpm build\",\n \"storybook:dev\": \"storybook dev --config-dir src/storybook/__tests__/storybook-app -p ${PORT:-6007}\",\n \"test\": \"node --env-file-if-exists=.env.local ./scripts/test.ts\",\n \"test:custom\": \"pnpm build:dist && pnpm build:custom && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.custom.config.ts\",\n \"test:cypress\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.cypress.config.ts e2e -- cypress run -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:cypress:open\": \"cypress open -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:playwright\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.playwright.config.ts e2e -- playwright test\",\n \"test:storybook\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.storybook.config.ts\",\n \"test:pages\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.pages.config.ts\",\n \"tsc\": \"tsc --build tsconfig.json\"\n },\n \"browserslist\": {\n \"node\": [\n \"node 22\"\n ],\n \"browser\": [\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ],\n \"isomorphic\": [\n \"node 22\",\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ]\n },\n \"prettier\": {\n \"printWidth\": 85,\n \"singleQuote\": true,\n \"trailingComma\": \"all\",\n \"arrowParens\": \"always\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.36.0\",\n \"@playwright/test\": \"^1.55.1\",\n \"@reporters/github\": \"^1.11.0\",\n \"@storybook/builder-vite\": \"^10.0.1\",\n \"@storybook/react-vite\": \"^10.0.1\",\n \"@types/async-retry\": \"^1.4.9\",\n \"@types/base64-stream\": \"^1.0.5\",\n \"@types/jsdom\": \"^27.0.0\",\n \"@types/mime-types\": \"^3.0.1\",\n \"@types/multiparty\": \"^4.2.1\",\n \"@types/node\": \"^24.9.1\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@types/serve-handler\": \"^6.1.4\",\n \"cypress\": \"^15.5.0\",\n \"esbuild\": \"^0.27.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-compat\": \"^6.0.2\",\n \"eslint-plugin-depend\": \"^1.3.1\",\n \"eslint-plugin-simple-import-sort\": \"^12.1.1\",\n \"eslint-plugin-unicorn\": \"^62.0.0\",\n \"jiti\": \"^2.6.0\",\n \"jsdom\": \"^27.0.0\",\n \"multiparty\": \"^4.2.3\",\n \"prettier\": \"^3.6.2\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"react-error-boundary\": \"^6.0.0\",\n \"serve-handler\": \"^6.1.6\",\n \"storybook\": \"^10.0.1\",\n \"typescript\": \"^5.9.2\",\n \"typescript-eslint\": \"^8.44.1\"\n },\n \"dependencies\": {\n \"async-retry\": \"^1.3.3\",\n \"base64-stream\": \"^1.0.0\",\n \"empathic\": \"^2.0.0\",\n \"fflate\": \"^0.8.2\",\n \"jose\": \"^6.1.0\",\n \"limit-concur\": \"^4.0.0\",\n \"mime-types\": \"^3.0.1\",\n \"srcset\": \"^5.0.2\"\n },\n \"keywords\": [\n \"accessibility\",\n \"cypress\",\n \"playwright\",\n \"regression\",\n \"storybook\",\n \"testing\",\n \"ui\",\n \"visual regression\",\n \"visual\"\n ],\n \"engines\": {\n \"node\": \">=22\"\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-MGX62D4H.js";
3
+ } from "./chunk-5TMGUI7R.js";
4
4
 
5
5
  // src/network/createAsyncComparison.ts
6
6
  function assertResultIsCreateAsyncComparisonResult(result) {
@@ -56,4 +56,4 @@ async function createAsyncComparison(config, {
56
56
  export {
57
57
  createAsyncComparison
58
58
  };
59
- //# sourceMappingURL=chunk-LCJMFFCO.js.map
59
+ //# sourceMappingURL=chunk-TN4ETT64.js.map
@@ -0,0 +1,9 @@
1
+ import {
2
+ createAsyncComparison
3
+ } from "./chunk-TN4ETT64.js";
4
+ import "./chunk-5TMGUI7R.js";
5
+ import "./chunk-FJEU3Q5K.js";
6
+ export {
7
+ createAsyncComparison as default
8
+ };
9
+ //# sourceMappingURL=createAsyncComparison-M67S4LND.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-MGX62D4H.js";
4
- import "./chunk-HM2REEUJ.js";
3
+ } from "./chunk-5TMGUI7R.js";
4
+ import "./chunk-FJEU3Q5K.js";
5
5
 
6
6
  // src/network/createAsyncReport.ts
7
7
  function assertResultIsCreateAsyncReportResult(result) {
@@ -37,4 +37,4 @@ async function createAsyncReport(snapRequestIds, config, { afterSha, link, messa
37
37
  export {
38
38
  createAsyncReport as default
39
39
  };
40
- //# sourceMappingURL=createAsyncReport-BCUCIDBQ.js.map
40
+ //# sourceMappingURL=createAsyncReport-4JQLIRC3.js.map
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  package_default
4
- } from "./chunk-HM2REEUJ.js";
4
+ } from "./chunk-FJEU3Q5K.js";
5
5
 
6
6
  // src/cli/index.ts
7
7
  import path2 from "node:path";
@@ -30,6 +30,18 @@ function findConfigFile() {
30
30
  }
31
31
  return configFilePath;
32
32
  }
33
+ function validateConfig(config) {
34
+ if (!config.apiKey) {
35
+ throw new Error(
36
+ "Missing `apiKey` in your Happo config. Reference yours at https://happo.io/settings"
37
+ );
38
+ }
39
+ if (!config.apiSecret) {
40
+ throw new Error(
41
+ "Missing `apiSecret` in your Happo config. Reference yours at https://happo.io/settings"
42
+ );
43
+ }
44
+ }
33
45
  async function loadConfigFile(configFilePath) {
34
46
  try {
35
47
  const stats = await fs.promises.stat(configFilePath);
@@ -62,12 +74,14 @@ async function loadConfigFile(configFilePath) {
62
74
  target.freezeAnimations = target.freezeAnimations || "last-frame";
63
75
  target.prefersReducedMotion = target.prefersReducedMotion ?? true;
64
76
  }
65
- return {
77
+ const configWithDefaults = {
66
78
  endpoint: "https://happo.io",
67
79
  githubApiUrl: "https://api.github.com",
68
80
  targets: allTargets,
69
81
  ...config.default
70
82
  };
83
+ validateConfig(configWithDefaults);
84
+ return configWithDefaults;
71
85
  }
72
86
 
73
87
  // src/environment/index.ts
@@ -353,7 +367,8 @@ async function resolveAfterSha(cliArgs, env) {
353
367
  GITHUB_EVENT_PATH,
354
368
  GITHUB_SHA,
355
369
  BUILD_SOURCEVERSION,
356
- SYSTEM_PULLREQUEST_SOURCEBRANCH
370
+ SYSTEM_PULLREQUEST_SOURCEBRANCH,
371
+ CI
357
372
  } = env;
358
373
  const sha = CIRCLE_SHA1 || TRAVIS_PULL_REQUEST_SHA || TRAVIS_COMMIT;
359
374
  if (sha) {
@@ -389,7 +404,11 @@ async function resolveAfterSha(cliArgs, env) {
389
404
  return GITHUB_SHA;
390
405
  }
391
406
  }
392
- return getHeadShaWithLocalChanges();
407
+ const headShaWithLocalChanges = getHeadShaWithLocalChanges();
408
+ if (CI) {
409
+ return headShaWithLocalChanges.headSha;
410
+ }
411
+ return headShaWithLocalChanges;
393
412
  }
394
413
  function resolveFallbackShas(cliArgs, beforeSha) {
395
414
  if (cliArgs.fallbackShas) {
@@ -743,7 +762,7 @@ function createReporter(opts = {}) {
743
762
 
744
763
  // src/cli/index.ts
745
764
  async function getVersion() {
746
- const packageJson = await import("./package-SP4QZDNI.js");
765
+ const packageJson = await import("./package-46H7ER65.js");
747
766
  return packageJson.default.version;
748
767
  }
749
768
  function parseDashdashCommandParts(rawArgs) {
@@ -933,10 +952,10 @@ async function main(rawArgs = process.argv, logger = console) {
933
952
  async function handleDefaultCommand(config, environment, logger) {
934
953
  logger.log("Running happo tests...");
935
954
  const [startJob, createAsyncComparison, createAsyncReport, prepareSnapRequests] = await Promise.all([
936
- (await import("./startJob-L7MU4ZEI.js")).default,
937
- (await import("./createAsyncComparison-VJ4CBNBI.js")).default,
938
- (await import("./createAsyncReport-BCUCIDBQ.js")).default,
939
- (await import("./prepareSnapRequests-JY6YQY7D.js")).default
955
+ (await import("./startJob-F6F63N2M.js")).default,
956
+ (await import("./createAsyncComparison-M67S4LND.js")).default,
957
+ (await import("./createAsyncReport-4JQLIRC3.js")).default,
958
+ (await import("./prepareSnapRequests-3QY7GDSP.js")).default
940
959
  ]);
941
960
  await startJob(config, environment, logger);
942
961
  try {
@@ -958,7 +977,7 @@ async function handleDefaultCommand(config, environment, logger) {
958
977
  }
959
978
  } catch (e) {
960
979
  logger.error(e instanceof Error ? e.message : String(e), e);
961
- const cancelJob = (await import("./cancelJob-D6TPCMA5.js")).default;
980
+ const cancelJob = (await import("./cancelJob-WJENZG2D.js")).default;
962
981
  await cancelJob("failure", config, environment, logger);
963
982
  process.exitCode = 1;
964
983
  return;
@@ -969,7 +988,7 @@ async function handleFinalizeCommand(config, environment, logger) {
969
988
  logger.log("Config:", config);
970
989
  logger.log("Environment:", environment);
971
990
  try {
972
- const finalizeAll = (await import("./wrapper-TZQSSHAC.js")).finalizeAll;
991
+ const finalizeAll = (await import("./wrapper-4HPTAS7H.js")).finalizeAll;
973
992
  await finalizeAll({ happoConfig: config, environment, logger });
974
993
  } catch (e) {
975
994
  logger.error(e instanceof Error ? e.message : String(e), e);
@@ -998,7 +1017,7 @@ async function handleE2ECommand(config, environment, dashdashCommandParts, confi
998
1017
  logger.log("Config:", config);
999
1018
  logger.log("Environment:", environment);
1000
1019
  logger.log("Dashdash command parts:", dashdashCommandParts);
1001
- const runWithWrapper = (await import("./wrapper-TZQSSHAC.js")).default;
1020
+ const runWithWrapper = (await import("./wrapper-4HPTAS7H.js")).default;
1002
1021
  const exitCode = await runWithWrapper(
1003
1022
  dashdashCommandParts,
1004
1023
  config,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/index.ts", "../../src/config/loadConfig.ts", "../../src/environment/index.ts", "../../src/cli/telemetry.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n\nimport path from 'node:path';\nimport { parseArgs } from 'node:util';\n\nimport type { ConfigWithDefaults } from '../config/index.ts';\nimport { findConfigFile, loadConfigFile } from '../config/loadConfig.ts';\nimport type { EnvironmentResult } from '../environment/index.ts';\nimport resolveEnvironment from '../environment/index.ts';\nimport type { Logger } from '../isomorphic/types.ts';\nimport type { Reporter } from './telemetry.ts';\nimport { createReporter } from './telemetry.ts';\n\nasync function getVersion() {\n const packageJson = await import('../../package.json', {\n with: { type: 'json' },\n });\n return packageJson.default.version;\n}\n\nfunction parseDashdashCommandParts(\n rawArgs: Array<string>,\n): Array<string> | undefined {\n const dashdashIndex = rawArgs.indexOf('--');\n if (dashdashIndex === -1) {\n return undefined;\n }\n return rawArgs.slice(dashdashIndex + 1);\n}\n\nfunction parseRawArgs(rawArgs: Array<string>) {\n const parsedArgs = parseArgs({\n args: rawArgs,\n\n options: {\n version: {\n type: 'boolean',\n short: 'v',\n },\n\n help: {\n type: 'boolean',\n short: 'h',\n },\n\n config: {\n type: 'string',\n short: 'c',\n },\n\n baseBranch: {\n type: 'string',\n },\n\n link: {\n type: 'string',\n },\n\n message: {\n type: 'string',\n },\n\n authorEmail: {\n type: 'string',\n },\n\n afterSha: {\n type: 'string',\n },\n\n beforeSha: {\n type: 'string',\n },\n\n fallbackShas: {\n type: 'string',\n },\n\n fallbackShasCount: {\n type: 'string',\n },\n\n notify: {\n type: 'string',\n },\n\n nonce: {\n type: 'string',\n },\n\n githubToken: {\n type: 'string',\n },\n },\n\n allowPositionals: true,\n });\n\n return {\n ...parsedArgs,\n dashdashCommandParts: parseDashdashCommandParts(rawArgs),\n };\n}\n\nconst helpText = `Happo ${await getVersion()}\nUsage: happo [options]\n\nCommands:\n <default> Run happo tests\n finalize Finalize happo report for Cypress/Playwright tests running in parallel\n\nOptions:\n --config Path to happo config file\n --version Show version number\n --help Show help text\n --baseBranch <branch> Base branch to use for comparison (default: 'origin/main')\n --link <url> URL to contextualize the comparison (default: auto-detected from CI environment)\n --message <message> Message to associate with the comparison (default: auto-detected from CI environment)\n --authorEmail <email> Email address of the author of the comparison (default: auto-detected from CI environment)\n --afterSha <sha> \"After\" SHA to use for comparison (default: auto-detected from CI environment, or HEAD SHA if not set)\n --beforeSha <sha> \"Before\" SHA to use for comparison (default: auto-detected from CI environment)\n --beforeShaTagMatcher <matcher> git tag matcher to use for \"before\" SHA resolution\n --fallbackShas <shas> Space-, newline- or comma-separated list of fallback shas for compare calls (default: auto-detected from CI environment)\n --fallbackShasCount <count> Number of fallback shas to use for compare calls (default: 50)\n --notify <emails> One or more (comma-separated) email addresses to notify with results\n --nonce <nonce> Nonce to use for Cypress/Playwright comparison\n --githubToken <token> GitHub token to use for posting Happo statuses as comments. Use in combination with the \\`githubApiUrl\\` configuration option. (default: auto-detected from environment)\n\nExamples:\n happo\n\n happo --config path/to/happo.config.ts\n happo --baseBranch origin/long-lived-branch\n happo --link https://github.com/happo/happo/pull/123\n happo --message \"Add new feature\"\n happo --notify me@example.com,you@example.com\n happo --nonce my-unique-nonce\n happo --githubToken {{ secrets.GITHUB_TOKEN }}\n\n happo --version\n happo --help\n\n happo -- playwright test\n\n happo finalize\n happo finalize --nonce my-unique-nonce\n `;\n\nfunction makeAbsolute(configFilePath: string): string {\n if (configFilePath.startsWith('.')) {\n return path.resolve(process.cwd(), configFilePath);\n }\n return configFilePath;\n}\n\nfunction installErrorHandlers(reporter: Reporter, logger: Logger) {\n const unhandledRejectionHandler: NodeJS.UnhandledRejectionListener = (reason) => {\n if (reason instanceof Error) {\n reporter.captureException(reason);\n logger.error(reason.stack || reason.message || String(reason));\n } else {\n reporter.captureException(reason);\n logger.error(`Unhandled rejection (non-Error value): ${String(reason)}`);\n }\n\n process.exitCode = 1;\n return;\n };\n\n const uncaughtExceptionHandler: NodeJS.UncaughtExceptionListener = (error) => {\n reporter.captureException(error);\n logger.error(error.stack || error.message || String(error));\n process.exitCode = 1;\n };\n\n process.on('unhandledRejection', unhandledRejectionHandler);\n process.on('uncaughtException', uncaughtExceptionHandler);\n\n return () => {\n process.removeListener('unhandledRejection', unhandledRejectionHandler);\n process.removeListener('uncaughtException', uncaughtExceptionHandler);\n };\n}\n\nexport async function main(\n rawArgs: Array<string> = process.argv,\n logger: Logger = console,\n): Promise<void> {\n const reporter = createReporter();\n const uninstallErrorHandlers = installErrorHandlers(reporter, logger);\n\n try {\n const args = parseRawArgs(rawArgs.slice(2));\n\n if (args.values.version) {\n // --version\n logger.log(await getVersion());\n return;\n }\n\n if (args.values.help) {\n // --help\n logger.log(helpText);\n return;\n }\n\n // Get config file path (use --config if provided, otherwise find default)\n const configFilePath = makeAbsolute(args.values.config || findConfigFile());\n const config = await loadConfigFile(configFilePath);\n const environment = await resolveEnvironment(args.values);\n\n // Handle positional arguments (commands)\n const command = args.positionals[0];\n\n if (args.dashdashCommandParts) {\n await handleE2ECommand(\n config,\n environment,\n args.dashdashCommandParts,\n configFilePath,\n logger,\n );\n return;\n }\n\n if (command === 'finalize') {\n await handleFinalizeCommand(config, environment, logger);\n return;\n }\n\n if (command === undefined) {\n await handleDefaultCommand(config, environment, logger);\n return;\n }\n\n logger.error(`Unknown command: ${command}\\n`);\n logger.error(helpText);\n process.exitCode = 1;\n } catch (error) {\n await reporter.captureException(error);\n logger.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n } finally {\n uninstallErrorHandlers();\n }\n}\n\nasync function handleDefaultCommand(\n config: ConfigWithDefaults,\n environment: EnvironmentResult,\n logger: Logger,\n): Promise<void> {\n logger.log('Running happo tests...');\n\n const [startJob, createAsyncComparison, createAsyncReport, prepareSnapRequests] =\n await Promise.all([\n (await import('../network/startJob.ts')).default,\n (await import('../network/createAsyncComparison.ts')).default,\n (await import('../network/createAsyncReport.ts')).default,\n (await import('../network/prepareSnapRequests.ts')).default,\n ]);\n\n // Tell Happo that we are about to run a job\n await startJob(config, environment, logger);\n\n try {\n // Prepare the snap requests for the job. This includes bundling static\n // assets and uploading them.\n const snapRequestIds = await prepareSnapRequests(config);\n\n // Put together a report from the snap requests.\n const asyncReport = await createAsyncReport(\n snapRequestIds,\n config,\n environment,\n logger,\n );\n\n // Create an async comparison.\n logger.log(`[HAPPO] Async report URL: ${asyncReport.url}`);\n if (environment.beforeSha !== environment.afterSha) {\n const asyncComparison = await createAsyncComparison(\n config,\n environment,\n logger,\n );\n logger.log(`[HAPPO] Async comparison URL: ${asyncComparison.compareUrl}`);\n }\n } catch (e) {\n logger.error(e instanceof Error ? e.message : String(e), e);\n const cancelJob = (await import('../network/cancelJob.ts')).default;\n await cancelJob('failure', config, environment, logger);\n process.exitCode = 1;\n return;\n }\n}\n\nasync function handleFinalizeCommand(\n config: ConfigWithDefaults,\n environment: EnvironmentResult,\n logger: Logger,\n): Promise<void> {\n logger.log('Finalizing happo report...');\n logger.log('Config:', config);\n logger.log('Environment:', environment);\n\n try {\n const finalizeAll = (await import('../e2e/wrapper.ts')).finalizeAll;\n await finalizeAll({ happoConfig: config, environment, logger });\n } catch (e) {\n logger.error(e instanceof Error ? e.message : String(e), e);\n process.exitCode = 1;\n return;\n }\n process.exitCode = 0;\n return;\n}\n\nconst E2E_INTEGRATION_TYPES = ['cypress', 'playwright'];\n\nasync function handleE2ECommand(\n config: ConfigWithDefaults,\n environment: EnvironmentResult,\n dashdashCommandParts: Array<string>,\n configFilePath: string,\n logger: Logger,\n): Promise<void> {\n if (!E2E_INTEGRATION_TYPES.includes(config.integration.type)) {\n logger.error(\n `Unsupported integration type used for e2e command: ${config.integration.type}. Supported integration types for e2e are: ${E2E_INTEGRATION_TYPES.join(', ')}`,\n );\n process.exitCode = 1;\n return;\n }\n\n if (!dashdashCommandParts || dashdashCommandParts.length === 0) {\n logger.error('Missing command for e2e action');\n logger.error(helpText);\n process.exitCode = 1;\n return;\n }\n\n logger.log('Setting up happo wrapper for Cypress and Playwright...');\n logger.log('Config:', config);\n logger.log('Environment:', environment);\n logger.log('Dashdash command parts:', dashdashCommandParts);\n\n const runWithWrapper = (await import('../e2e/wrapper.ts')).default;\n const exitCode = await runWithWrapper(\n dashdashCommandParts,\n config,\n environment,\n logger,\n configFilePath,\n );\n process.exitCode = exitCode;\n}\n\nif (import.meta.main) {\n await main();\n}\n", "import fs from 'node:fs';\n\nimport { any as findAny } from 'empathic/find';\n\nimport type { ConfigWithDefaults, TargetWithDefaults } from './index.ts';\n\nconst CONFIG_FILENAMES = [\n 'happo.config.js',\n 'happo.config.mjs',\n 'happo.config.cjs',\n 'happo.config.ts',\n 'happo.config.mts',\n 'happo.config.cts',\n];\n\nexport function findConfigFile(): string {\n if (process.env.HAPPO_CONFIG_FILE) {\n return process.env.HAPPO_CONFIG_FILE;\n }\n\n const configFilePath = findAny(CONFIG_FILENAMES, { cwd: process.cwd() });\n\n if (!configFilePath) {\n throw new Error(\n 'Happo config file could not be found. Please create a config file in the root of your project.',\n );\n }\n\n return configFilePath;\n}\n\nexport async function loadConfigFile(\n configFilePath: string,\n): Promise<ConfigWithDefaults> {\n try {\n const stats = await fs.promises.stat(configFilePath);\n if (!stats.isFile()) {\n throw new Error(`Happo config file path is not a file: ${configFilePath}`);\n }\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n throw new Error(`Happo config file could not be found: ${configFilePath}`);\n }\n\n throw error;\n }\n\n const config = await import(configFilePath);\n\n if (!config.default.targets) {\n config.default.targets = {\n chrome: {\n type: 'chrome',\n viewport: '1024x768',\n },\n };\n }\n\n if (!config.default.integration) {\n config.default.integration = {\n type: 'storybook',\n };\n }\n\n const allTargets = Object.values(config.default.targets);\n for (const target of allTargets as Array<TargetWithDefaults>) {\n target.viewport = target.viewport || '1024x768';\n target.freezeAnimations = target.freezeAnimations || 'last-frame';\n target.prefersReducedMotion = target.prefersReducedMotion ?? true;\n }\n\n return {\n endpoint: 'https://happo.io',\n githubApiUrl: 'https://api.github.com',\n targets: allTargets,\n ...config.default,\n };\n}\n", "import { spawnSync } from 'node:child_process';\nimport crypto, { randomBytes } from 'node:crypto';\nimport { readFileSync } from 'node:fs';\n\ninterface GitHubEvent {\n pull_request?: {\n html_url: string;\n title: string;\n base: {\n sha: string;\n };\n head: {\n sha: string;\n };\n };\n head_commit?: {\n url: string;\n };\n merge_group?: {\n head_sha: string;\n base_sha: string;\n };\n repository?: {\n html_url: string;\n };\n before?: string;\n after?: string;\n}\n\ninterface CLIArgs {\n baseBranch?: string;\n afterSha?: string;\n beforeSha?: string;\n message?: string;\n link?: string;\n authorEmail?: string;\n beforeShaTagMatcher?: string;\n notify?: string;\n fallbackShas?: string;\n fallbackShasCount?: string;\n nonce?: string;\n githubToken?: string;\n}\n\nexport interface EnvironmentResult {\n link: string | undefined;\n message: string | undefined;\n authorEmail: string | undefined;\n beforeSha: string;\n afterSha: string;\n nonce: string | undefined;\n debugMode: boolean;\n notify: string | undefined;\n fallbackShas: Array<string> | undefined;\n githubToken: string | undefined;\n}\n\nconst envKeys: ReadonlyArray<string> = [\n 'BUILD_REPOSITORY_URI',\n 'BUILD_SOURCEVERSION',\n 'CIRCLE_PROJECT_REPONAME',\n 'CIRCLE_PROJECT_USERNAME',\n 'CIRCLE_SHA1',\n 'CI_PULL_REQUEST',\n 'GITHUB_EVENT_PATH',\n 'GITHUB_SERVER_URL',\n 'GITHUB_SHA',\n 'HAPPO_DEBUG',\n 'SYSTEM_PULLREQUEST_PULLREQUESTID',\n 'SYSTEM_PULLREQUEST_SOURCEBRANCH',\n 'SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI',\n 'SYSTEM_PULLREQUEST_TARGETBRANCH',\n 'TRAVIS_COMMIT',\n 'TRAVIS_COMMIT_RANGE',\n 'TRAVIS_PULL_REQUEST',\n 'TRAVIS_PULL_REQUEST_SHA',\n 'TRAVIS_REPO_SLUG',\n];\n\nasync function resolveGithubEvent(GITHUB_EVENT_PATH: string): Promise<GitHubEvent> {\n try {\n const fs = await import('node:fs/promises');\n const content = await fs.readFile(GITHUB_EVENT_PATH, 'utf8');\n return JSON.parse(content);\n } catch (e) {\n throw new Error(\n `Failed to load GitHub event from the GITHUB_EVENT_PATH environment variable: ${JSON.stringify(GITHUB_EVENT_PATH)}`,\n { cause: e },\n );\n }\n}\n\nasync function resolveLink(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n): Promise<string | undefined> {\n if (cliArgs.link) {\n // Validate the link\n let parsed: URL;\n try {\n parsed = new URL(cliArgs.link);\n } catch (e) {\n throw new TypeError(\n `link must be a valid http/https URL. Invalid URL: '${cliArgs.link}'`,\n { cause: e },\n );\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new TypeError(\n `link must be a valid http/https URL. Invalid protocol: '${parsed.protocol}' (from '${cliArgs.link}')`,\n );\n }\n\n return cliArgs.link;\n }\n\n const {\n BUILD_REPOSITORY_URI,\n BUILD_SOURCEVERSION,\n\n // https://circleci.com/docs/reference/variables/\n CIRCLE_PROJECT_REPONAME,\n CIRCLE_PROJECT_USERNAME,\n CIRCLE_PULL_REQUEST,\n CIRCLE_SHA1,\n\n CI_PULL_REQUEST,\n\n // https://docs.github.com/en/actions/reference/workflows-and-actions/variables#default-environment-variables\n GITHUB_EVENT_PATH,\n GITHUB_SHA,\n\n SYSTEM_PULLREQUEST_PULLREQUESTID,\n SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI,\n\n // https://docs.travis-ci.com/user/environment-variables/#default-environment-variables\n TRAVIS_COMMIT,\n TRAVIS_PULL_REQUEST,\n TRAVIS_REPO_SLUG,\n } = env;\n\n if (CI_PULL_REQUEST) {\n // Circle CI\n return CI_PULL_REQUEST;\n }\n\n if (GITHUB_EVENT_PATH) {\n const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n\n if (ghEvent.pull_request) {\n return ghEvent.pull_request.html_url;\n }\n if (ghEvent.head_commit) {\n return ghEvent.head_commit.url;\n }\n if (ghEvent.merge_group && ghEvent.repository) {\n return `${ghEvent.repository.html_url}/commit/${ghEvent.merge_group.head_sha}`;\n }\n if (GITHUB_SHA && ghEvent.repository) {\n return `${ghEvent.repository.html_url}/commit/${GITHUB_SHA}`;\n }\n }\n\n if (SYSTEM_PULLREQUEST_PULLREQUESTID && SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI) {\n return `${SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI}/pullrequest/${SYSTEM_PULLREQUEST_PULLREQUESTID}`.replace(\n /[^/]+@/,\n '',\n );\n }\n\n if (BUILD_REPOSITORY_URI && BUILD_SOURCEVERSION) {\n return `${BUILD_REPOSITORY_URI}/commit/${BUILD_SOURCEVERSION}`.replace(\n /[^/]+@/,\n '',\n );\n }\n\n const githubBase = 'https://github.com';\n\n if (TRAVIS_REPO_SLUG && TRAVIS_PULL_REQUEST) {\n return `${githubBase}/${TRAVIS_REPO_SLUG}/pull/${TRAVIS_PULL_REQUEST}`;\n }\n\n if (TRAVIS_REPO_SLUG && TRAVIS_COMMIT) {\n return `${githubBase}/${TRAVIS_REPO_SLUG}/commit/${TRAVIS_COMMIT}`;\n }\n\n if (CIRCLE_PULL_REQUEST) {\n return CIRCLE_PULL_REQUEST;\n }\n\n if (CIRCLE_PROJECT_USERNAME && CIRCLE_PROJECT_REPONAME && CIRCLE_SHA1) {\n return `${githubBase}/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}`;\n }\n\n return undefined;\n}\n\nasync function resolveAuthorEmail(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n): Promise<string | undefined> {\n if (cliArgs.authorEmail) {\n return cliArgs.authorEmail;\n }\n\n const { GITHUB_EVENT_PATH } = env;\n\n if (GITHUB_EVENT_PATH) {\n // const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n // TODO: do something with the github event\n }\n\n const res = spawnSync('git', ['show', '-s', '--format=%ae'], {\n encoding: 'utf8',\n });\n\n if (res.status !== 0) {\n return undefined;\n }\n\n return res.stdout.trim();\n}\n\nasync function resolveMessage(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n afterSha: string,\n): Promise<string | undefined> {\n if (cliArgs.message) {\n return cliArgs.message;\n }\n\n const { GITHUB_EVENT_PATH } = env;\n\n if (GITHUB_EVENT_PATH) {\n const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n if (ghEvent.pull_request) {\n return ghEvent.pull_request.title;\n }\n }\n\n const res = spawnSync('git', ['log', '-1', '--pretty=%s', afterSha], {\n encoding: 'utf8',\n });\n\n if (res.status !== 0) {\n return undefined;\n }\n\n const message = res.stdout.split('\\n')[0];\n\n if (!message) {\n return undefined;\n }\n\n return message;\n}\n\nfunction resolveShaFromTagMatcher(tagMatcher: string): string | undefined {\n const res = spawnSync(\n 'git',\n ['tag', '--list', tagMatcher, '--sort', 'refname', '--no-contains'],\n {\n encoding: 'utf8',\n },\n );\n\n if (res.status !== 0) {\n throw new Error(\n `Failed to list git tags when matching against --beforeShaTagMatcher '${tagMatcher}'. Error: ${res.stderr}`,\n );\n }\n\n const rawAllTags = res.stdout.trim();\n if (!rawAllTags.length) {\n return undefined;\n }\n\n const allTags = rawAllTags.split('\\n');\n const tag = allTags.at(-1);\n\n if (!tag) {\n throw new Error('No tag found matching the pattern');\n }\n\n const commitRes = spawnSync('git', ['rev-list', '-n', '1', tag], {\n encoding: 'utf8',\n });\n\n if (commitRes.status !== 0) {\n throw new Error(\n `Failed to resolve commit sha from tag \"${tag}\". Error: ${res.stderr}`,\n );\n }\n\n return commitRes.stdout.trim();\n}\n\nasync function resolveBeforeSha(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n afterSha: string,\n): Promise<string | undefined> {\n if (cliArgs.beforeSha) {\n return cliArgs.beforeSha;\n }\n\n if (cliArgs.beforeShaTagMatcher) {\n const resolvedSha = resolveShaFromTagMatcher(cliArgs.beforeShaTagMatcher);\n if (resolvedSha) {\n return resolvedSha;\n }\n }\n\n const { TRAVIS_COMMIT_RANGE, GITHUB_EVENT_PATH, SYSTEM_PULLREQUEST_TARGETBRANCH } =\n env;\n\n if (GITHUB_EVENT_PATH) {\n const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n if (ghEvent.pull_request) {\n return ghEvent.pull_request.base.sha;\n }\n if (ghEvent.merge_group) {\n return ghEvent.merge_group.base_sha;\n }\n return ghEvent.before;\n }\n\n if (TRAVIS_COMMIT_RANGE) {\n const [first] = TRAVIS_COMMIT_RANGE.split('...');\n return first;\n }\n\n let baseAzureBranch;\n if (SYSTEM_PULLREQUEST_TARGETBRANCH) {\n baseAzureBranch = [\n 'origin',\n SYSTEM_PULLREQUEST_TARGETBRANCH.split('/').toReversed()[0],\n ].join('/');\n }\n\n const baseBranch = cliArgs.baseBranch || baseAzureBranch || 'origin/main';\n const res = spawnSync('git', ['merge-base', baseBranch, afterSha], {\n encoding: 'utf8',\n });\n if (res.status !== 0) {\n console.error(`[HAPPO] Ignored error when resolving base commit: ${res.stderr}`);\n return undefined;\n }\n return res.stdout.split('\\n')[0];\n}\n\nfunction getHeadShaWithLocalChanges(): {\n headSha: string;\n headShaWithLocalChanges: string;\n} {\n const randomSha = randomBytes(20).toString('hex');\n // Get the HEAD sha from the git repo, or if we have local changes, add them to the sha\n const res = spawnSync('git', ['rev-parse', 'HEAD'], {\n encoding: 'utf8',\n });\n if (res.status !== 0) {\n return { headSha: randomSha, headShaWithLocalChanges: randomSha };\n }\n const headSha = res.stdout.split('\\n')[0];\n if (!headSha) {\n return { headSha: randomSha, headShaWithLocalChanges: randomSha };\n }\n\n // Check for local changes\n const diffRes = spawnSync('git', ['diff', 'HEAD'], {\n encoding: 'utf8',\n });\n\n // If git diff fails, return HEAD sha\n if (diffRes.status !== 0) {\n return { headSha, headShaWithLocalChanges: headSha };\n }\n\n const lsRes = spawnSync('git', ['ls-files', '--other', '--exclude-standard'], {\n encoding: 'utf8',\n });\n\n if (lsRes.status !== 0) {\n return { headSha, headShaWithLocalChanges: headSha };\n }\n\n const localChanges = [diffRes.stdout.trim(), lsRes.stdout.trim()];\n\n // Get contents of untracked files\n const untrackedFiles = lsRes.stdout\n .trim()\n .split('\\n')\n .filter((file) => file.trim());\n\n for (const file of untrackedFiles) {\n try {\n const content = readFileSync(file, 'utf8');\n localChanges.push(content);\n } catch {\n // If we can't read the file, include just the filename\n localChanges.push(`${file}:<unreadable>`);\n }\n }\n\n const allChanges = localChanges.join('');\n\n if (!allChanges.trim()) {\n return { headSha, headShaWithLocalChanges: headSha };\n }\n\n // If there are local changes, create a hash that includes both HEAD and the changes\n const headShaWithLocalChanges = crypto\n .createHash('sha256')\n .update(headSha)\n .update(allChanges)\n .digest('hex')\n .slice(0, 40);\n\n return { headSha, headShaWithLocalChanges };\n}\n\nasync function resolveAfterSha(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n): Promise<string | { headSha: string; headShaWithLocalChanges: string }> {\n if (cliArgs.afterSha) {\n return cliArgs.afterSha;\n }\n\n const {\n CIRCLE_SHA1,\n TRAVIS_PULL_REQUEST_SHA,\n TRAVIS_COMMIT,\n GITHUB_EVENT_PATH,\n GITHUB_SHA,\n BUILD_SOURCEVERSION,\n SYSTEM_PULLREQUEST_SOURCEBRANCH,\n } = env;\n\n const sha = CIRCLE_SHA1 || TRAVIS_PULL_REQUEST_SHA || TRAVIS_COMMIT;\n\n if (sha) {\n return sha;\n }\n\n if (SYSTEM_PULLREQUEST_SOURCEBRANCH) {\n // azure pull request\n const rawBranchName = SYSTEM_PULLREQUEST_SOURCEBRANCH.split('/').toReversed()[0];\n const res = spawnSync('git', ['rev-parse', `origin/${rawBranchName}`], {\n encoding: 'utf8',\n });\n if (res.status === 0 && res.stdout) {\n const sha = res.stdout.split('\\n')[0];\n if (sha) {\n return sha;\n }\n }\n }\n if (BUILD_SOURCEVERSION) {\n // azure master job\n return BUILD_SOURCEVERSION;\n }\n if (GITHUB_EVENT_PATH) {\n const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n if (ghEvent.pull_request) {\n return ghEvent.pull_request.head.sha;\n }\n if (ghEvent.merge_group) {\n return ghEvent.merge_group.head_sha;\n }\n if (ghEvent.after) {\n return ghEvent.after;\n }\n if (GITHUB_SHA) {\n return GITHUB_SHA;\n }\n }\n return getHeadShaWithLocalChanges();\n}\n\nfunction resolveFallbackShas(\n cliArgs: CLIArgs,\n beforeSha: string | undefined,\n): Array<string> | undefined {\n if (cliArgs.fallbackShas) {\n return cliArgs.fallbackShas.split(/[,\\s]+/).filter(Boolean);\n }\n\n const fallbackShasCount = cliArgs.fallbackShasCount\n ? Number.parseInt(cliArgs.fallbackShasCount, 10)\n : 50;\n\n if (Number.isNaN(fallbackShasCount)) {\n throw new TypeError(\n `fallbackShasCount must be a number. Invalid value: '${cliArgs.fallbackShasCount}'`,\n );\n }\n\n const res = spawnSync(\n 'git',\n [\n 'log',\n '--format=%H',\n '--first-parent',\n `--max-count=${fallbackShasCount}`,\n `${beforeSha}^`,\n ],\n {\n encoding: 'utf8',\n },\n );\n\n if (res.status !== 0) {\n return undefined;\n }\n\n return res.stdout.split('\\n').filter(Boolean);\n}\n\nfunction getRawEnv(\n env: Record<string, string | undefined>,\n): Record<string, string | undefined> {\n const res: Record<string, string | undefined> = {};\n for (const key of envKeys) {\n res[key] = env[key];\n }\n return res;\n}\n\nexport default async function resolveEnvironment(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined> = process.env,\n): Promise<EnvironmentResult> {\n const debugMode = !!env.HAPPO_DEBUG;\n const afterSha = await resolveAfterSha(cliArgs, env);\n\n const realAfterSha = typeof afterSha === 'string' ? afterSha : afterSha.headSha;\n const afterShaWithLocalChanges =\n typeof afterSha === 'string' ? afterSha : afterSha.headShaWithLocalChanges;\n\n // Resolve the before SHA with the true HEAD SHA\n const [beforeSha, link, authorEmail, message] = await Promise.all([\n resolveBeforeSha(cliArgs, env, realAfterSha),\n resolveLink(cliArgs, env),\n resolveAuthorEmail(cliArgs, env),\n\n // Resolve message with the SHA that includes local changes\n resolveMessage(cliArgs, env, afterShaWithLocalChanges),\n ]);\n\n const nonNullBeforeSha = beforeSha || afterShaWithLocalChanges;\n\n const result = {\n link,\n authorEmail,\n message,\n beforeSha: nonNullBeforeSha,\n afterSha: afterShaWithLocalChanges,\n nonce: cliArgs.nonce,\n debugMode,\n notify: cliArgs.notify,\n fallbackShas: resolveFallbackShas(cliArgs, nonNullBeforeSha),\n githubToken: cliArgs.githubToken,\n };\n\n if (debugMode) {\n console.log('[HAPPO] Raw environment', getRawEnv(env));\n console.log('[HAPPO] Resolved environment', result);\n }\n\n return result;\n}\n", "import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { createInterface } from 'node:readline';\n\nimport { up as findPackage } from 'empathic/package';\n\nimport pkg from '../../package.json' with { type: 'json' };\n\n/**\n * Happo's PUBLIC DSN. Safe to ship.\n */\nconst SENTRY_DSN =\n 'https://3a495ff2101313edb024de73b005398f@o108341.ingest.us.sentry.io/4510341337645056';\n\nconst MAX_STACK_FRAMES = 50;\nconst MAX_FUNCTION_NAME_LENGTH = 120;\n\ntype CI =\n | 'github'\n | 'circleci'\n | 'travis'\n | 'azure'\n | 'buildkite'\n | 'jenkins'\n | 'gitlab'\n | 'bitbucket'\n | 'appveyor'\n | 'drone'\n | 'ci'\n | 'unknown';\n\ntype ErrorPayload = {\n pkg: {\n name: string;\n version: string;\n };\n\n error: {\n name: string;\n message: string;\n stack?: string;\n };\n\n env: string;\n\n /** Detected CI vendor if any */\n ci: CI;\n\n nodeVersion: string;\n platform: string;\n};\n\nexport type ReporterOptions = {\n maxPerMinute?: number; // default 10\n env?: string;\n};\n\nexport interface Reporter {\n captureException(e: unknown): Promise<void>;\n}\n\nexport function detectCI(env: Record<string, string | undefined> = process.env): CI {\n if (env.GITHUB_ACTIONS) {\n return 'github';\n }\n\n if (env.CIRCLECI) {\n return 'circleci';\n }\n\n if (env.TRAVIS) {\n return 'travis';\n }\n\n if (env.TF_BUILD) {\n return 'azure';\n }\n\n if (env.BUILDKITE) {\n return 'buildkite';\n }\n\n if (env.JENKINS_URL) {\n return 'jenkins';\n }\n\n if (env.GITLAB_CI) {\n return 'gitlab';\n }\n\n if (env.BITBUCKET_BUILD_NUMBER) {\n return 'bitbucket';\n }\n\n if (env.APPVEYOR) {\n return 'appveyor';\n }\n\n if (env.DRONE) {\n return 'drone';\n }\n\n if (env.CI) {\n return 'ci';\n }\n\n return 'unknown';\n}\n\nexport function parseDsn(dsn: string): {\n host: string;\n projectId: string;\n key: string;\n protocol: string;\n} | null {\n try {\n // https://{PUBLIC_KEY}@{host}/{project_id}\n const u = new URL(dsn);\n const projectId = u.pathname.replace(/^\\//, '');\n const key = u.username; // public key\n const host = u.host; // includes subdomain + port\n return {\n host,\n projectId,\n key,\n protocol: u.protocol.replace(':', ''),\n };\n } catch {\n return null;\n }\n}\n\nasync function sendToSentry(payload: ErrorPayload) {\n const dsn = parseDsn(SENTRY_DSN);\n\n if (!dsn) {\n return;\n }\n\n // Sentry envelope: https://develop.sentry.dev/sdk/envelopes/\n const now = Date.now();\n\n // Hexadecimal string representing a uuid4 value. The length is exactly 32\n // characters. Dashes are not allowed. Has to be lowercase.\n const eventId = crypto.randomUUID().replaceAll('-', '');\n\n const url = `https://${dsn.host}/api/${dsn.projectId}/envelope/`;\n\n const httpHeaders = {\n 'content-type': 'application/x-sentry-envelope',\n 'x-sentry-auth': [\n 'Sentry sentry_version=7',\n `sentry_key=${dsn.key}`,\n `sentry_client=${pkg.name}@${pkg.version}`,\n ].join(', '),\n };\n\n const memoryInfo = process.memoryUsage();\n\n // Minimal event; we keep fields lean & sanitized\n // https://develop.sentry.dev/sdk/data-model/event-payloads/#required-attributes\n const event = {\n event_id: eventId,\n\n // RFC 3339 format\n timestamp: new Date(now).toISOString(),\n\n // A string representing the platform the SDK is submitting from. This will\n // be used by the Sentry interface to customize various components in the\n // interface.\n platform: 'node',\n\n // Possible values: fatal, error, warning, info, debug\n level: 'error',\n\n logger: 'happo.telemetry.cli',\n\n environment: payload.env ?? 'unknown',\n\n // Release versions must be unique across all projects in the organization.\n release: `${payload.pkg.name}@${payload.pkg.version}`,\n\n tags: {\n ci: payload.ci ?? '',\n },\n\n contexts: {\n runtime: {\n type: 'runtime',\n name: 'node',\n version: payload.nodeVersion ?? '',\n },\n os: {\n type: 'os',\n name: payload.platform ?? '',\n },\n memory_info: {\n type: 'memory_info',\n ...memoryInfo,\n },\n },\n\n exception: {\n values: [\n {\n type: payload.error.name || 'Error',\n value: payload.error.message,\n\n // https://develop.sentry.dev/sdk/data-model/event-payloads/stacktrace/\n stacktrace: payload.error.stack\n ? {\n frames: await parseFrames(payload.error.stack),\n }\n : undefined,\n },\n ],\n },\n };\n\n /**\n * Envelope is ndjson-like chunks\n *\n * Envelope = Headers { \"\\n\" Item } [ \"\\n\" ] ;\n * Item = Headers \"\\n\" Payload ;\n * Payload = { * } ;\n *\n * @see https://develop.sentry.dev/sdk/data-model/envelopes/#headers\n */\n const envelopeHeader = JSON.stringify({\n event_id: eventId,\n dsn: SENTRY_DSN,\n sent_at: new Date(now).toISOString(),\n });\n\n // https://develop.sentry.dev/sdk/data-model/envelopes/#items\n const item = JSON.stringify(event);\n const itemHeader = JSON.stringify({ type: 'event', length: item.length });\n\n const body = [envelopeHeader, itemHeader, item].join('\\n');\n\n try {\n await fetch(url, { method: 'POST', headers: httpHeaders, body });\n } catch {\n // swallow; never throw in library code\n }\n}\n\ninterface SentryFrame {\n function: string;\n raw_function: string;\n abs_path: string | undefined;\n filename: string | undefined;\n lineno: number | undefined;\n colno: number | undefined;\n context_line?: string;\n pre_context?: Array<string>;\n post_context?: Array<string>;\n}\n\n/**\n * Get the package root directory\n */\nfunction getPackageRoot(): string {\n const packageJsonPath = findPackage({ cwd: import.meta.dirname });\n\n if (!packageJsonPath) {\n // Fallback to relative path if empathic can't find it\n return path.resolve(import.meta.dirname, '../..');\n }\n\n return path.dirname(packageJsonPath);\n}\n\n/**\n * Check if a file path is part of this package\n */\nfunction isFileInThisPackage(filePath: string): boolean {\n // Skip node: internal modules\n if (filePath.startsWith('node:')) {\n return false;\n }\n\n try {\n const packageRoot = getPackageRoot();\n // Remove file:// prefix if present\n const cleanPath = filePath.replace(/^file:\\/\\//, '');\n const resolvedPath = path.resolve(cleanPath);\n return resolvedPath.startsWith(packageRoot + path.sep);\n } catch {\n return false;\n }\n}\n\n/**\n * Read context lines from a source file around a given line number\n * Only reads files that are part of this package\n */\nasync function readContextLines(\n filePath: string,\n lineNumber: number,\n contextLines: number = 5,\n): Promise<{\n context_line?: string;\n pre_context?: Array<string>;\n post_context?: Array<string>;\n}> {\n // Only read context for files in this package. This is to avoid reading\n // context from external files that may contain sensitive information.\n if (!isFileInThisPackage(filePath)) {\n return {};\n }\n\n try {\n // Remove file:// prefix if present\n const cleanPath = filePath.replace(/^file:\\/\\//, '');\n\n // Line numbers are 1-indexed in stack traces, but arrays are 0-indexed\n const lineIndex = lineNumber - 1;\n\n if (lineIndex < 0) {\n return {};\n }\n\n const startLine = Math.max(0, lineIndex - contextLines);\n const endLine = lineIndex + contextLines + 1;\n\n const pre_context: Array<string> = [];\n let context_line: string | undefined;\n const post_context: Array<string> = [];\n\n const fileStream = fs.createReadStream(cleanPath, { encoding: 'utf8' });\n const rl = createInterface({\n input: fileStream,\n crlfDelay: Infinity,\n });\n\n let currentLine = 0;\n\n for await (const line of rl) {\n if (currentLine < startLine) {\n // Skip lines before our context window\n currentLine++;\n continue;\n }\n\n if (currentLine === lineIndex) {\n context_line = line;\n } else if (currentLine < lineIndex) {\n pre_context.push(line);\n } else if (currentLine < endLine) {\n post_context.push(line);\n } else {\n // We've read all the lines we need\n break;\n }\n\n currentLine++;\n }\n\n // Check if we found the target line\n if (context_line === undefined) {\n return {};\n }\n\n const result: {\n context_line: string;\n pre_context?: Array<string>;\n post_context?: Array<string>;\n } = {\n context_line,\n };\n\n if (pre_context.length > 0) {\n result.pre_context = pre_context;\n }\n\n if (post_context.length > 0) {\n result.post_context = post_context;\n }\n\n return result;\n } catch {\n // File might not exist, might not be readable, etc. Best-effort only.\n return {};\n }\n}\n\n/**\n * Convert an error stack to Sentry frames (best-effort)\n */\nexport async function parseFrames(\n stack: string,\n cwd: string = process.cwd(),\n): Promise<Array<SentryFrame>> {\n // Node stack lines like: \" at func (file:///absolute/path/to/file.js:10:5)\"\n const stackLines = stack.split('\\n').slice(0, MAX_STACK_FRAMES);\n\n const frames = [];\n\n for (const stackLine of stackLines) {\n const match = stackLine.match(\n /\\s+at\\s+(?<functionName>.*?)\\s+\\((?:file:\\/\\/)?(?<absPath>.+?):(?<lineno>\\d+):(?<colno>\\d+)\\)/,\n );\n\n if (!match || !match.groups) {\n // We didn't match a stack line, so skip it. This could cause some stack\n // lines to be dropped.\n continue;\n }\n\n const rawAbsPath = match.groups.absPath ?? '';\n\n const absPath = rawAbsPath.startsWith('node:')\n ? rawAbsPath\n : path.relative(cwd, rawAbsPath);\n const filename = rawAbsPath.startsWith('node:')\n ? rawAbsPath\n : path.basename(rawAbsPath);\n\n const functionName = match.groups.functionName ?? '';\n\n const lineno = match.groups.lineno\n ? Number.parseInt(match.groups.lineno, 10)\n : undefined;\n\n // Read context lines from the source file (only for package files)\n const context =\n rawAbsPath && lineno ? await readContextLines(rawAbsPath, lineno) : {};\n\n // https://develop.sentry.dev/sdk/data-model/event-payloads/stacktrace/#frame-attributes\n const frame: SentryFrame = {\n function: functionName.slice(0, MAX_FUNCTION_NAME_LENGTH),\n raw_function: functionName,\n\n abs_path: absPath,\n filename,\n\n lineno,\n\n colno: match.groups.colno\n ? Number.parseInt(match.groups.colno, 10)\n : undefined,\n\n ...context,\n };\n\n frames.push(frame);\n }\n\n // Sentry expects most recent frame last\n return frames.toReversed();\n}\n\n/**\n * Create a reporter with rate limiting\n */\nexport function createReporter(opts: ReporterOptions = {}): Reporter {\n const maxPerMinute = Math.max(1, opts.maxPerMinute ?? 10);\n let sentThisMinute = 0;\n let minuteTick = Date.now();\n\n function isRateLimitExceeded(): boolean {\n const now = Date.now();\n\n if (now - minuteTick >= 60_000) {\n minuteTick = now;\n sentThisMinute = 0;\n }\n\n if (sentThisMinute >= maxPerMinute) {\n return true;\n }\n\n sentThisMinute++;\n\n return false;\n }\n\n const ci = detectCI(process.env);\n const nodeVersion = process.version;\n const platform = process.platform;\n\n return {\n async captureException(e: unknown) {\n if (isRateLimitExceeded()) {\n return;\n }\n\n const err = e instanceof Error ? e : new Error(String(e));\n const message = err.message ?? 'Error';\n const stack = err.stack;\n\n const payload: ErrorPayload = {\n pkg,\n env: opts.env ?? process.env.NODE_ENV ?? 'unknown',\n ci,\n nodeVersion,\n platform,\n\n error: {\n name: err.name || 'Error',\n message,\n stack: stack ?? '',\n },\n };\n\n await sendToSentry(payload);\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["#!/usr/bin/env node\n\nimport path from 'node:path';\nimport { parseArgs } from 'node:util';\n\nimport type { ConfigWithDefaults } from '../config/index.ts';\nimport { findConfigFile, loadConfigFile } from '../config/loadConfig.ts';\nimport type { EnvironmentResult } from '../environment/index.ts';\nimport resolveEnvironment from '../environment/index.ts';\nimport type { Logger } from '../isomorphic/types.ts';\nimport type { Reporter } from './telemetry.ts';\nimport { createReporter } from './telemetry.ts';\n\nasync function getVersion() {\n const packageJson = await import('../../package.json', {\n with: { type: 'json' },\n });\n return packageJson.default.version;\n}\n\nfunction parseDashdashCommandParts(\n rawArgs: Array<string>,\n): Array<string> | undefined {\n const dashdashIndex = rawArgs.indexOf('--');\n if (dashdashIndex === -1) {\n return undefined;\n }\n return rawArgs.slice(dashdashIndex + 1);\n}\n\nfunction parseRawArgs(rawArgs: Array<string>) {\n const parsedArgs = parseArgs({\n args: rawArgs,\n\n options: {\n version: {\n type: 'boolean',\n short: 'v',\n },\n\n help: {\n type: 'boolean',\n short: 'h',\n },\n\n config: {\n type: 'string',\n short: 'c',\n },\n\n baseBranch: {\n type: 'string',\n },\n\n link: {\n type: 'string',\n },\n\n message: {\n type: 'string',\n },\n\n authorEmail: {\n type: 'string',\n },\n\n afterSha: {\n type: 'string',\n },\n\n beforeSha: {\n type: 'string',\n },\n\n fallbackShas: {\n type: 'string',\n },\n\n fallbackShasCount: {\n type: 'string',\n },\n\n notify: {\n type: 'string',\n },\n\n nonce: {\n type: 'string',\n },\n\n githubToken: {\n type: 'string',\n },\n },\n\n allowPositionals: true,\n });\n\n return {\n ...parsedArgs,\n dashdashCommandParts: parseDashdashCommandParts(rawArgs),\n };\n}\n\nconst helpText = `Happo ${await getVersion()}\nUsage: happo [options]\n\nCommands:\n <default> Run happo tests\n finalize Finalize happo report for Cypress/Playwright tests running in parallel\n\nOptions:\n --config Path to happo config file\n --version Show version number\n --help Show help text\n --baseBranch <branch> Base branch to use for comparison (default: 'origin/main')\n --link <url> URL to contextualize the comparison (default: auto-detected from CI environment)\n --message <message> Message to associate with the comparison (default: auto-detected from CI environment)\n --authorEmail <email> Email address of the author of the comparison (default: auto-detected from CI environment)\n --afterSha <sha> \"After\" SHA to use for comparison (default: auto-detected from CI environment, or HEAD SHA if not set)\n --beforeSha <sha> \"Before\" SHA to use for comparison (default: auto-detected from CI environment)\n --beforeShaTagMatcher <matcher> git tag matcher to use for \"before\" SHA resolution\n --fallbackShas <shas> Space-, newline- or comma-separated list of fallback shas for compare calls (default: auto-detected from CI environment)\n --fallbackShasCount <count> Number of fallback shas to use for compare calls (default: 50)\n --notify <emails> One or more (comma-separated) email addresses to notify with results\n --nonce <nonce> Nonce to use for Cypress/Playwright comparison\n --githubToken <token> GitHub token to use for posting Happo statuses as comments. Use in combination with the \\`githubApiUrl\\` configuration option. (default: auto-detected from environment)\n\nExamples:\n happo\n\n happo --config path/to/happo.config.ts\n happo --baseBranch origin/long-lived-branch\n happo --link https://github.com/happo/happo/pull/123\n happo --message \"Add new feature\"\n happo --notify me@example.com,you@example.com\n happo --nonce my-unique-nonce\n happo --githubToken {{ secrets.GITHUB_TOKEN }}\n\n happo --version\n happo --help\n\n happo -- playwright test\n\n happo finalize\n happo finalize --nonce my-unique-nonce\n `;\n\nfunction makeAbsolute(configFilePath: string): string {\n if (configFilePath.startsWith('.')) {\n return path.resolve(process.cwd(), configFilePath);\n }\n return configFilePath;\n}\n\nfunction installErrorHandlers(reporter: Reporter, logger: Logger) {\n const unhandledRejectionHandler: NodeJS.UnhandledRejectionListener = (reason) => {\n if (reason instanceof Error) {\n reporter.captureException(reason);\n logger.error(reason.stack || reason.message || String(reason));\n } else {\n reporter.captureException(reason);\n logger.error(`Unhandled rejection (non-Error value): ${String(reason)}`);\n }\n\n process.exitCode = 1;\n return;\n };\n\n const uncaughtExceptionHandler: NodeJS.UncaughtExceptionListener = (error) => {\n reporter.captureException(error);\n logger.error(error.stack || error.message || String(error));\n process.exitCode = 1;\n };\n\n process.on('unhandledRejection', unhandledRejectionHandler);\n process.on('uncaughtException', uncaughtExceptionHandler);\n\n return () => {\n process.removeListener('unhandledRejection', unhandledRejectionHandler);\n process.removeListener('uncaughtException', uncaughtExceptionHandler);\n };\n}\n\nexport async function main(\n rawArgs: Array<string> = process.argv,\n logger: Logger = console,\n): Promise<void> {\n const reporter = createReporter();\n const uninstallErrorHandlers = installErrorHandlers(reporter, logger);\n\n try {\n const args = parseRawArgs(rawArgs.slice(2));\n\n if (args.values.version) {\n // --version\n logger.log(await getVersion());\n return;\n }\n\n if (args.values.help) {\n // --help\n logger.log(helpText);\n return;\n }\n\n // Get config file path (use --config if provided, otherwise find default)\n const configFilePath = makeAbsolute(args.values.config || findConfigFile());\n const config = await loadConfigFile(configFilePath);\n const environment = await resolveEnvironment(args.values);\n\n // Handle positional arguments (commands)\n const command = args.positionals[0];\n\n if (args.dashdashCommandParts) {\n await handleE2ECommand(\n config,\n environment,\n args.dashdashCommandParts,\n configFilePath,\n logger,\n );\n return;\n }\n\n if (command === 'finalize') {\n await handleFinalizeCommand(config, environment, logger);\n return;\n }\n\n if (command === undefined) {\n await handleDefaultCommand(config, environment, logger);\n return;\n }\n\n logger.error(`Unknown command: ${command}\\n`);\n logger.error(helpText);\n process.exitCode = 1;\n } catch (error) {\n await reporter.captureException(error);\n logger.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n } finally {\n uninstallErrorHandlers();\n }\n}\n\nasync function handleDefaultCommand(\n config: ConfigWithDefaults,\n environment: EnvironmentResult,\n logger: Logger,\n): Promise<void> {\n logger.log('Running happo tests...');\n\n const [startJob, createAsyncComparison, createAsyncReport, prepareSnapRequests] =\n await Promise.all([\n (await import('../network/startJob.ts')).default,\n (await import('../network/createAsyncComparison.ts')).default,\n (await import('../network/createAsyncReport.ts')).default,\n (await import('../network/prepareSnapRequests.ts')).default,\n ]);\n\n // Tell Happo that we are about to run a job\n await startJob(config, environment, logger);\n\n try {\n // Prepare the snap requests for the job. This includes bundling static\n // assets and uploading them.\n const snapRequestIds = await prepareSnapRequests(config);\n\n // Put together a report from the snap requests.\n const asyncReport = await createAsyncReport(\n snapRequestIds,\n config,\n environment,\n logger,\n );\n\n // Create an async comparison.\n logger.log(`[HAPPO] Async report URL: ${asyncReport.url}`);\n if (environment.beforeSha !== environment.afterSha) {\n const asyncComparison = await createAsyncComparison(\n config,\n environment,\n logger,\n );\n logger.log(`[HAPPO] Async comparison URL: ${asyncComparison.compareUrl}`);\n }\n } catch (e) {\n logger.error(e instanceof Error ? e.message : String(e), e);\n const cancelJob = (await import('../network/cancelJob.ts')).default;\n await cancelJob('failure', config, environment, logger);\n process.exitCode = 1;\n return;\n }\n}\n\nasync function handleFinalizeCommand(\n config: ConfigWithDefaults,\n environment: EnvironmentResult,\n logger: Logger,\n): Promise<void> {\n logger.log('Finalizing happo report...');\n logger.log('Config:', config);\n logger.log('Environment:', environment);\n\n try {\n const finalizeAll = (await import('../e2e/wrapper.ts')).finalizeAll;\n await finalizeAll({ happoConfig: config, environment, logger });\n } catch (e) {\n logger.error(e instanceof Error ? e.message : String(e), e);\n process.exitCode = 1;\n return;\n }\n process.exitCode = 0;\n return;\n}\n\nconst E2E_INTEGRATION_TYPES = ['cypress', 'playwright'];\n\nasync function handleE2ECommand(\n config: ConfigWithDefaults,\n environment: EnvironmentResult,\n dashdashCommandParts: Array<string>,\n configFilePath: string,\n logger: Logger,\n): Promise<void> {\n if (!E2E_INTEGRATION_TYPES.includes(config.integration.type)) {\n logger.error(\n `Unsupported integration type used for e2e command: ${config.integration.type}. Supported integration types for e2e are: ${E2E_INTEGRATION_TYPES.join(', ')}`,\n );\n process.exitCode = 1;\n return;\n }\n\n if (!dashdashCommandParts || dashdashCommandParts.length === 0) {\n logger.error('Missing command for e2e action');\n logger.error(helpText);\n process.exitCode = 1;\n return;\n }\n\n logger.log('Setting up happo wrapper for Cypress and Playwright...');\n logger.log('Config:', config);\n logger.log('Environment:', environment);\n logger.log('Dashdash command parts:', dashdashCommandParts);\n\n const runWithWrapper = (await import('../e2e/wrapper.ts')).default;\n const exitCode = await runWithWrapper(\n dashdashCommandParts,\n config,\n environment,\n logger,\n configFilePath,\n );\n process.exitCode = exitCode;\n}\n\nif (import.meta.main) {\n await main();\n}\n", "import fs from 'node:fs';\n\nimport { any as findAny } from 'empathic/find';\n\nimport type { ConfigWithDefaults, TargetWithDefaults } from './index.ts';\n\nconst CONFIG_FILENAMES = [\n 'happo.config.js',\n 'happo.config.mjs',\n 'happo.config.cjs',\n 'happo.config.ts',\n 'happo.config.mts',\n 'happo.config.cts',\n];\n\nexport function findConfigFile(): string {\n if (process.env.HAPPO_CONFIG_FILE) {\n return process.env.HAPPO_CONFIG_FILE;\n }\n\n const configFilePath = findAny(CONFIG_FILENAMES, { cwd: process.cwd() });\n\n if (!configFilePath) {\n throw new Error(\n 'Happo config file could not be found. Please create a config file in the root of your project.',\n );\n }\n\n return configFilePath;\n}\n\nfunction validateConfig(config: ConfigWithDefaults) {\n if (!config.apiKey) {\n throw new Error(\n 'Missing `apiKey` in your Happo config. Reference yours at https://happo.io/settings',\n );\n }\n\n if (!config.apiSecret) {\n throw new Error(\n 'Missing `apiSecret` in your Happo config. Reference yours at https://happo.io/settings',\n );\n }\n}\n\nexport async function loadConfigFile(\n configFilePath: string,\n): Promise<ConfigWithDefaults> {\n try {\n const stats = await fs.promises.stat(configFilePath);\n if (!stats.isFile()) {\n throw new Error(`Happo config file path is not a file: ${configFilePath}`);\n }\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n throw new Error(`Happo config file could not be found: ${configFilePath}`);\n }\n\n throw error;\n }\n\n const config = await import(configFilePath);\n\n if (!config.default.targets) {\n config.default.targets = {\n chrome: {\n type: 'chrome',\n viewport: '1024x768',\n },\n };\n }\n\n if (!config.default.integration) {\n config.default.integration = {\n type: 'storybook',\n };\n }\n\n const allTargets = Object.values(config.default.targets);\n for (const target of allTargets as Array<TargetWithDefaults>) {\n target.viewport = target.viewport || '1024x768';\n target.freezeAnimations = target.freezeAnimations || 'last-frame';\n target.prefersReducedMotion = target.prefersReducedMotion ?? true;\n }\n\n const configWithDefaults = {\n endpoint: 'https://happo.io',\n githubApiUrl: 'https://api.github.com',\n targets: allTargets,\n ...config.default,\n };\n\n validateConfig(configWithDefaults);\n\n return configWithDefaults;\n}\n", "import { spawnSync } from 'node:child_process';\nimport crypto, { randomBytes } from 'node:crypto';\nimport { readFileSync } from 'node:fs';\n\ninterface GitHubEvent {\n pull_request?: {\n html_url: string;\n title: string;\n base: {\n sha: string;\n };\n head: {\n sha: string;\n };\n };\n head_commit?: {\n url: string;\n };\n merge_group?: {\n head_sha: string;\n base_sha: string;\n };\n repository?: {\n html_url: string;\n };\n before?: string;\n after?: string;\n}\n\ninterface CLIArgs {\n baseBranch?: string;\n afterSha?: string;\n beforeSha?: string;\n message?: string;\n link?: string;\n authorEmail?: string;\n beforeShaTagMatcher?: string;\n notify?: string;\n fallbackShas?: string;\n fallbackShasCount?: string;\n nonce?: string;\n githubToken?: string;\n}\n\nexport interface EnvironmentResult {\n link: string | undefined;\n message: string | undefined;\n authorEmail: string | undefined;\n beforeSha: string;\n afterSha: string;\n nonce: string | undefined;\n debugMode: boolean;\n notify: string | undefined;\n fallbackShas: Array<string> | undefined;\n githubToken: string | undefined;\n}\n\nconst envKeys: ReadonlyArray<string> = [\n 'BUILD_REPOSITORY_URI',\n 'BUILD_SOURCEVERSION',\n 'CIRCLE_PROJECT_REPONAME',\n 'CIRCLE_PROJECT_USERNAME',\n 'CIRCLE_SHA1',\n 'CI_PULL_REQUEST',\n 'GITHUB_EVENT_PATH',\n 'GITHUB_SERVER_URL',\n 'GITHUB_SHA',\n 'HAPPO_DEBUG',\n 'SYSTEM_PULLREQUEST_PULLREQUESTID',\n 'SYSTEM_PULLREQUEST_SOURCEBRANCH',\n 'SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI',\n 'SYSTEM_PULLREQUEST_TARGETBRANCH',\n 'TRAVIS_COMMIT',\n 'TRAVIS_COMMIT_RANGE',\n 'TRAVIS_PULL_REQUEST',\n 'TRAVIS_PULL_REQUEST_SHA',\n 'TRAVIS_REPO_SLUG',\n];\n\nasync function resolveGithubEvent(GITHUB_EVENT_PATH: string): Promise<GitHubEvent> {\n try {\n const fs = await import('node:fs/promises');\n const content = await fs.readFile(GITHUB_EVENT_PATH, 'utf8');\n return JSON.parse(content);\n } catch (e) {\n throw new Error(\n `Failed to load GitHub event from the GITHUB_EVENT_PATH environment variable: ${JSON.stringify(GITHUB_EVENT_PATH)}`,\n { cause: e },\n );\n }\n}\n\nasync function resolveLink(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n): Promise<string | undefined> {\n if (cliArgs.link) {\n // Validate the link\n let parsed: URL;\n try {\n parsed = new URL(cliArgs.link);\n } catch (e) {\n throw new TypeError(\n `link must be a valid http/https URL. Invalid URL: '${cliArgs.link}'`,\n { cause: e },\n );\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new TypeError(\n `link must be a valid http/https URL. Invalid protocol: '${parsed.protocol}' (from '${cliArgs.link}')`,\n );\n }\n\n return cliArgs.link;\n }\n\n const {\n BUILD_REPOSITORY_URI,\n BUILD_SOURCEVERSION,\n\n // https://circleci.com/docs/reference/variables/\n CIRCLE_PROJECT_REPONAME,\n CIRCLE_PROJECT_USERNAME,\n CIRCLE_PULL_REQUEST,\n CIRCLE_SHA1,\n\n CI_PULL_REQUEST,\n\n // https://docs.github.com/en/actions/reference/workflows-and-actions/variables#default-environment-variables\n GITHUB_EVENT_PATH,\n GITHUB_SHA,\n\n SYSTEM_PULLREQUEST_PULLREQUESTID,\n SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI,\n\n // https://docs.travis-ci.com/user/environment-variables/#default-environment-variables\n TRAVIS_COMMIT,\n TRAVIS_PULL_REQUEST,\n TRAVIS_REPO_SLUG,\n } = env;\n\n if (CI_PULL_REQUEST) {\n // Circle CI\n return CI_PULL_REQUEST;\n }\n\n if (GITHUB_EVENT_PATH) {\n const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n\n if (ghEvent.pull_request) {\n return ghEvent.pull_request.html_url;\n }\n if (ghEvent.head_commit) {\n return ghEvent.head_commit.url;\n }\n if (ghEvent.merge_group && ghEvent.repository) {\n return `${ghEvent.repository.html_url}/commit/${ghEvent.merge_group.head_sha}`;\n }\n if (GITHUB_SHA && ghEvent.repository) {\n return `${ghEvent.repository.html_url}/commit/${GITHUB_SHA}`;\n }\n }\n\n if (SYSTEM_PULLREQUEST_PULLREQUESTID && SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI) {\n return `${SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI}/pullrequest/${SYSTEM_PULLREQUEST_PULLREQUESTID}`.replace(\n /[^/]+@/,\n '',\n );\n }\n\n if (BUILD_REPOSITORY_URI && BUILD_SOURCEVERSION) {\n return `${BUILD_REPOSITORY_URI}/commit/${BUILD_SOURCEVERSION}`.replace(\n /[^/]+@/,\n '',\n );\n }\n\n const githubBase = 'https://github.com';\n\n if (TRAVIS_REPO_SLUG && TRAVIS_PULL_REQUEST) {\n return `${githubBase}/${TRAVIS_REPO_SLUG}/pull/${TRAVIS_PULL_REQUEST}`;\n }\n\n if (TRAVIS_REPO_SLUG && TRAVIS_COMMIT) {\n return `${githubBase}/${TRAVIS_REPO_SLUG}/commit/${TRAVIS_COMMIT}`;\n }\n\n if (CIRCLE_PULL_REQUEST) {\n return CIRCLE_PULL_REQUEST;\n }\n\n if (CIRCLE_PROJECT_USERNAME && CIRCLE_PROJECT_REPONAME && CIRCLE_SHA1) {\n return `${githubBase}/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}`;\n }\n\n return undefined;\n}\n\nasync function resolveAuthorEmail(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n): Promise<string | undefined> {\n if (cliArgs.authorEmail) {\n return cliArgs.authorEmail;\n }\n\n const { GITHUB_EVENT_PATH } = env;\n\n if (GITHUB_EVENT_PATH) {\n // const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n // TODO: do something with the github event\n }\n\n const res = spawnSync('git', ['show', '-s', '--format=%ae'], {\n encoding: 'utf8',\n });\n\n if (res.status !== 0) {\n return undefined;\n }\n\n return res.stdout.trim();\n}\n\nasync function resolveMessage(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n afterSha: string,\n): Promise<string | undefined> {\n if (cliArgs.message) {\n return cliArgs.message;\n }\n\n const { GITHUB_EVENT_PATH } = env;\n\n if (GITHUB_EVENT_PATH) {\n const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n if (ghEvent.pull_request) {\n return ghEvent.pull_request.title;\n }\n }\n\n const res = spawnSync('git', ['log', '-1', '--pretty=%s', afterSha], {\n encoding: 'utf8',\n });\n\n if (res.status !== 0) {\n return undefined;\n }\n\n const message = res.stdout.split('\\n')[0];\n\n if (!message) {\n return undefined;\n }\n\n return message;\n}\n\nfunction resolveShaFromTagMatcher(tagMatcher: string): string | undefined {\n const res = spawnSync(\n 'git',\n ['tag', '--list', tagMatcher, '--sort', 'refname', '--no-contains'],\n {\n encoding: 'utf8',\n },\n );\n\n if (res.status !== 0) {\n throw new Error(\n `Failed to list git tags when matching against --beforeShaTagMatcher '${tagMatcher}'. Error: ${res.stderr}`,\n );\n }\n\n const rawAllTags = res.stdout.trim();\n if (!rawAllTags.length) {\n return undefined;\n }\n\n const allTags = rawAllTags.split('\\n');\n const tag = allTags.at(-1);\n\n if (!tag) {\n throw new Error('No tag found matching the pattern');\n }\n\n const commitRes = spawnSync('git', ['rev-list', '-n', '1', tag], {\n encoding: 'utf8',\n });\n\n if (commitRes.status !== 0) {\n throw new Error(\n `Failed to resolve commit sha from tag \"${tag}\". Error: ${res.stderr}`,\n );\n }\n\n return commitRes.stdout.trim();\n}\n\nasync function resolveBeforeSha(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n afterSha: string,\n): Promise<string | undefined> {\n if (cliArgs.beforeSha) {\n return cliArgs.beforeSha;\n }\n\n if (cliArgs.beforeShaTagMatcher) {\n const resolvedSha = resolveShaFromTagMatcher(cliArgs.beforeShaTagMatcher);\n if (resolvedSha) {\n return resolvedSha;\n }\n }\n\n const { TRAVIS_COMMIT_RANGE, GITHUB_EVENT_PATH, SYSTEM_PULLREQUEST_TARGETBRANCH } =\n env;\n\n if (GITHUB_EVENT_PATH) {\n const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n if (ghEvent.pull_request) {\n return ghEvent.pull_request.base.sha;\n }\n if (ghEvent.merge_group) {\n return ghEvent.merge_group.base_sha;\n }\n return ghEvent.before;\n }\n\n if (TRAVIS_COMMIT_RANGE) {\n const [first] = TRAVIS_COMMIT_RANGE.split('...');\n return first;\n }\n\n let baseAzureBranch;\n if (SYSTEM_PULLREQUEST_TARGETBRANCH) {\n baseAzureBranch = [\n 'origin',\n SYSTEM_PULLREQUEST_TARGETBRANCH.split('/').toReversed()[0],\n ].join('/');\n }\n\n const baseBranch = cliArgs.baseBranch || baseAzureBranch || 'origin/main';\n const res = spawnSync('git', ['merge-base', baseBranch, afterSha], {\n encoding: 'utf8',\n });\n if (res.status !== 0) {\n console.error(`[HAPPO] Ignored error when resolving base commit: ${res.stderr}`);\n return undefined;\n }\n return res.stdout.split('\\n')[0];\n}\n\nfunction getHeadShaWithLocalChanges(): {\n headSha: string;\n headShaWithLocalChanges: string;\n} {\n const randomSha = randomBytes(20).toString('hex');\n // Get the HEAD sha from the git repo, or if we have local changes, add them to the sha\n const res = spawnSync('git', ['rev-parse', 'HEAD'], {\n encoding: 'utf8',\n });\n if (res.status !== 0) {\n return { headSha: randomSha, headShaWithLocalChanges: randomSha };\n }\n const headSha = res.stdout.split('\\n')[0];\n if (!headSha) {\n return { headSha: randomSha, headShaWithLocalChanges: randomSha };\n }\n\n // Check for local changes\n const diffRes = spawnSync('git', ['diff', 'HEAD'], {\n encoding: 'utf8',\n });\n\n // If git diff fails, return HEAD sha\n if (diffRes.status !== 0) {\n return { headSha, headShaWithLocalChanges: headSha };\n }\n\n const lsRes = spawnSync('git', ['ls-files', '--other', '--exclude-standard'], {\n encoding: 'utf8',\n });\n\n if (lsRes.status !== 0) {\n return { headSha, headShaWithLocalChanges: headSha };\n }\n\n const localChanges = [diffRes.stdout.trim(), lsRes.stdout.trim()];\n\n // Get contents of untracked files\n const untrackedFiles = lsRes.stdout\n .trim()\n .split('\\n')\n .filter((file) => file.trim());\n\n for (const file of untrackedFiles) {\n try {\n const content = readFileSync(file, 'utf8');\n localChanges.push(content);\n } catch {\n // If we can't read the file, include just the filename\n localChanges.push(`${file}:<unreadable>`);\n }\n }\n\n const allChanges = localChanges.join('');\n\n if (!allChanges.trim()) {\n return { headSha, headShaWithLocalChanges: headSha };\n }\n\n // If there are local changes, create a hash that includes both HEAD and the changes\n const headShaWithLocalChanges = crypto\n .createHash('sha256')\n .update(headSha)\n .update(allChanges)\n .digest('hex')\n .slice(0, 40);\n\n return { headSha, headShaWithLocalChanges };\n}\n\nasync function resolveAfterSha(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined>,\n): Promise<string | { headSha: string; headShaWithLocalChanges: string }> {\n if (cliArgs.afterSha) {\n return cliArgs.afterSha;\n }\n\n const {\n CIRCLE_SHA1,\n TRAVIS_PULL_REQUEST_SHA,\n TRAVIS_COMMIT,\n GITHUB_EVENT_PATH,\n GITHUB_SHA,\n BUILD_SOURCEVERSION,\n SYSTEM_PULLREQUEST_SOURCEBRANCH,\n CI,\n } = env;\n\n const sha = CIRCLE_SHA1 || TRAVIS_PULL_REQUEST_SHA || TRAVIS_COMMIT;\n\n if (sha) {\n return sha;\n }\n\n if (SYSTEM_PULLREQUEST_SOURCEBRANCH) {\n // azure pull request\n const rawBranchName = SYSTEM_PULLREQUEST_SOURCEBRANCH.split('/').toReversed()[0];\n const res = spawnSync('git', ['rev-parse', `origin/${rawBranchName}`], {\n encoding: 'utf8',\n });\n if (res.status === 0 && res.stdout) {\n const sha = res.stdout.split('\\n')[0];\n if (sha) {\n return sha;\n }\n }\n }\n if (BUILD_SOURCEVERSION) {\n // azure master job\n return BUILD_SOURCEVERSION;\n }\n if (GITHUB_EVENT_PATH) {\n const ghEvent = await resolveGithubEvent(GITHUB_EVENT_PATH);\n if (ghEvent.pull_request) {\n return ghEvent.pull_request.head.sha;\n }\n if (ghEvent.merge_group) {\n return ghEvent.merge_group.head_sha;\n }\n if (ghEvent.after) {\n return ghEvent.after;\n }\n if (GITHUB_SHA) {\n return GITHUB_SHA;\n }\n }\n const headShaWithLocalChanges = getHeadShaWithLocalChanges();\n if (CI) {\n return headShaWithLocalChanges.headSha;\n }\n return headShaWithLocalChanges;\n}\n\nfunction resolveFallbackShas(\n cliArgs: CLIArgs,\n beforeSha: string | undefined,\n): Array<string> | undefined {\n if (cliArgs.fallbackShas) {\n return cliArgs.fallbackShas.split(/[,\\s]+/).filter(Boolean);\n }\n\n const fallbackShasCount = cliArgs.fallbackShasCount\n ? Number.parseInt(cliArgs.fallbackShasCount, 10)\n : 50;\n\n if (Number.isNaN(fallbackShasCount)) {\n throw new TypeError(\n `fallbackShasCount must be a number. Invalid value: '${cliArgs.fallbackShasCount}'`,\n );\n }\n\n const res = spawnSync(\n 'git',\n [\n 'log',\n '--format=%H',\n '--first-parent',\n `--max-count=${fallbackShasCount}`,\n `${beforeSha}^`,\n ],\n {\n encoding: 'utf8',\n },\n );\n\n if (res.status !== 0) {\n return undefined;\n }\n\n return res.stdout.split('\\n').filter(Boolean);\n}\n\nfunction getRawEnv(\n env: Record<string, string | undefined>,\n): Record<string, string | undefined> {\n const res: Record<string, string | undefined> = {};\n for (const key of envKeys) {\n res[key] = env[key];\n }\n return res;\n}\n\nexport default async function resolveEnvironment(\n cliArgs: CLIArgs,\n env: Record<string, string | undefined> = process.env,\n): Promise<EnvironmentResult> {\n const debugMode = !!env.HAPPO_DEBUG;\n const afterSha = await resolveAfterSha(cliArgs, env);\n\n const realAfterSha = typeof afterSha === 'string' ? afterSha : afterSha.headSha;\n const afterShaWithLocalChanges =\n typeof afterSha === 'string' ? afterSha : afterSha.headShaWithLocalChanges;\n\n // Resolve the before SHA with the true HEAD SHA\n const [beforeSha, link, authorEmail, message] = await Promise.all([\n resolveBeforeSha(cliArgs, env, realAfterSha),\n resolveLink(cliArgs, env),\n resolveAuthorEmail(cliArgs, env),\n\n // Resolve message with the SHA that includes local changes\n resolveMessage(cliArgs, env, afterShaWithLocalChanges),\n ]);\n\n const nonNullBeforeSha = beforeSha || afterShaWithLocalChanges;\n\n const result = {\n link,\n authorEmail,\n message,\n beforeSha: nonNullBeforeSha,\n afterSha: afterShaWithLocalChanges,\n nonce: cliArgs.nonce,\n debugMode,\n notify: cliArgs.notify,\n fallbackShas: resolveFallbackShas(cliArgs, nonNullBeforeSha),\n githubToken: cliArgs.githubToken,\n };\n\n if (debugMode) {\n console.log('[HAPPO] Raw environment', getRawEnv(env));\n console.log('[HAPPO] Resolved environment', result);\n }\n\n return result;\n}\n", "import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { createInterface } from 'node:readline';\n\nimport { up as findPackage } from 'empathic/package';\n\nimport pkg from '../../package.json' with { type: 'json' };\n\n/**\n * Happo's PUBLIC DSN. Safe to ship.\n */\nconst SENTRY_DSN =\n 'https://3a495ff2101313edb024de73b005398f@o108341.ingest.us.sentry.io/4510341337645056';\n\nconst MAX_STACK_FRAMES = 50;\nconst MAX_FUNCTION_NAME_LENGTH = 120;\n\ntype CI =\n | 'github'\n | 'circleci'\n | 'travis'\n | 'azure'\n | 'buildkite'\n | 'jenkins'\n | 'gitlab'\n | 'bitbucket'\n | 'appveyor'\n | 'drone'\n | 'ci'\n | 'unknown';\n\ntype ErrorPayload = {\n pkg: {\n name: string;\n version: string;\n };\n\n error: {\n name: string;\n message: string;\n stack?: string;\n };\n\n env: string;\n\n /** Detected CI vendor if any */\n ci: CI;\n\n nodeVersion: string;\n platform: string;\n};\n\nexport type ReporterOptions = {\n maxPerMinute?: number; // default 10\n env?: string;\n};\n\nexport interface Reporter {\n captureException(e: unknown): Promise<void>;\n}\n\nexport function detectCI(env: Record<string, string | undefined> = process.env): CI {\n if (env.GITHUB_ACTIONS) {\n return 'github';\n }\n\n if (env.CIRCLECI) {\n return 'circleci';\n }\n\n if (env.TRAVIS) {\n return 'travis';\n }\n\n if (env.TF_BUILD) {\n return 'azure';\n }\n\n if (env.BUILDKITE) {\n return 'buildkite';\n }\n\n if (env.JENKINS_URL) {\n return 'jenkins';\n }\n\n if (env.GITLAB_CI) {\n return 'gitlab';\n }\n\n if (env.BITBUCKET_BUILD_NUMBER) {\n return 'bitbucket';\n }\n\n if (env.APPVEYOR) {\n return 'appveyor';\n }\n\n if (env.DRONE) {\n return 'drone';\n }\n\n if (env.CI) {\n return 'ci';\n }\n\n return 'unknown';\n}\n\nexport function parseDsn(dsn: string): {\n host: string;\n projectId: string;\n key: string;\n protocol: string;\n} | null {\n try {\n // https://{PUBLIC_KEY}@{host}/{project_id}\n const u = new URL(dsn);\n const projectId = u.pathname.replace(/^\\//, '');\n const key = u.username; // public key\n const host = u.host; // includes subdomain + port\n return {\n host,\n projectId,\n key,\n protocol: u.protocol.replace(':', ''),\n };\n } catch {\n return null;\n }\n}\n\nasync function sendToSentry(payload: ErrorPayload) {\n const dsn = parseDsn(SENTRY_DSN);\n\n if (!dsn) {\n return;\n }\n\n // Sentry envelope: https://develop.sentry.dev/sdk/envelopes/\n const now = Date.now();\n\n // Hexadecimal string representing a uuid4 value. The length is exactly 32\n // characters. Dashes are not allowed. Has to be lowercase.\n const eventId = crypto.randomUUID().replaceAll('-', '');\n\n const url = `https://${dsn.host}/api/${dsn.projectId}/envelope/`;\n\n const httpHeaders = {\n 'content-type': 'application/x-sentry-envelope',\n 'x-sentry-auth': [\n 'Sentry sentry_version=7',\n `sentry_key=${dsn.key}`,\n `sentry_client=${pkg.name}@${pkg.version}`,\n ].join(', '),\n };\n\n const memoryInfo = process.memoryUsage();\n\n // Minimal event; we keep fields lean & sanitized\n // https://develop.sentry.dev/sdk/data-model/event-payloads/#required-attributes\n const event = {\n event_id: eventId,\n\n // RFC 3339 format\n timestamp: new Date(now).toISOString(),\n\n // A string representing the platform the SDK is submitting from. This will\n // be used by the Sentry interface to customize various components in the\n // interface.\n platform: 'node',\n\n // Possible values: fatal, error, warning, info, debug\n level: 'error',\n\n logger: 'happo.telemetry.cli',\n\n environment: payload.env ?? 'unknown',\n\n // Release versions must be unique across all projects in the organization.\n release: `${payload.pkg.name}@${payload.pkg.version}`,\n\n tags: {\n ci: payload.ci ?? '',\n },\n\n contexts: {\n runtime: {\n type: 'runtime',\n name: 'node',\n version: payload.nodeVersion ?? '',\n },\n os: {\n type: 'os',\n name: payload.platform ?? '',\n },\n memory_info: {\n type: 'memory_info',\n ...memoryInfo,\n },\n },\n\n exception: {\n values: [\n {\n type: payload.error.name || 'Error',\n value: payload.error.message,\n\n // https://develop.sentry.dev/sdk/data-model/event-payloads/stacktrace/\n stacktrace: payload.error.stack\n ? {\n frames: await parseFrames(payload.error.stack),\n }\n : undefined,\n },\n ],\n },\n };\n\n /**\n * Envelope is ndjson-like chunks\n *\n * Envelope = Headers { \"\\n\" Item } [ \"\\n\" ] ;\n * Item = Headers \"\\n\" Payload ;\n * Payload = { * } ;\n *\n * @see https://develop.sentry.dev/sdk/data-model/envelopes/#headers\n */\n const envelopeHeader = JSON.stringify({\n event_id: eventId,\n dsn: SENTRY_DSN,\n sent_at: new Date(now).toISOString(),\n });\n\n // https://develop.sentry.dev/sdk/data-model/envelopes/#items\n const item = JSON.stringify(event);\n const itemHeader = JSON.stringify({ type: 'event', length: item.length });\n\n const body = [envelopeHeader, itemHeader, item].join('\\n');\n\n try {\n await fetch(url, { method: 'POST', headers: httpHeaders, body });\n } catch {\n // swallow; never throw in library code\n }\n}\n\ninterface SentryFrame {\n function: string;\n raw_function: string;\n abs_path: string | undefined;\n filename: string | undefined;\n lineno: number | undefined;\n colno: number | undefined;\n context_line?: string;\n pre_context?: Array<string>;\n post_context?: Array<string>;\n}\n\n/**\n * Get the package root directory\n */\nfunction getPackageRoot(): string {\n const packageJsonPath = findPackage({ cwd: import.meta.dirname });\n\n if (!packageJsonPath) {\n // Fallback to relative path if empathic can't find it\n return path.resolve(import.meta.dirname, '../..');\n }\n\n return path.dirname(packageJsonPath);\n}\n\n/**\n * Check if a file path is part of this package\n */\nfunction isFileInThisPackage(filePath: string): boolean {\n // Skip node: internal modules\n if (filePath.startsWith('node:')) {\n return false;\n }\n\n try {\n const packageRoot = getPackageRoot();\n // Remove file:// prefix if present\n const cleanPath = filePath.replace(/^file:\\/\\//, '');\n const resolvedPath = path.resolve(cleanPath);\n return resolvedPath.startsWith(packageRoot + path.sep);\n } catch {\n return false;\n }\n}\n\n/**\n * Read context lines from a source file around a given line number\n * Only reads files that are part of this package\n */\nasync function readContextLines(\n filePath: string,\n lineNumber: number,\n contextLines: number = 5,\n): Promise<{\n context_line?: string;\n pre_context?: Array<string>;\n post_context?: Array<string>;\n}> {\n // Only read context for files in this package. This is to avoid reading\n // context from external files that may contain sensitive information.\n if (!isFileInThisPackage(filePath)) {\n return {};\n }\n\n try {\n // Remove file:// prefix if present\n const cleanPath = filePath.replace(/^file:\\/\\//, '');\n\n // Line numbers are 1-indexed in stack traces, but arrays are 0-indexed\n const lineIndex = lineNumber - 1;\n\n if (lineIndex < 0) {\n return {};\n }\n\n const startLine = Math.max(0, lineIndex - contextLines);\n const endLine = lineIndex + contextLines + 1;\n\n const pre_context: Array<string> = [];\n let context_line: string | undefined;\n const post_context: Array<string> = [];\n\n const fileStream = fs.createReadStream(cleanPath, { encoding: 'utf8' });\n const rl = createInterface({\n input: fileStream,\n crlfDelay: Infinity,\n });\n\n let currentLine = 0;\n\n for await (const line of rl) {\n if (currentLine < startLine) {\n // Skip lines before our context window\n currentLine++;\n continue;\n }\n\n if (currentLine === lineIndex) {\n context_line = line;\n } else if (currentLine < lineIndex) {\n pre_context.push(line);\n } else if (currentLine < endLine) {\n post_context.push(line);\n } else {\n // We've read all the lines we need\n break;\n }\n\n currentLine++;\n }\n\n // Check if we found the target line\n if (context_line === undefined) {\n return {};\n }\n\n const result: {\n context_line: string;\n pre_context?: Array<string>;\n post_context?: Array<string>;\n } = {\n context_line,\n };\n\n if (pre_context.length > 0) {\n result.pre_context = pre_context;\n }\n\n if (post_context.length > 0) {\n result.post_context = post_context;\n }\n\n return result;\n } catch {\n // File might not exist, might not be readable, etc. Best-effort only.\n return {};\n }\n}\n\n/**\n * Convert an error stack to Sentry frames (best-effort)\n */\nexport async function parseFrames(\n stack: string,\n cwd: string = process.cwd(),\n): Promise<Array<SentryFrame>> {\n // Node stack lines like: \" at func (file:///absolute/path/to/file.js:10:5)\"\n const stackLines = stack.split('\\n').slice(0, MAX_STACK_FRAMES);\n\n const frames = [];\n\n for (const stackLine of stackLines) {\n const match = stackLine.match(\n /\\s+at\\s+(?<functionName>.*?)\\s+\\((?:file:\\/\\/)?(?<absPath>.+?):(?<lineno>\\d+):(?<colno>\\d+)\\)/,\n );\n\n if (!match || !match.groups) {\n // We didn't match a stack line, so skip it. This could cause some stack\n // lines to be dropped.\n continue;\n }\n\n const rawAbsPath = match.groups.absPath ?? '';\n\n const absPath = rawAbsPath.startsWith('node:')\n ? rawAbsPath\n : path.relative(cwd, rawAbsPath);\n const filename = rawAbsPath.startsWith('node:')\n ? rawAbsPath\n : path.basename(rawAbsPath);\n\n const functionName = match.groups.functionName ?? '';\n\n const lineno = match.groups.lineno\n ? Number.parseInt(match.groups.lineno, 10)\n : undefined;\n\n // Read context lines from the source file (only for package files)\n const context =\n rawAbsPath && lineno ? await readContextLines(rawAbsPath, lineno) : {};\n\n // https://develop.sentry.dev/sdk/data-model/event-payloads/stacktrace/#frame-attributes\n const frame: SentryFrame = {\n function: functionName.slice(0, MAX_FUNCTION_NAME_LENGTH),\n raw_function: functionName,\n\n abs_path: absPath,\n filename,\n\n lineno,\n\n colno: match.groups.colno\n ? Number.parseInt(match.groups.colno, 10)\n : undefined,\n\n ...context,\n };\n\n frames.push(frame);\n }\n\n // Sentry expects most recent frame last\n return frames.toReversed();\n}\n\n/**\n * Create a reporter with rate limiting\n */\nexport function createReporter(opts: ReporterOptions = {}): Reporter {\n const maxPerMinute = Math.max(1, opts.maxPerMinute ?? 10);\n let sentThisMinute = 0;\n let minuteTick = Date.now();\n\n function isRateLimitExceeded(): boolean {\n const now = Date.now();\n\n if (now - minuteTick >= 60_000) {\n minuteTick = now;\n sentThisMinute = 0;\n }\n\n if (sentThisMinute >= maxPerMinute) {\n return true;\n }\n\n sentThisMinute++;\n\n return false;\n }\n\n const ci = detectCI(process.env);\n const nodeVersion = process.version;\n const platform = process.platform;\n\n return {\n async captureException(e: unknown) {\n if (isRateLimitExceeded()) {\n return;\n }\n\n const err = e instanceof Error ? e : new Error(String(e));\n const message = err.message ?? 'Error';\n const stack = err.stack;\n\n const payload: ErrorPayload = {\n pkg,\n env: opts.env ?? process.env.NODE_ENV ?? 'unknown',\n ci,\n nodeVersion,\n platform,\n\n error: {\n name: err.name || 'Error',\n message,\n stack: stack ?? '',\n },\n };\n\n await sendToSentry(payload);\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["path", "fs", "sha", "crypto", "fs", "crypto", "fs", "path"]
7
7
  }
@@ -0,0 +1,7 @@
1
+ import {
2
+ package_default
3
+ } from "./chunk-FJEU3Q5K.js";
4
+ export {
5
+ package_default as default
6
+ };
7
+ //# sourceMappingURL=package-46H7ER65.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-MGX62D4H.js";
4
- import "./chunk-HM2REEUJ.js";
3
+ } from "./chunk-5TMGUI7R.js";
4
+ import "./chunk-FJEU3Q5K.js";
5
5
 
6
6
  // src/network/prepareSnapRequests.ts
7
7
  import fs5 from "node:fs";
@@ -731,4 +731,4 @@ async function prepareSnapRequests(config) {
731
731
  export {
732
732
  prepareSnapRequests as default
733
733
  };
734
- //# sourceMappingURL=prepareSnapRequests-JY6YQY7D.js.map
734
+ //# sourceMappingURL=prepareSnapRequests-3QY7GDSP.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-MGX62D4H.js";
4
- import "./chunk-HM2REEUJ.js";
3
+ } from "./chunk-5TMGUI7R.js";
4
+ import "./chunk-FJEU3Q5K.js";
5
5
 
6
6
  // src/network/startJob.ts
7
7
  function assertResultIsStartJobResult(result) {
@@ -36,4 +36,4 @@ async function startJob(config, { beforeSha, afterSha, link, message }, logger)
36
36
  export {
37
37
  startJob as default
38
38
  };
39
- //# sourceMappingURL=startJob-L7MU4ZEI.js.map
39
+ //# sourceMappingURL=startJob-F6F63N2M.js.map