@currents/cmd 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/index.js CHANGED
@@ -1,64 +1,69 @@
1
1
  #! /usr/bin/env node
2
- "use strict";var Zc=Object.create;var Ir=Object.defineProperty;var tp=Object.getOwnPropertyDescriptor;var ep=Object.getOwnPropertyNames;var rp=Object.getPrototypeOf,op=Object.prototype.hasOwnProperty;var np=(t,e)=>{for(var r in e)Ir(t,r,{get:e[r],enumerable:!0})},sp=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ep(e))!op.call(t,n)&&n!==r&&Ir(t,n,{get:()=>e[n],enumerable:!(o=tp(e,n))||o.enumerable});return t};var l=(t,e,r)=>(r=t!=null?Zc(rp(t)):{},sp(e||!t||!t.__esModule?Ir(r,"default",{value:t,enumerable:!0}):r,t));var mx=require("source-map-support/register");var zc=require("@commander-js/extra-typings");var Fo={name:"@currents/cmd",version:"2.1.0",main:"./dist/index.js",author:{name:"Currents Software Inc",email:"hello@currents.dev"},license:"MIT",repository:{type:"git",url:"https://github.com/currents-dev/currents-reporter"},description:"Currents CLI tools",engines:{node:">=20"},scripts:{test:"vitest",rm:"rimraf dist",lint:'TIMING=1 eslint "**/*.ts*"',types:"tsc --noEmit",build:"tsup-node --minify --dts",dev:"tsup-node --watch --dts",release:"release-it","publish:npm":"npm run rm && npm run build && ./publish.js"},devDependencies:{"@jest/reporters":"^30.4.1","@jest/types":"^30.4.1","@release-it/conventional-changelog":"^12.0.0","release-it":"^21.0.2","@types/archiver":"^6.0.3","@types/async-retry":"^1.4.9","@types/debug":"^4.1.12","@types/fs-extra":"^11.0.4","@types/getos":"^3.0.4","@types/lodash":"^4.17.16","@types/node":"^25.5.0","@types/proxy-from-env":"^1.0.4","@types/semver":"^7.5.8","@types/tmp":"^0.2.6","@types/unzipper":"^0.10.11","@types/uuid":"^10.0.0","@types/xml2js":"^0.4.14","@types/xxhashjs":"^0.2.4",jest:"^30.4.2","jest-cli":"^30.4.2","jest-config":"^30.4.2",rimraf:"^6.0.1",tsup:"^8.3.5",typescript:"^5.9.3",vitest:"^4.1.11"},dependencies:{"@commander-js/extra-typings":"^14.0.0","@currents/commit-info":"2.0.0",archiver:"^7.0.1","async-retry":"^1.3.3",axios:"1.20.0","axios-retry":"4.5.0",chalk:"^4.1.2",commander:"^14.0.0",debug:"^4.4.0",dotenv:"^17.4.2",execa:"^9.5.1","fs-extra":"^11.3.4",getos:"^3.2.1",globby:"^11.1.0","https-proxy-agent":"^7.0.4",lodash:"^4.18.1",nanoid:"^3.3.8","pretty-ms":"^7.0.1","proxy-from-env":"^1.1.0",semver:"^7.8.5","source-map-support":"^0.5.21",tmp:"^0.2.7","tmp-promise":"^3.0.3","ts-pattern":"^5.8.0",unzipper:"^0.12.3",uuid:"11.1.1",xml2js:"^0.6.2",xxhashjs:"^0.2.2"},bin:{currents:"./dist/bin/index.js","currents-cli":"./dist/bin/index.js"},files:["dist","!**/*.map","!**/*/*.map"],keywords:["cloud test dashboard","test reporter","test results","currents","currents dashboard","ci"],exports:{".":{import:"./dist/index.js",require:"./dist/index.js",types:"./dist/index.d.ts"},"./discovery/jest":{import:"./dist/services/upload/discovery/jest/reporter.js",require:"./dist/services/upload/discovery/jest/reporter.js",types:"./dist/services/upload/discovery/jest/reporter.d.ts"},"./package.json":"./package.json"},"release-it":{npm:{publish:!1},github:{release:!0,releaseName:"${npm.name} v${version}"},plugins:{"@release-it/conventional-changelog":{preset:{name:"conventionalcommits"},header:"# Changelog",ignoreVersion:!0,infile:"./CHANGELOG.md"}},git:{commitMessage:"chore: release ${npm.name} v${version}",tagName:"${npm.name}-v${version}"}}};var St=Fo.version;var po=require("@commander-js/extra-typings");var ap=[];function Cr(t){ap.push(t)}var N=l(require("chalk")),W=l(require("util"));var Tr=require("debug"),cp=l(require("fs-extra")),p=(0,Tr.debug)("currents"),pp=null;function Mo(){Tr.debug.enable("currents,currents:*")}function ko(t){pp=t}var jo=[],Go=[];var ae=(...t)=>{let e=W.default.format(...t);Cr(e),console.log(e)},$o=(...t)=>{let e=W.default.format(...t);Cr(e),console.error(e)},T=ae,I=(...t)=>{let e=W.default.format(...t);return Go.push(e),p("WARNING: ",e),ae(N.default.bgYellow.black(" WARNING "),e)},gt=(...t)=>{let e=W.default.format(...Ko(t));return p("WARNING: ",W.default.format(...t)),ae(N.default.bgYellow.black(" WARNING "),e)},ce=(...t)=>$o(N.default.bgYellow.black(" WARNING "),W.default.format(...t)),pe=(...t)=>ae(N.default.green.bold(W.default.format(...t))),C=(...t)=>{let e=W.default.format(...Ko(t));return jo.push(e),p("ERROR: ",W.default.format(...t)),$o(N.default.bgRed.white(" ERROR "),e)};var Ko=t=>t.map(e=>e instanceof Error?e.message:e),de=(t=2)=>console.log(Array(t).fill("").join(`
3
- `)),sl=N.default.cyan,il=N.default.blueBright,al=N.default.red,cl=N.default.yellow,pl=N.default.green,dl=N.default.gray,ml=N.default.white,ul=N.default.black,ll=N.default.magenta,x=N.default.dim,fl=N.default.bold;var Ho=80,yr=" ",mp=" ";function up(t){let e=t.match(/"[^"]*"|'[^']*'|\S+/g)??[],r=[];for(let o of e){let n=r[r.length-1];n?.startsWith("-")&&!n.includes(" ")&&!o.startsWith("-")?r[r.length-1]=`${n} ${o}`:r.push(o)}return r}function lp(t){if(t.includes(`
2
+ "use strict";var cp=Object.create;var yr=Object.defineProperty;var pp=Object.getOwnPropertyDescriptor;var dp=Object.getOwnPropertyNames;var mp=Object.getPrototypeOf,up=Object.prototype.hasOwnProperty;var lp=(t,e)=>{for(var r in e)yr(t,r,{get:e[r],enumerable:!0})},fp=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of dp(e))!up.call(t,n)&&n!==r&&yr(t,n,{get:()=>e[n],enumerable:!(o=pp(e,n))||o.enumerable});return t};var l=(t,e,r)=>(r=t!=null?cp(mp(t)):{},fp(e||!t||!t.__esModule?yr(r,"default",{value:t,enumerable:!0}):r,t));var Fx=require("source-map-support/register");var sp=require("@commander-js/extra-typings");var Go={name:"@currents/cmd",version:"2.2.0",main:"./dist/index.js",author:{name:"Currents Software Inc",email:"hello@currents.dev"},license:"MIT",repository:{type:"git",url:"https://github.com/currents-dev/currents-reporter"},description:"Currents CLI tools",engines:{node:">=20"},scripts:{test:"vitest",rm:"rimraf dist",lint:'TIMING=1 eslint "**/*.ts*"',types:"tsc --noEmit",build:"tsup-node --minify --dts",dev:"tsup-node --watch --dts",release:"release-it","publish:npm":"npm run rm && npm run build && ./publish.js"},devDependencies:{"@jest/reporters":"^30.4.1","@jest/types":"^30.4.1","@release-it/conventional-changelog":"^12.0.0","release-it":"^21.0.2","@types/archiver":"^6.0.3","@types/async-retry":"^1.4.9","@types/debug":"^4.1.12","@types/fs-extra":"^11.0.4","@types/getos":"^3.0.4","@types/lodash":"^4.17.16","@types/node":"^25.5.0","@types/proxy-from-env":"^1.0.4","@types/semver":"^7.5.8","@types/tmp":"^0.2.6","@types/unzipper":"^0.10.11","@types/uuid":"^10.0.0","@types/xml2js":"^0.4.14","@types/xxhashjs":"^0.2.4",jest:"^30.4.2","jest-cli":"^30.4.2","jest-config":"^30.4.2",rimraf:"^6.0.1",tsup:"^8.3.5",typescript:"^5.9.3",vitest:"^4.1.11"},dependencies:{"@commander-js/extra-typings":"^14.0.0","@currents/commit-info":"2.0.0",archiver:"^7.0.1","async-retry":"^1.3.3",axios:"1.20.0","axios-retry":"4.5.0",chalk:"^4.1.2",commander:"^14.0.0",debug:"^4.4.0",dotenv:"^17.4.2",execa:"^9.5.1","fs-extra":"^11.3.4",getos:"^3.2.1",globby:"^11.1.0","https-proxy-agent":"^7.0.4",lodash:"^4.18.1",nanoid:"^3.3.8","pretty-ms":"^7.0.1","proxy-from-env":"^1.1.0",semver:"^7.8.5","source-map-support":"^0.5.21",tmp:"^0.2.7","tmp-promise":"^3.0.3","ts-pattern":"^5.8.0",unzipper:"^0.12.3",uuid:"11.1.1",xml2js:"^0.6.2",xxhashjs:"^0.2.2"},bin:{currents:"./dist/bin/index.js","currents-cli":"./dist/bin/index.js"},files:["dist","docs","!**/*.map","!**/*/*.map"],keywords:["cloud test dashboard","test reporter","test results","currents","currents dashboard","ci"],exports:{".":{import:"./dist/index.js",require:"./dist/index.js",types:"./dist/index.d.ts"},"./discovery/jest":{import:"./dist/services/upload/discovery/jest/reporter.js",require:"./dist/services/upload/discovery/jest/reporter.js",types:"./dist/services/upload/discovery/jest/reporter.d.ts"},"./package.json":"./package.json"},"release-it":{npm:{publish:!1},github:{release:!0,releaseName:"${npm.name} v${version}"},plugins:{"@release-it/conventional-changelog":{preset:{name:"conventionalcommits"},header:"# Changelog",ignoreVersion:!0,infile:"./CHANGELOG.md"}},git:{commitMessage:"chore: release ${npm.name} v${version}",tagName:"${npm.name}-v${version}"}}};var At=Go.version;var lo=require("@commander-js/extra-typings");var hp=[];function Rr(t){hp.push(t)}var N=l(require("chalk")),q=l(require("util"));var wr=require("debug"),Ep=l(require("fs-extra")),p=(0,wr.debug)("currents"),Ip=null;function Ko(){wr.debug.enable("currents,currents:*")}function Ho(t){Ip=t}var Jo=[],Vo=[];var ce=(...t)=>{let e=q.default.format(...t);Rr(e),console.log(e)},Yo=(...t)=>{let e=q.default.format(...t);Rr(e),console.error(e)},T=ce,I=(...t)=>{let e=q.default.format(...t);return Vo.push(e),p("WARNING: ",e),ce(N.default.bgYellow.black(" WARNING "),e)},gt=(...t)=>{let e=q.default.format(...Wo(t));return p("WARNING: ",q.default.format(...t)),ce(N.default.bgYellow.black(" WARNING "),e)},pe=(...t)=>Yo(N.default.bgYellow.black(" WARNING "),q.default.format(...t)),de=(...t)=>ce(N.default.green.bold(q.default.format(...t))),C=(...t)=>{let e=q.default.format(...Wo(t));return Jo.push(e),p("ERROR: ",q.default.format(...t)),Yo(N.default.bgRed.white(" ERROR "),e)};var Wo=t=>t.map(e=>e instanceof Error?e.message:e),me=(t=2)=>console.log(Array(t).fill("").join(`
3
+ `)),Il=N.default.cyan,Cl=N.default.blueBright,Tl=N.default.red,yl=N.default.yellow,Rl=N.default.green,wl=N.default.gray,_l=N.default.white,Ol=N.default.black,xl=N.default.magenta,x=N.default.dim,Sl=N.default.bold;var qo=80,_r=" ",Tp=" ";function yp(t){let e=t.match(/"[^"]*"|'[^']*'|\S+/g)??[],r=[];for(let o of e){let n=r[r.length-1];n?.startsWith("-")&&!n.includes(" ")&&!o.startsWith("-")?r[r.length-1]=`${n} ${o}`:r.push(o)}return r}function Rp(t){if(t.includes(`
4
4
  `))return t.split(`
5
- `).map(o=>yr+o);let e=[],r=yr;for(let o of up(t)){let n=r.trim()==="";!n&&r.length+1+o.length+2>Ho?(e.push(`${r} \\`),r=mp+o):r=n?r+o:`${r} ${o}`}return[...e,r]}function fp(t){let e=`${yr}# `,r=[],o=e;for(let n of t.split(" "))o!==e&&o.length+1+n.length>Ho?(r.push(o),o=e+n):o=o===e?o+n:`${o} ${n}`;return[...r,o].map(n=>x(n))}function y(t){return`
5
+ `).map(o=>_r+o);let e=[],r=_r;for(let o of yp(t)){let n=r.trim()==="";!n&&r.length+1+o.length+2>qo?(e.push(`${r} \\`),r=Tp+o):r=n?r+o:`${r} ${o}`}return[...e,r]}function wp(t){let e=`${_r}# `,r=[],o=e;for(let n of t.split(" "))o!==e&&o.length+1+n.length>qo?(r.push(o),o=e+n):o=o===e?o+n:`${o} ${n}`;return[...r,o].map(n=>x(n))}function y(t){return`
6
6
  Examples:
7
- ${t.map(r=>[...fp(r.comment),...r.commands.flatMap(lp)].join(`
7
+ ${t.map(r=>[...wp(r.comment),...r.commands.flatMap(Rp)].join(`
8
8
  `)).join(`
9
9
 
10
10
  `)}
11
- `}var Rr=l(require("lodash")),gp=["apiKey","recordKey","key"];function Jo(t,e){return Rr.default.isPlainObject(t)?Rr.default.mapValues(t,(r,o)=>e.includes(o)&&r!==void 0?"*****":Jo(r,e)):t}function h(t){return Jo(t,gp)}var q=class extends Error{};var z=l(require("fs-extra")),Vt=require("path"),Vo=require("uuid");async function ht(t){try{return await z.default.readJson(t)}catch(e){throw C("Error while reading JSON file: %s",t,e),C}}async function Et(t,e){try{return await z.default.writeFile(t,e,"utf8"),t}catch(r){throw C(`Error writing file at ${t}:`,r),r}}async function Yt(t,e){try{try{return await z.default.access(t),t}catch{return await z.default.writeFile(t,e,"utf8"),t}}catch(r){throw C(`Error writing file at ${t}:`,r),r}}async function Yo(t,e){if(e){await z.default.ensureDir(t);return}let r=(0,Vt.dirname)(t);await z.default.ensureDir(r)}function hp(){let t=new Date().toISOString().replace(/[:.]/g,"-"),e=(0,Vo.v4)();return`${t}-${e}`}async function Wo(t,e){let r=hp(),o=(0,Vt.join)(t,e,r);return It(o)}async function It(t){try{return await z.default.ensureDir(t),p("Folder created",t),t}catch(e){throw C(`Failed to create folder at ${t}:`,e),e}}async function me(t,e){try{return await z.default.ensureDir((0,Vt.dirname)(e)),await z.default.copy(t,e),p("File copied from %s to %s",t,e),e}catch(r){throw C(`Failed to copy file from ${t} to ${e}:`,r),r}}var qo=l(require("crypto"));function rt(t){return qo.createHash("sha256").update(t).digest("base64").slice(0,8).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var ue={};np(ue,{getNanoid:()=>wr,userFacingNanoid:()=>Or});var _r=require("nanoid"),zo="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",wr=(t=16)=>(0,_r.customAlphabet)(zo,t)(),Or=(0,_r.customAlphabet)(zo,12);function xr(t){return t.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^/?#\s]*@/i,"$1")}function At(t){return xr(t).replace(/[?#].*$/,"")}function Ep(t){return Object.entries(t??{}).reduce((e,[r,o])=>o===void 0?e:{...e,[r]:o},{})}function Qo(t){if(!(t===void 0||t.trim()===""))return!["false","0","no","off"].includes(t.trim().toLowerCase())}function L(t,e){return"env"in t[e]&&t[e].env?t[e].env:""}function le(t,e){return t[e].cli}function fe(t,e){return t[e].name}function U(t,e,r,o){let n=Ep(r);return e.forEach(s=>{if(!n[s]){let i=s,c=L(t,i);throw C(`${fe(t,i)} is required: pass ${x(le(t,i))}${c?` or set ${x(c)}`:""}`),new q("Missing required config variable")}}),typeof o=="function"&&o(n),n}var _={apiKey:{name:"API key",env:"CURRENTS_API_KEY",cli:"--api-key"},recordKey:{name:"Record key",env:"CURRENTS_RECORD_KEY",cli:"--key"},projectId:{name:"Project ID",env:"CURRENTS_PROJECT_ID",cli:"--project-id"},ciBuildId:{name:"CI build ID",env:"CURRENTS_CI_BUILD_ID",cli:"--ci-build-id"},machineId:{name:"Machine ID",env:"CURRENTS_MACHINE_ID",cli:"--machine-id"},tag:{name:"Tag",cli:"--tag"},debug:{name:"Debug",env:"CURRENTS_DEBUG",cli:"--debug"}};var{apiKey:Ip,debug:Cp,ciBuildId:Tp,projectId:yp,tag:Rp}=_,ge={apiKey:Ip,debug:Cp,ciBuildId:Tp,projectId:yp,tag:Rp,branch:{name:"Branch",cli:"--branch"},output:{name:"Output file",env:"CURRENTS_OUTPUT",cli:"--output"}};var _p=p.extend("config"),wp=["apiKey","projectId"],Op=t=>{let{ciBuildId:e,tag:r,branch:o}=t;if(!([e,r,o].filter(Boolean).length===1||r&&o&&!e))throw C("Pass --ci-build-id, or --branch, --tag or both"),new q("Missing or invalid parameters")},Sr=null;function Xo(t){Sr=U(ge,wp,t,Op),_p("Resolved config: %o",h(Sr))}function he(){return Sr}var Nn=require("fs/promises");function Dt({apiKey:t,recordKey:e}){return e?{"x-currents-key":e}:t?{Authorization:`Bearer ${t}`}:{}}var hn=l(require("lodash"));var cn=l(require("axios")),pn=l(require("axios-retry")),br=l(require("lodash"));var Zo=()=>process.env.CURRENTS_API_URL??"https://cy.currents.dev",Wt=()=>process.env.CURRENTS_REST_API_URL??"https://api.currents.dev",tn=()=>3e4;var Ee=require("axios"),Ar=l(require("pretty-ms"));var rn=p.extend("http"),en=[3*1e3,15*1e3,30*1e3],on=60*1e3;function Te(t,e=Date.now()){let r=t?.response?.headers?.["retry-after"];if(r==null||r==="")return;let o=Number(r);if(Number.isFinite(o))return Math.max(0,o*1e3);let n=Date.parse(String(r));return Number.isNaN(n)?void 0:Math.max(0,n-e)}var Ie=(t,e)=>{let r=en[Math.min(t,en.length)-1],o=Te(e);return o===void 0?r:Math.min(Math.max(o,r),on)},Dr=t=>(rn("isRetriableError: %o",{message:t.message,code:"code"in t?t.code:void 0,status:"response"in t?t.response?.status:void 0,headers:"response"in t?t.response?.headers:void 0,data:"response"in t?t.response?.data:void 0,isAxiosError:(0,Ee.isAxiosError)(t)}),"code"in t&&t.code&&["ECONNABORTED","ECONNREFUSED","ECONNRESET","ETIMEDOUT","ENETRESET"].includes(t.code)?!0:(0,Ee.isAxiosError)(t)?[408,429,502,503,504].includes(t.response?.status??0):!1),xp=["get","head","options","put","delete"],nn=t=>{if(!(0,Ee.isAxiosError)(t))return!1;let e=t.response?.status;if(e===429){let r=Te(t);return r===void 0||r<=on}return xp.includes(t.config?.method?.toLowerCase()??"get")?Dr(t):e===408||t.code==="ECONNREFUSED"||t.code==="ENOTFOUND"},Ce=()=>3;function sn(t,e,r){rn("Network request '%s' failed: '%s'. Next attempt is in %s (%d/%d).",`${r.method?.toUpperCase()} ${r.url}`,e.message,(0,Ar.default)(Ie(t,e)??0),t,Ce()),I("Network request '%s' failed: '%s'. Next attempt is in %s (%d/%d).",`${r.method?.toUpperCase()} ${r.url}`,e.message,(0,Ar.default)(Ie(t,e)??0),t,Ce())}var Ur=p.extend("http");var Pr={api:null,restApi:null};function Sp(t){let e=t==="api"?Zo():Wt();Ur("client base url: %s",e);let r=cn.default.create({baseURL:e,timeout:tn(),transitional:{clarifyTimeoutError:!0}});return r.interceptors.request.use(o=>{let n=o["axios-retry"]?.retryCount??0;o.headers.set({"x-cmd-version":St}),o.headers.get("Content-Type")||o.headers.set("Content-Type","application/json");let s={...br.default.pick(o,"method","url","headers"),baseURL:e,data:Buffer.isBuffer(o.data)?"buffer":o.data,params:o.params};return n?Ur("network request retry: %o",an({...s,baseURL:e,isRetry:!0})):Ur("network request: %o",an(s)),o}),(0,pn.default)(r,{retries:Ce(),retryCondition:t==="restApi"?nn:Dr,retryDelay:(o,n)=>Ie(o,n),shouldResetTimeout:!0,onRetry:sn}),r}function Ut(t){return Pr[t]===null&&(Pr[t]=Sp(t)),Pr[t]}function an(t){return{method:t.method,baseURL:t.baseURL,url:t.url,data:t.isRetry?"<retry>":Ap(t.data),params:t.isRetry?"<retry>":t.params,headers:{...t.headers,Authorization:"Bearer ***","x-currents-key":"***"}}}function Ap(t){if(t?.results?.raw)return h({...t,results:{...t.results,raw:"***"}});if(typeof t=="string")try{return h(JSON.parse(t))}catch{return t}return br.default.isPlainObject(t)?h(t):t}var un=require("axios"),ln=l(require("lodash")),B=require("ts-pattern");function fn(t){(0,B.match)(t).when(un.isAxiosError,Dp).otherwise(()=>{I("Unexpected error while sending network request: %s",t)})}function Dp(t){return(0,B.match)(t).with({code:"ECONNABORTED"},()=>{I("Network connection aborted")}).with({code:"ECONNREFUSED"},()=>{I("Network connection aborted")}).with({code:"ECONNRESET"},()=>{I("Network connection reset")}).with({code:"ETIMEDOUT"},()=>{I("Network connection timeout")}).with({response:B.P.not(B.P.nullish)},e=>{Up(e,{status:e.response.status,data:e.response.data})}).otherwise(e=>{I(`[currents] Unexpected network error: %s
12
- %O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status,payload:t.response?.config.data})})}function Up(t,{status:e,data:r}){(0,B.match)(e).with(401,()=>{I(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 401 Unauthorized Request from cloud service`)}).with(400,()=>{I(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 400 Bad Request from cloud service:
13
- %o`,r)}).with(404,()=>{I(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 404 Not Found from cloud service`)}).with(429,()=>{I(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 429 Too Many Requests from cloud service`)}).with(422,()=>{Pp(t,r)}).otherwise(()=>{I(`[currents] Unexpected network response: %s
14
- %O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}function Pp(t,e){(0,B.match)(e).with({code:dn.MISSING_SUITE,message:B.P.string,errors:B.P.array(B.P.string)},async r=>{let{message:o,errors:n}=r;de(1),C(...mn(o,n))}).with({code:dn.RUN_EXPIRED,message:B.P.string},r=>{I(r.message)}).with({message:B.P.string,errors:B.P.array(B.P.string)},r=>{let{message:o,errors:n}=r;de(1),I(...mn(o,n)),de(1)}).otherwise(()=>{I(`[currents] Unexpected network response: %s
15
- %O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}var dn={RUN_CANCELLED:"RUN_CANCELLED",RUN_EXPIRED:"RUN_EXPIRED",MISSING_SUITE:"MISSING_SUITE"};function mn(t,e){return ln.default.isString(t)?e?.length===0?[t]:[t,`
11
+ `}var Or=l(require("lodash")),_p=["apiKey","recordKey","key"];function zo(t,e){return Or.default.isPlainObject(t)?Or.default.mapValues(t,(r,o)=>e.includes(o)&&r!==void 0?"*****":zo(r,e)):t}function h(t){return zo(t,_p)}var z=class extends Error{};var K=l(require("fs-extra")),ht=require("path"),Qo=require("uuid");async function Et(t){try{return await K.default.readJson(t)}catch(e){throw C("Error while reading JSON file: %s",t,e),C}}async function It(t,e){try{return await K.default.writeFile(t,e,"utf8"),t}catch(r){throw C(`Error writing file at ${t}:`,r),r}}async function Yt(t,e){try{try{return await K.default.access(t),t}catch{return await K.default.writeFile(t,e,"utf8"),t}}catch(r){throw C(`Error writing file at ${t}:`,r),r}}async function Xo(t,e){if(e){await K.default.ensureDir(t);return}let r=(0,ht.dirname)(t);await K.default.ensureDir(r)}function Op(){let t=new Date().toISOString().replace(/[:.]/g,"-"),e=(0,Qo.v4)();return`${t}-${e}`}async function Zo(t,e){let r=Op(),o=(0,ht.join)(t,e,r);return Ct(o)}async function Ct(t){try{return await K.default.ensureDir(t),p("Folder created",t),t}catch(e){throw C(`Failed to create folder at ${t}:`,e),e}}async function ue(t,e){try{return await K.default.ensureDir((0,ht.dirname)(e)),await K.default.copy(t,e),p("File copied from %s to %s",t,e),e}catch(r){throw C(`Failed to copy file from ${t} to ${e}:`,r),r}}function le(t,e){let r=e;for(;!K.default.existsSync((0,ht.join)(r,t));){let o=(0,ht.dirname)(r);if(o===r)return;r=o}return r}var tn=l(require("crypto"));function et(t){return tn.createHash("sha256").update(t).digest("base64").slice(0,8).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var fe={};lp(fe,{getNanoid:()=>Sr,userFacingNanoid:()=>Ar});var xr=require("nanoid"),en="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Sr=(t=16)=>(0,xr.customAlphabet)(en,t)(),Ar=(0,xr.customAlphabet)(en,12);function Dr(t){return t.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^/?#\s]*@/i,"$1")}function Dt(t){return Dr(t).replace(/[?#].*$/,"")}function xp(t){return Object.entries(t??{}).reduce((e,[r,o])=>o===void 0?e:{...e,[r]:o},{})}function rn(t){if(!(t===void 0||t.trim()===""))return!["false","0","no","off"].includes(t.trim().toLowerCase())}function L(t,e){return"env"in t[e]&&t[e].env?t[e].env:""}function ge(t,e){return t[e].cli}function he(t,e){return t[e].name}function U(t,e,r,o){let n=xp(r);return e.forEach(s=>{if(!n[s]){let i=s,c=L(t,i);throw C(`${he(t,i)} is required: pass ${x(ge(t,i))}${c?` or set ${x(c)}`:""}`),new z("Missing required config variable")}}),typeof o=="function"&&o(n),n}var _={apiKey:{name:"API key",env:"CURRENTS_API_KEY",cli:"--api-key"},recordKey:{name:"Record key",env:"CURRENTS_RECORD_KEY",cli:"--key"},projectId:{name:"Project ID",env:"CURRENTS_PROJECT_ID",cli:"--project-id"},ciBuildId:{name:"CI build ID",env:"CURRENTS_CI_BUILD_ID",cli:"--ci-build-id"},machineId:{name:"Machine ID",env:"CURRENTS_MACHINE_ID",cli:"--machine-id"},tag:{name:"Tag",cli:"--tag"},debug:{name:"Debug",env:"CURRENTS_DEBUG",cli:"--debug"}};var{apiKey:Sp,debug:Ap,ciBuildId:Dp,projectId:Up,tag:Pp}=_,Ee={apiKey:Sp,debug:Ap,ciBuildId:Dp,projectId:Up,tag:Pp,branch:{name:"Branch",cli:"--branch"},output:{name:"Output file",env:"CURRENTS_OUTPUT",cli:"--output"}};var bp=p.extend("config"),Np=["apiKey","projectId"],Lp=t=>{let{ciBuildId:e,tag:r,branch:o}=t;if(!([e,r,o].filter(Boolean).length===1||r&&o&&!e))throw C("Pass --ci-build-id, or --branch, --tag or both"),new z("Missing or invalid parameters")},Ur=null;function on(t){Ur=U(Ee,Np,t,Lp),bp("Resolved config: %o",h(Ur))}function Ie(){return Ur}var Mn=require("fs/promises");function Ut({apiKey:t,recordKey:e}){return e?{"x-currents-key":e}:t?{Authorization:`Bearer ${t}`}:{}}var yn=l(require("lodash"));var ln=l(require("axios")),fn=l(require("axios-retry")),vr=l(require("lodash"));var nn=()=>process.env.CURRENTS_API_URL??"https://cy.currents.dev",Wt=()=>process.env.CURRENTS_REST_API_URL??"https://api.currents.dev",sn=()=>3e4;var Ce=require("axios"),Pr=l(require("pretty-ms"));var cn=p.extend("http"),an=[3*1e3,15*1e3,30*1e3],pn=60*1e3;function Re(t,e=Date.now()){let r=t?.response?.headers?.["retry-after"];if(r==null||r==="")return;let o=Number(r);if(Number.isFinite(o))return Math.max(0,o*1e3);let n=Date.parse(String(r));return Number.isNaN(n)?void 0:Math.max(0,n-e)}var Te=(t,e)=>{let r=an[Math.min(t,an.length)-1],o=Re(e);return o===void 0?r:Math.min(Math.max(o,r),pn)},br=t=>(cn("isRetriableError: %o",{message:t.message,code:"code"in t?t.code:void 0,status:"response"in t?t.response?.status:void 0,headers:"response"in t?t.response?.headers:void 0,data:"response"in t?t.response?.data:void 0,isAxiosError:(0,Ce.isAxiosError)(t)}),"code"in t&&t.code&&["ECONNABORTED","ECONNREFUSED","ECONNRESET","ETIMEDOUT","ENETRESET"].includes(t.code)?!0:(0,Ce.isAxiosError)(t)?[408,429,502,503,504].includes(t.response?.status??0):!1),vp=["get","head","options","put","delete"],dn=t=>{if(!(0,Ce.isAxiosError)(t))return!1;let e=t.response?.status;if(e===429){let r=Re(t);return r===void 0||r<=pn}return vp.includes(t.config?.method?.toLowerCase()??"get")?br(t):e===408||t.code==="ECONNREFUSED"||t.code==="ENOTFOUND"},ye=()=>3;function mn(t,e,r){cn("Network request '%s' failed: '%s'. Next attempt is in %s (%d/%d).",`${r.method?.toUpperCase()} ${r.url}`,e.message,(0,Pr.default)(Te(t,e)??0),t,ye()),I("Network request '%s' failed: '%s'. Next attempt is in %s (%d/%d).",`${r.method?.toUpperCase()} ${r.url}`,e.message,(0,Pr.default)(Te(t,e)??0),t,ye())}var Nr=p.extend("http");var Lr={api:null,restApi:null};function Bp(t){let e=t==="api"?nn():Wt();Nr("client base url: %s",e);let r=ln.default.create({baseURL:e,timeout:sn(),transitional:{clarifyTimeoutError:!0}});return r.interceptors.request.use(o=>{let n=o["axios-retry"]?.retryCount??0;o.headers.set({"x-cmd-version":At}),o.headers.get("Content-Type")||o.headers.set("Content-Type","application/json");let s={...vr.default.pick(o,"method","url","headers"),baseURL:e,data:Buffer.isBuffer(o.data)?"buffer":o.data,params:o.params};return n?Nr("network request retry: %o",un({...s,baseURL:e,isRetry:!0})):Nr("network request: %o",un(s)),o}),(0,fn.default)(r,{retries:ye(),retryCondition:t==="restApi"?dn:br,retryDelay:(o,n)=>Te(o,n),shouldResetTimeout:!0,onRetry:mn}),r}function Pt(t){return Lr[t]===null&&(Lr[t]=Bp(t)),Lr[t]}function un(t){return{method:t.method,baseURL:t.baseURL,url:t.url,data:t.isRetry?"<retry>":Fp(t.data),params:t.isRetry?"<retry>":t.params,headers:{...t.headers,Authorization:"Bearer ***","x-currents-key":"***"}}}function Fp(t){if(t?.results?.raw)return h({...t,results:{...t.results,raw:"***"}});if(typeof t=="string")try{return h(JSON.parse(t))}catch{return t}return vr.default.isPlainObject(t)?h(t):t}var En=require("axios"),In=l(require("lodash")),B=require("ts-pattern");function Cn(t){(0,B.match)(t).when(En.isAxiosError,Mp).otherwise(()=>{I("Unexpected error while sending network request: %s",t)})}function Mp(t){return(0,B.match)(t).with({code:"ECONNABORTED"},()=>{I("Network connection aborted")}).with({code:"ECONNREFUSED"},()=>{I("Network connection aborted")}).with({code:"ECONNRESET"},()=>{I("Network connection reset")}).with({code:"ETIMEDOUT"},()=>{I("Network connection timeout")}).with({response:B.P.not(B.P.nullish)},e=>{kp(e,{status:e.response.status,data:e.response.data})}).otherwise(e=>{I(`[currents] Unexpected network error: %s
12
+ %O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status,payload:t.response?.config.data})})}function kp(t,{status:e,data:r}){(0,B.match)(e).with(401,()=>{I(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 401 Unauthorized Request from cloud service`)}).with(400,()=>{I(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 400 Bad Request from cloud service:
13
+ %o`,r)}).with(404,()=>{I(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 404 Not Found from cloud service`)}).with(429,()=>{I(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 429 Too Many Requests from cloud service`)}).with(422,()=>{jp(t,r)}).otherwise(()=>{I(`[currents] Unexpected network response: %s
14
+ %O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}function jp(t,e){(0,B.match)(e).with({code:gn.MISSING_SUITE,message:B.P.string,errors:B.P.array(B.P.string)},async r=>{let{message:o,errors:n}=r;me(1),C(...hn(o,n))}).with({code:gn.RUN_EXPIRED,message:B.P.string},r=>{I(r.message)}).with({message:B.P.string,errors:B.P.array(B.P.string)},r=>{let{message:o,errors:n}=r;me(1),I(...hn(o,n)),me(1)}).otherwise(()=>{I(`[currents] Unexpected network response: %s
15
+ %O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}var gn={RUN_CANCELLED:"RUN_CANCELLED",RUN_EXPIRED:"RUN_EXPIRED",MISSING_SUITE:"MISSING_SUITE"};function hn(t,e){return In.default.isString(t)?e?.length===0?[t]:[t,`
16
16
  ${(e??[]).map(r=>` - ${r}`).join(`
17
17
  `)}
18
- `]:["Unexpected network error"]}var gn=p.extend("http");async function Q(t,e,r=Ut){try{let o=await r(t).request(e);return gn("network response: %o",{...hn.default.omit(o,"request","config"),url:o.config.url,method:o.config.method}),o}catch(o){let n=o;throw gn("network error: %o",{code:n.code,message:n.message,url:n.config?.url,method:n.config?.method,status:n.response?.status,headers:n.response?.headers,data:n.response?.data}),fn(n),n}}var Pt=p.extend("api");async function En(t){try{return Pt("Request params: %o",h(t)),Q("api",{url:"cache/upload",method:"POST",data:t}).then(e=>e.data)}catch(e){throw Pt("Failed to create cache:",e),e}}async function In(t){try{return Pt("Request params: %o",h(t)),Q("api",{url:"cache/v2/download",method:"POST",data:t}).then(e=>e.data)}catch(e){throw Pt("Failed to retrieve cache:",e),e}}async function Cn(t){try{return Pt("Request params: %o",h(t)),Q("api",{url:"cache/meta",method:"POST",data:t}).then(e=>e.data)}catch(e){throw Pt("Failed to retrieve reference cache meta:",e),e}}var bp=p.extend("api");async function Tn(t){return bp("Cancel params: %o",h(t)),(await Q("api",{url:"v1/runs/cancel",method:"POST",data:t})).data}var Rn=require("util"),_n=require("zlib");var yn=p.extend("api"),Np=(0,Rn.promisify)(_n.gzip);async function wn(t){try{yn("Run params: %o",h(t));let e=await Lp(JSON.stringify(t));return Q("api",{url:"v1/runs",method:"POST",headers:{"Content-Type":"application/json","Content-Encoding":"gzip"},data:e}).then(r=>r.data)}catch(e){throw yn("Failed to create the run:",e),e}}async function Lp(t){try{return await Np(t)}catch(e){throw C("Failed to compress run payload:",e),e}}var On=p.extend("api");async function xn(t,e){try{return On("Run params: %o",e),Q("restApi",{url:"v1/runs/find",params:e,method:"GET",headers:{"Content-Type":"application/json",...Dt({apiKey:t})}}).then(r=>r.data)}catch(r){throw On("Failed to obtain run data:",r),r}}var Sn=require("axios");var An=p.extend("api");function vp(t){if(!(0,Sn.isAxiosError)(t)||!t.response)return t;let e=t.response.data,r=[`${t.response.status}`];e?.code&&r.push(e.code);let o=e?.error??t.message,n=Te(t),s=n?` Retry in ${Math.ceil(n/1e3)} seconds.`:"",i=Bp(e?.candidates);return new Error(`${r.join(" ")}: ${o}${s}${i}`)}function Bp(t){return!Array.isArray(t)||t.length===0?"":`
18
+ `]:["Unexpected network error"]}var Tn=p.extend("http");async function Q(t,e,r=Pt){try{let o=await r(t).request(e);return Tn("network response: %o",{...yn.default.omit(o,"request","config"),url:o.config.url,method:o.config.method}),o}catch(o){let n=o;throw Tn("network error: %o",{code:n.code,message:n.message,url:n.config?.url,method:n.config?.method,status:n.response?.status,headers:n.response?.headers,data:n.response?.data}),Cn(n),n}}var bt=p.extend("api");async function Rn(t){try{return bt("Request params: %o",h(t)),Q("api",{url:"cache/upload",method:"POST",data:t}).then(e=>e.data)}catch(e){throw bt("Failed to create cache:",e),e}}async function wn(t){try{return bt("Request params: %o",h(t)),Q("api",{url:"cache/v2/download",method:"POST",data:t}).then(e=>e.data)}catch(e){throw bt("Failed to retrieve cache:",e),e}}async function _n(t){try{return bt("Request params: %o",h(t)),Q("api",{url:"cache/meta",method:"POST",data:t}).then(e=>e.data)}catch(e){throw bt("Failed to retrieve reference cache meta:",e),e}}var $p=p.extend("api");async function On(t){return $p("Cancel params: %o",h(t)),(await Q("api",{url:"v1/runs/cancel",method:"POST",data:t})).data}var Sn=require("util"),An=require("zlib");var xn=p.extend("api"),Gp=(0,Sn.promisify)(An.gzip);async function Dn(t){try{xn("Run params: %o",h(t));let e=await Kp(JSON.stringify(t));return Q("api",{url:"v1/runs",method:"POST",headers:{"Content-Type":"application/json","Content-Encoding":"gzip"},data:e}).then(r=>r.data)}catch(e){throw xn("Failed to create the run:",e),e}}async function Kp(t){try{return await Gp(t)}catch(e){throw C("Failed to compress run payload:",e),e}}var Un=p.extend("api");async function Pn(t,e){try{return Un("Run params: %o",e),Q("restApi",{url:"v1/runs/find",params:e,method:"GET",headers:{"Content-Type":"application/json",...Ut({apiKey:t})}}).then(r=>r.data)}catch(r){throw Un("Failed to obtain run data:",r),r}}var bn=require("axios");var Nn=p.extend("api");function Hp(t){if(!(0,bn.isAxiosError)(t)||!t.response)return t;let e=t.response.data,r=[`${t.response.status}`];e?.code&&r.push(e.code);let o=e?.error??t.message,n=Re(t),s=n?` Retry in ${Math.ceil(n/1e3)} seconds.`:"",i=Jp(e?.candidates);return new Error(`${r.join(" ")}: ${o}${s}${i}`)}function Jp(t){return!Array.isArray(t)||t.length===0?"":`
19
19
  Matches:
20
20
  ${t.map(({spec:r,title:o,instanceId:n,testId:s,runId:i,ciBuildId:c})=>i?` - run ${i} (CI build ID ${c})`:` - ${[r,o].filter(Boolean).join(" > ")} (instance ${n}${s?`, test ${s}`:""})`).join(`
21
- `)}`}async function zt(t,e,r){try{return(await Ut("restApi").post(t,r,{headers:Dt(e)})).data.data}catch(o){throw vp(o)}}function Dn(t,e){return An("Create session params: %o",e),zt("v1/sessions",t,e)}function Un(t,e,r,o){return An("Create attachments: %o",{owner:e,target:r,attachments:o}),"sessionId"in e?zt(`v1/sessions/${encodeURIComponent(e.sessionId)}/attachments`,t,{attachments:o}):"runId"in e?zt(`v1/runs/${encodeURIComponent(e.runId)}/attachments`,t,{...r,attachments:o}):zt("v1/runs/attachments",t,{...e,...r,attachments:o})}function Pn(t,e){return zt("v1/share",t,e)}function bn(t,e){return Ut("restApi").request({...e,headers:{...Dt({apiKey:t}),...e.headers},responseType:"text",transformResponse:r=>r})}async function Nr(){try{let t=he();if(!t)throw new Error("Config is missing!");let e=t.ciBuildId?{projectId:t.projectId,ciBuildId:t.ciBuildId,pwLastRun:t.pwLastRun}:{projectId:t.projectId,branch:t.branch,tag:t.tag,pwLastRun:t.pwLastRun},r=await xn(t.apiKey,e);if(t.pwLastRun&&!r.data.pwLastRun)throw new Error("The API answered without the status and failed tests of the run (pwLastRun). Nothing was written.");await Fp(t.pwLastRun?r.data.pwLastRun:r.data,t)}catch(t){throw p("Failed to get run data"),t}}async function Fp(t,e){let r=JSON.stringify(t,null,2);e.output?(await Yo(e.output),await(0,Nn.writeFile)(e.output,r,"utf-8"),T(`Successfully written to ${e.output}`)):process.stdout.write(r+`
22
- `)}var Us=require("axios"),Jr=l(require("path"));var F=require("@commander-js/extra-typings");var Ln=require("@commander-js/extra-typings");function ye(t,e=[]){return t?e.concat(t.split(",").map(r=>r.trim())):e}function vn(t){for(let e of t.options){let r=e.attributeName();if(!e.envVar||!e.isBoolean()||t.getOptionValueSource(r)!=="env")continue;let o=Qo(process.env[e.envVar]);t.setOptionValueWithSource(r,o??e.defaultValue,o===void 0?"default":"env")}}function Mp(t,e){if(!Array.isArray(t))return String(t)===e;let r=o=>o.map(n=>n.trim()).filter(Boolean).join(",");return r(t.map(String))===r(e.split(","))}function Bn(t){for(let e of t.options){let r=e.attributeName(),o=e.envVar?process.env[e.envVar]:void 0,n=t.getOptionValue(r);!o||e.isBoolean()||t.getOptionValueSource(r)!=="cli"||Mp(n,o)||ce(`${e.long} and ${e.envVar} are set to different values; using ${e.long}`)}}function bt(){console.log=(...t)=>console.error(...t)}async function w(t,e){try{e.debug&&Mo(),await t(e),process.exit(0)}catch(r){C(r.message);let o=r instanceof Ln.CommanderError?r.exitCode:1;process.exit(o)}}var Fn="Without it the ID comes from the CI job: on GitHub Actions the repository, the run ID and --matrix-index; on GitLab the pipeline ID and the job name; on other CI the variables that identify the pipeline and the job, and --matrix-index. When no CI job is detected the ID is random, so pass --id",Mn=new F.Option("--id <id>",`the ID to save the files under. ${Fn}`),kn=new F.Option("--id <id>",`the ID the files were saved under. ${Fn}`),jn=new F.Option("--path <path>",'comma-separated paths or glob patterns of the files to save, inside the current folder; quote globs, e.g. "dist/**/*". At most 50 MB zipped').argParser(ye),Qt=(e=>(e.lastRun="last-run",e))(Qt||{}),Gn=new F.Option("--preset <preset-name>",'"last-run" saves the Playwright .last-run.json files of --pw-output-dir, to rerun only the failed tests').choices(Object.values(Qt)),$n=new F.Option("--preset <preset-name>",'"last-run" restores the saved .last-run.json files and writes the Playwright options for the rerun to --preset-output').choices(Object.values(Qt)),Kn=new F.Option("--output-dir <folder>","the folder to restore the files to; by default the current folder"),Hn=new F.Option("--pw-output-dir <folder>","the Playwright output folder that holds .last-run.json").default("test-results"),Xt=".currents_env",Jn=new F.Option("--preset-output <path>",'the file the "last-run" preset writes, relative to the current folder. On GitHub Actions and CircleCI it holds options for "playwright test"; on GitLab the shell variables EXTRA_PW_FLAGS, EXTRA_PWCP_FLAGS and RUN_ATTEMPT, to source. Nothing is written on other CI').default(Xt),Lr=new F.Option("--matrix-index <number>","the index of this job among parallel jobs, from 1; each job has its own cache. Pass it when the CI does not tell the jobs apart, as in a GitHub Actions matrix").default(1).argParser(Vn),vr=new F.Option("--matrix-total <number>","GitHub Actions only: the number of jobs in the matrix, for the shards that the last-run preset writes").default(1).argParser(Vn);function Vn(t){let e=parseInt(t,10);if(isNaN(e)||e<=0||!Number.isInteger(e))throw new F.InvalidArgumentError("A positive integer is expected.");return e}var Yn=new F.Option("--continue","exit with 0 when the cache is not found").default(!1),Wn=new F.Option("--continue","exit with 0 when no files are found, and save the cache without files").default(!1);var kp={recordKey:_.recordKey,debug:_.debug},jp={id:{name:"Cache id",cli:"--id"},preset:{name:"Preset",cli:"--preset"},pwOutputDir:{name:"Playwright output folder",cli:"--pw-output-dir"},presetOutput:{name:"Preset output path",cli:"--preset-output"},path:{name:"Paths to cache",cli:"--path"},matrixIndex:{name:"Matrix index",cli:"--matrix-index"},matrixTotal:{name:"Matrix total",cli:"--matrix-total"},continue:{name:"Continue when upload path missing",cli:"--continue"}},Gp={id:{name:"Cache id",cli:"--id"},preset:{name:"Preset",cli:"--preset"},outputDir:{name:"Output folder",cli:"--output-dir"},matrixIndex:{name:"Matrix index",cli:"--matrix-index"},matrixTotal:{name:"Matrix total",cli:"--matrix-total"},continue:{name:"Continue on cache miss",cli:"--continue"}},Br={...kp,...jp,...Gp};var qn=p.extend("config"),zn=["recordKey"],Ct;function Qn(t){Ct={type:"SET_COMMAND_CONFIG",values:U(Br,zn,t)},qn("Resolved config: %o",{...Ct,values:h(Ct.values)})}function Xn(t){Ct={type:"GET_COMMAND_CONFIG",values:U(Br,zn,t)},qn("Resolved config: %o",{...Ct,values:h(Ct.values)})}function dt(){return Ct}function Zn(t){return{recordKey:t.key,id:t.id,preset:t.preset,outputDir:t.outputDir,presetOutput:t.presetOutput,debug:t.debug,matrixIndex:t.matrixIndex,matrixTotal:t.matrixTotal,continue:t.continue}}function ts(t){return{recordKey:t.key,id:t.id,preset:t.preset,pwOutputDir:t.pwOutputDir,path:t.path,debug:t.debug,matrixIndex:t.matrixIndex,matrixTotal:t.matrixTotal,continue:t.continue}}var R=require("lodash");var Re=p.extend("ci"),$p=(t,e)=>(0,R.set)(t,(0,R.camelCase)(e),process.env[e]),P=t=>(0,R.transform)(t,$p,{}),Kp=()=>process.env.TF_BUILD&&process.env.AZURE_HTTP_USER_AGENT,Hp=()=>(0,R.some)(process.env,(t,e)=>/^CODEBUILD_/.test(e)),Jp=()=>process.env.bamboo_buildNumber,Vp=()=>(0,R.some)(process.env,(t,e)=>/^CONCOURSE_/.test(e)),Yp=()=>process.env.GITLAB_CI||process.env.CI_SERVER_NAME&&/^GitLab/.test(process.env.CI_SERVER_NAME),Wp=()=>!!(process.env.BUILD_ID&&process.env.PROJECT_ID&&process.env.PROJECT_NUMBER||process.env.GCP_PROJECT||process.env.GCLOUD_PROJECT||process.env.GOOGLE_CLOUD_PROJECT),qp=()=>process.env.JENKINS_URL||process.env.JENKINS_HOME||process.env.JENKINS_VERSION||process.env.HUDSON_URL||process.env.HUDSON_HOME,zp={appveyor:"APPVEYOR",azure:Kp,awsCodeBuild:Hp,bamboo:Jp,bitbucket:"BITBUCKET_BUILD_NUMBER",buildkite:"BUILDKITE",circle:"CIRCLECI",concourse:Vp,codeFresh:"CF_BUILD_ID",drone:"DRONE",githubActions:"GITHUB_ACTIONS",gitlab:Yp,goCD:"GO_JOB_NAME",jenkins:qp,googleCloud:Wp,semaphore:"SEMAPHORE",teamcity:"TEAMCITY_VERSION",travis:"TRAVIS",netlify:"NETLIFY"};function Qp(){let{env:t}=process;return(0,R.findKey)(zp,e=>{if((0,R.isString)(e))return t[e];if((0,R.isFunction)(e))return e()})}var es=()=>({appveyor:P(["APPVEYOR_JOB_ID","APPVEYOR_ACCOUNT_NAME","APPVEYOR_PROJECT_SLUG","APPVEYOR_BUILD_NUMBER","APPVEYOR_BUILD_VERSION","APPVEYOR_PULL_REQUEST_NUMBER","APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH"]),azure:P(["AGENT_BUILDDIRECTORY","AGENT_ID","AGENT_JOBNAME","AGENT_JOBSTATUS","AGENT_MACHINENAME","AGENT_NAME","AGENT_OS","AGENT_OSARCHITECTURE","BUILD_BUILDID","BUILD_BUILDNUMBER","BUILD_BUILDURI","BUILD_CONTAINERID","BUILD_CRONSCHEDULE_DISPLAYNAME","BUILD_DEFINITIONNAME","BUILD_DEFINITIONVERSION","BUILD_QUEUEDBY","BUILD_QUEUEDBYID","BUILD_REASON","BUILD_REPOSITORY_ID","BUILD_REPOSITORY_NAME","BUILD_REPOSITORY_PROVIDER","BUILD_REPOSITORY_URI","BUILD_REQUESTEDFOR","BUILD_REQUESTEDFOREMAIL","BUILD_REQUESTEDFORID","BUILD_SOURCEBRANCH","BUILD_SOURCEBRANCHNAME","BUILD_SOURCESDIRECTORY","BUILD_SOURCEVERSION","BUILD_SOURCEVERSIONAUTHOR","BUILD_SOURCEVERSIONMESSAGE","BUILD_STAGINGDIRECTORY","BUILD_TRIGGEREDBY_BUILDID","BUILD_TRIGGEREDBY_BUILDNUMBER","BUILD_TRIGGEREDBY_DEFINITIONID","BUILD_TRIGGEREDBY_DEFINITIONNAME","BUILD_TRIGGEREDBY_PROJECTID","COMMON_TESTRESULTSDIRECTORY","PIPELINE_WORKSPACE","SYSTEM_COLLECTIONID","SYSTEM_COLLECTIONURI","SYSTEM_DEFAULTWORKINGDIRECTORY","SYSTEM_DEFINITIONID","SYSTEM_HOSTTYPE","SYSTEM_JOBATTEMPT","SYSTEM_JOBDISPLAYNAME","SYSTEM_JOBID","SYSTEM_JOBNAME","SYSTEM_PHASEATTEMPT","SYSTEM_PHASEDISPLAYNAME","SYSTEM_PHASENAME","SYSTEM_PLANID","SYSTEM_PULLREQUEST_ISFORK","SYSTEM_PULLREQUEST_PULLREQUESTID","SYSTEM_PULLREQUEST_PULLREQUESTNUMBER","SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI","SYSTEM_PULLREQUEST_SOURCEBRANCH","SYSTEM_PULLREQUEST_SOURCECOMMITID","SYSTEM_PULLREQUEST_TARGETBRANCH","SYSTEM_PULLREQUEST_TARGETBRANCHNAME","SYSTEM_STAGEATTEMPT","SYSTEM_STAGEDISPLAYNAME","SYSTEM_STAGENAME","SYSTEM_TEAMFOUNDATIONCOLLECTIONURI","SYSTEM_TEAMPROJECT","SYSTEM_TEAMPROJECTID","SYSTEM_TIMELINEID"]),awsCodeBuild:P(["AWS_DEFAULT_REGION","AWS_REGION","CODEBUILD_BATCH_BUILD_IDENTIFIER","CODEBUILD_BUILD_ARN","CODEBUILD_BUILD_ID","CODEBUILD_BUILD_IMAGE","CODEBUILD_BUILD_NUMBER","CODEBUILD_BUILD_SUCCEEDING","CODEBUILD_BUILD_URL","CODEBUILD_INITIATOR","CODEBUILD_PROJECT_ARN","CODEBUILD_PUBLIC_BUILD_URL","CODEBUILD_RESOLVED_SOURCE_VERSION","CODEBUILD_SOURCE_REPO_URL","CODEBUILD_SOURCE_VERSION","CODEBUILD_SRC_DIR","CODEBUILD_START_TIME","CODEBUILD_WEBHOOK_ACTOR_ACCOUNT_ID","CODEBUILD_WEBHOOK_BASE_REF","CODEBUILD_WEBHOOK_EVENT","CODEBUILD_WEBHOOK_HEAD_REF","CODEBUILD_WEBHOOK_MERGE_COMMIT","CODEBUILD_WEBHOOK_PREV_COMMIT","CODEBUILD_WEBHOOK_TRIGGER","CODEBUILD_WEBHOOK_LABEL","CODEBUILD_WEBHOOK_RUN_ID","CODEBUILD_WEBHOOK_JOB_ID","CODEBUILD_WEBHOOK_WORKFLOW_NAME","CODEBUILD_RUNNER_OWNER","CODEBUILD_RUNNER_REPO","CODEBUILD_RUNNER_REPO_DOMAIN","CODEBUILD_RUNNER_WITH_BUILDSPEC"]),bamboo:P(["bamboo_buildNumber","bamboo_buildResultsUrl","bamboo_planRepository_repositoryUrl","bamboo_buildKey"]),bitbucket:P(["CI","BITBUCKET_WORKSPACE","BITBUCKET_REPO_SLUG","BITBUCKET_REPO_UUID","BITBUCKET_REPO_FULL_NAME","BITBUCKET_REPO_IS_PRIVATE","BITBUCKET_REPO_OWNER","BITBUCKET_REPO_OWNER_UUID","BITBUCKET_PROJECT_KEY","BITBUCKET_PROJECT_UUID","BITBUCKET_BUILD_NUMBER","BITBUCKET_PIPELINE_UUID","BITBUCKET_STEP_UUID","BITBUCKET_STEP_RUN_NUMBER","BITBUCKET_STEP_TRIGGERER_UUID","BITBUCKET_PARALLEL_STEP","BITBUCKET_PARALLEL_STEP_COUNT","BITBUCKET_CLONE_DIR","BITBUCKET_COMMIT","BITBUCKET_BRANCH","BITBUCKET_TAG","BITBUCKET_BOOKMARK","BITBUCKET_GIT_HTTP_ORIGIN","BITBUCKET_GIT_SSH_ORIGIN","BITBUCKET_PR_ID","BITBUCKET_PR_DESTINATION_BRANCH","BITBUCKET_PR_DESTINATION_COMMIT","BITBUCKET_DEPLOYMENT_ENVIRONMENT","BITBUCKET_DEPLOYMENT_ENVIRONMENT_UUID","BITBUCKET_EXIT_CODE"]),buildkite:P(["BUILDKITE_ORGANIZATION_SLUG","BUILDKITE_PIPELINE_ID","BUILDKITE_PIPELINE_NAME","BUILDKITE_PIPELINE_SLUG","BUILDKITE_PIPELINE_DEFAULT_BRANCH","BUILDKITE_REPO","BUILDKITE_SOURCE","BUILDKITE_BRANCH","BUILDKITE_TAG","BUILDKITE_COMMIT","BUILDKITE_MESSAGE","BUILDKITE_BUILD_AUTHOR","BUILDKITE_BUILD_AUTHOR_EMAIL","BUILDKITE_JOB_ID","BUILDKITE_BUILD_ID","BUILDKITE_BUILD_URL","BUILDKITE_BUILD_NUMBER","BUILDKITE_LABEL","BUILDKITE_COMMAND","BUILDKITE_STEP_ID","BUILDKITE_STEP_KEY","BUILDKITE_PARALLEL_JOB","BUILDKITE_PARALLEL_JOB_COUNT","BUILDKITE_RETRY_COUNT","BUILDKITE_COMPUTE_TYPE","BUILDKITE_CLUSTER_NAME","BUILDKITE_PULL_REQUEST","BUILDKITE_PULL_REQUEST_REPO","BUILDKITE_PULL_REQUEST_BASE_BRANCH","BUILDKITE_PULL_REQUEST_DRAFT","BUILDKITE_PULL_REQUEST_LABELS","BUILDKITE_MERGE_QUEUE_BASE_BRANCH","BUILDKITE_MERGE_QUEUE_BASE_COMMIT","BUILDKITE_REBUILT_FROM_BUILD_ID","BUILDKITE_REBUILT_FROM_BUILD_NUMBER","BUILDKITE_TRIGGERED_FROM_BUILD_ID","BUILDKITE_TRIGGERED_FROM_BUILD_NUMBER","BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG"]),circle:P(["CI","CIRCLECI","CIRCLE_BRANCH","CIRCLE_BUILD_NUM","CIRCLE_BUILD_URL","CIRCLE_PREVIOUS_BUILD_NUM","CIRCLE_JOB","CIRCLE_WORKFLOW_ID","CIRCLE_WORKFLOW_JOB_ID","CIRCLE_WORKFLOW_WORKSPACE_ID","CIRCLE_PIPELINE_ID","CIRCLE_ORGANIZATION_ID","CIRCLE_PROJECT_ID","CIRCLE_PROJECT_REPONAME","CIRCLE_PROJECT_USERNAME","CIRCLE_REPOSITORY_URL","CIRCLE_WORKING_DIRECTORY","CIRCLE_SHA1","CIRCLE_TAG","CIRCLE_USERNAME","CIRCLE_NODE_INDEX","CIRCLE_NODE_TOTAL","CIRCLE_PR_NUMBER","CIRCLE_PR_REPONAME","CIRCLE_PR_USERNAME","CIRCLE_PULL_REQUEST","CIRCLE_PULL_REQUESTS","CI_PULL_REQUEST"]),concourse:P(["BUILD_ID","BUILD_NAME","BUILD_JOB_NAME","BUILD_PIPELINE_NAME","BUILD_TEAM_NAME","ATC_EXTERNAL_URL"]),codeFresh:P(["CF_BUILD_ID","CF_BUILD_URL","CF_CURRENT_ATTEMPT","CF_STEP_NAME","CF_PIPELINE_NAME","CF_PIPELINE_TRIGGER_ID","CF_PULL_REQUEST_ID","CF_PULL_REQUEST_IS_FORK","CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_TARGET"]),drone:P(["DRONE_BUILD_LINK","DRONE_BUILD_NUMBER","DRONE_PULL_REQUEST"]),githubActions:P(["CI","GITHUB_ACTIONS","GITHUB_WORKFLOW","GITHUB_WORKFLOW_REF","GITHUB_WORKFLOW_SHA","GITHUB_ACTION","GITHUB_ACTION_PATH","GITHUB_ACTION_REPOSITORY","GITHUB_JOB","GITHUB_EVENT_NAME","GITHUB_EVENT_PATH","GITHUB_RUN_ID","GITHUB_RUN_NUMBER","GITHUB_RUN_ATTEMPT","GITHUB_REPOSITORY","GITHUB_REPOSITORY_ID","GITHUB_REPOSITORY_OWNER","GITHUB_REPOSITORY_OWNER_ID","GITHUB_REF","GITHUB_REF_NAME","GITHUB_REF_TYPE","GITHUB_REF_PROTECTED","GITHUB_BASE_REF","GITHUB_HEAD_REF","GITHUB_SHA","GITHUB_ACTOR","GITHUB_ACTOR_ID","GITHUB_TRIGGERING_ACTOR","GITHUB_SERVER_URL","GITHUB_API_URL","GITHUB_GRAPHQL_URL","GITHUB_WORKSPACE","GITHUB_RETENTION_DAYS","RUNNER_OS","RUNNER_ARCH","RUNNER_NAME","RUNNER_ENVIRONMENT","RUNNER_DEBUG"]),gitlab:P(["CI_PIPELINE_ID","CI_PIPELINE_URL","CI_BUILD_ID","CI_JOB_ID","CI_JOB_URL","CI_JOB_NAME","CI_NODE_INDEX","CI_NODE_TOTAL","GITLAB_HOST","CI_PROJECT_ID","CI_PROJECT_URL","CI_REPOSITORY_URL","CI_ENVIRONMENT_URL","CI_DEFAULT_BRANCH","RUN_ATTEMPT","CI_MERGE_REQUEST_IID","CI_MERGE_REQUEST_PROJECT_URL","CI_MERGE_REQUEST_TITLE","CI_MERGE_REQUEST_SOURCE_BRANCH_NAME","CI_MERGE_REQUEST_TARGET_BRANCH_NAME","CI_OPEN_MERGE_REQUESTS"]),goCD:P(["GO_SERVER_URL","GO_ENVIRONMENT_NAME","GO_PIPELINE_NAME","GO_PIPELINE_COUNTER","GO_PIPELINE_LABEL","GO_STAGE_NAME","GO_STAGE_COUNTER","GO_JOB_NAME","GO_TRIGGER_USER","GO_REVISION","GO_TO_REVISION","GO_FROM_REVISION","GO_MATERIAL_HAS_CHANGED"]),googleCloud:P(["BUILD_ID","PROJECT_ID","REPO_NAME","BRANCH_NAME","TAG_NAME","COMMIT_SHA","SHORT_SHA"]),jenkins:P(["BRANCH_NAME","BUILD_DISPLAY_NAME","BUILD_ID","BUILD_NUMBER","BUILD_TAG","BUILD_URL","CHANGE_AUTHOR","CHANGE_AUTHOR_DISPLAY_NAME","CHANGE_AUTHOR_EMAIL","CHANGE_BRANCH","CHANGE_FORK","CHANGE_ID","CHANGE_TARGET","CHANGE_TITLE","CHANGE_URL","CI","EXECUTOR_NUMBER","JAVA_HOME","JENKINS_HOME","JENKINS_URL","JOB_BASE_NAME","JOB_NAME","JOB_URL","NODE_LABELS","NODE_NAME","RUN_ARTIFACTS_DISPLAY_URL","RUN_CHANGES_DISPLAY_URL","TAG_NAME","WORKSPACE","WORKSPACE_TMP","GIT_AUTHOR_EMAIL","GIT_AUTHOR_NAME","GIT_BRANCH","GIT_COMMIT","GIT_COMMITTER_EMAIL","GIT_COMMITTER_NAME","GIT_LOCAL_BRANCH","GIT_PREVIOUS_COMMIT","GIT_PREVIOUS_SUCCESSFUL_COMMIT","GIT_URL","ghprbActualCommit","ghprbGhRepository","ghprbPullId","ghprbPullLink","ghprbSourceBranch","ghprbTargetBranch","ghprbTriggerAuthorLogin"]),semaphore:P(["SEMAPHORE_BRANCH_ID","SEMAPHORE_BUILD_NUMBER","SEMAPHORE_CURRENT_JOB","SEMAPHORE_CURRENT_THREAD","SEMAPHORE_EXECUTABLE_UUID","SEMAPHORE_GIT_BRANCH","SEMAPHORE_GIT_DIR","SEMAPHORE_GIT_REF","SEMAPHORE_GIT_REF_TYPE","SEMAPHORE_GIT_REPO_SLUG","SEMAPHORE_GIT_SHA","SEMAPHORE_GIT_URL","SEMAPHORE_JOB_COUNT","SEMAPHORE_JOB_ID","SEMAPHORE_JOB_NAME","SEMAPHORE_JOB_UUID","SEMAPHORE_PIPELINE_ID","SEMAPHORE_PLATFORM","SEMAPHORE_PROJECT_DIR","SEMAPHORE_PROJECT_HASH_ID","SEMAPHORE_PROJECT_ID","SEMAPHORE_PROJECT_NAME","SEMAPHORE_PROJECT_UUID","SEMAPHORE_REPO_SLUG","SEMAPHORE_TRIGGER_SOURCE","SEMAPHORE_WORKFLOW_ID","PULL_REQUEST_NUMBER"]),teamcity:null,travis:P(["TRAVIS_JOB_ID","TRAVIS_BUILD_ID","TRAVIS_BUILD_WEB_URL","TRAVIS_REPO_SLUG","TRAVIS_JOB_NUMBER","TRAVIS_EVENT_TYPE","TRAVIS_COMMIT_RANGE","TRAVIS_BUILD_NUMBER","TRAVIS_PULL_REQUEST","TRAVIS_PULL_REQUEST_BRANCH","TRAVIS_PULL_REQUEST_SHA"]),netlify:P(["BUILD_ID","CONTEXT","URL","DEPLOY_URL","DEPLOY_PRIME_URL","DEPLOY_ID"])}),Xp=t=>{let e=rs();return e?(0,R.chain)(t()).get(e).value():{}};function Zp(){return(0,R.chain)(es()).omitBy(R.isNull).keys().value()}function td(t){return t&&Zp().includes(t)}function rs(){let t=Qp();return Re("detected CI provider name: %s",t),t||null}function ed(){let t=Xp(es);return(0,R.mapValues)(t,e=>(0,R.isString)(e)?xr(e):e)}function ot(t){let e=ed(),r=rs(),o=rd(t,r);return Re("detected CI provider: %s",r),Re("detected CI params: %O",e),Re("detected CI build ID: %o",o),{params:e,provider:r,ciBuildId:o}}function rd(t,e){return t?{source:"user",value:t}:td(e)?{source:"server",value:null}:{source:"random",value:`auto:${Or()}`}}var os=l(require("archiver")),ns=l(require("fs-extra")),Fr=l(require("path")),ss=l(require("unzipper"));var od=50*1024*1024;async function is(t,e=od){return new Promise((r,o)=>{let n=(0,os.default)("zip",{zlib:{level:9}}),s=[],i=0;n.on("data",d=>{s.push(d),i+=d.length,i>e&&o(new Error(`Zip size exceeded the limit of ${e} bytes`))}),n.on("warning",d=>{d.code==="ENOENT"?I(d):o(d)}),n.on("error",d=>o(d)),n.on("end",()=>{let d=Buffer.concat(s);r(d)});let c=async d=>{let f=process.cwd(),u=Fr.default.normalize(d),E=Fr.default.relative(f,u),g=await ns.default.stat(d);g.isDirectory()?n.directory(d,E):n.file(d,{name:E,stats:g})};(async d=>{for(let f of d)await c(f);await n.finalize()})(t).catch(o)})}async function as(t,e){return ss.default.Open.buffer(t).then(r=>r.extract({path:e,concurrency:3}))}var cs=require("lodash");var nd={githubActions:[],gitlab:[],appveyor:["APPVEYOR_ACCOUNT_NAME","APPVEYOR_PROJECT_SLUG","APPVEYOR_BUILD_NUMBER"],azure:["SYSTEM_COLLECTIONID","BUILD_BUILDID"],awsCodeBuild:["CODEBUILD_BUILD_ID"],bamboo:["bamboo_buildKey","bamboo_buildNumber"],bitbucket:["BITBUCKET_PIPELINE_UUID"],buildkite:["BUILDKITE_BUILD_ID"],circle:["CIRCLE_WORKFLOW_WORKSPACE_ID"],concourse:["BUILD_ID"],codeFresh:["CF_BUILD_ID"],drone:["DRONE_BUILD_LINK"],goCD:["GO_PIPELINE_NAME","GO_PIPELINE_COUNTER"],googleCloud:["BUILD_ID"],jenkins:["JOB_NAME","BUILD_NUMBER"],semaphore:["SEMAPHORE_PIPELINE_ID"],travis:["TRAVIS_JOB_ID"],netlify:["BUILD_ID"]};function sd({provider:t,params:e}){let r=t?nd[t]:null;return!r||!e?!1:r.every(o=>!!e[(0,cs.camelCase)(o)])}function _e(t,e){e||sd(t)||ce("No CI job detected: without --id the cache ID is random, so cache get does not find what cache set saved. Pass --id to save and restore the same cache.")}var ls=l(require("async-retry")),fs=l(require("fs")),gs=require("stream"),Zt=require("axios");var ps=l(require("axios")),ds=require("https-proxy-agent"),ms=l(require("proxy-from-env"));var id=p.extend("axios");function Mr(t={}){let e=ps.default.create(t);return e.interceptors.request.use(r=>{let o={...r},n=e.getUri(r),s=ms.default.getProxyForUrl(n);return s&&(id("Using HTTP proxy %s for %s",At(s),At(n)),o.proxy=!1,o.httpsAgent=ad(s)),o}),e}var we=null;function ad(t){return we||(we=new ds.HttpsProxyAgent(t),we)}var te=p.extend("upload"),Oe=5;async function kr(t,e,r){return te("Uploading buffer %s",t.name,{buffer:Buffer.byteLength(t.buffer)}),Ts(t.buffer,t.uploadUrl,e,r,t.headers,Es(Buffer.byteLength(t.buffer)))}var cd=256*1024,pd=120*1e3;async function hs(t){return te("Uploading file %s",t.name,{bytes:t.sizeBytes}),Ts(()=>t.sizeBytes>0?fs.default.createReadStream(t.path,{end:t.sizeBytes-1}):gs.Readable.from([]),t.uploadUrl,t.contentType,void 0,{...t.headers??{"Content-Type":t.contentType},"Content-Length":String(t.sizeBytes)},Es(t.sizeBytes))}function Es(t){return pd+Math.ceil(t/cd)*1e3}async function dd(t,e,r,o,n,s){return Mr().request({method:"put",url:e,timeout:s,data:typeof t=="function"?t():t,...typeof t=="function"&&{maxRedirects:0},onUploadProgress:o,headers:n??{"Content-Disposition":"inline","Content-Type":r}})}async function jr(t,e){try{let r=await Mr().get(t,{responseType:"arraybuffer",onDownloadProgress:e});return Buffer.isBuffer(r.data)?r.data:Buffer.from(r.data)}catch(r){throw(0,Zt.isAxiosError)(r)&&te("Failed to download %s: %s",At(t),r.message),r}}var md=["RequestTimeout","OperationAborted","SlowDown"];function Is(t){if(t)return t.replace(/[\u0000-\u001f\u007f-\u009f]/g,"").replace(/\b[a-z][a-z0-9+.-]*:\/\/\S+/gi,e=>At(e)).slice(0,200)}function Cs(t){let e=(0,Zt.isAxiosError)(t)?t.response?.data:void 0,r=typeof e=="string"?e:"";return{code:r.match(/<Code>([^<]*)<\/Code>/)?.[1],message:Is(r.match(/<Message>([^<]*)<\/Message>/)?.[1])}}function ud(t){let e=(0,Zt.isAxiosError)(t)?t.response?.status:void 0;if(e===void 0||e<400||e>=500||e===408||e===429)return!1;let{code:r}=Cs(t);return!(r&&md.includes(r))}function ld(t){if(!(0,Zt.isAxiosError)(t)||!t.response)return t instanceof Error?t:new Error(String(t));let{code:e,message:r}=Cs(t),o=[Is(e),r].filter(Boolean).join(": ");return new Error(`storage answered ${t.response.status}${o?` ${o}`:""}`)}async function Ts(...t){try{await fd(t)}catch(e){throw ld(e)}}async function fd(t){await(0,ls.default)(async e=>{try{await dd(...t)}catch(r){if(ud(r)){e(r);return}throw r}},{retries:Oe,onRetry:(e,r)=>{if(te("Upload failed %d out of %d attempts: %s",r,Oe,e.message),r===Oe){C(`Cannot upload after ${r} times: ${e.message}`);return}I(`Upload failed ${r} out of ${Oe} attempts: ${e.message}`)}})}var Gr=t=>({total:e,loaded:r})=>{te("Uploading %s: %d / %d",t,us(r),us(e??0))};function us(t){return t/1e3/1e3}var Hr=l(require("lodash"));var nt=l(require("path")),Kr=l(require("globby"));var ys=require("lodash");function $r({config:t,cacheId:e,orgId:r,path:o,ci:n,cacheKey:s,metaCacheKey:i}){let c={id:e,orgId:r,config:(0,ys.omit)(t,"recordKey"),path:o,ci:n,createdAt:new Date().toISOString(),cacheKey:s,metaCacheKey:i};return Buffer.from(JSON.stringify(c))}function Rs(t,e){t instanceof Error?gt("%s. %s.",e,t.message):gt("%s. %s.",e,"Unknown error")}var _s=async t=>{let e=nt.default.resolve(t??"./test-results"),r=[nt.default.posix.join(e.replace(/\\/g,"/"),"**/.last-run.json"),nt.default.posix.join(e.replace(/\\/g,"/"),".last-run.json")];return Kr.sync(r)},ws=async(t=[])=>{let e=gd(t);return e.length===0?[]:Kr.sync(e.map(r=>r.replace(/\\/g,"/")))};function gd(t){let e=process.cwd();return t.filter(r=>{let o=nt.default.relative(e,nt.default.resolve(r));return o===".."||o.startsWith(`..${nt.default.sep}`)||nt.default.isAbsolute(o)?(Rs(null,`Invalid path: "${r}". Path traversal detected. The path was skipped.`),!1):!0})}function xe(t){return t?t.path.some(e=>nt.default.basename(e)===".last-run.json"):!1}async function Os(t,e){switch(e.provider){case"githubActions":await As(t,e);break;case"gitlab":await Ss(t,e);break;case"circle":await Ds(t,e);break;default:break}}async function xs(t,e,r){switch(e.provider){case"githubActions":await As(t,e,r);break;case"gitlab":await Ss(t,e,r);break;case"circle":await Ds(t,e,r);break;default:break}}async function Ss(t,e,r=null){let o=e.params,n=r?.ci.params,i=(n?Nt(n.runAttempt,0):0)+1,c=Nt(o.ciNodeIndex,1),m=Nt(o.ciNodeTotal,1),d=xe(r),f=i>1&&d,u=f?"--last-failed":"",E="";m>1&&(E=f?"--shard=1/1":`--shard=${c}/${m}`);let g=[u,E].filter(Boolean).join(" ");await Et(t.presetOutput??Xt,`EXTRA_PW_FLAGS="${g}"
21
+ `)}`}async function zt(t,e,r){try{return(await Pt("restApi").post(t,r,{headers:Ut(e)})).data.data}catch(o){throw Hp(o)}}function Ln(t,e){return Nn("Create session params: %o",e),zt("v1/sessions",t,e)}function vn(t,e,r,o){return Nn("Create attachments: %o",{owner:e,target:r,attachments:o}),"sessionId"in e?zt(`v1/sessions/${encodeURIComponent(e.sessionId)}/attachments`,t,{attachments:o}):"runId"in e?zt(`v1/runs/${encodeURIComponent(e.runId)}/attachments`,t,{...r,attachments:o}):zt("v1/runs/attachments",t,{...e,...r,attachments:o})}function Bn(t,e){return zt("v1/share",t,e)}function Fn(t,e){return Pt("restApi").request({...e,headers:{...Ut({apiKey:t}),...e.headers},responseType:"text",transformResponse:r=>r})}async function Br(){try{let t=Ie();if(!t)throw new Error("Config is missing!");let e=t.ciBuildId?{projectId:t.projectId,ciBuildId:t.ciBuildId,pwLastRun:t.pwLastRun}:{projectId:t.projectId,branch:t.branch,tag:t.tag,pwLastRun:t.pwLastRun},r=await Pn(t.apiKey,e);if(t.pwLastRun&&!r.data.pwLastRun)throw new Error("The API answered without the status and failed tests of the run (pwLastRun). Nothing was written.");await Vp(t.pwLastRun?r.data.pwLastRun:r.data,t)}catch(t){throw p("Failed to get run data"),t}}async function Vp(t,e){let r=JSON.stringify(t,null,2);e.output?(await Xo(e.output),await(0,Mn.writeFile)(e.output,r,"utf-8"),T(`Successfully written to ${e.output}`)):process.stdout.write(r+`
22
+ `)}var vs=require("axios"),Wr=l(require("path"));var F=require("@commander-js/extra-typings");var kn=require("@commander-js/extra-typings");function we(t,e=[]){return t?e.concat(t.split(",").map(r=>r.trim())):e}function jn(t){for(let e of t.options){let r=e.attributeName();if(!e.envVar||!e.isBoolean()||t.getOptionValueSource(r)!=="env")continue;let o=rn(process.env[e.envVar]);t.setOptionValueWithSource(r,o??e.defaultValue,o===void 0?"default":"env")}}function Yp(t,e){if(!Array.isArray(t))return String(t)===e;let r=o=>o.map(n=>n.trim()).filter(Boolean).join(",");return r(t.map(String))===r(e.split(","))}function $n(t){for(let e of t.options){let r=e.attributeName(),o=e.envVar?process.env[e.envVar]:void 0,n=t.getOptionValue(r);!o||e.isBoolean()||t.getOptionValueSource(r)!=="cli"||Yp(n,o)||pe(`${e.long} and ${e.envVar} are set to different values; using ${e.long}`)}}function Nt(){console.log=(...t)=>console.error(...t)}async function R(t,e){try{e.debug&&Ko(),await t(e),process.exit(0)}catch(r){C(r.message);let o=r instanceof kn.CommanderError?r.exitCode:1;process.exit(o)}}function Qt(t){return new Promise((e,r)=>process.stdout.write(t,o=>o?r(o):e()))}var Gn="Without it the ID comes from the CI job: on GitHub Actions the repository, the run ID and --matrix-index; on GitLab the pipeline ID and the job name; on other CI the variables that identify the pipeline and the job, and --matrix-index. When no CI job is detected the ID is random, so pass --id",Kn=new F.Option("--id <id>",`the ID to save the files under. ${Gn}`),Hn=new F.Option("--id <id>",`the ID the files were saved under. ${Gn}`),Jn=new F.Option("--path <path>",'comma-separated paths or glob patterns of the files to save, inside the current folder; quote globs, e.g. "dist/**/*". At most 50 MB zipped').argParser(we),Xt=(e=>(e.lastRun="last-run",e))(Xt||{}),Vn=new F.Option("--preset <preset-name>",'"last-run" saves the Playwright .last-run.json files of --pw-output-dir, to rerun only the failed tests').choices(Object.values(Xt)),Yn=new F.Option("--preset <preset-name>",'"last-run" restores the saved .last-run.json files and writes the Playwright options for the rerun to --preset-output').choices(Object.values(Xt)),Wn=new F.Option("--output-dir <folder>","the folder to restore the files to; by default the current folder"),qn=new F.Option("--pw-output-dir <folder>","the Playwright output folder that holds .last-run.json").default("test-results"),Zt=".currents_env",zn=new F.Option("--preset-output <path>",'the file the "last-run" preset writes, relative to the current folder. On GitHub Actions and CircleCI it holds options for "playwright test"; on GitLab the shell variables EXTRA_PW_FLAGS, EXTRA_PWCP_FLAGS and RUN_ATTEMPT, to source. Nothing is written on other CI').default(Zt),Fr=new F.Option("--matrix-index <number>","the index of this job among parallel jobs, from 1; each job has its own cache. Pass it when the CI does not tell the jobs apart, as in a GitHub Actions matrix").default(1).argParser(Qn),Mr=new F.Option("--matrix-total <number>","GitHub Actions only: the number of jobs in the matrix, for the shards that the last-run preset writes").default(1).argParser(Qn);function Qn(t){let e=parseInt(t,10);if(isNaN(e)||e<=0||!Number.isInteger(e))throw new F.InvalidArgumentError("A positive integer is expected.");return e}var Xn=new F.Option("--continue","exit with 0 when the cache is not found").default(!1),Zn=new F.Option("--continue","exit with 0 when no files are found, and save the cache without files").default(!1);var Wp={recordKey:_.recordKey,debug:_.debug},qp={id:{name:"Cache id",cli:"--id"},preset:{name:"Preset",cli:"--preset"},pwOutputDir:{name:"Playwright output folder",cli:"--pw-output-dir"},presetOutput:{name:"Preset output path",cli:"--preset-output"},path:{name:"Paths to cache",cli:"--path"},matrixIndex:{name:"Matrix index",cli:"--matrix-index"},matrixTotal:{name:"Matrix total",cli:"--matrix-total"},continue:{name:"Continue when upload path missing",cli:"--continue"}},zp={id:{name:"Cache id",cli:"--id"},preset:{name:"Preset",cli:"--preset"},outputDir:{name:"Output folder",cli:"--output-dir"},matrixIndex:{name:"Matrix index",cli:"--matrix-index"},matrixTotal:{name:"Matrix total",cli:"--matrix-total"},continue:{name:"Continue on cache miss",cli:"--continue"}},kr={...Wp,...qp,...zp};var ts=p.extend("config"),es=["recordKey"],Tt;function rs(t){Tt={type:"SET_COMMAND_CONFIG",values:U(kr,es,t)},ts("Resolved config: %o",{...Tt,values:h(Tt.values)})}function os(t){Tt={type:"GET_COMMAND_CONFIG",values:U(kr,es,t)},ts("Resolved config: %o",{...Tt,values:h(Tt.values)})}function dt(){return Tt}function ns(t){return{recordKey:t.key,id:t.id,preset:t.preset,outputDir:t.outputDir,presetOutput:t.presetOutput,debug:t.debug,matrixIndex:t.matrixIndex,matrixTotal:t.matrixTotal,continue:t.continue}}function ss(t){return{recordKey:t.key,id:t.id,preset:t.preset,pwOutputDir:t.pwOutputDir,path:t.path,debug:t.debug,matrixIndex:t.matrixIndex,matrixTotal:t.matrixTotal,continue:t.continue}}var w=require("lodash");var _e=p.extend("ci"),Qp=(t,e)=>(0,w.set)(t,(0,w.camelCase)(e),process.env[e]),P=t=>(0,w.transform)(t,Qp,{}),Xp=()=>process.env.TF_BUILD&&process.env.AZURE_HTTP_USER_AGENT,Zp=()=>(0,w.some)(process.env,(t,e)=>/^CODEBUILD_/.test(e)),td=()=>process.env.bamboo_buildNumber,ed=()=>(0,w.some)(process.env,(t,e)=>/^CONCOURSE_/.test(e)),rd=()=>process.env.GITLAB_CI||process.env.CI_SERVER_NAME&&/^GitLab/.test(process.env.CI_SERVER_NAME),od=()=>!!(process.env.BUILD_ID&&process.env.PROJECT_ID&&process.env.PROJECT_NUMBER||process.env.GCP_PROJECT||process.env.GCLOUD_PROJECT||process.env.GOOGLE_CLOUD_PROJECT),nd=()=>process.env.JENKINS_URL||process.env.JENKINS_HOME||process.env.JENKINS_VERSION||process.env.HUDSON_URL||process.env.HUDSON_HOME,sd={appveyor:"APPVEYOR",azure:Xp,awsCodeBuild:Zp,bamboo:td,bitbucket:"BITBUCKET_BUILD_NUMBER",buildkite:"BUILDKITE",circle:"CIRCLECI",concourse:ed,codeFresh:"CF_BUILD_ID",drone:"DRONE",githubActions:"GITHUB_ACTIONS",gitlab:rd,goCD:"GO_JOB_NAME",jenkins:nd,googleCloud:od,semaphore:"SEMAPHORE",teamcity:"TEAMCITY_VERSION",travis:"TRAVIS",netlify:"NETLIFY"};function id(){let{env:t}=process;return(0,w.findKey)(sd,e=>{if((0,w.isString)(e))return t[e];if((0,w.isFunction)(e))return e()})}var is=()=>({appveyor:P(["APPVEYOR_JOB_ID","APPVEYOR_ACCOUNT_NAME","APPVEYOR_PROJECT_SLUG","APPVEYOR_BUILD_NUMBER","APPVEYOR_BUILD_VERSION","APPVEYOR_PULL_REQUEST_NUMBER","APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH"]),azure:P(["AGENT_BUILDDIRECTORY","AGENT_ID","AGENT_JOBNAME","AGENT_JOBSTATUS","AGENT_MACHINENAME","AGENT_NAME","AGENT_OS","AGENT_OSARCHITECTURE","BUILD_BUILDID","BUILD_BUILDNUMBER","BUILD_BUILDURI","BUILD_CONTAINERID","BUILD_CRONSCHEDULE_DISPLAYNAME","BUILD_DEFINITIONNAME","BUILD_DEFINITIONVERSION","BUILD_QUEUEDBY","BUILD_QUEUEDBYID","BUILD_REASON","BUILD_REPOSITORY_ID","BUILD_REPOSITORY_NAME","BUILD_REPOSITORY_PROVIDER","BUILD_REPOSITORY_URI","BUILD_REQUESTEDFOR","BUILD_REQUESTEDFOREMAIL","BUILD_REQUESTEDFORID","BUILD_SOURCEBRANCH","BUILD_SOURCEBRANCHNAME","BUILD_SOURCESDIRECTORY","BUILD_SOURCEVERSION","BUILD_SOURCEVERSIONAUTHOR","BUILD_SOURCEVERSIONMESSAGE","BUILD_STAGINGDIRECTORY","BUILD_TRIGGEREDBY_BUILDID","BUILD_TRIGGEREDBY_BUILDNUMBER","BUILD_TRIGGEREDBY_DEFINITIONID","BUILD_TRIGGEREDBY_DEFINITIONNAME","BUILD_TRIGGEREDBY_PROJECTID","COMMON_TESTRESULTSDIRECTORY","PIPELINE_WORKSPACE","SYSTEM_COLLECTIONID","SYSTEM_COLLECTIONURI","SYSTEM_DEFAULTWORKINGDIRECTORY","SYSTEM_DEFINITIONID","SYSTEM_HOSTTYPE","SYSTEM_JOBATTEMPT","SYSTEM_JOBDISPLAYNAME","SYSTEM_JOBID","SYSTEM_JOBNAME","SYSTEM_PHASEATTEMPT","SYSTEM_PHASEDISPLAYNAME","SYSTEM_PHASENAME","SYSTEM_PLANID","SYSTEM_PULLREQUEST_ISFORK","SYSTEM_PULLREQUEST_PULLREQUESTID","SYSTEM_PULLREQUEST_PULLREQUESTNUMBER","SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI","SYSTEM_PULLREQUEST_SOURCEBRANCH","SYSTEM_PULLREQUEST_SOURCECOMMITID","SYSTEM_PULLREQUEST_TARGETBRANCH","SYSTEM_PULLREQUEST_TARGETBRANCHNAME","SYSTEM_STAGEATTEMPT","SYSTEM_STAGEDISPLAYNAME","SYSTEM_STAGENAME","SYSTEM_TEAMFOUNDATIONCOLLECTIONURI","SYSTEM_TEAMPROJECT","SYSTEM_TEAMPROJECTID","SYSTEM_TIMELINEID"]),awsCodeBuild:P(["AWS_DEFAULT_REGION","AWS_REGION","CODEBUILD_BATCH_BUILD_IDENTIFIER","CODEBUILD_BUILD_ARN","CODEBUILD_BUILD_ID","CODEBUILD_BUILD_IMAGE","CODEBUILD_BUILD_NUMBER","CODEBUILD_BUILD_SUCCEEDING","CODEBUILD_BUILD_URL","CODEBUILD_INITIATOR","CODEBUILD_PROJECT_ARN","CODEBUILD_PUBLIC_BUILD_URL","CODEBUILD_RESOLVED_SOURCE_VERSION","CODEBUILD_SOURCE_REPO_URL","CODEBUILD_SOURCE_VERSION","CODEBUILD_SRC_DIR","CODEBUILD_START_TIME","CODEBUILD_WEBHOOK_ACTOR_ACCOUNT_ID","CODEBUILD_WEBHOOK_BASE_REF","CODEBUILD_WEBHOOK_EVENT","CODEBUILD_WEBHOOK_HEAD_REF","CODEBUILD_WEBHOOK_MERGE_COMMIT","CODEBUILD_WEBHOOK_PREV_COMMIT","CODEBUILD_WEBHOOK_TRIGGER","CODEBUILD_WEBHOOK_LABEL","CODEBUILD_WEBHOOK_RUN_ID","CODEBUILD_WEBHOOK_JOB_ID","CODEBUILD_WEBHOOK_WORKFLOW_NAME","CODEBUILD_RUNNER_OWNER","CODEBUILD_RUNNER_REPO","CODEBUILD_RUNNER_REPO_DOMAIN","CODEBUILD_RUNNER_WITH_BUILDSPEC"]),bamboo:P(["bamboo_buildNumber","bamboo_buildResultsUrl","bamboo_planRepository_repositoryUrl","bamboo_buildKey"]),bitbucket:P(["CI","BITBUCKET_WORKSPACE","BITBUCKET_REPO_SLUG","BITBUCKET_REPO_UUID","BITBUCKET_REPO_FULL_NAME","BITBUCKET_REPO_IS_PRIVATE","BITBUCKET_REPO_OWNER","BITBUCKET_REPO_OWNER_UUID","BITBUCKET_PROJECT_KEY","BITBUCKET_PROJECT_UUID","BITBUCKET_BUILD_NUMBER","BITBUCKET_PIPELINE_UUID","BITBUCKET_STEP_UUID","BITBUCKET_STEP_RUN_NUMBER","BITBUCKET_STEP_TRIGGERER_UUID","BITBUCKET_PARALLEL_STEP","BITBUCKET_PARALLEL_STEP_COUNT","BITBUCKET_CLONE_DIR","BITBUCKET_COMMIT","BITBUCKET_BRANCH","BITBUCKET_TAG","BITBUCKET_BOOKMARK","BITBUCKET_GIT_HTTP_ORIGIN","BITBUCKET_GIT_SSH_ORIGIN","BITBUCKET_PR_ID","BITBUCKET_PR_DESTINATION_BRANCH","BITBUCKET_PR_DESTINATION_COMMIT","BITBUCKET_DEPLOYMENT_ENVIRONMENT","BITBUCKET_DEPLOYMENT_ENVIRONMENT_UUID","BITBUCKET_EXIT_CODE"]),buildkite:P(["BUILDKITE_ORGANIZATION_SLUG","BUILDKITE_PIPELINE_ID","BUILDKITE_PIPELINE_NAME","BUILDKITE_PIPELINE_SLUG","BUILDKITE_PIPELINE_DEFAULT_BRANCH","BUILDKITE_REPO","BUILDKITE_SOURCE","BUILDKITE_BRANCH","BUILDKITE_TAG","BUILDKITE_COMMIT","BUILDKITE_MESSAGE","BUILDKITE_BUILD_AUTHOR","BUILDKITE_BUILD_AUTHOR_EMAIL","BUILDKITE_JOB_ID","BUILDKITE_BUILD_ID","BUILDKITE_BUILD_URL","BUILDKITE_BUILD_NUMBER","BUILDKITE_LABEL","BUILDKITE_COMMAND","BUILDKITE_STEP_ID","BUILDKITE_STEP_KEY","BUILDKITE_PARALLEL_JOB","BUILDKITE_PARALLEL_JOB_COUNT","BUILDKITE_RETRY_COUNT","BUILDKITE_COMPUTE_TYPE","BUILDKITE_CLUSTER_NAME","BUILDKITE_PULL_REQUEST","BUILDKITE_PULL_REQUEST_REPO","BUILDKITE_PULL_REQUEST_BASE_BRANCH","BUILDKITE_PULL_REQUEST_DRAFT","BUILDKITE_PULL_REQUEST_LABELS","BUILDKITE_MERGE_QUEUE_BASE_BRANCH","BUILDKITE_MERGE_QUEUE_BASE_COMMIT","BUILDKITE_REBUILT_FROM_BUILD_ID","BUILDKITE_REBUILT_FROM_BUILD_NUMBER","BUILDKITE_TRIGGERED_FROM_BUILD_ID","BUILDKITE_TRIGGERED_FROM_BUILD_NUMBER","BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG"]),circle:P(["CI","CIRCLECI","CIRCLE_BRANCH","CIRCLE_BUILD_NUM","CIRCLE_BUILD_URL","CIRCLE_PREVIOUS_BUILD_NUM","CIRCLE_JOB","CIRCLE_WORKFLOW_ID","CIRCLE_WORKFLOW_JOB_ID","CIRCLE_WORKFLOW_WORKSPACE_ID","CIRCLE_PIPELINE_ID","CIRCLE_ORGANIZATION_ID","CIRCLE_PROJECT_ID","CIRCLE_PROJECT_REPONAME","CIRCLE_PROJECT_USERNAME","CIRCLE_REPOSITORY_URL","CIRCLE_WORKING_DIRECTORY","CIRCLE_SHA1","CIRCLE_TAG","CIRCLE_USERNAME","CIRCLE_NODE_INDEX","CIRCLE_NODE_TOTAL","CIRCLE_PR_NUMBER","CIRCLE_PR_REPONAME","CIRCLE_PR_USERNAME","CIRCLE_PULL_REQUEST","CIRCLE_PULL_REQUESTS","CI_PULL_REQUEST"]),concourse:P(["BUILD_ID","BUILD_NAME","BUILD_JOB_NAME","BUILD_PIPELINE_NAME","BUILD_TEAM_NAME","ATC_EXTERNAL_URL"]),codeFresh:P(["CF_BUILD_ID","CF_BUILD_URL","CF_CURRENT_ATTEMPT","CF_STEP_NAME","CF_PIPELINE_NAME","CF_PIPELINE_TRIGGER_ID","CF_PULL_REQUEST_ID","CF_PULL_REQUEST_IS_FORK","CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_TARGET"]),drone:P(["DRONE_BUILD_LINK","DRONE_BUILD_NUMBER","DRONE_PULL_REQUEST"]),githubActions:P(["CI","GITHUB_ACTIONS","GITHUB_WORKFLOW","GITHUB_WORKFLOW_REF","GITHUB_WORKFLOW_SHA","GITHUB_ACTION","GITHUB_ACTION_PATH","GITHUB_ACTION_REPOSITORY","GITHUB_JOB","GITHUB_EVENT_NAME","GITHUB_EVENT_PATH","GITHUB_RUN_ID","GITHUB_RUN_NUMBER","GITHUB_RUN_ATTEMPT","GITHUB_REPOSITORY","GITHUB_REPOSITORY_ID","GITHUB_REPOSITORY_OWNER","GITHUB_REPOSITORY_OWNER_ID","GITHUB_REF","GITHUB_REF_NAME","GITHUB_REF_TYPE","GITHUB_REF_PROTECTED","GITHUB_BASE_REF","GITHUB_HEAD_REF","GITHUB_SHA","GITHUB_ACTOR","GITHUB_ACTOR_ID","GITHUB_TRIGGERING_ACTOR","GITHUB_SERVER_URL","GITHUB_API_URL","GITHUB_GRAPHQL_URL","GITHUB_WORKSPACE","GITHUB_RETENTION_DAYS","RUNNER_OS","RUNNER_ARCH","RUNNER_NAME","RUNNER_ENVIRONMENT","RUNNER_DEBUG"]),gitlab:P(["CI_PIPELINE_ID","CI_PIPELINE_URL","CI_BUILD_ID","CI_JOB_ID","CI_JOB_URL","CI_JOB_NAME","CI_NODE_INDEX","CI_NODE_TOTAL","GITLAB_HOST","CI_PROJECT_ID","CI_PROJECT_URL","CI_REPOSITORY_URL","CI_ENVIRONMENT_URL","CI_DEFAULT_BRANCH","RUN_ATTEMPT","CI_MERGE_REQUEST_IID","CI_MERGE_REQUEST_PROJECT_URL","CI_MERGE_REQUEST_TITLE","CI_MERGE_REQUEST_SOURCE_BRANCH_NAME","CI_MERGE_REQUEST_TARGET_BRANCH_NAME","CI_OPEN_MERGE_REQUESTS"]),goCD:P(["GO_SERVER_URL","GO_ENVIRONMENT_NAME","GO_PIPELINE_NAME","GO_PIPELINE_COUNTER","GO_PIPELINE_LABEL","GO_STAGE_NAME","GO_STAGE_COUNTER","GO_JOB_NAME","GO_TRIGGER_USER","GO_REVISION","GO_TO_REVISION","GO_FROM_REVISION","GO_MATERIAL_HAS_CHANGED"]),googleCloud:P(["BUILD_ID","PROJECT_ID","REPO_NAME","BRANCH_NAME","TAG_NAME","COMMIT_SHA","SHORT_SHA"]),jenkins:P(["BRANCH_NAME","BUILD_DISPLAY_NAME","BUILD_ID","BUILD_NUMBER","BUILD_TAG","BUILD_URL","CHANGE_AUTHOR","CHANGE_AUTHOR_DISPLAY_NAME","CHANGE_AUTHOR_EMAIL","CHANGE_BRANCH","CHANGE_FORK","CHANGE_ID","CHANGE_TARGET","CHANGE_TITLE","CHANGE_URL","CI","EXECUTOR_NUMBER","JAVA_HOME","JENKINS_HOME","JENKINS_URL","JOB_BASE_NAME","JOB_NAME","JOB_URL","NODE_LABELS","NODE_NAME","RUN_ARTIFACTS_DISPLAY_URL","RUN_CHANGES_DISPLAY_URL","TAG_NAME","WORKSPACE","WORKSPACE_TMP","GIT_AUTHOR_EMAIL","GIT_AUTHOR_NAME","GIT_BRANCH","GIT_COMMIT","GIT_COMMITTER_EMAIL","GIT_COMMITTER_NAME","GIT_LOCAL_BRANCH","GIT_PREVIOUS_COMMIT","GIT_PREVIOUS_SUCCESSFUL_COMMIT","GIT_URL","ghprbActualCommit","ghprbGhRepository","ghprbPullId","ghprbPullLink","ghprbSourceBranch","ghprbTargetBranch","ghprbTriggerAuthorLogin"]),semaphore:P(["SEMAPHORE_BRANCH_ID","SEMAPHORE_BUILD_NUMBER","SEMAPHORE_CURRENT_JOB","SEMAPHORE_CURRENT_THREAD","SEMAPHORE_EXECUTABLE_UUID","SEMAPHORE_GIT_BRANCH","SEMAPHORE_GIT_DIR","SEMAPHORE_GIT_REF","SEMAPHORE_GIT_REF_TYPE","SEMAPHORE_GIT_REPO_SLUG","SEMAPHORE_GIT_SHA","SEMAPHORE_GIT_URL","SEMAPHORE_JOB_COUNT","SEMAPHORE_JOB_ID","SEMAPHORE_JOB_NAME","SEMAPHORE_JOB_UUID","SEMAPHORE_PIPELINE_ID","SEMAPHORE_PLATFORM","SEMAPHORE_PROJECT_DIR","SEMAPHORE_PROJECT_HASH_ID","SEMAPHORE_PROJECT_ID","SEMAPHORE_PROJECT_NAME","SEMAPHORE_PROJECT_UUID","SEMAPHORE_REPO_SLUG","SEMAPHORE_TRIGGER_SOURCE","SEMAPHORE_WORKFLOW_ID","PULL_REQUEST_NUMBER"]),teamcity:null,travis:P(["TRAVIS_JOB_ID","TRAVIS_BUILD_ID","TRAVIS_BUILD_WEB_URL","TRAVIS_REPO_SLUG","TRAVIS_JOB_NUMBER","TRAVIS_EVENT_TYPE","TRAVIS_COMMIT_RANGE","TRAVIS_BUILD_NUMBER","TRAVIS_PULL_REQUEST","TRAVIS_PULL_REQUEST_BRANCH","TRAVIS_PULL_REQUEST_SHA"]),netlify:P(["BUILD_ID","CONTEXT","URL","DEPLOY_URL","DEPLOY_PRIME_URL","DEPLOY_ID"])}),ad=t=>{let e=as();return e?(0,w.chain)(t()).get(e).value():{}};function cd(){return(0,w.chain)(is()).omitBy(w.isNull).keys().value()}function pd(t){return t&&cd().includes(t)}function as(){let t=id();return _e("detected CI provider name: %s",t),t||null}function dd(){let t=ad(is);return(0,w.mapValues)(t,e=>(0,w.isString)(e)?Dr(e):e)}function rt(t){let e=dd(),r=as(),o=md(t,r);return _e("detected CI provider: %s",r),_e("detected CI params: %O",e),_e("detected CI build ID: %o",o),{params:e,provider:r,ciBuildId:o}}function md(t,e){return t?{source:"user",value:t}:pd(e)?{source:"server",value:null}:{source:"random",value:`auto:${Ar()}`}}var cs=l(require("archiver")),ps=l(require("fs-extra")),jr=l(require("path")),ds=l(require("unzipper"));var ud=50*1024*1024;async function ms(t,e=ud){return new Promise((r,o)=>{let n=(0,cs.default)("zip",{zlib:{level:9}}),s=[],i=0;n.on("data",d=>{s.push(d),i+=d.length,i>e&&o(new Error(`Zip size exceeded the limit of ${e} bytes`))}),n.on("warning",d=>{d.code==="ENOENT"?I(d):o(d)}),n.on("error",d=>o(d)),n.on("end",()=>{let d=Buffer.concat(s);r(d)});let c=async d=>{let f=process.cwd(),u=jr.default.normalize(d),E=jr.default.relative(f,u),g=await ps.default.stat(d);g.isDirectory()?n.directory(d,E):n.file(d,{name:E,stats:g})};(async d=>{for(let f of d)await c(f);await n.finalize()})(t).catch(o)})}async function us(t,e){return ds.default.Open.buffer(t).then(r=>r.extract({path:e,concurrency:3}))}var ls=require("lodash");var ld={githubActions:[],gitlab:[],appveyor:["APPVEYOR_ACCOUNT_NAME","APPVEYOR_PROJECT_SLUG","APPVEYOR_BUILD_NUMBER"],azure:["SYSTEM_COLLECTIONID","BUILD_BUILDID"],awsCodeBuild:["CODEBUILD_BUILD_ID"],bamboo:["bamboo_buildKey","bamboo_buildNumber"],bitbucket:["BITBUCKET_PIPELINE_UUID"],buildkite:["BUILDKITE_BUILD_ID"],circle:["CIRCLE_WORKFLOW_WORKSPACE_ID"],concourse:["BUILD_ID"],codeFresh:["CF_BUILD_ID"],drone:["DRONE_BUILD_LINK"],goCD:["GO_PIPELINE_NAME","GO_PIPELINE_COUNTER"],googleCloud:["BUILD_ID"],jenkins:["JOB_NAME","BUILD_NUMBER"],semaphore:["SEMAPHORE_PIPELINE_ID"],travis:["TRAVIS_JOB_ID"],netlify:["BUILD_ID"]};function fd({provider:t,params:e}){let r=t?ld[t]:null;return!r||!e?!1:r.every(o=>!!e[(0,ls.camelCase)(o)])}function Oe(t,e){e||fd(t)||pe("No CI job detected: without --id the cache ID is random, so cache get does not find what cache set saved. Pass --id to save and restore the same cache.")}var Is=l(require("async-retry")),Cs=l(require("fs")),Ts=require("stream"),te=require("axios");var fs=l(require("axios")),gs=require("https-proxy-agent"),hs=l(require("proxy-from-env"));var gd=p.extend("axios");function $r(t={}){let e=fs.default.create(t);return e.interceptors.request.use(r=>{let o={...r},n=e.getUri(r),s=hs.default.getProxyForUrl(n);return s&&(gd("Using HTTP proxy %s for %s",Dt(s),Dt(n)),o.proxy=!1,o.httpsAgent=hd(s)),o}),e}var xe=null;function hd(t){return xe||(xe=new gs.HttpsProxyAgent(t),xe)}var ee=p.extend("upload"),Se=5;async function Gr(t,e,r){return ee("Uploading buffer %s",t.name,{buffer:Buffer.byteLength(t.buffer)}),Os(t.buffer,t.uploadUrl,e,r,t.headers,Rs(Buffer.byteLength(t.buffer)))}var Ed=256*1024,Id=120*1e3;async function ys(t){return ee("Uploading file %s",t.name,{bytes:t.sizeBytes}),Os(()=>t.sizeBytes>0?Cs.default.createReadStream(t.path,{end:t.sizeBytes-1}):Ts.Readable.from([]),t.uploadUrl,t.contentType,void 0,{...t.headers??{"Content-Type":t.contentType},"Content-Length":String(t.sizeBytes)},Rs(t.sizeBytes))}function Rs(t){return Id+Math.ceil(t/Ed)*1e3}async function Cd(t,e,r,o,n,s){return $r().request({method:"put",url:e,timeout:s,data:typeof t=="function"?t():t,...typeof t=="function"&&{maxRedirects:0},onUploadProgress:o,headers:n??{"Content-Disposition":"inline","Content-Type":r}})}async function Kr(t,e){try{let r=await $r().get(t,{responseType:"arraybuffer",onDownloadProgress:e});return Buffer.isBuffer(r.data)?r.data:Buffer.from(r.data)}catch(r){throw(0,te.isAxiosError)(r)&&ee("Failed to download %s: %s",Dt(t),r.message),r}}var Td=["RequestTimeout","OperationAborted","SlowDown"];function ws(t){if(t)return t.replace(/[\u0000-\u001f\u007f-\u009f]/g,"").replace(/\b[a-z][a-z0-9+.-]*:\/\/\S+/gi,e=>Dt(e)).slice(0,200)}function _s(t){let e=(0,te.isAxiosError)(t)?t.response?.data:void 0,r=typeof e=="string"?e:"";return{code:r.match(/<Code>([^<]*)<\/Code>/)?.[1],message:ws(r.match(/<Message>([^<]*)<\/Message>/)?.[1])}}function yd(t){let e=(0,te.isAxiosError)(t)?t.response?.status:void 0;if(e===void 0||e<400||e>=500||e===408||e===429)return!1;let{code:r}=_s(t);return!(r&&Td.includes(r))}function Rd(t){if(!(0,te.isAxiosError)(t)||!t.response)return t instanceof Error?t:new Error(String(t));let{code:e,message:r}=_s(t),o=[ws(e),r].filter(Boolean).join(": ");return new Error(`storage answered ${t.response.status}${o?` ${o}`:""}`)}async function Os(...t){try{await wd(t)}catch(e){throw Rd(e)}}async function wd(t){await(0,Is.default)(async e=>{try{await Cd(...t)}catch(r){if(yd(r)){e(r);return}throw r}},{retries:Se,onRetry:(e,r)=>{if(ee("Upload failed %d out of %d attempts: %s",r,Se,e.message),r===Se){C(`Cannot upload after ${r} times: ${e.message}`);return}I(`Upload failed ${r} out of ${Se} attempts: ${e.message}`)}})}var Hr=t=>({total:e,loaded:r})=>{ee("Uploading %s: %d / %d",t,Es(r),Es(e??0))};function Es(t){return t/1e3/1e3}var Yr=l(require("lodash"));var ot=l(require("path")),Vr=l(require("globby"));var xs=require("lodash");function Jr({config:t,cacheId:e,orgId:r,path:o,ci:n,cacheKey:s,metaCacheKey:i}){let c={id:e,orgId:r,config:(0,xs.omit)(t,"recordKey"),path:o,ci:n,createdAt:new Date().toISOString(),cacheKey:s,metaCacheKey:i};return Buffer.from(JSON.stringify(c))}function Ss(t,e){t instanceof Error?gt("%s. %s.",e,t.message):gt("%s. %s.",e,"Unknown error")}var As=async t=>{let e=ot.default.resolve(t??"./test-results"),r=[ot.default.posix.join(e.replace(/\\/g,"/"),"**/.last-run.json"),ot.default.posix.join(e.replace(/\\/g,"/"),".last-run.json")];return Vr.sync(r)},Ds=async(t=[])=>{let e=_d(t);return e.length===0?[]:Vr.sync(e.map(r=>r.replace(/\\/g,"/")))};function _d(t){let e=process.cwd();return t.filter(r=>{let o=ot.default.relative(e,ot.default.resolve(r));return o===".."||o.startsWith(`..${ot.default.sep}`)||ot.default.isAbsolute(o)?(Ss(null,`Invalid path: "${r}". Path traversal detected. The path was skipped.`),!1):!0})}function Ae(t){return t?t.path.some(e=>ot.default.basename(e)===".last-run.json"):!1}async function Us(t,e){switch(e.provider){case"githubActions":await Ns(t,e);break;case"gitlab":await bs(t,e);break;case"circle":await Ls(t,e);break;default:break}}async function Ps(t,e,r){switch(e.provider){case"githubActions":await Ns(t,e,r);break;case"gitlab":await bs(t,e,r);break;case"circle":await Ls(t,e,r);break;default:break}}async function bs(t,e,r=null){let o=e.params,n=r?.ci.params,i=(n?Lt(n.runAttempt,0):0)+1,c=Lt(o.ciNodeIndex,1),m=Lt(o.ciNodeTotal,1),d=Ae(r),f=i>1&&d,u=f?"--last-failed":"",E="";m>1&&(E=f?"--shard=1/1":`--shard=${c}/${m}`);let g=[u,E].filter(Boolean).join(" ");await It(t.presetOutput??Zt,`EXTRA_PW_FLAGS="${g}"
23
23
  EXTRA_PWCP_FLAGS="${u}"
24
24
  RUN_ATTEMPT=${i}
25
- `)}async function As(t,e,r=null){let{matrixIndex:o,matrixTotal:n}=t,s=e.params,i=Nt(s.githubRunAttempt,1),c=xe(r),m=i>1&&c,d=m?"--last-failed":"",f="";n>1&&(f=m?"--shard=1/1":`--shard=${o}/${n}`);let u=[d,f].filter(Boolean).join(" "),E=t.presetOutput??Xt;await Et(E,u),p('Dumped PW config: "%s" for GHA to %s',u,E)}async function Ds(t,e,r=null){let o=e.params,n=r?.ci.params,s=n?.circleWorkflowId,i=n?.circleWorkflowWorkspaceId,c=Nt(o.circleNodeIndex,0),m=Nt(o.circleNodeTotal,1),d=i==o.circleWorkflowWorkspaceId&&s!==o.circleWorkflowId,f=xe(r),u=d&&f,E=u?"--last-failed":"",g="";m>1&&(g=u?"--shard=1/1":`--shard=${c+1}/${m}`);let A=[E,g].filter(Boolean).join(" "),V=t.presetOutput??Xt;await Et(V,A),p('Dumped PW config: "%s" for Circle to %s',A,V)}var Nt=(t,e)=>{let r=Hr.default.toNumber(t);return Hr.default.isNaN(r)?e:r};async function Vr(){let t=dt();if(t.type!=="GET_COMMAND_CONFIG"||!t.values)throw new Error("Config is missing!");let{recordKey:e,id:r,preset:o,matrixIndex:n,matrixTotal:s,continue:i}=t.values,c=t.values.outputDir,m=ot();_e(m,r),o==="last-run"&&await Os(t.values,m);let{cacheId:d,refMetaReadUrl:f}=await Cn({recordKey:e,ci:m,id:r,config:{matrixIndex:n,matrixTotal:s}});try{let u=await Id(f),{readUrl:E}=await In({recordKey:e,cacheKey:u.cacheKey}),g=await hd({readUrl:E,outputDir:c});o==="last-run"&&await xs(t.values,m,u),T(x("- restoring cache to"),g),pe("Cache restored. Cache ID: %s",d)}catch(u){if((0,Us.isAxiosError)(u)&&(u.response?.status===403||u.response?.status===404)){let E=`Cache with ID "${d}" not found`;if(i){gt(E);return}throw new Error(E)}throw u}}async function hd({readUrl:t,outputDir:e}){let r=await jr(t),o=Ed(e);return await as(r,o),p("Cache downloaded",{readUrl:t,destination:o}),o}function Ed(t){let e=t??process.cwd();return Jr.default.isAbsolute(e)?e:Jr.default.resolve(process.cwd(),e)}async function Id(t){let e=await jr(t),r=JSON.parse(e.toString("utf-8"));return p("Meta file downloaded: %O",r),r}var bs=require("lodash");async function Yr(){let t=dt();if(t.type!=="SET_COMMAND_CONFIG"||!t.values)throw new Error("Config is missing!");let{recordKey:e,id:r,preset:o,pwOutputDir:n,matrixIndex:s,matrixTotal:i,continue:c}=t.values,m=await ws(t.values.path),d=t.values.path||[],f=ot();if(_e(f,r),o==="last-run"&&(d.push(n),m.push(...await _s(n))),m.length===0){let V=`No files available to upload: ${d.filter(Boolean).join(",")}`;if(!c)throw new Error(V);gt(V)}let u=await En({recordKey:e,ci:f,id:r,config:{matrixIndex:s,matrixTotal:i}});p("Cache upload url created",{result:u});let E=Td(f),g=m.length>0?await is(m):null,A=[];g&&A.push(Cd({archive:g,cacheId:u.cacheId,uploadUrl:u.uploadUrl}).then(()=>{yd(m),p("Cache archive uploaded",{uploadUrl:u.uploadUrl})})),A.push(Ps({meta:$r({cacheId:u.cacheId,config:t.values,ci:E,orgId:u.orgId,path:m}),cacheId:u.cacheId,uploadUrl:u.metaUploadUrl}).then(()=>p("Meta uploaded",{uploadUrl:u.metaUploadUrl})),Ps({meta:$r({cacheId:u.cacheId,config:t.values,ci:E,orgId:u.orgId,path:m,cacheKey:u.cacheKey,metaCacheKey:u.metaCacheKey}),cacheId:u.cacheId,uploadUrl:u.refMetaUploadUrl}).then(()=>p("Ref meta uploaded",{uploadUrl:u.refMetaUploadUrl}))),await Promise.all(A),pe("Cache uploaded. Cache ID: %s",u.cacheId)}async function Cd({archive:t,cacheId:e,uploadUrl:r}){try{let o="application/zip";await kr({buffer:t,contentType:o,name:e,uploadUrl:r},o,Gr(e)),p("Cache archive uploaded",{cacheId:e})}catch(o){throw p("Failed to upload cache archive",o),o}}async function Ps({meta:t,cacheId:e,uploadUrl:r}){try{let o=`${e}_meta`,n="application/json";await kr({buffer:t,contentType:n,name:o,uploadUrl:r},n,Gr(o)),p("Cache meta uploaded",{cacheId:e})}catch(o){throw p("Failed to upload cache meta",o),o}}function Td(t){return t.ciBuildId.source==="server"||t.ciBuildId.source==="random"?(0,bs.omit)(t,"ciBuildId"):t}function yd(t){T(`Cache upload paths:
25
+ `)}async function Ns(t,e,r=null){let{matrixIndex:o,matrixTotal:n}=t,s=e.params,i=Lt(s.githubRunAttempt,1),c=Ae(r),m=i>1&&c,d=m?"--last-failed":"",f="";n>1&&(f=m?"--shard=1/1":`--shard=${o}/${n}`);let u=[d,f].filter(Boolean).join(" "),E=t.presetOutput??Zt;await It(E,u),p('Dumped PW config: "%s" for GHA to %s',u,E)}async function Ls(t,e,r=null){let o=e.params,n=r?.ci.params,s=n?.circleWorkflowId,i=n?.circleWorkflowWorkspaceId,c=Lt(o.circleNodeIndex,0),m=Lt(o.circleNodeTotal,1),d=i==o.circleWorkflowWorkspaceId&&s!==o.circleWorkflowId,f=Ae(r),u=d&&f,E=u?"--last-failed":"",g="";m>1&&(g=u?"--shard=1/1":`--shard=${c+1}/${m}`);let A=[E,g].filter(Boolean).join(" "),Y=t.presetOutput??Zt;await It(Y,A),p('Dumped PW config: "%s" for Circle to %s',A,Y)}var Lt=(t,e)=>{let r=Yr.default.toNumber(t);return Yr.default.isNaN(r)?e:r};async function qr(){let t=dt();if(t.type!=="GET_COMMAND_CONFIG"||!t.values)throw new Error("Config is missing!");let{recordKey:e,id:r,preset:o,matrixIndex:n,matrixTotal:s,continue:i}=t.values,c=t.values.outputDir,m=rt();Oe(m,r),o==="last-run"&&await Us(t.values,m);let{cacheId:d,refMetaReadUrl:f}=await _n({recordKey:e,ci:m,id:r,config:{matrixIndex:n,matrixTotal:s}});try{let u=await Sd(f),{readUrl:E}=await wn({recordKey:e,cacheKey:u.cacheKey}),g=await Od({readUrl:E,outputDir:c});o==="last-run"&&await Ps(t.values,m,u),T(x("- restoring cache to"),g),de("Cache restored. Cache ID: %s",d)}catch(u){if((0,vs.isAxiosError)(u)&&(u.response?.status===403||u.response?.status===404)){let E=`Cache with ID "${d}" not found`;if(i){gt(E);return}throw new Error(E)}throw u}}async function Od({readUrl:t,outputDir:e}){let r=await Kr(t),o=xd(e);return await us(r,o),p("Cache downloaded",{readUrl:t,destination:o}),o}function xd(t){let e=t??process.cwd();return Wr.default.isAbsolute(e)?e:Wr.default.resolve(process.cwd(),e)}async function Sd(t){let e=await Kr(t),r=JSON.parse(e.toString("utf-8"));return p("Meta file downloaded: %O",r),r}var Fs=require("lodash");async function zr(){let t=dt();if(t.type!=="SET_COMMAND_CONFIG"||!t.values)throw new Error("Config is missing!");let{recordKey:e,id:r,preset:o,pwOutputDir:n,matrixIndex:s,matrixTotal:i,continue:c}=t.values,m=await Ds(t.values.path),d=t.values.path||[],f=rt();if(Oe(f,r),o==="last-run"&&(d.push(n),m.push(...await As(n))),m.length===0){let Y=`No files available to upload: ${d.filter(Boolean).join(",")}`;if(!c)throw new Error(Y);gt(Y)}let u=await Rn({recordKey:e,ci:f,id:r,config:{matrixIndex:s,matrixTotal:i}});p("Cache upload url created",{result:u});let E=Dd(f),g=m.length>0?await ms(m):null,A=[];g&&A.push(Ad({archive:g,cacheId:u.cacheId,uploadUrl:u.uploadUrl}).then(()=>{Ud(m),p("Cache archive uploaded",{uploadUrl:u.uploadUrl})})),A.push(Bs({meta:Jr({cacheId:u.cacheId,config:t.values,ci:E,orgId:u.orgId,path:m}),cacheId:u.cacheId,uploadUrl:u.metaUploadUrl}).then(()=>p("Meta uploaded",{uploadUrl:u.metaUploadUrl})),Bs({meta:Jr({cacheId:u.cacheId,config:t.values,ci:E,orgId:u.orgId,path:m,cacheKey:u.cacheKey,metaCacheKey:u.metaCacheKey}),cacheId:u.cacheId,uploadUrl:u.refMetaUploadUrl}).then(()=>p("Ref meta uploaded",{uploadUrl:u.refMetaUploadUrl}))),await Promise.all(A),de("Cache uploaded. Cache ID: %s",u.cacheId)}async function Ad({archive:t,cacheId:e,uploadUrl:r}){try{let o="application/zip";await Gr({buffer:t,contentType:o,name:e,uploadUrl:r},o,Hr(e)),p("Cache archive uploaded",{cacheId:e})}catch(o){throw p("Failed to upload cache archive",o),o}}async function Bs({meta:t,cacheId:e,uploadUrl:r}){try{let o=`${e}_meta`,n="application/json";await Gr({buffer:t,contentType:n,name:o,uploadUrl:r},n,Hr(o)),p("Cache meta uploaded",{cacheId:e})}catch(o){throw p("Failed to upload cache meta",o),o}}function Dd(t){return t.ciBuildId.source==="server"||t.ciBuildId.source==="random"?(0,Fs.omit)(t,"ciBuildId"):t}function Ud(t){T(`Cache upload paths:
26
26
  `+t.map(e=>`${x("- uploading")} ${e}`).join(`
27
- `))}var{recordKey:Rd,projectId:_d,ciBuildId:wd,debug:Od}=_,X={recordKey:Rd,projectId:_d,ciBuildId:wd,runId:{name:"Run ID",env:"CURRENTS_RUN_ID",cli:"--run-id"},debug:Od};var xd=p.extend("config"),Sd=["recordKey","projectId"];function Ad(t){if(!(t.runId||t.ciBuildId))throw C(`${fe(X,"runId")} or ${fe(X,"ciBuildId")} is required: pass ${x(le(X,"runId"))} or ${x(le(X,"ciBuildId"))}, or set ${x(L(X,"runId"))} or ${x(L(X,"ciBuildId"))}`),new q("Missing required config variable")}var Wr=null;function Ns(t){Wr=U(X,Sd,t,Ad),xd("Resolved config: %o",h(Wr))}function Se(){return Wr}async function qr(){let t=Se();if(!t)throw new Error("Config is missing!");let e=t.runId?`runId: ${t.runId}`:`ciBuildId: ${t.ciBuildId}`;try{let r=await Tn({recordKey:t.recordKey,projectId:t.projectId,ciBuildId:t.ciBuildId,runId:t.runId});return r.data.runId?T('Run "%s" (%s) is cancelled',r.data.runId,e):T('No run to cancel (%s) in project "%s"',e,t.projectId),r}catch(r){throw p("Failed to cancel the run"),r}}var Ls=require("@currents/commit-info"),vs=require("lodash");var Dd=p.extend("git"),Ud=async()=>{let t=await(0,Ls.commitInfo)();return Dd("commit: %O",t),{branch:t.branch,remoteOrigin:t.remote,authorEmail:t.email,authorName:t.author,message:t.message,sha:t.sha,ghaEventData:t.ghaEventData??null}},Ae=(0,vs.memoize)(Ud);var Bs=l(require("getos")),Fs=require("lodash"),K=require("os"),Ms=require("util"),Pd=async()=>{if((0,K.platform)()==="linux")try{let t=await(0,Ms.promisify)(Bs.default)();return"dist"in t&&"release"in t?[t.dist,t.release].join(" - "):(0,K.release)()}catch{return(0,K.release)()}return(0,K.release)()},bd=async()=>{let t=await Pd();return{osName:(0,K.platform)(),osVersion:t,osCpus:[],osMemory:{free:(0,K.freemem)(),total:(0,K.totalmem)()}}},ks=(0,Fs.memoize)(bd);var vi=l(require("axios")),no=l(require("fs-extra")),ke=l(require("path")),Bi=l(require("semver"));var{debug:Nd,ciBuildId:Ld,recordKey:vd,projectId:Bd,machineId:Fd}=_,st={debug:Nd,ciBuildId:Ld,recordKey:vd,projectId:Bd,machineId:Fd,tag:{..._.tag,env:"CURRENTS_TAG"},disableTitleTags:{name:"Disable title tags",env:"CURRENTS_DISABLE_TITLE_TAGS",cli:"--disable-title-tags"},removeTitleTags:{name:"Remove title tags",env:"CURRENTS_REMOVE_TITLE_TAGS",cli:"--remove-title-tags"},reportDir:{name:"Report folder",env:"CURRENTS_REPORT_DIR",cli:"--report-dir"}};var Md=p.extend("config"),kd=["projectId","recordKey"],zr=null;function js(t){zr=U(st,kd,t),Md("Resolved Currents config: %o",h(zr))}function De(){return zr}function Gs(t){return{ciBuildId:t.ciBuildId,projectId:t.projectId,recordKey:t.key,tag:t.tag,removeTitleTags:t.removeTitleTags,disableTitleTags:t.disableTitleTags,debug:t.debug,machineId:t.machineId,reportDir:t.reportDir}}var to=l(require("fs-extra")),it=require("path");var $s=l(require("path")),Qr={".png":{type:"screenshot",contentType:"image/png"},".jpg":{type:"screenshot",contentType:"image/jpeg"},".jpeg":{type:"screenshot",contentType:"image/jpeg"},".webp":{type:"screenshot",contentType:"image/webp"},".gif":{type:"screenshot",contentType:"image/gif"},".mp4":{type:"video",contentType:"video/mp4"},".webm":{type:"video",contentType:"video/webm"},".svg":{type:"attachment",contentType:"image/svg+xml"},".log":{type:"attachment",contentType:"text/plain"},".txt":{type:"attachment",contentType:"text/plain"},".yml":{type:"attachment",contentType:"text/plain"},".yaml":{type:"attachment",contentType:"text/plain"},".md":{type:"attachment",contentType:"text/markdown"},".html":{type:"attachment",contentType:"text/html"},".csv":{type:"attachment",contentType:"text/csv"},".json":{type:"attachment",contentType:"application/json"},".pdf":{type:"attachment",contentType:"application/pdf"},".gz":{type:"attachment",contentType:"application/gzip"},".viewhierarchy":{type:"attachment",contentType:"application/xml"}},Xr=t=>Qr[$s.default.extname(t).toLowerCase()];var Ks=l(require("fs-extra")),Hs=require("path"),Zr=p.extend("detox"),jd="detox.json";function Js(t){return[...t].sort((e,r)=>(e.session??0)-(r.session??0)||e.invocations-r.invocations)}async function Vs(t){let e=(0,Hs.join)(t,jd);try{let r=await Ks.default.readJson(e);if(typeof r?.artifactsRootDir!="string"||!Array.isArray(r?.tests)){Zr("Unexpected Detox manifest contents at %s",e);return}return Zr("Detox manifest: %o",r),r}catch{Zr("No Detox manifest at %s",e);return}}var Ue=require("path"),Gd=p.extend("detox"),Ys=255,$d=/[/\\?<>:*|"$\u0000-\u001f]/g,Ws=4;function qs(t){return Kd(t)??Hd(t)}function Kd({rootDir:t,fullName:e,status:r,invocations:o}){try{let n=require.resolve("detox/src/artifacts/utils/ArtifactPathBuilder",{paths:[process.cwd()]}),s=require(n),i=new s({rootDir:t});return(0,Ue.dirname)(i.buildPathForTestArtifact("test.mp4",{fullName:e,status:r,invocations:o}))}catch(n){Gd("Detox path builder is not available: %o",n);return}}function Hd({rootDir:t,fullName:e,status:r,invocations:o}){let n=Vd(r),s=o>1?` (${o})`:"",i=e.slice(-Ys+n.length+s.length),c=`${n}${i}${s}`.replace($d,"_");return(0,Ue.join)(t,Jd(c,Ys))}function Jd(t,e){let r=Buffer.from(t,"utf8");return r.length<=e?t:r.subarray(0,e).toString("utf8").replace(/\uFFFD$/,"")}function Vd(t){switch(t){case"passed":return"\u2713 ";case"failed":return"\u2717 ";default:return""}}var Qs=l(require("fs-extra")),Xs=require("path"),zs=p.extend("detox"),Pe="detox.trace.json",Yd="ws-client-invocation";async function Zs(t){let e=(0,Xs.join)(t,Pe),r=new Map,o;try{o=await Qs.default.readJson(e)}catch{return zs("No Detox trace at %s",e),r}if(!Array.isArray(o))return zs("Unexpected Detox trace contents at %s",e),r;let n=Wd(o);return zd(o).forEach(({pid:i,ts:c,step:m})=>{n.filter(f=>f.pid===i&&c>=f.startTs&&c<=f.endTs).sort((f,u)=>f.startTs-u.startTs).pop()?.steps.push(m)}),n.forEach(({fullName:i,invocations:c,steps:m})=>{let d=r.get(i)??[];d.push({fullName:i,invocations:c,steps:m.sort((f,u)=>+new Date(f.startTime)-+new Date(u.startTime))}),r.set(i,d)}),r}function Wd(t){let e=new Map,r=[];t.forEach(n=>{let s=`${n.pid}:${n.tid}`,i=e.get(s)??[];if(e.set(s,i),n.ph==="B"){i.push(qd(n));return}if(n.ph==="E"){let c=i.pop();c&&r.push({...c,endTs:Number(n.ts)})}});let o=[...e.values()].flatMap(n=>n.filter(s=>s!==void 0));return[...r,...o]}function qd(t){let e=t.args?.fullName;if(!(t.args?.context!=="test"||typeof e!="string"))return{fullName:e,invocations:Number(t.args?.invocations??1),pid:Number(t.pid),startTs:Number(t.ts),endTs:Number.MAX_SAFE_INTEGER,steps:[]}}function zd(t){let e=new Map,r=[];return t.forEach(o=>{if(!o.cat?.includes(Yd))return;let n=`${o.pid}:${o.tid}`,s=e.get(n)??[];if(o.ph==="B"){s.push({name:o.name??"action",cat:o.cat,ts:Number(o.ts)}),e.set(n,s);return}if(o.ph==="E"){let i=s.pop();if(!i)return;r.push({pid:Number(o.pid),ts:i.ts,step:{title:i.name,category:"detox",startTime:new Date(i.ts/1e3).toISOString(),duration:Math.round((Number(o.ts)-i.ts)/1e3),steps:[]}})}}),r}var ee=p.extend("detox"),ti="artifacts",Qd=[".mp4",".png",".jpg",".log",".txt",".json",".viewhierarchy"],Xd=t=>{let e=(0,it.extname)(t);return Qd.includes(e)?Qr[e]:void 0};async function ei({instances:t,reportDir:e,manifest:r}){let o=tm(r),n=await Zs(r.artifactsRootDir),s=await It((0,it.join)(e,ti)),i={artifacts:0,steps:0};for(let c of t)for(let m of c.results.tests){let d=o.get(m.testId);if(!d){ee("No Detox manifest entry for %s",m.testId);continue}await em({test:m,manifestTest:d,rootDir:r.artifactsRootDir,artifactsDir:s,traceSlices:n.get(d.fullName)??[],result:i})}return i.artifacts+=await Zd({instances:t,rootDir:r.artifactsRootDir,artifactsDir:s}),i}async function Zd({instances:t,rootDir:e,artifactsDir:r}){if(!await to.default.pathExists((0,it.join)(e,Pe)))return 0;let[o]=await ri(e,[Pe],r),n=t.map(s=>s.results.tests[0]).filter(s=>s!==void 0);return n.forEach(s=>{s.artifacts=[...s.artifacts??[],o]}),n.length}function tm(t){let e=new Map;return t.tests.forEach(r=>{e.set(r.fullName,[...e.get(r.fullName)??[],r.testId])}),new Map(t.tests.filter(r=>{let o=e.get(r.fullName)?.length===1;return o||ee("Ambiguous Detox test name, skipping: %s",r.fullName),o}).map(r=>[r.testId,r]))}async function em({test:t,manifestTest:e,rootDir:r,artifactsDir:o,traceSlices:n,result:s}){let i=[...t.attempts].sort((d,f)=>d.attempt-f.attempt),c=Js(e.attempts),m=1;for(let[d,f]of c.entries()){let u=i[d];if(!u){ee("No reported attempt %d of %s",d,e.fullName);continue}let E=await rm({fullName:e.fullName,status:f.status,rootDir:r,artifactsDir:o,fromInvocation:m});E&&(m=E.invocation+1,u.artifacts=[...u.artifacts??[],...E.artifacts],s.artifacts+=E.artifacts.length);let g=nm(n,d,E?.invocation);g.length&&(u.steps=[...u.steps??[],...g],s.steps+=g.length)}}async function rm({fullName:t,status:e,rootDir:r,artifactsDir:o,fromInvocation:n}){for(let s=n;s<n+Ws;s++){let i=qs({rootDir:r,fullName:t,status:e,invocations:s}),c=await om(i);if(c)return{invocation:s,artifacts:await ri(i,c,o)}}ee("No Detox artifacts for %s [%s]",t,e)}async function om(t){try{return(await to.default.readdir(t)).sort()}catch{return}}async function ri(t,e,r){let o=[];for(let n of e){let s=Xd(n);if(!s){ee("Skipping unsupported Detox artifact %s",n);continue}let i=(0,it.join)(t,n),c=`${rt(i)}${(0,it.extname)(n)}`;await me(i,(0,it.join)(r,c)),o.push({...s,path:(0,it.join)(ti,c),name:n})}return o}function nm(t,e,r){return((r===void 0?void 0:t.find(s=>s.invocations===r))??[...t].sort((s,i)=>s.invocations-i.invocations)[e])?.steps??[]}var mt=class{constructor(e){this.config=e}async getFullTestSuite(){return[]}};var im=l(require("crypto"));var oi=l(require("fs-extra")),sm=l(require("path"));async function be(t){let e=await oi.default.pathExists(t);if(!e)throw new Error("File does not exist");return e}function ni(){return"root"}function si(t){let e=(t.join(" ").match(/@(\S+)/g)??[]).filter(Boolean).map(r=>r);return Array.from(new Set([...e].map(r=>r.trim()).map(r=>r.replace("@",""))))}var am=/^[0-9a-f]{32}$/;function ii(t){let e=[];for(let r of t){let o=e.find(n=>n.name===r.groupId);o||(o={name:r.groupId,tags:[],tests:[]},e.push(o)),o.tests.push(...ci(r))}return e.length===1&&am.test(e[0].name)&&(e[0].name=ni()),e}function ai(t,e,r){let o=[];for(let{projectId:n,spec:s}of e){let i=r.find(m=>m.spec===s&&m.groupId===n)??(t.length===1?r.find(m=>m.spec===s):void 0);if(!i){o.push(s);continue}let c=t.length===1?t[0]:t.find(m=>m.name===n);c||(c={name:n,tags:[],tests:[]},t.push(c)),c.tests.push(...ci(i))}return o}function ci(t){return t.results.tests.map(e=>({spec:t.spec,testId:e.testId,title:e.title,tags:e.tags??si(e.title)}))}var _i=l(require("fs-extra")),wi=l(require("tmp"));var yi=require("lodash");function pi(t){let e=[];for(let[r,o]of Object.entries(t))r==="_"||r==="$0"||r.includes("-")||(typeof o=="boolean"?o&&e.push(`--${r}`):Array.isArray(o)?o.forEach(n=>{e.push(`--${r}=${n}`)}):e.push(`--${r}=${o}`));return e.join(" ")}var di=require("lodash"),cm=["bail","clearCache","collectCoverage","collectCoverageFrom","color","colors","config","coverage","coverageDirectory","coveragePathIgnorePatterns","coverageProvider","coverageReporters","coverageThreshold","debug","detectLeaks","detectOpenHandles","errorOnDeprecated","expand","forceExit","json","listTests","logHeapUsage","noStackTrace","notify","notifyMode","openHandlesTimeout","outputFile","reporters","runner","shard","showConfig","showSeed","silent","testFailureExitCode","testNamePattern","verbose","waitNextEventLoopTurnForUnhandledRejectionEvents","watch","watchAll","watchPathIgnorePatterns","watchman"];function mi(t){return(0,di.omit)(t,...cm)}var Ci=l(require("fs")),Be=require("lodash"),ro=l(require("path"));var eo=l(require("fs")),Ne=require("module"),Le=l(require("path")),ui=l(require("semver")),pm=">=29.5.0";function dm(){let t=(0,Ne.createRequire)(Le.default.join(process.cwd(),"package.json"));if(mm(t)==="jest-cli")return t.resolve("jest-cli");try{return(0,Ne.createRequire)(t.resolve("jest")).resolve("jest-cli")}catch{}try{return t.resolve("jest-cli")}catch{throw new Error(`Jest discovery needs the "jest" package, and it is not installed in ${process.cwd()}. Run the command from the folder of the project that ran the tests, or install Jest 29.5 or later: npm install --save-dev jest`)}}function mm(t){for(let e of t.resolve.paths("jest")??[]){if(eo.default.existsSync(Le.default.join(e,"jest","package.json")))return"jest";if(eo.default.existsSync(Le.default.join(e,"jest-cli","package.json")))return"jest-cli"}return null}function li(){let t=(0,Ne.createRequire)(dm()),{version:e}=t("jest-cli/package.json");if(!ui.default.satisfies(e,pm,{includePrerelease:!0}))throw new Error(`Jest discovery needs Jest 29.5 or later, and ${process.cwd()} has Jest ${e}. Update Jest: npm install --save-dev jest@latest`);return t}function fi(){return li()("jest-cli")}function gi(){return li()("jest-config")}function ve(t,e){return(...r)=>new Promise((o,n)=>{let s=0,i=()=>{s++;try{let c=t(...r);o(c)}catch(c){if(s>=e.length)n(c);else{let m=e[s-1];setTimeout(i,m)}}};i()})}var hi=p.extend("jest-discovery");function Ei(t){return["testEnvironment","globalSetup","globalTeardown"].some(e=>String(t[e]??"").includes("detox"))}function Ii(t){return{...(0,Be.omit)(t,["globalSetup","globalTeardown","testEnvironmentOptions"]),testEnvironment:"node"}}async function Ti(t,e){let r=e.detox;try{let{readInitialOptions:o}=gi(),{config:n,configPath:s}=await o(t);r||=[n,...n.projects??[]].some(E=>typeof E!="string"&&Ei(E));let i=["collectCoverage","collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","coverageProvider","coverageReporters","coverageThreshold","errorOnDeprecated","forceCoverageMatch","notify","notifyMode","openHandlesTimeout","reporters","runner","showSeed","testFailureExitCode","verbose","watchPathIgnorePatterns","watchPlugins","watchman","bail","clearCache","color","colors","debug","detectLeaks","detectOpenHandles","expand","forceExit","json","listTests","logHeapUsage","noStackTrace","outputFile","shard","showConfig","silent","testNamePattern","waitNextEventLoopTurnForUnhandledRejectionEvents","watch","watchAll"],c=["collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","detectLeaks","detectOpenHandles","errorOnDeprecated","forceCoverageMatch","openHandlesTimeout","runner","watchPathIgnorePatterns"],m=E=>e.detox||Ei(E),d=(0,Be.omit)(n,i);if(m(d)&&(d=Ii(d)),d.projects&&(d.projects=d.projects.map(E=>{if(typeof E=="string")return E;let g=(0,Be.omit)(E,c);return m(g)?Ii(g):g})),d.rootDir&&Object.keys(d).length===1)return null;let f=ro.default.resolve(s?ro.default.dirname(s):process.cwd(),`.jest-scanner-${new Date().getTime()}.config.cjs`),u=`module.exports=${JSON.stringify(d,null,2)}`;return hi("configFileContent: %O",u),Ci.default.writeFileSync(f,u),await ve(be,[200,200,200,200,200,1e3])(f),f}catch(o){if(hi("error %o",o),r)throw new Error(`Failed to recreate the Jest config for discovery: ${o.message}`);return C("Failed to recreate the config file"),null}}async function Ri(t,e){let r="!!##ThisPatternWillNotMatchAnyTestName##!!",o=t.options,n=mi(o),s=pi(n),i=o.config,c=await Ti(i,e);return{cliArgs:[s,"--testNamePattern",r,"--reporters",require.resolve("@currents/cmd/discovery/jest"),"--shard=1/1","--testFailureExitCode=0",c?`--config=${c}`:"",...t.args].filter(d=>!(0,yi.isEmpty)(d)),configFilePath:c}}var um=p.extend("jest-discovery");async function Oi(t,e){console.time(x("@currents/jest:fullTestSuite-ready"));let{run:r}=fi(),{cliArgs:o,configFilePath:n}=await Ri(t,e);try{let s=wi.default.fileSync({postfix:".json"});return um("running scanner: %o",o),process.env.CURRENTS_DISCOVERY_PATH=s.name,await r(o.concat(["--openHandlesTimeout=0"])),await ve(be,Array.from({length:300},()=>100))(s.name),console.timeEnd(x("@currents/jest:fullTestSuite-ready")),await ht(s.name)}catch(s){return C("Failed to obtain the jest full test suite:",s),{fullTestSuite:[],specsWithoutResults:[]}}finally{n&&_i.default.unlinkSync(n)}}var xi=p.extend("jest-discovery"),Fe=class extends mt{constructor(r,o){super(r);this.instances=o}async getFullTestSuite(){if(!this.config.frameworkConfig?.shard)return xi("Not a sharded run, listing the tests of the results"),ii(this.instances);let{fullTestSuite:r,specsWithoutResults:o}=await Oi(this.config.cliArgs,{detox:this.config.frameworkConfig.originFramework==="detox"});if(o.length===0)return r;for(let{spec:s,message:i}of o)I("Discovery could not load %s: %s",s,lm(i));let n=ai(r,o,this.instances);return I("The tests of these files are listed from the results of the shard that ran them. Currents can show the run as finished before the other shards upload."),xi("Files that did not run on this shard: %o",n),r.filter(s=>s.tests.length>0)}};function lm(t){return t.split(`
28
- `).map(e=>e.trim()).find(e=>e&&!e.startsWith("\u25CF"))??""}var Ai=l(require("fs-extra"));var Si=l(require("path"));function Tt(t){return Si.default.join(t,"fullTestSuite.json")}var fm=p.extend("junit-discovery");async function Di(t){console.time(x("@currents/junit:fullTestSuite-ready"));try{fm("running scanner: %o",t);let e=Tt(t);process.env.CURRENTS_DISCOVERY_PATH=e;let r=Ai.default.readFileSync(e,"utf-8");return JSON.parse(r)}catch(e){return C("Failed to obtain the junit full test suite:",e),[]}}var Me=class extends mt{constructor(e,r){super(e),this.reportDir=r}async getFullTestSuite(){return Di(this.reportDir)}};function Ui(t,e,r){switch(t.framework){case"jest":return new Fe(t,r);case"junit":return new Me(t,e);default:return new mt(t)}}var ut=l(require("fs-extra")),at=l(require("path"));async function Pi(t){let e=await gm(t?.reportDir);return{reportDir:e,configFilePath:t?.configFilePath??at.default.join(e,"config.json")}}async function gm(t){if(t){if(!await ut.default.pathExists(t))throw new Error(`No reports found: the folder "${t}" does not exist.`);return t}let e=(0,at.join)(process.cwd(),".currents"),r=await ut.default.pathExists(e)?await hm(e):null;if(!r)throw new Error(`No reports found: there is no report folder in "${e}". Run the tests with a Currents reporter first, or pass --report-dir with the folder of the reports.`);return r}async function hm(t){let e=await ut.default.readdir(t),r=null;for(let o of e){let n=at.default.join(t,o),s=await ut.default.stat(n);s.isDirectory()&&(!r||s.birthtime>r.birthtime)&&(r={name:o,birthtime:s.birthtime})}return r?(0,at.resolve)(t,r.name):null}async function oo(t){try{return await ut.default.pathExists(t)}catch{return C("Error checking if path exists:",C),!1}}async function bi(t){let e=at.default.join(t,"instances");return Em(e)}async function Em(t){let e=await ut.default.readdir(t),r=[];for(let o of e){let n=at.default.join(t,o);(await ut.default.stat(n)).isFile()&&r.push(n)}return r}var Im=t=>Buffer.byteLength(JSON.stringify(t),"utf8"),Ni=(t,e=1048576)=>{let r=[],o=[],n=0;for(let s of t){let i=Im(s);n+i>e&&(r.push(o),o=[],n=0),o.push(s),n+=i}return o.length>0&&r.push(o),r};var Cm=3e4;async function so(){let t=De();if(!t)throw new Error("Currents config is missing!");let e=await Pi(t);ko(ym(e.reportDir)),p("Reporter options: %o",e),T("Report directory: %s",e.reportDir);let r=await ht(e.configFilePath);p("Report config: %o",r);let o=await bi(e.reportDir);p("Found %d instance results in the reportDir: %s",o.length,e.reportDir);let n=Tm(e.reportDir),s=await oo(n),i=Tt(e.reportDir),c=null;if(s){let D=await ht(n);I("Marker file detected. The report was already uploaded: %o",{runUrl:D.response.runUrl,isoDate:D.isoDate})}let m=[];for(let D of o)m.push(await ht(D));if(c=await Rm(i),c)p("Full test suite file detected: %s",i);else{let Y=await Ui(r,e.reportDir,m).getFullTestSuite();if(!Fi(Y)||Mi(Y))throw new Error("Failed to discover the full test suite!");c=Y,await Et(i,JSON.stringify(c))}let d=c.length===1?c[0].name:null,f={currents:t},u={type:r.framework,version:r.frameworkVersion,clientVersion:St,frameworkConfig:{originFramework:r.frameworkConfig?.originFramework,originFrameworkVersion:r.frameworkConfig?.originFrameworkVersion}},E=ue.userFacingNanoid(),g=ot(t.ciBuildId),A={};for(let D of m)A[D.groupId]||(A[D.groupId]=[]),A[D.groupId].push(D);let V=await Vs(e.reportDir);if(V){let D=await ei({instances:Object.values(A).flat(),reportDir:e.reportDir,manifest:V});T("[currents] Attached %d Detox artifacts and %d steps",D.artifacts,D.steps)}let xt=new Map;Object.values(A).forEach(D=>{D.forEach(Y=>{Y.artifacts?.forEach($=>{$&&xt.set($.path,$.contentType)}),Y.results.tests.forEach($=>{$.artifacts?.forEach(j=>{j&&xt.set(j.path,j.contentType)}),$.attempts.forEach(j=>{j.artifacts?.forEach(ft=>{ft&&xt.set(ft.path,ft.contentType)})})})})});for await(let D of Object.keys(A)){let Y=A[D],$=D;d&&(p("Default group found: %s, overwriting the group in the results",d),$=d,Y=Y.map(j=>({...j,groupId:d})));try{let j=Ni(Y),ft=await Li({ci:g,group:$,instances:[],fullTestSuite:c,config:f,machineId:E,framework:u});for(let hr=0;hr<j.length;hr++){let Er=await Li({ci:g,group:$,instances:j[hr],fullTestSuite:[],config:f,machineId:E,framework:u});Er.artifactUploadUrls&&Er.artifactUploadUrls.length>0&&await _m(Er.artifactUploadUrls,e.reportDir,xt)}p("Api response: %o",ft),T("[%s] Run created: %s",$,ft.runUrl);let Xc={response:ft,isoDate:new Date().toISOString()};await Et(n,JSON.stringify(Xc)),p("Marker file %s: %s",s?"overwritten":"created",n)}catch(j){throw p("Failed to upload the results to the dashboard"),j}}}async function Li({ci:t,group:e,instances:r,fullTestSuite:o,config:n,machineId:s,framework:i}){let c=await Ae(),m=await ks(),d={browserName:"node",browserVersion:Bi.default.coerce(process.version)?.version},{currents:f}=n,E={platform:{...d,...m},ci:t,commit:c,group:e,fullTestSuite:o,config:n,projectId:f.projectId,recordKey:f.recordKey,ciBuildId:t.ciBuildId.value??void 0,tags:f.tag??[],machineId:f.machineId??s,framework:i,instances:r,previousCiBuildId:process.env.CURRENTS_PREVIOUS_CI_BUILD_ID};return p("Creating run: %o",h(E)),wn(E)}function Tm(t){return ke.default.join(t,"upload.marker.json")}function ym(t){return ke.default.join(t,`.debug-${new Date().toISOString()}.log`)}async function Rm(t){if(!await oo(t))return null;try{let e=await ht(t);return!Fi(e)||Mi(e)?(I("Ignoring %s, it is not a list of projects and tests",t),null):e}catch(e){return I("Ignoring %s, it is not valid JSON: %s",t,e),null}}function Fi(t){return Array.isArray(t)&&t.every(e=>typeof e?.name=="string"&&Array.isArray(e.tests)&&e.tests.every(r=>typeof r?.spec=="string"&&typeof r.testId=="string"&&Array.isArray(r.title)&&r.title.every(o=>typeof o=="string")))}function Mi(t){return t.length===0||t.some(e=>e.tests.length===0)}async function _m(t,e,r){p("Uploading %d artifacts",t.length),await Promise.all(t.map(o=>{let n=ke.default.join(e,o.path),s=r.get(o.path)||"application/octet-stream";return wm(n,s,o.uploadUrl)}))}var wm=async(t,e,r)=>{try{if(!await no.default.pathExists(t)){I("Artifact file not found: %s",t);return}let o=await no.default.readFile(t);await vi.default.put(r,o,{headers:{"Content-Type":e},timeout:Cm})}catch(o){p("Failed to upload artifact %s: %o",t,o)}};var Om=p.extend("cli");async function ki(t,e){await w(async r=>{r.output||bt(),e.getOptionValueSource("ciBuildId")==="env"&&(r.branch||r.tag)&&(r={...r,ciBuildId:void 0}),Xo(r);let n=he();Om("Config: %o",h(n)),await Nr()},t)}var Z=require("@commander-js/extra-typings");var $i=require("axios"),Ki=l(require("fs-extra"));var xm=p.extend("api");function Sm(t){if(/^[a-z][a-z0-9+.-]*:\/\//i.test(t))throw new Error(`Pass a path such as /v1/runs/<run-id>, not a URL. The CLI sends requests to ${Wt()}`);let e=t.replace(/^\/+/,""),r=o=>/^(\.|%2e){1,2}$/i.test(o);if(e.split(/[?#]/)[0].split("/").some(r))throw new Error(`The path cannot hold "." or ".." segments: ${t}`);return/^v1(\/|\?|$)/.test(e)?e:`v1/${e}`}function Am(t){let e=Object.create(null);for(let[r,o]of t)if(r.endsWith("[]")){let n=r.slice(0,-2);e[n]=[...Array.isArray(e[n])?e[n]:[],o]}else e[r]=o;return e}function Dm(t){let e=new URLSearchParams;for(let[r,o]of t)e.append(r,String(o));return e}async function Um(t){let e=t==="-"?await new Promise((r,o)=>{let n="";process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>n+=s),process.stdin.on("end",()=>r(n)),process.stdin.on("error",o)}):await Ki.default.readFile(t,"utf8");try{return JSON.parse(e)}catch(r){throw new Error(`--input ${t} is not valid JSON: ${r.message}`)}}async function Pm(t,e){let r=[...e.field??[],...e.rawField??[]],o=e.input!==void 0,n=e.method??(o||r.length>0?"POST":"GET"),s=o||n==="GET"||n==="HEAD";return{method:n,url:Sm(t),params:s&&r.length>0?Dm(r):void 0,data:o?JSON.stringify(await Um(e.input)):!s&&r.length>0?JSON.stringify(Am(r)):void 0,headers:Object.fromEntries(e.header??[])}}function ji(t){let e=Object.entries(t.headers).map(([r,o])=>`${r}: ${Array.isArray(o)?o.join(", "):o}`);return[`HTTP/1.1 ${t.status} ${t.statusText}`,...e,"",""].join(`
29
- `)}function Gi(t,e){let r=t.data??"",o=String(t.headers["content-type"]??"").toLowerCase().includes("json");if(!e||!o||!r)return r;try{return JSON.stringify(JSON.parse(r),null,2)+`
30
- `}catch{return r}}async function Hi(t,e){let{apiKey:r}=U(_,["apiKey"],e),o=s=>s?.map(([i])=>i);xm("Options: %o",h({...e,field:o(e.field),rawField:o(e.rawField),header:o(e.header)}));let n=await Pm(t,e);try{let s=await bn(r,n);e.include&&process.stdout.write(ji(s)),process.stdout.write(Gi(s,!!process.stdout.isTTY))}catch(s){if(!(0,$i.isAxiosError)(s))throw s;let i=s.response;if(!i)throw new Error(`Could not reach the REST API at ${Wt()}: ${s.message}`);e.include&&process.stderr.write(ji(i));let c=Gi(i,!!process.stderr.isTTY);throw c&&process.stderr.write(c.endsWith(`
27
+ `))}var{recordKey:Pd,projectId:bd,ciBuildId:Nd,debug:Ld}=_,X={recordKey:Pd,projectId:bd,ciBuildId:Nd,runId:{name:"Run ID",env:"CURRENTS_RUN_ID",cli:"--run-id"},debug:Ld};var vd=p.extend("config"),Bd=["recordKey","projectId"];function Fd(t){if(!(t.runId||t.ciBuildId))throw C(`${he(X,"runId")} or ${he(X,"ciBuildId")} is required: pass ${x(ge(X,"runId"))} or ${x(ge(X,"ciBuildId"))}, or set ${x(L(X,"runId"))} or ${x(L(X,"ciBuildId"))}`),new z("Missing required config variable")}var Qr=null;function Ms(t){Qr=U(X,Bd,t,Fd),vd("Resolved config: %o",h(Qr))}function De(){return Qr}async function Xr(){let t=De();if(!t)throw new Error("Config is missing!");let e=t.runId?`runId: ${t.runId}`:`ciBuildId: ${t.ciBuildId}`;try{let r=await On({recordKey:t.recordKey,projectId:t.projectId,ciBuildId:t.ciBuildId,runId:t.runId});return r.data.runId?T('Run "%s" (%s) is cancelled',r.data.runId,e):T('No run to cancel (%s) in project "%s"',e,t.projectId),r}catch(r){throw p("Failed to cancel the run"),r}}var ks=require("@currents/commit-info"),js=require("lodash");var Md=p.extend("git"),kd=async()=>{let t=await(0,ks.commitInfo)();return Md("commit: %O",t),{branch:t.branch,remoteOrigin:t.remote,authorEmail:t.email,authorName:t.author,message:t.message,sha:t.sha,ghaEventData:t.ghaEventData??null}},Ue=(0,js.memoize)(kd);var $s=l(require("getos")),Gs=require("lodash"),H=require("os"),Ks=require("util"),jd=async()=>{if((0,H.platform)()==="linux")try{let t=await(0,Ks.promisify)($s.default)();return"dist"in t&&"release"in t?[t.dist,t.release].join(" - "):(0,H.release)()}catch{return(0,H.release)()}return(0,H.release)()},$d=async()=>{let t=await jd();return{osName:(0,H.platform)(),osVersion:t,osCpus:[],osMemory:{free:(0,H.freemem)(),total:(0,H.totalmem)()}}},Hs=(0,Gs.memoize)($d);var ji=l(require("axios")),ao=l(require("fs-extra")),$e=l(require("path")),$i=l(require("semver"));var{debug:Gd,ciBuildId:Kd,recordKey:Hd,projectId:Jd,machineId:Vd}=_,nt={debug:Gd,ciBuildId:Kd,recordKey:Hd,projectId:Jd,machineId:Vd,tag:{..._.tag,env:"CURRENTS_TAG"},disableTitleTags:{name:"Disable title tags",env:"CURRENTS_DISABLE_TITLE_TAGS",cli:"--disable-title-tags"},removeTitleTags:{name:"Remove title tags",env:"CURRENTS_REMOVE_TITLE_TAGS",cli:"--remove-title-tags"},reportDir:{name:"Report folder",env:"CURRENTS_REPORT_DIR",cli:"--report-dir"}};var Yd=p.extend("config"),Wd=["projectId","recordKey"],Zr=null;function Js(t){Zr=U(nt,Wd,t),Yd("Resolved Currents config: %o",h(Zr))}function Pe(){return Zr}function Vs(t){return{ciBuildId:t.ciBuildId,projectId:t.projectId,recordKey:t.key,tag:t.tag,removeTitleTags:t.removeTitleTags,disableTitleTags:t.disableTitleTags,debug:t.debug,machineId:t.machineId,reportDir:t.reportDir}}var oo=l(require("fs-extra")),st=require("path");var Ys=l(require("path")),to={".png":{type:"screenshot",contentType:"image/png"},".jpg":{type:"screenshot",contentType:"image/jpeg"},".jpeg":{type:"screenshot",contentType:"image/jpeg"},".webp":{type:"screenshot",contentType:"image/webp"},".gif":{type:"screenshot",contentType:"image/gif"},".mp4":{type:"video",contentType:"video/mp4"},".webm":{type:"video",contentType:"video/webm"},".svg":{type:"attachment",contentType:"image/svg+xml"},".log":{type:"attachment",contentType:"text/plain"},".txt":{type:"attachment",contentType:"text/plain"},".yml":{type:"attachment",contentType:"text/plain"},".yaml":{type:"attachment",contentType:"text/plain"},".md":{type:"attachment",contentType:"text/markdown"},".html":{type:"attachment",contentType:"text/html"},".csv":{type:"attachment",contentType:"text/csv"},".json":{type:"attachment",contentType:"application/json"},".pdf":{type:"attachment",contentType:"application/pdf"},".gz":{type:"attachment",contentType:"application/gzip"},".viewhierarchy":{type:"attachment",contentType:"application/xml"}},eo=t=>to[Ys.default.extname(t).toLowerCase()];var Ws=l(require("fs-extra")),qs=require("path"),ro=p.extend("detox"),qd="detox.json";function zs(t){return[...t].sort((e,r)=>(e.session??0)-(r.session??0)||e.invocations-r.invocations)}async function Qs(t){let e=(0,qs.join)(t,qd);try{let r=await Ws.default.readJson(e);if(typeof r?.artifactsRootDir!="string"||!Array.isArray(r?.tests)){ro("Unexpected Detox manifest contents at %s",e);return}return ro("Detox manifest: %o",r),r}catch{ro("No Detox manifest at %s",e);return}}var be=require("path"),zd=p.extend("detox"),Xs=255,Qd=/[/\\?<>:*|"$\u0000-\u001f]/g,Zs=4;function ti(t){return Xd(t)??Zd(t)}function Xd({rootDir:t,fullName:e,status:r,invocations:o}){try{let n=require.resolve("detox/src/artifacts/utils/ArtifactPathBuilder",{paths:[process.cwd()]}),s=require(n),i=new s({rootDir:t});return(0,be.dirname)(i.buildPathForTestArtifact("test.mp4",{fullName:e,status:r,invocations:o}))}catch(n){zd("Detox path builder is not available: %o",n);return}}function Zd({rootDir:t,fullName:e,status:r,invocations:o}){let n=em(r),s=o>1?` (${o})`:"",i=e.slice(-Xs+n.length+s.length),c=`${n}${i}${s}`.replace(Qd,"_");return(0,be.join)(t,tm(c,Xs))}function tm(t,e){let r=Buffer.from(t,"utf8");return r.length<=e?t:r.subarray(0,e).toString("utf8").replace(/\uFFFD$/,"")}function em(t){switch(t){case"passed":return"\u2713 ";case"failed":return"\u2717 ";default:return""}}var ri=l(require("fs-extra")),oi=require("path"),ei=p.extend("detox"),Ne="detox.trace.json",rm="ws-client-invocation";async function ni(t){let e=(0,oi.join)(t,Ne),r=new Map,o;try{o=await ri.default.readJson(e)}catch{return ei("No Detox trace at %s",e),r}if(!Array.isArray(o))return ei("Unexpected Detox trace contents at %s",e),r;let n=om(o);return sm(o).forEach(({pid:i,ts:c,step:m})=>{n.filter(f=>f.pid===i&&c>=f.startTs&&c<=f.endTs).sort((f,u)=>f.startTs-u.startTs).pop()?.steps.push(m)}),n.forEach(({fullName:i,invocations:c,steps:m})=>{let d=r.get(i)??[];d.push({fullName:i,invocations:c,steps:m.sort((f,u)=>+new Date(f.startTime)-+new Date(u.startTime))}),r.set(i,d)}),r}function om(t){let e=new Map,r=[];t.forEach(n=>{let s=`${n.pid}:${n.tid}`,i=e.get(s)??[];if(e.set(s,i),n.ph==="B"){i.push(nm(n));return}if(n.ph==="E"){let c=i.pop();c&&r.push({...c,endTs:Number(n.ts)})}});let o=[...e.values()].flatMap(n=>n.filter(s=>s!==void 0));return[...r,...o]}function nm(t){let e=t.args?.fullName;if(!(t.args?.context!=="test"||typeof e!="string"))return{fullName:e,invocations:Number(t.args?.invocations??1),pid:Number(t.pid),startTs:Number(t.ts),endTs:Number.MAX_SAFE_INTEGER,steps:[]}}function sm(t){let e=new Map,r=[];return t.forEach(o=>{if(!o.cat?.includes(rm))return;let n=`${o.pid}:${o.tid}`,s=e.get(n)??[];if(o.ph==="B"){s.push({name:o.name??"action",cat:o.cat,ts:Number(o.ts)}),e.set(n,s);return}if(o.ph==="E"){let i=s.pop();if(!i)return;r.push({pid:Number(o.pid),ts:i.ts,step:{title:i.name,category:"detox",startTime:new Date(i.ts/1e3).toISOString(),duration:Math.round((Number(o.ts)-i.ts)/1e3),steps:[]}})}}),r}var re=p.extend("detox"),si="artifacts",im=[".mp4",".png",".jpg",".log",".txt",".json",".viewhierarchy"],am=t=>{let e=(0,st.extname)(t);return im.includes(e)?to[e]:void 0};async function ii({instances:t,reportDir:e,manifest:r}){let o=pm(r),n=await ni(r.artifactsRootDir),s=await Ct((0,st.join)(e,si)),i={artifacts:0,steps:0};for(let c of t)for(let m of c.results.tests){let d=o.get(m.testId);if(!d){re("No Detox manifest entry for %s",m.testId);continue}await dm({test:m,manifestTest:d,rootDir:r.artifactsRootDir,artifactsDir:s,traceSlices:n.get(d.fullName)??[],result:i})}return i.artifacts+=await cm({instances:t,rootDir:r.artifactsRootDir,artifactsDir:s}),i}async function cm({instances:t,rootDir:e,artifactsDir:r}){if(!await oo.default.pathExists((0,st.join)(e,Ne)))return 0;let[o]=await ai(e,[Ne],r),n=t.map(s=>s.results.tests[0]).filter(s=>s!==void 0);return n.forEach(s=>{s.artifacts=[...s.artifacts??[],o]}),n.length}function pm(t){let e=new Map;return t.tests.forEach(r=>{e.set(r.fullName,[...e.get(r.fullName)??[],r.testId])}),new Map(t.tests.filter(r=>{let o=e.get(r.fullName)?.length===1;return o||re("Ambiguous Detox test name, skipping: %s",r.fullName),o}).map(r=>[r.testId,r]))}async function dm({test:t,manifestTest:e,rootDir:r,artifactsDir:o,traceSlices:n,result:s}){let i=[...t.attempts].sort((d,f)=>d.attempt-f.attempt),c=zs(e.attempts),m=1;for(let[d,f]of c.entries()){let u=i[d];if(!u){re("No reported attempt %d of %s",d,e.fullName);continue}let E=await mm({fullName:e.fullName,status:f.status,rootDir:r,artifactsDir:o,fromInvocation:m});E&&(m=E.invocation+1,u.artifacts=[...u.artifacts??[],...E.artifacts],s.artifacts+=E.artifacts.length);let g=lm(n,d,E?.invocation);g.length&&(u.steps=[...u.steps??[],...g],s.steps+=g.length)}}async function mm({fullName:t,status:e,rootDir:r,artifactsDir:o,fromInvocation:n}){for(let s=n;s<n+Zs;s++){let i=ti({rootDir:r,fullName:t,status:e,invocations:s}),c=await um(i);if(c)return{invocation:s,artifacts:await ai(i,c,o)}}re("No Detox artifacts for %s [%s]",t,e)}async function um(t){try{return(await oo.default.readdir(t)).sort()}catch{return}}async function ai(t,e,r){let o=[];for(let n of e){let s=am(n);if(!s){re("Skipping unsupported Detox artifact %s",n);continue}let i=(0,st.join)(t,n),c=`${et(i)}${(0,st.extname)(n)}`;await ue(i,(0,st.join)(r,c)),o.push({...s,path:(0,st.join)(si,c),name:n})}return o}function lm(t,e,r){return((r===void 0?void 0:t.find(s=>s.invocations===r))??[...t].sort((s,i)=>s.invocations-i.invocations)[e])?.steps??[]}var mt=class{constructor(e){this.config=e}async getFullTestSuite(){return[]}};var gm=l(require("crypto"));var ci=l(require("fs-extra")),fm=l(require("path"));async function Le(t){let e=await ci.default.pathExists(t);if(!e)throw new Error("File does not exist");return e}function pi(){return"root"}function di(t){let e=(t.join(" ").match(/@(\S+)/g)??[]).filter(Boolean).map(r=>r);return Array.from(new Set([...e].map(r=>r.trim()).map(r=>r.replace("@",""))))}var hm=/^[0-9a-f]{32}$/;function mi(t){let e=[];for(let r of t){let o=e.find(n=>n.name===r.groupId);o||(o={name:r.groupId,tags:[],tests:[]},e.push(o)),o.tests.push(...li(r))}return e.length===1&&hm.test(e[0].name)&&(e[0].name=pi()),e}function ui(t,e,r){let o=[];for(let{projectId:n,spec:s}of e){let i=r.find(m=>m.spec===s&&m.groupId===n)??(t.length===1?r.find(m=>m.spec===s):void 0);if(!i){o.push(s);continue}let c=t.length===1?t[0]:t.find(m=>m.name===n);c||(c={name:n,tags:[],tests:[]},t.push(c)),c.tests.push(...li(i))}return o}function li(t){return t.results.tests.map(e=>({spec:t.spec,testId:e.testId,title:e.title,tags:e.tags??di(e.title)}))}var Ai=l(require("fs-extra")),Di=l(require("tmp"));var xi=require("lodash");function fi(t){let e=[];for(let[r,o]of Object.entries(t))r==="_"||r==="$0"||r.includes("-")||(typeof o=="boolean"?o&&e.push(`--${r}`):Array.isArray(o)?o.forEach(n=>{e.push(`--${r}=${n}`)}):e.push(`--${r}=${o}`));return e.join(" ")}var gi=require("lodash"),Em=["bail","clearCache","collectCoverage","collectCoverageFrom","color","colors","config","coverage","coverageDirectory","coveragePathIgnorePatterns","coverageProvider","coverageReporters","coverageThreshold","debug","detectLeaks","detectOpenHandles","errorOnDeprecated","expand","forceExit","json","listTests","logHeapUsage","noStackTrace","notify","notifyMode","openHandlesTimeout","outputFile","reporters","runner","shard","showConfig","showSeed","silent","testFailureExitCode","testNamePattern","verbose","waitNextEventLoopTurnForUnhandledRejectionEvents","watch","watchAll","watchPathIgnorePatterns","watchman"];function hi(t){return(0,gi.omit)(t,...Em)}var _i=l(require("fs")),Me=require("lodash"),so=l(require("path"));var no=l(require("fs")),ve=require("module"),Be=l(require("path")),Ei=l(require("semver")),Im=">=29.5.0";function Cm(){let t=(0,ve.createRequire)(Be.default.join(process.cwd(),"package.json"));if(Tm(t)==="jest-cli")return t.resolve("jest-cli");try{return(0,ve.createRequire)(t.resolve("jest")).resolve("jest-cli")}catch{}try{return t.resolve("jest-cli")}catch{throw new Error(`Jest discovery needs the "jest" package, and it is not installed in ${process.cwd()}. Run the command from the folder of the project that ran the tests, or install Jest 29.5 or later: npm install --save-dev jest`)}}function Tm(t){for(let e of t.resolve.paths("jest")??[]){if(no.default.existsSync(Be.default.join(e,"jest","package.json")))return"jest";if(no.default.existsSync(Be.default.join(e,"jest-cli","package.json")))return"jest-cli"}return null}function Ii(){let t=(0,ve.createRequire)(Cm()),{version:e}=t("jest-cli/package.json");if(!Ei.default.satisfies(e,Im,{includePrerelease:!0}))throw new Error(`Jest discovery needs Jest 29.5 or later, and ${process.cwd()} has Jest ${e}. Update Jest: npm install --save-dev jest@latest`);return t}function Ci(){return Ii()("jest-cli")}function Ti(){return Ii()("jest-config")}function Fe(t,e){return(...r)=>new Promise((o,n)=>{let s=0,i=()=>{s++;try{let c=t(...r);o(c)}catch(c){if(s>=e.length)n(c);else{let m=e[s-1];setTimeout(i,m)}}};i()})}var yi=p.extend("jest-discovery");function Ri(t){return["testEnvironment","globalSetup","globalTeardown"].some(e=>String(t[e]??"").includes("detox"))}function wi(t){return{...(0,Me.omit)(t,["globalSetup","globalTeardown","testEnvironmentOptions"]),testEnvironment:"node"}}async function Oi(t,e){let r=e.detox;try{let{readInitialOptions:o}=Ti(),{config:n,configPath:s}=await o(t);r||=[n,...n.projects??[]].some(E=>typeof E!="string"&&Ri(E));let i=["collectCoverage","collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","coverageProvider","coverageReporters","coverageThreshold","errorOnDeprecated","forceCoverageMatch","notify","notifyMode","openHandlesTimeout","reporters","runner","showSeed","testFailureExitCode","verbose","watchPathIgnorePatterns","watchPlugins","watchman","bail","clearCache","color","colors","debug","detectLeaks","detectOpenHandles","expand","forceExit","json","listTests","logHeapUsage","noStackTrace","outputFile","shard","showConfig","silent","testNamePattern","waitNextEventLoopTurnForUnhandledRejectionEvents","watch","watchAll"],c=["collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","detectLeaks","detectOpenHandles","errorOnDeprecated","forceCoverageMatch","openHandlesTimeout","runner","watchPathIgnorePatterns"],m=E=>e.detox||Ri(E),d=(0,Me.omit)(n,i);if(m(d)&&(d=wi(d)),d.projects&&(d.projects=d.projects.map(E=>{if(typeof E=="string")return E;let g=(0,Me.omit)(E,c);return m(g)?wi(g):g})),d.rootDir&&Object.keys(d).length===1)return null;let f=so.default.resolve(s?so.default.dirname(s):process.cwd(),`.jest-scanner-${new Date().getTime()}.config.cjs`),u=`module.exports=${JSON.stringify(d,null,2)}`;return yi("configFileContent: %O",u),_i.default.writeFileSync(f,u),await Fe(Le,[200,200,200,200,200,1e3])(f),f}catch(o){if(yi("error %o",o),r)throw new Error(`Failed to recreate the Jest config for discovery: ${o.message}`);return C("Failed to recreate the config file"),null}}async function Si(t,e){let r="!!##ThisPatternWillNotMatchAnyTestName##!!",o=t.options,n=hi(o),s=fi(n),i=o.config,c=await Oi(i,e);return{cliArgs:[s,"--testNamePattern",r,"--reporters",require.resolve("@currents/cmd/discovery/jest"),"--shard=1/1","--testFailureExitCode=0",c?`--config=${c}`:"",...t.args].filter(d=>!(0,xi.isEmpty)(d)),configFilePath:c}}var ym=p.extend("jest-discovery");async function Ui(t,e){console.time(x("@currents/jest:fullTestSuite-ready"));let{run:r}=Ci(),{cliArgs:o,configFilePath:n}=await Si(t,e);try{let s=Di.default.fileSync({postfix:".json"});return ym("running scanner: %o",o),process.env.CURRENTS_DISCOVERY_PATH=s.name,await r(o.concat(["--openHandlesTimeout=0"])),await Fe(Le,Array.from({length:300},()=>100))(s.name),console.timeEnd(x("@currents/jest:fullTestSuite-ready")),await Et(s.name)}catch(s){return C("Failed to obtain the jest full test suite:",s),{fullTestSuite:[],specsWithoutResults:[]}}finally{n&&Ai.default.unlinkSync(n)}}var Pi=p.extend("jest-discovery"),ke=class extends mt{constructor(r,o){super(r);this.instances=o}async getFullTestSuite(){if(!this.config.frameworkConfig?.shard)return Pi("Not a sharded run, listing the tests of the results"),mi(this.instances);let{fullTestSuite:r,specsWithoutResults:o}=await Ui(this.config.cliArgs,{detox:this.config.frameworkConfig.originFramework==="detox"});if(o.length===0)return r;for(let{spec:s,message:i}of o)I("Discovery could not load %s: %s",s,Rm(i));let n=ui(r,o,this.instances);return I("The tests of these files are listed from the results of the shard that ran them. Currents can show the run as finished before the other shards upload."),Pi("Files that did not run on this shard: %o",n),r.filter(s=>s.tests.length>0)}};function Rm(t){return t.split(`
28
+ `).map(e=>e.trim()).find(e=>e&&!e.startsWith("\u25CF"))??""}var Ni=l(require("fs-extra"));var bi=l(require("path"));function yt(t){return bi.default.join(t,"fullTestSuite.json")}var wm=p.extend("junit-discovery");async function Li(t){console.time(x("@currents/junit:fullTestSuite-ready"));try{wm("running scanner: %o",t);let e=yt(t);process.env.CURRENTS_DISCOVERY_PATH=e;let r=Ni.default.readFileSync(e,"utf-8");return JSON.parse(r)}catch(e){return C("Failed to obtain the junit full test suite:",e),[]}}var je=class extends mt{constructor(e,r){super(e),this.reportDir=r}async getFullTestSuite(){return Li(this.reportDir)}};function vi(t,e,r){switch(t.framework){case"jest":return new ke(t,r);case"junit":return new je(t,e);default:return new mt(t)}}var ut=l(require("fs-extra")),it=l(require("path"));async function Bi(t){let e=await _m(t?.reportDir);return{reportDir:e,configFilePath:t?.configFilePath??it.default.join(e,"config.json")}}async function _m(t){if(t){if(!await ut.default.pathExists(t))throw new Error(`No reports found: the folder "${t}" does not exist.`);return t}let e=(0,it.join)(process.cwd(),".currents"),r=await ut.default.pathExists(e)?await Om(e):null;if(!r)throw new Error(`No reports found: there is no report folder in "${e}". Run the tests with a Currents reporter first, or pass --report-dir with the folder of the reports.`);return r}async function Om(t){let e=await ut.default.readdir(t),r=null;for(let o of e){let n=it.default.join(t,o),s=await ut.default.stat(n);s.isDirectory()&&(!r||s.birthtime>r.birthtime)&&(r={name:o,birthtime:s.birthtime})}return r?(0,it.resolve)(t,r.name):null}async function io(t){try{return await ut.default.pathExists(t)}catch{return C("Error checking if path exists:",C),!1}}async function Fi(t){let e=it.default.join(t,"instances");return xm(e)}async function xm(t){let e=await ut.default.readdir(t),r=[];for(let o of e){let n=it.default.join(t,o);(await ut.default.stat(n)).isFile()&&r.push(n)}return r}var Sm=t=>Buffer.byteLength(JSON.stringify(t),"utf8"),Mi=(t,e=1048576)=>{let r=[],o=[],n=0;for(let s of t){let i=Sm(s);n+i>e&&(r.push(o),o=[],n=0),o.push(s),n+=i}return o.length>0&&r.push(o),r};var Am=3e4;async function co(){let t=Pe();if(!t)throw new Error("Currents config is missing!");let e=await Bi(t);Ho(Um(e.reportDir)),p("Reporter options: %o",e),T("Report directory: %s",e.reportDir);let r=await Et(e.configFilePath);p("Report config: %o",r);let o=await Fi(e.reportDir);p("Found %d instance results in the reportDir: %s",o.length,e.reportDir);let n=Dm(e.reportDir),s=await io(n),i=yt(e.reportDir),c=null;if(s){let D=await Et(n);I("Marker file detected. The report was already uploaded: %o",{runUrl:D.response.runUrl,isoDate:D.isoDate})}let m=[];for(let D of o)m.push(await Et(D));if(c=await Pm(i),c)p("Full test suite file detected: %s",i);else{let W=await vi(r,e.reportDir,m).getFullTestSuite();if(!Gi(W)||Ki(W))throw new Error("Failed to discover the full test suite!");c=W,await It(i,JSON.stringify(c))}let d=c.length===1?c[0].name:null,f={currents:t},u={type:r.framework,version:r.frameworkVersion,clientVersion:At,frameworkConfig:{originFramework:r.frameworkConfig?.originFramework,originFrameworkVersion:r.frameworkConfig?.originFrameworkVersion}},E=fe.userFacingNanoid(),g=rt(t.ciBuildId),A={};for(let D of m)A[D.groupId]||(A[D.groupId]=[]),A[D.groupId].push(D);let Y=await Qs(e.reportDir);if(Y){let D=await ii({instances:Object.values(A).flat(),reportDir:e.reportDir,manifest:Y});T("[currents] Attached %d Detox artifacts and %d steps",D.artifacts,D.steps)}let St=new Map;Object.values(A).forEach(D=>{D.forEach(W=>{W.artifacts?.forEach(G=>{G&&St.set(G.path,G.contentType)}),W.results.tests.forEach(G=>{G.artifacts?.forEach(j=>{j&&St.set(j.path,j.contentType)}),G.attempts.forEach(j=>{j.artifacts?.forEach(ft=>{ft&&St.set(ft.path,ft.contentType)})})})})});for await(let D of Object.keys(A)){let W=A[D],G=D;d&&(p("Default group found: %s, overwriting the group in the results",d),G=d,W=W.map(j=>({...j,groupId:d})));try{let j=Mi(W),ft=await ki({ci:g,group:G,instances:[],fullTestSuite:c,config:f,machineId:E,framework:u});for(let Cr=0;Cr<j.length;Cr++){let Tr=await ki({ci:g,group:G,instances:j[Cr],fullTestSuite:[],config:f,machineId:E,framework:u});Tr.artifactUploadUrls&&Tr.artifactUploadUrls.length>0&&await bm(Tr.artifactUploadUrls,e.reportDir,St)}p("Api response: %o",ft),T("[%s] Run created: %s",G,ft.runUrl);let ap={response:ft,isoDate:new Date().toISOString()};await It(n,JSON.stringify(ap)),p("Marker file %s: %s",s?"overwritten":"created",n)}catch(j){throw p("Failed to upload the results to the dashboard"),j}}}async function ki({ci:t,group:e,instances:r,fullTestSuite:o,config:n,machineId:s,framework:i}){let c=await Ue(),m=await Hs(),d={browserName:"node",browserVersion:$i.default.coerce(process.version)?.version},{currents:f}=n,E={platform:{...d,...m},ci:t,commit:c,group:e,fullTestSuite:o,config:n,projectId:f.projectId,recordKey:f.recordKey,ciBuildId:t.ciBuildId.value??void 0,tags:f.tag??[],machineId:f.machineId??s,framework:i,instances:r,previousCiBuildId:process.env.CURRENTS_PREVIOUS_CI_BUILD_ID};return p("Creating run: %o",h(E)),Dn(E)}function Dm(t){return $e.default.join(t,"upload.marker.json")}function Um(t){return $e.default.join(t,`.debug-${new Date().toISOString()}.log`)}async function Pm(t){if(!await io(t))return null;try{let e=await Et(t);return!Gi(e)||Ki(e)?(I("Ignoring %s, it is not a list of projects and tests",t),null):e}catch(e){return I("Ignoring %s, it is not valid JSON: %s",t,e),null}}function Gi(t){return Array.isArray(t)&&t.every(e=>typeof e?.name=="string"&&Array.isArray(e.tests)&&e.tests.every(r=>typeof r?.spec=="string"&&typeof r.testId=="string"&&Array.isArray(r.title)&&r.title.every(o=>typeof o=="string")))}function Ki(t){return t.length===0||t.some(e=>e.tests.length===0)}async function bm(t,e,r){p("Uploading %d artifacts",t.length),await Promise.all(t.map(o=>{let n=$e.default.join(e,o.path),s=r.get(o.path)||"application/octet-stream";return Nm(n,s,o.uploadUrl)}))}var Nm=async(t,e,r)=>{try{if(!await ao.default.pathExists(t)){I("Artifact file not found: %s",t);return}let o=await ao.default.readFile(t);await ji.default.put(r,o,{headers:{"Content-Type":e},timeout:Am})}catch(o){p("Failed to upload artifact %s: %o",t,o)}};var Lm=p.extend("cli");async function Hi(t,e){await R(async r=>{r.output||Nt(),e.getOptionValueSource("ciBuildId")==="env"&&(r.branch||r.tag)&&(r={...r,ciBuildId:void 0}),on(r);let n=Ie();Lm("Config: %o",h(n)),await Br()},t)}var Z=require("@commander-js/extra-typings");var Yi=require("axios"),Wi=l(require("fs-extra"));var vm=p.extend("api");function Bm(t){if(/^[a-z][a-z0-9+.-]*:\/\//i.test(t))throw new Error(`Pass a path such as /v1/runs/<run-id>, not a URL. The CLI sends requests to ${Wt()}`);let e=t.replace(/^\/+/,""),r=o=>/^(\.|%2e){1,2}$/i.test(o);if(e.split(/[?#]/)[0].split("/").some(r))throw new Error(`The path cannot hold "." or ".." segments: ${t}`);return/^v1(\/|\?|$)/.test(e)?e:`v1/${e}`}function Fm(t){let e=Object.create(null);for(let[r,o]of t)if(r.endsWith("[]")){let n=r.slice(0,-2);e[n]=[...Array.isArray(e[n])?e[n]:[],o]}else e[r]=o;return e}function Mm(t){let e=new URLSearchParams;for(let[r,o]of t)e.append(r,String(o));return e}async function km(t){let e=t==="-"?await new Promise((r,o)=>{let n="";process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>n+=s),process.stdin.on("end",()=>r(n)),process.stdin.on("error",o)}):await Wi.default.readFile(t,"utf8");try{return JSON.parse(e)}catch(r){throw new Error(`--input ${t} is not valid JSON: ${r.message}`)}}async function jm(t,e){let r=[...e.field??[],...e.rawField??[]],o=e.input!==void 0,n=e.method??(o||r.length>0?"POST":"GET"),s=o||n==="GET"||n==="HEAD";return{method:n,url:Bm(t),params:s&&r.length>0?Mm(r):void 0,data:o?JSON.stringify(await km(e.input)):!s&&r.length>0?JSON.stringify(Fm(r)):void 0,headers:Object.fromEntries(e.header??[])}}function Ji(t){let e=Object.entries(t.headers).map(([r,o])=>`${r}: ${Array.isArray(o)?o.join(", "):o}`);return[`HTTP/1.1 ${t.status} ${t.statusText}`,...e,"",""].join(`
29
+ `)}function Vi(t,e){let r=t.data??"",o=String(t.headers["content-type"]??"").toLowerCase().includes("json");if(!e||!o||!r)return r;try{return JSON.stringify(JSON.parse(r),null,2)+`
30
+ `}catch{return r}}async function qi(t,e){let{apiKey:r}=U(_,["apiKey"],e),o=s=>s?.map(([i])=>i);vm("Options: %o",h({...e,field:o(e.field),rawField:o(e.rawField),header:o(e.header)}));let n=await jm(t,e);try{let s=await Fn(r,n);e.include&&process.stdout.write(Ji(s)),process.stdout.write(Vi(s,!!process.stdout.isTTY))}catch(s){if(!(0,Yi.isAxiosError)(s))throw s;let i=s.response;if(!i)throw new Error(`Could not reach the REST API at ${Wt()}: ${s.message}`);e.include&&process.stderr.write(Ji(i));let c=Vi(i,!!process.stderr.isTTY);throw c&&process.stderr.write(c.endsWith(`
31
31
  `)?c:`${c}
32
- `),new Error(`${n.method} ${n.url.split("?")[0]} failed: the REST API answered ${i.status} ${i.statusText}`)}}var Ji=["GET","POST","PUT","PATCH","DELETE","HEAD"];function io(t,e){let r=t.indexOf(e),o=r<0?"":t.slice(0,r).trim();if(!o)throw new Z.InvalidArgumentError(`Expected key${e}value.`);let n=t.slice(r+1);return[o,e===":"?n.trim():n]}function bm(t){if(t==="true")return!0;if(t==="false")return!1;if(t==="null")return null;if(/^-?\d+(\.\d+)?$/.test(t)){let e=Number(t);if(t.includes(".")?Number.isFinite(e):Number.isSafeInteger(e))return e}return t}var Nm=(t,e=[])=>{let[r,o]=io(t,"=");return[...e,[r,bm(o)]]},Lm=(t,e=[])=>[...e,io(t,"=")],vm=(t,e=[])=>[...e,io(t,":")],Vi=new Z.Option("-X, --method <method>","the HTTP method; GET by default, POST when --field, --raw-field or --input is given").argParser(t=>{let e=t.toUpperCase();if(!Ji.includes(e))throw new Z.InvalidArgumentError(`Use one of ${Ji.join(", ")}.`);return e}),Yi=new Z.Option("-f, --field <key=value>","a request parameter; repeat for more. Sent in the query string of a GET and in the JSON body otherwise. true, false, null and numbers are sent as JSON values; in a JSON body, key[]=value adds the value to an array").argParser(Nm),Wi=new Z.Option("-F, --raw-field <key=value>","like --field, but the value is always a string").argParser(Lm),qi=new Z.Option("--input <file>",'send the JSON in this file as the body, or the JSON from stdin with "-"; fields then go to the query string'),zi=new Z.Option("-H, --header <key:value>","an HTTP header to send; repeat for more").argParser(vm),Qi=new Z.Option("-i, --include","print the HTTP status line and the response headers before the body");async function Xi(t,e){await w(async r=>{bt(),await Hi(t,r)},e)}var yt=require("@commander-js/extra-typings");var ao="(required)",M=(t=ao)=>new yt.Option("-k, --key <record-key>",`the record key from the Currents dashboard ${t}`).env(_.recordKey.env),ct=(t=ao)=>new yt.Option("--api-key <api-key>",`an API key from the Currents dashboard ${t}`).env(_.apiKey.env),tt=()=>new yt.Option("-p, --project-id <id>",`the project ID from the Currents dashboard ${ao}`).env(_.projectId.env),Lt=t=>new yt.Option("--ci-build-id <id>",`the CI build ID the run was recorded with${t}`).env(_.ciBuildId.env),vt=t=>new yt.Option("-t, --tag <tag>",`${t}; comma-separated or repeated`).argParser(ye),b=()=>new yt.Option("--debug","print debug logs; keys are hidden in them").env(_.debug.env).default(!1);var je=require("@commander-js/extra-typings");var Zi=new je.Option("-o, --output <path>","write the JSON to this file instead of stdout").env(L(ge,"output")),ta=Lt("; cannot be combined with --branch or --tag. The environment variable is ignored when --branch or --tag is set"),ea=vt("find the last run with these tags"),ra=new je.Option("-b, --branch <branch>","find the last run of this git branch"),oa=new je.Option("--pw-last-run","print only the status and the failed tests of the run, in the format of Playwright's .last-run.json");var Ge="get",co="run",mo=t=>[{comment:"Get the data of the run recorded under a CI build ID",commands:[`${t} ${co} ${Ge} --api-key <api-key> --project-id <project-id> --ci-build-id <ci-build-id>`]},{comment:"Get the data of the last run of a branch with the tags tagA and tagB",commands:[`${t} ${co} ${Ge} --api-key <api-key> --project-id <project-id> --branch <branch> --tag tagA,tagB`]},{comment:'Save the failed tests of a run where Playwright reads them, for "playwright test --last-failed"',commands:[`${t} ${co} ${Ge} --api-key <api-key> --project-id <project-id> --ci-build-id <ci-build-id> --pw-last-run --output test-results/.last-run.json`]}],Bm=t=>[{comment:"Get a run, with the API key in CURRENTS_API_KEY",commands:[`${t} api /v1/runs/<run-id>`]},{comment:"List the failed runs of the main branch of a project",commands:[`${t} api /v1/projects/<project-id>/runs -X GET -f "branches[]=main" -f status=FAILED -f limit=20`]},{comment:"Cancel a run",commands:[`${t} api /v1/runs/<run-id>/cancel -X PUT`]},{comment:"Create a webhook from the JSON in webhook.json",commands:[`${t} api /v1/webhooks -X POST -F projectId=<project-id> --input webhook.json`]}],na=t=>new po.Command().name("api").summary("Make an authenticated request to the Currents REST API").description(`Make an authenticated request to the Currents REST API and print the response body. The path is a REST API route, such as /v1/runs/<run-id>; v1/runs/<run-id> and runs/<run-id> are the same route. A response that is not 2xx prints its body on stderr and exits with 1.
32
+ `),new Error(`${n.method} ${n.url.split("?")[0]} failed: the REST API answered ${i.status} ${i.statusText}`)}}var zi=["GET","POST","PUT","PATCH","DELETE","HEAD"];function po(t,e){let r=t.indexOf(e),o=r<0?"":t.slice(0,r).trim();if(!o)throw new Z.InvalidArgumentError(`Expected key${e}value.`);let n=t.slice(r+1);return[o,e===":"?n.trim():n]}function $m(t){if(t==="true")return!0;if(t==="false")return!1;if(t==="null")return null;if(/^-?\d+(\.\d+)?$/.test(t)){let e=Number(t);if(t.includes(".")?Number.isFinite(e):Number.isSafeInteger(e))return e}return t}var Gm=(t,e=[])=>{let[r,o]=po(t,"=");return[...e,[r,$m(o)]]},Km=(t,e=[])=>[...e,po(t,"=")],Hm=(t,e=[])=>[...e,po(t,":")],Qi=new Z.Option("-X, --method <method>","the HTTP method; GET by default, POST when --field, --raw-field or --input is given").argParser(t=>{let e=t.toUpperCase();if(!zi.includes(e))throw new Z.InvalidArgumentError(`Use one of ${zi.join(", ")}.`);return e}),Xi=new Z.Option("-f, --field <key=value>","a request parameter; repeat for more. Sent in the query string of a GET and in the JSON body otherwise. true, false, null and numbers are sent as JSON values; in a JSON body, key[]=value adds the value to an array").argParser(Gm),Zi=new Z.Option("-F, --raw-field <key=value>","like --field, but the value is always a string").argParser(Km),ta=new Z.Option("--input <file>",'send the JSON in this file as the body, or the JSON from stdin with "-"; fields then go to the query string'),ea=new Z.Option("-H, --header <key:value>","an HTTP header to send; repeat for more").argParser(Hm),ra=new Z.Option("-i, --include","print the HTTP status line and the response headers before the body");async function oa(t,e){await R(async r=>{Nt(),await qi(t,r)},e)}var Rt=require("@commander-js/extra-typings");var mo="(required)",M=(t=mo)=>new Rt.Option("-k, --key <record-key>",`the record key from the Currents dashboard ${t}`).env(_.recordKey.env),at=(t=mo)=>new Rt.Option("--api-key <api-key>",`an API key from the Currents dashboard ${t}`).env(_.apiKey.env),tt=()=>new Rt.Option("-p, --project-id <id>",`the project ID from the Currents dashboard ${mo}`).env(_.projectId.env),vt=t=>new Rt.Option("--ci-build-id <id>",`the CI build ID the run was recorded with${t}`).env(_.ciBuildId.env),Bt=t=>new Rt.Option("-t, --tag <tag>",`${t}; comma-separated or repeated`).argParser(we),b=()=>new Rt.Option("--debug","print debug logs; keys are hidden in them").env(_.debug.env).default(!1);var Ge=require("@commander-js/extra-typings");var na=new Ge.Option("-o, --output <path>","write the JSON to this file instead of stdout").env(L(Ee,"output")),sa=vt("; cannot be combined with --branch or --tag. The environment variable is ignored when --branch or --tag is set"),ia=Bt("find the last run with these tags"),aa=new Ge.Option("-b, --branch <branch>","find the last run of this git branch"),ca=new Ge.Option("--pw-last-run","print only the status and the failed tests of the run, in the format of Playwright's .last-run.json");var Ke="get",uo="run",fo=t=>[{comment:"Get the data of the run recorded under a CI build ID",commands:[`${t} ${uo} ${Ke} --api-key <api-key> --project-id <project-id> --ci-build-id <ci-build-id>`]},{comment:"Get the data of the last run of a branch with the tags tagA and tagB",commands:[`${t} ${uo} ${Ke} --api-key <api-key> --project-id <project-id> --branch <branch> --tag tagA,tagB`]},{comment:'Save the failed tests of a run where Playwright reads them, for "playwright test --last-failed"',commands:[`${t} ${uo} ${Ke} --api-key <api-key> --project-id <project-id> --ci-build-id <ci-build-id> --pw-last-run --output test-results/.last-run.json`]}],Jm=t=>[{comment:"Get a run, with the API key in CURRENTS_API_KEY",commands:[`${t} api /v1/runs/<run-id>`]},{comment:"List the failed runs of the main branch of a project",commands:[`${t} api /v1/projects/<project-id>/runs -X GET -f "branches[]=main" -f status=FAILED -f limit=20`]},{comment:"Cancel a run",commands:[`${t} api /v1/runs/<run-id>/cancel -X PUT`]},{comment:"Create a webhook from the JSON in webhook.json",commands:[`${t} api /v1/webhooks -X POST -F projectId=<project-id> --input webhook.json`]}],pa=t=>new lo.Command().name("api").summary("Make an authenticated request to the Currents REST API").description(`Make an authenticated request to the Currents REST API and print the response body. The path is a REST API route, such as /v1/runs/<run-id>; v1/runs/<run-id> and runs/<run-id> are the same route. A response that is not 2xx prints its body on stderr and exits with 1.
33
33
 
34
- The REST API routes: https://docs.currents.dev/resources/api/api-resources`).usage("<path> [options]").argument("<path>","the REST API route, such as /v1/runs/<run-id>").enablePositionalOptions().helpCommand(!1).addOption(ct()).addOption(Vi).addOption(Yi).addOption(Wi).addOption(qi).addOption(zi).addOption(Qi).addOption(b()).addHelpText("after",y(Bm(t))).showHelpAfterError("(add --help for additional information)").addCommand(uo(t).name("get-run"),{hidden:!0}).action((r,o,n)=>r==="help"?n.help():Xi(r,o)),uo=t=>new po.Command().name(Ge).summary("Get the data of a run from the Currents API").description("Get the data of a run from the Currents API and print it as JSON, or write it to --output. Find the run by --ci-build-id, or the last run by --branch, --tag or both").addHelpText("after",y(mo(t))).allowUnknownOption().addOption(ct()).addOption(b()).addOption(ta).addOption(tt()).addOption(ra).addOption(ea).addOption(Zi).addOption(oa).action(ki);var $e=require("@commander-js/extra-typings");var Fm=p.extend("cli");async function sa(t){await w(async e=>{Xn(Zn(e));let r=dt();Fm("Config: %o",h(r.values)),await Vr()},t)}var Mm=p.extend("cli");async function ia(t){await w(async e=>{Qn(ts(e));let r=dt();Mm("Config: %o",h(r.values)),await Yr()},t)}var Bt="cache",Ke=t=>[{comment:"Save files to the cache under an ID",commands:[`${t} ${Bt} set --key <record-key> --id <id> --path <path-1,path-2,...path-n>`]},{comment:"Save Playwright's .last-run.json to the cache",commands:[`${t} ${Bt} set --key <record-key> --preset last-run`]}],He=t=>[{comment:"Restore the files saved in the cache under an ID",commands:[`${t} ${Bt} get --key <record-key> --id <id>`]},{comment:"Restore Playwright's .last-run.json from the cache, to rerun only the failed tests",commands:[`${t} ${Bt} get --key <record-key> --preset last-run`]},{comment:"Restore Playwright's .last-run.json to another folder",commands:[`${t} ${Bt} get --key <record-key> --preset last-run --output-dir <output-dir>`]}],aa=t=>new $e.Command().command(Bt).summary("Save files to the Currents cache and restore them").description("Save files to the Currents cache and restore them, e.g. in another CI job").addHelpText("after",y([...Ke(t),...He(t)])).showHelpAfterError("(add --help for additional information)").allowUnknownOption().addCommand(km(t)).addCommand(jm(t)),km=t=>new $e.Command().name("set").description("Save files to the cache").addHelpText("after",y(Ke(t))).allowUnknownOption().addOption(M()).addOption(Mn).addOption(Gn).addOption(jn).addOption(b()).addOption(Hn).addOption(Lr).addOption(vr).addOption(Wn).action(ia),jm=t=>new $e.Command().name("get").description("Restore files from the cache").addHelpText("after",y(He(t))).allowUnknownOption().addOption(M()).addOption(kn).addOption($n).addOption(Kn).addOption(Jn).addOption(b()).addOption(Lr).addOption(vr).addOption(Yn).action(sa);var ua=require("@commander-js/extra-typings");var Gm=p.extend("cli");async function ca(t){await w(async({key:e,...r})=>{Ns({...r,recordKey:e});let o=Se();Gm("Config: %o",h(o??{})),await qr()},t)}var pa=require("@commander-js/extra-typings");var da=Lt(" (required unless --run-id is set)"),ma=new pa.Option("--run-id <id>","the ID of the run to cancel, as printed when the run was created; wins over --ci-build-id").env(L(X,"runId"));var Ft="cancel",Je="run",re=t=>[{comment:"Cancel the run recorded under a CI build ID",commands:[`${t} ${Je} ${Ft} --key <record-key> --project-id <id> --ci-build-id <build-id>`]},{comment:"Cancel a run by its ID, as printed when the run was created",commands:[`${t} ${Je} ${Ft} --key <record-key> --project-id <id> --run-id <run-id>`]},{comment:"Cancel the run when a GitHub Actions workflow is cancelled (workflow step). It reads CURRENTS_RECORD_KEY, CURRENTS_PROJECT_ID and CURRENTS_CI_BUILD_ID from the environment",commands:[`- if: \${{ cancelled() }}
35
- run: npx ${t} ${Je} ${Ft}`]}],Ve=(t,{deprecated:e=!1}={})=>{let r=new ua.Command().name(Ft).summary("Cancel a run in progress").description("Cancel a run in progress, e.g. when the CI job it belongs to is cancelled").addHelpText("after",y(re(t))).allowUnknownOption().addOption(M()).addOption(tt()).addOption(da).addOption(ma).addOption(b()).action(ca);return e&&r.hook("preAction",()=>{process.stderr.write(`'${t} ${Ft}' is deprecated and will be removed in a future version. Use '${t} ${Je} ${Ft}'.
36
- `)}),r};var La=require("@commander-js/extra-typings");var la={debug:_.debug,inputFormat:{name:"Input format",cli:"--input-format"},inputFiles:{name:"Input file",cli:"--input-file"},outputDir:{name:"Output folder",cli:"--output-dir"},framework:{name:"Framework",cli:"--framework"},frameworkVersion:{name:"Framework version",cli:"--framework-version"}};var $m=p.extend("config"),Km=["inputFormat","inputFiles","framework"],lo=null;function fa(t){lo=U(la,Km,t),$m("Resolved config: %o",lo)}function Ye(){return lo}function ga(t){return{inputFiles:t.inputFile,inputFormat:t.inputFormat,outputDir:t.outputDir,framework:t.framework,frameworkVersion:t.frameworkVersion,debug:t.debug}}var yo=l(require("fs-extra")),v=require("path");var Ta=require("lodash"),ya=l(require("crypto"));var H=require("path"),qe=async(t,e,r,o)=>{if(t)for(let n of t)try{let s=(0,H.resolve)(o,n.path),i=(0,H.relative)(o,s);if(i.startsWith("..")||(0,H.isAbsolute)(i)){p("Skipping artifact outside workspace: %s (resolved: %s)",n.path,s);continue}let c=`${rt(e+n.path)}.${(0,H.extname)(n.path).slice(1)||"bin"}`;await me(s,(0,H.join)(r,c)),n.path=(0,H.join)("artifacts",c)}catch(s){p("Failed to copy artifact %s: %o",n.path,s)}};function Ea(t){let e=Ca(t.properties?.property??t.property);return We(e,"currents.artifact.instance.","spec")}function Ia(t){let e=Ca(t.properties?.property),r=We(e,"currents.artifact.test.","test"),o=new Map;Hm(e).forEach((i,c)=>{o.has(c)||o.set(c,[]),o.get(c).push(...i)});let s=We(e,"currents.artifact.attempt.","attempt");return s.length>0&&(o.has(0)||o.set(0,[]),o.get(0).push(...s)),{testArtifacts:r,attemptArtifacts:o}}function Hm(t){let e=new Map,r=/^currents\.artifact\.attempt\.(\d+)\.(.+)$/,o=new Map;for(let n of t){let s=n.value??n._;if(!n.name||!s)continue;let i=n.name.match(r);if(!i)continue;let[,c,m]=i,d=parseInt(c,10);o.has(d)||o.set(d,[]),o.get(d).push({name:`currents.artifact.attempt.${m}`,value:s})}for(let[n,s]of o.entries()){let i=We(s,"currents.artifact.attempt.","attempt");i.length>0&&e.set(n,i)}return e}function We(t,e,r){let o=[],n={};for(let s of t){let i=s.value??s._;if(!s.name||!i||!s.name.startsWith(e))continue;let c=s.name.slice(e.length);/^\d+\./.test(c)||["path","type","contentType","name"].includes(c)&&(n[c]&&(ha(n)&&o.push({...n,level:r}),n={}),n[c]=i)}return ha(n)&&o.push({...n,level:r}),o}function ha(t){return!!(t.path&&t.type&&t.contentType)}function Ca(t){return t?Array.isArray(t)?t:[t]:[]}function Ra(t,e,r,o){let n=Rt(t.failure),s=n.length>0,i=e?.timestamp??"",c="skipped"in t,m=c?"pending":s?"failed":"passed",{testArtifacts:d,attemptArtifacts:f}=Ia(t);return{_t:ze(i),testId:Eo(oe(t.name,o).join(", "),o),title:oe(t.name,o),state:m,isFlaky:Jm(),expectedStatus:"passed",timeout:Vm(),location:Ym(e?.file??""),retries:Wm(n),artifacts:d,attempts:qm(t,n,Io(i),r,f,c)}}function Eo(t,e){let r=`${t}${e}`;return ya.default.createHash("sha256").update(r).digest("hex").substring(0,16)}function ze(t){return _a(t)?new Date(t).getTime():new Date().getTime()}function Io(t){return _a(t)?new Date(t).toISOString():new Date().toISOString()}function _a(t){let e=new Date(t);return!isNaN(e.getTime())}function oe(t,e){return[e,t].filter(Boolean)}function Jm(){return!1}function Vm(){return 0}function Ym(t){return{column:1,file:t,line:1}}function Wm(t){let e=0;return t.forEach(r=>{typeof r!="string"&&e++}),e}function qm(t,e,r,o,n,s){let i=t.time?Qe(t.time):0;if(s)return[{_s:"pending",attempt:0,startTime:r,steps:[],duration:i,status:"skipped",stdout:fo(t?.["system-out"]),stderr:go(t?.["system-err"]),artifacts:n.get(0),errors:[],error:void 0}];if(e.length===0){let c=[];return n.forEach(m=>{c.push(...m)}),[{_s:"passed",attempt:0,startTime:r,steps:[],duration:i,status:"passed",stdout:fo(t?.["system-out"]),stderr:go(t?.["system-err"]),artifacts:c,errors:[],error:void 0}]}return e.reduce((c,m,d)=>{if(m!=="true"&&m!=="false"){let f=zm(m);c.push({_s:"failed",attempt:d,startTime:Qm(o,r),steps:[],duration:i,status:"failed",stdout:fo(t?.["system-out"]),stderr:go(t?.["system-err"]),artifacts:n.get(d),errors:f,error:f[0]})}return c},[])}function fo(t){return t?[t]:[]}function go(t){return t?[t]:[]}function zm(t){return t==="true"||t==="false"?[]:[typeof t=="string"?{message:t}:{message:t.message,stack:t._,value:t.type}]}function Qm(t,e){let r=ze(e)+t;return new Date(r).toISOString()}function Rt(t){return t?Array.isArray(t)?t:[t]:[]}function Xm(t){return Math.round(t*1e3)}function Qe(t){let e=parseFloat(t);return isNaN(e)?0:Xm(e)}function Xe(t,e,r){let o=(0,Ta.isNumber)(r)&&r>0,n=!!t.id&&ho(e,"id",t.id);if(t.file){let s=ho(e,"file",t.file);return s&&!n?`${t.file} - ${t.id}`:s&&o?`${t.file} - ${r}`:t.file}if(t.name){let s=ho(e,"name",t.name);return s&&!n?`${t.name} - ${t.id}`:s&&o?`${t.name} - ${r}`:t.name}return t.id?n&&o?`${t.id} - ${r}`:t.id:o?`unknown - ${r}`:"unknown"}function ho(t,e,r){return t.filter(n=>n[e]===r).length>1}function wa(t){let e=[];return t.forEach(r=>{let o=Rt(r.testsuites?.testsuite),n={name:r.testsuites?.name??"No name",tags:[],tests:[]};o?.forEach(s=>{let i=Xe(s,o);Rt(s?.testcase)?.forEach(m=>{let d={title:oe(m.name,i),spec:i,tags:[],testId:Eo(oe(m.name,i).join(", "),i)};n.tests.push(d)})}),e.push(n)}),e}var lt=require("@commander-js/extra-typings"),Oa=l(require("globby")),Co=(e=>(e.junit="junit",e))(Co||{}),Ze=t=>new lt.Option("--input-format <format>",["the format of the reports to convert",t].filter(Boolean).join(" ")).choices(Object.values(Co)),tr=t=>new lt.Option("--input-file <patterns>",`comma-separated glob patterns of the report files, e.g. "reports/*.xml,other.xml"; quote them so that the shell does not expand them ${t}`).argParser(Zm),er=new lt.Option("-o, --output-dir <folder>","the folder to save the converted reports to; it must be empty, not exist, or hold only the reports being converted"),To=(n=>(n.postman="postman",n.node="node",n.vitest="vitest",n.wdio="wdio",n))(To||{}),rr=t=>new lt.Option("--framework <framework>",`the test framework that wrote the reports ${t}`).choices(Object.values(To)),or=new lt.Option("--framework-version <version>","the version of the test framework that wrote the reports");function Zm(t){let e=t.split(",").map(o=>o.trim()),r=Oa.sync(e);if(r.length===0)throw new lt.InvalidArgumentError("No files found with the provided patterns");return r}async function J(t){let e=new Map;return t.forEach(r=>{let o=Rt(r.testsuites?.testsuite),n=r.testsuites?.name??"No name";o.forEach((s,i)=>{let c=Xe(s,o,i),m=tu(s,n,c),d=rt(n+c);m.results.tests.length!==0&&e.set(d,m)})}),e}function tu(t,e,r){let o=Io(t.timestamp??""),n=t.time?Qe(t.time):0,s=new Date(ze(t.timestamp??"")+n),i=Rt(t.testcase),c=[t["system-out"],t["system-err"],...i.flatMap(g=>[g["system-out"],g["system-err"]])].filter(g=>g).join(`
37
- `),m=0,d=i.filter(g=>"failure"in g).length,f=i.filter(g=>"skipped"in g).length,u=i.length-d-f;return{groupId:e,spec:r,startTime:o,artifacts:Ea(t),_stdout:c,results:{stats:{suites:1,tests:i.length,passes:u,pending:f,skipped:0,failures:d,flaky:0,wallClockStartedAt:o,wallClockEndedAt:s.toISOString(),wallClockDuration:n},tests:i?.map(g=>(i[0]?.time&&(m+=Qe(i[0].time)),Ra(g,t,m,r)))}}}async function xa({inputFormat:t,framework:e,parsedXMLArray:r}){return t==="junit"?eu(e,r):new Map}async function eu(t,e){switch(t){case"node":return J(e);case"postman":return J(e);case"vitest":return J(e);case"wdio":return J(e);default:return I("Unsupported framework: %s",t),new Map}}var Sa=require("fs-extra"),Aa=require("xml2js");async function Da(t){let e=await Promise.all(t.map(o=>(0,Sa.readFile)(o,"utf-8"))),r=(await Promise.all(e.map(ru))).filter(Boolean);return e.length!==r.length&&I("Some files could not be parsed. Enable debug logging for more details"),r}async function ru(t){let e=t.trim();if(!e)return null;try{return await(0,Aa.parseStringPromise)(e,{explicitArray:!1,mergeAttrs:!0})||null}catch(r){return p("Error parsing XML input",r),null}}function Ua(t){return{framework:t.inputFormat,frameworkVersion:t.frameworkVersion??null,frameworkConfig:{originFramework:t.framework,originFrameworkVersion:t.frameworkVersion}}}async function Pa(){try{let t=Ye();if(!t)throw new Error("Config is missing!");t.outputDir&&await ou(t.outputDir,t.inputFiles);let e=t.outputDir?await It(t.outputDir):await Wo(process.cwd(),".currents"),r=await It((0,v.join)(e,"instances")),o=Ua(t);p("Report config:",o),T("[currents] Convertion files: %s",t.inputFiles.join(", ")),await Yt((0,v.join)(e,"config.json"),JSON.stringify(o));let n=await Da(t.inputFiles);if(n.length===0)throw new Error("No valid XML JUnit report was found.");let s=wa(n);await Yt(Tt(e),JSON.stringify(s));let i=await xa({inputFormat:t.inputFormat,framework:t.framework,parsedXMLArray:n}),c=await It((0,v.join)(e,"artifacts")),m=process.cwd();return await Promise.all(Array.from(i.values()).map(async d=>{if(await qe(d.artifacts,d.spec,c,m),d._stdout){let f=`${rt(d.spec)}.stdout.txt`;await Yt((0,v.join)(c,f),d._stdout),d.artifacts||(d.artifacts=[]),d.artifacts.push({path:(0,v.join)("artifacts",f),type:"stdout",contentType:"text/plain",level:"spec"}),delete d._stdout}for(let f of d.results.tests){await qe(f.artifacts,f.testId,c,m);for(let u of f.attempts)await qe(u.artifacts,f.testId+u.attempt,c,m)}})),await Promise.all(Array.from(i.entries()).map(([d,f])=>Yt((0,v.join)(r,`${rt(d)}.json`),JSON.stringify(f)))),T("[currents] Conversion completed, report saved to: %s",e),e}catch(t){throw p("Failed to convert: %o",t),t}}async function ou(t,e){let r=(0,v.resolve)(t),o=new Set(e.map(c=>(0,v.resolve)(c))),n=[(0,v.join)(r,"config.json"),Tt(r),(0,v.join)(r,"instances"),(0,v.join)(r,"artifacts")],s=[...o].find(c=>n.some(m=>c===m||c.startsWith(m+v.sep)));if(s)throw new Error(`The report "${s}" is where the conversion writes its own files. Move the reports out of "${t}", or leave out --output-dir to convert into a new folder in .currents.`);if(await yo.default.pathExists(r)?await ba(r,o):void 0)throw new Error(`The folder "${t}" is not empty. Reports already in it would be uploaded with the converted ones. Remove the folder, or leave out --output-dir to convert into a new folder in .currents.`)}async function ba(t,e){for(let r of await yo.default.readdir(t,{withFileTypes:!0})){let o=(0,v.join)(t,r.name),n=r.isDirectory()?await ba(o,e):e.has(o)?void 0:o;if(n)return n}}var nu=p.extend("cli");async function Ro(t){return fa(ga(t)),nu("Config: %o",Ye()),Pa()}async function Na(t){await w(async e=>{await Ro(e)},t)}var _o="convert",su=t=>[{comment:"Convert JUnit test reports to the Currents format, to check the result before an upload",commands:[`${t} ${_o} --input-format junit --input-file "./*.xml" --framework postman`]}],va=t=>new La.Command().name(_o).command(_o).showHelpAfterError("(add --help for additional information)").allowUnknownOption().summary("Convert JUnit XML reports to the Currents format").description("Convert JUnit XML reports to the Currents format, without uploading them. The converted reports are saved to --output-dir or a new folder in .currents").addHelpText("after",y(su(t))).addOption(b()).addOption(Ze("(required)")).addOption(tr("(required)")).addOption(er).addOption(rr("(required)")).addOption(or).action(r=>Na(r));var vo=require("@commander-js/extra-typings");var{apiKey:iu,recordKey:au,projectId:cu,ciBuildId:pu,machineId:du,debug:mu}=_,k={apiKey:iu,recordKey:au,projectId:cu,ciBuildId:pu,machineId:du,sessionId:{name:"Session ID",env:"CURRENTS_SESSION_ID",cli:"--session-id"},title:{name:"Title",cli:"--title"},debug:mu};var nr=p.extend("config");function Ba(t){let e=U(k,["projectId","title"],t,sr);return nr("Resolved config: %o",h(e)),e}function Fa(t){let e=U(k,[],t,sr);return nr("Resolved config: %o",h(e)),e}function Ma(t){let e=U(k,[],t,sr);return nr("Resolved config: %o",h(e)),e}function ka(t){let e=U(k,["projectId"],t,sr);return nr("Resolved config: %o",h(e)),e}function sr(t){if(!(t.recordKey||t.apiKey))throw new q(`${k.recordKey.name} or ${k.apiKey.name} is required. Set ${k.recordKey.env} or ${k.apiKey.env}, or pass ${k.recordKey.cli} or ${k.apiKey.cli}`)}var ne=l(require("fs-extra")),wt=l(require("path"));var Ga=l(require("path"));var ja=["trace","screenshot","video","attachment"];var uu=["image/png","image/jpeg","image/webp","image/gif"],$a=t=>Ga.default.extname(t).toLowerCase()===".zip";function Ka(t){return ja.includes(t)}function wo(t){return $a(t)?"application/zip":Xr(t)?.contentType??"application/octet-stream"}function lu(t){return $a(t)?"trace":Xr(t)?.type??"attachment"}function Oo(t,e){let r=lu(t);return e.includes(r)?r:"attachment"}function Ha(t,e,r){if(!r.includes(e))throw new Error(`Cannot attach "${t}" as type "${e}" here. The target takes: ${r.join(", ")}`)}function Ja(t,e){let r=wo(t);if(!(e==="attachment"||e==="trace"&&r==="application/zip"||e==="screenshot"&&uu.includes(r)||e==="video"&&r.startsWith("video/")))throw new Error(`Cannot attach "${t}" as type "${e}": its content type is ${r}`)}var Va=l(require("archiver")),_t=l(require("fs-extra")),ir=l(require("path")),Ya=l(require("unzipper")),Wa=require("tmp-promise");async function qa(t){try{return(await Ya.default.Open.file(t)).files.some(r=>/^(trace|test|\d+-trace)\.trace$/.test(r.path))}catch{return!1}}var za=/^trace-.*\.trace$/,fu=/^trace-.*\.network$/;async function xo(t){return(await _t.default.readdir(t)).some(r=>za.test(r))}function gu(t){if(!t)return!1;try{let e=JSON.parse(t),r=e.snapshot?.response;if(e.type!=="resource-snapshot"||!r)return!0;let o=r.status>=200&&r.status<400,n=/javascript|ecmascript/i.test(r.content?.mimeType??"");return!(o&&n)}catch{return!0}}async function Qa(t,e){return(await _t.default.readdir(t)).filter(o=>e.test(o)).sort().map(o=>ir.default.join(t,o))}async function hu(t){return(await Promise.all((await Qa(t,za)).map(r=>_t.default.readFile(r,"utf8")))).map(r=>r.endsWith(`
34
+ The REST API routes: https://docs.currents.dev/resources/api/api-resources`).usage("<path> [options]").argument("<path>","the REST API route, such as /v1/runs/<run-id>").enablePositionalOptions().helpCommand(!1).addOption(at()).addOption(Qi).addOption(Xi).addOption(Zi).addOption(ta).addOption(ea).addOption(ra).addOption(b()).addHelpText("after",y(Jm(t))).showHelpAfterError("(add --help for additional information)").addCommand(go(t).name("get-run"),{hidden:!0}).action((r,o,n)=>r==="help"?n.help():oa(r,o)),go=t=>new lo.Command().name(Ke).summary("Get the data of a run from the Currents API").description("Get the data of a run from the Currents API and print it as JSON, or write it to --output. Find the run by --ci-build-id, or the last run by --branch, --tag or both").addHelpText("after",y(fo(t))).allowUnknownOption().addOption(at()).addOption(b()).addOption(sa).addOption(tt()).addOption(aa).addOption(ia).addOption(na).addOption(ca).action(Hi);var He=require("@commander-js/extra-typings");var Vm=p.extend("cli");async function da(t){await R(async e=>{os(ns(e));let r=dt();Vm("Config: %o",h(r.values)),await qr()},t)}var Ym=p.extend("cli");async function ma(t){await R(async e=>{rs(ss(e));let r=dt();Ym("Config: %o",h(r.values)),await zr()},t)}var Ft="cache",Je=t=>[{comment:"Save files to the cache under an ID",commands:[`${t} ${Ft} set --key <record-key> --id <id> --path <path-1,path-2,...path-n>`]},{comment:"Save Playwright's .last-run.json to the cache",commands:[`${t} ${Ft} set --key <record-key> --preset last-run`]}],Ve=t=>[{comment:"Restore the files saved in the cache under an ID",commands:[`${t} ${Ft} get --key <record-key> --id <id>`]},{comment:"Restore Playwright's .last-run.json from the cache, to rerun only the failed tests",commands:[`${t} ${Ft} get --key <record-key> --preset last-run`]},{comment:"Restore Playwright's .last-run.json to another folder",commands:[`${t} ${Ft} get --key <record-key> --preset last-run --output-dir <output-dir>`]}],ua=t=>new He.Command().command(Ft).summary("Save files to the Currents cache and restore them").description("Save files to the Currents cache and restore them, e.g. in another CI job").addHelpText("after",y([...Je(t),...Ve(t)])).showHelpAfterError("(add --help for additional information)").allowUnknownOption().addCommand(Wm(t)).addCommand(qm(t)),Wm=t=>new He.Command().name("set").description("Save files to the cache").addHelpText("after",y(Je(t))).allowUnknownOption().addOption(M()).addOption(Kn).addOption(Vn).addOption(Jn).addOption(b()).addOption(qn).addOption(Fr).addOption(Mr).addOption(Zn).action(ma),qm=t=>new He.Command().name("get").description("Restore files from the cache").addHelpText("after",y(Ve(t))).allowUnknownOption().addOption(M()).addOption(Hn).addOption(Yn).addOption(Wn).addOption(zn).addOption(b()).addOption(Fr).addOption(Mr).addOption(Xn).action(da);var Ea=require("@commander-js/extra-typings");var zm=p.extend("cli");async function la(t){await R(async({key:e,...r})=>{Ms({...r,recordKey:e});let o=De();zm("Config: %o",h(o??{})),await Xr()},t)}var fa=require("@commander-js/extra-typings");var ga=vt(" (required unless --run-id is set)"),ha=new fa.Option("--run-id <id>","the ID of the run to cancel, as printed when the run was created; wins over --ci-build-id").env(L(X,"runId"));var Mt="cancel",Ye="run",oe=t=>[{comment:"Cancel the run recorded under a CI build ID",commands:[`${t} ${Ye} ${Mt} --key <record-key> --project-id <id> --ci-build-id <build-id>`]},{comment:"Cancel a run by its ID, as printed when the run was created",commands:[`${t} ${Ye} ${Mt} --key <record-key> --project-id <id> --run-id <run-id>`]},{comment:"Cancel the run when a GitHub Actions workflow is cancelled (workflow step). It reads CURRENTS_RECORD_KEY, CURRENTS_PROJECT_ID and CURRENTS_CI_BUILD_ID from the environment",commands:[`- if: \${{ cancelled() }}
35
+ run: npx ${t} ${Ye} ${Mt}`]}],We=(t,{deprecated:e=!1}={})=>{let r=new Ea.Command().name(Mt).summary("Cancel a run in progress").description("Cancel a run in progress, e.g. when the CI job it belongs to is cancelled").addHelpText("after",y(oe(t))).allowUnknownOption().addOption(M()).addOption(tt()).addOption(ga).addOption(ha).addOption(b()).action(la);return e&&r.hook("preAction",()=>{process.stderr.write(`'${t} ${Mt}' is deprecated and will be removed in a future version. Use '${t} ${Ye} ${Mt}'.
36
+ `)}),r};var ka=require("@commander-js/extra-typings");var Ia={debug:_.debug,inputFormat:{name:"Input format",cli:"--input-format"},inputFiles:{name:"Input file",cli:"--input-file"},outputDir:{name:"Output folder",cli:"--output-dir"},framework:{name:"Framework",cli:"--framework"},frameworkVersion:{name:"Framework version",cli:"--framework-version"}};var Qm=p.extend("config"),Xm=["inputFormat","inputFiles","framework"],ho=null;function Ca(t){ho=U(Ia,Xm,t),Qm("Resolved config: %o",ho)}function qe(){return ho}function Ta(t){return{inputFiles:t.inputFile,inputFormat:t.inputFormat,outputDir:t.outputDir,framework:t.framework,frameworkVersion:t.frameworkVersion,debug:t.debug}}var _o=l(require("fs-extra")),v=require("path");var Oa=require("lodash"),xa=l(require("crypto"));var J=require("path"),Qe=async(t,e,r,o)=>{if(t)for(let n of t)try{let s=(0,J.resolve)(o,n.path),i=(0,J.relative)(o,s);if(i.startsWith("..")||(0,J.isAbsolute)(i)){p("Skipping artifact outside workspace: %s (resolved: %s)",n.path,s);continue}let c=`${et(e+n.path)}.${(0,J.extname)(n.path).slice(1)||"bin"}`;await ue(s,(0,J.join)(r,c)),n.path=(0,J.join)("artifacts",c)}catch(s){p("Failed to copy artifact %s: %o",n.path,s)}};function Ra(t){let e=_a(t.properties?.property??t.property);return ze(e,"currents.artifact.instance.","spec")}function wa(t){let e=_a(t.properties?.property),r=ze(e,"currents.artifact.test.","test"),o=new Map;Zm(e).forEach((i,c)=>{o.has(c)||o.set(c,[]),o.get(c).push(...i)});let s=ze(e,"currents.artifact.attempt.","attempt");return s.length>0&&(o.has(0)||o.set(0,[]),o.get(0).push(...s)),{testArtifacts:r,attemptArtifacts:o}}function Zm(t){let e=new Map,r=/^currents\.artifact\.attempt\.(\d+)\.(.+)$/,o=new Map;for(let n of t){let s=n.value??n._;if(!n.name||!s)continue;let i=n.name.match(r);if(!i)continue;let[,c,m]=i,d=parseInt(c,10);o.has(d)||o.set(d,[]),o.get(d).push({name:`currents.artifact.attempt.${m}`,value:s})}for(let[n,s]of o.entries()){let i=ze(s,"currents.artifact.attempt.","attempt");i.length>0&&e.set(n,i)}return e}function ze(t,e,r){let o=[],n={};for(let s of t){let i=s.value??s._;if(!s.name||!i||!s.name.startsWith(e))continue;let c=s.name.slice(e.length);/^\d+\./.test(c)||["path","type","contentType","name"].includes(c)&&(n[c]&&(ya(n)&&o.push({...n,level:r}),n={}),n[c]=i)}return ya(n)&&o.push({...n,level:r}),o}function ya(t){return!!(t.path&&t.type&&t.contentType)}function _a(t){return t?Array.isArray(t)?t:[t]:[]}function Sa(t,e,r,o){let n=wt(t.failure),s=n.length>0,i=e?.timestamp??"",c="skipped"in t,m=c?"pending":s?"failed":"passed",{testArtifacts:d,attemptArtifacts:f}=wa(t);return{_t:Xe(i),testId:To(ne(t.name,o).join(", "),o),title:ne(t.name,o),state:m,isFlaky:tu(),expectedStatus:"passed",timeout:eu(),location:ru(e?.file??""),retries:ou(n),artifacts:d,attempts:nu(t,n,yo(i),r,f,c)}}function To(t,e){let r=`${t}${e}`;return xa.default.createHash("sha256").update(r).digest("hex").substring(0,16)}function Xe(t){return Aa(t)?new Date(t).getTime():new Date().getTime()}function yo(t){return Aa(t)?new Date(t).toISOString():new Date().toISOString()}function Aa(t){let e=new Date(t);return!isNaN(e.getTime())}function ne(t,e){return[e,t].filter(Boolean)}function tu(){return!1}function eu(){return 0}function ru(t){return{column:1,file:t,line:1}}function ou(t){let e=0;return t.forEach(r=>{typeof r!="string"&&e++}),e}function nu(t,e,r,o,n,s){let i=t.time?Ze(t.time):0;if(s)return[{_s:"pending",attempt:0,startTime:r,steps:[],duration:i,status:"skipped",stdout:Eo(t?.["system-out"]),stderr:Io(t?.["system-err"]),artifacts:n.get(0),errors:[],error:void 0}];if(e.length===0){let c=[];return n.forEach(m=>{c.push(...m)}),[{_s:"passed",attempt:0,startTime:r,steps:[],duration:i,status:"passed",stdout:Eo(t?.["system-out"]),stderr:Io(t?.["system-err"]),artifacts:c,errors:[],error:void 0}]}return e.reduce((c,m,d)=>{if(m!=="true"&&m!=="false"){let f=su(m);c.push({_s:"failed",attempt:d,startTime:iu(o,r),steps:[],duration:i,status:"failed",stdout:Eo(t?.["system-out"]),stderr:Io(t?.["system-err"]),artifacts:n.get(d),errors:f,error:f[0]})}return c},[])}function Eo(t){return t?[t]:[]}function Io(t){return t?[t]:[]}function su(t){return t==="true"||t==="false"?[]:[typeof t=="string"?{message:t}:{message:t.message,stack:t._,value:t.type}]}function iu(t,e){let r=Xe(e)+t;return new Date(r).toISOString()}function wt(t){return t?Array.isArray(t)?t:[t]:[]}function au(t){return Math.round(t*1e3)}function Ze(t){let e=parseFloat(t);return isNaN(e)?0:au(e)}function tr(t,e,r){let o=(0,Oa.isNumber)(r)&&r>0,n=!!t.id&&Co(e,"id",t.id);if(t.file){let s=Co(e,"file",t.file);return s&&!n?`${t.file} - ${t.id}`:s&&o?`${t.file} - ${r}`:t.file}if(t.name){let s=Co(e,"name",t.name);return s&&!n?`${t.name} - ${t.id}`:s&&o?`${t.name} - ${r}`:t.name}return t.id?n&&o?`${t.id} - ${r}`:t.id:o?`unknown - ${r}`:"unknown"}function Co(t,e,r){return t.filter(n=>n[e]===r).length>1}function Da(t){let e=[];return t.forEach(r=>{let o=wt(r.testsuites?.testsuite),n={name:r.testsuites?.name??"No name",tags:[],tests:[]};o?.forEach(s=>{let i=tr(s,o);wt(s?.testcase)?.forEach(m=>{let d={title:ne(m.name,i),spec:i,tags:[],testId:To(ne(m.name,i).join(", "),i)};n.tests.push(d)})}),e.push(n)}),e}var lt=require("@commander-js/extra-typings"),Ua=l(require("globby")),Ro=(e=>(e.junit="junit",e))(Ro||{}),er=t=>new lt.Option("--input-format <format>",["the format of the reports to convert",t].filter(Boolean).join(" ")).choices(Object.values(Ro)),rr=t=>new lt.Option("--input-file <patterns>",`comma-separated glob patterns of the report files, e.g. "reports/*.xml,other.xml"; quote them so that the shell does not expand them ${t}`).argParser(cu),or=new lt.Option("-o, --output-dir <folder>","the folder to save the converted reports to; it must be empty, not exist, or hold only the reports being converted"),wo=(n=>(n.postman="postman",n.node="node",n.vitest="vitest",n.wdio="wdio",n))(wo||{}),nr=t=>new lt.Option("--framework <framework>",`the test framework that wrote the reports ${t}`).choices(Object.values(wo)),sr=new lt.Option("--framework-version <version>","the version of the test framework that wrote the reports");function cu(t){let e=t.split(",").map(o=>o.trim()),r=Ua.sync(e);if(r.length===0)throw new lt.InvalidArgumentError("No files found with the provided patterns");return r}async function V(t){let e=new Map;return t.forEach(r=>{let o=wt(r.testsuites?.testsuite),n=r.testsuites?.name??"No name";o.forEach((s,i)=>{let c=tr(s,o,i),m=pu(s,n,c),d=et(n+c);m.results.tests.length!==0&&e.set(d,m)})}),e}function pu(t,e,r){let o=yo(t.timestamp??""),n=t.time?Ze(t.time):0,s=new Date(Xe(t.timestamp??"")+n),i=wt(t.testcase),c=[t["system-out"],t["system-err"],...i.flatMap(g=>[g["system-out"],g["system-err"]])].filter(g=>g).join(`
37
+ `),m=0,d=i.filter(g=>"failure"in g).length,f=i.filter(g=>"skipped"in g).length,u=i.length-d-f;return{groupId:e,spec:r,startTime:o,artifacts:Ra(t),_stdout:c,results:{stats:{suites:1,tests:i.length,passes:u,pending:f,skipped:0,failures:d,flaky:0,wallClockStartedAt:o,wallClockEndedAt:s.toISOString(),wallClockDuration:n},tests:i?.map(g=>(i[0]?.time&&(m+=Ze(i[0].time)),Sa(g,t,m,r)))}}}async function Pa({inputFormat:t,framework:e,parsedXMLArray:r}){return t==="junit"?du(e,r):new Map}async function du(t,e){switch(t){case"node":return V(e);case"postman":return V(e);case"vitest":return V(e);case"wdio":return V(e);default:return I("Unsupported framework: %s",t),new Map}}var ba=require("fs-extra"),Na=require("xml2js");async function La(t){let e=await Promise.all(t.map(o=>(0,ba.readFile)(o,"utf-8"))),r=(await Promise.all(e.map(mu))).filter(Boolean);return e.length!==r.length&&I("Some files could not be parsed. Enable debug logging for more details"),r}async function mu(t){let e=t.trim();if(!e)return null;try{return await(0,Na.parseStringPromise)(e,{explicitArray:!1,mergeAttrs:!0})||null}catch(r){return p("Error parsing XML input",r),null}}function va(t){return{framework:t.inputFormat,frameworkVersion:t.frameworkVersion??null,frameworkConfig:{originFramework:t.framework,originFrameworkVersion:t.frameworkVersion}}}async function Ba(){try{let t=qe();if(!t)throw new Error("Config is missing!");t.outputDir&&await uu(t.outputDir,t.inputFiles);let e=t.outputDir?await Ct(t.outputDir):await Zo(process.cwd(),".currents"),r=await Ct((0,v.join)(e,"instances")),o=va(t);p("Report config:",o),T("[currents] Convertion files: %s",t.inputFiles.join(", ")),await Yt((0,v.join)(e,"config.json"),JSON.stringify(o));let n=await La(t.inputFiles);if(n.length===0)throw new Error("No valid XML JUnit report was found.");let s=Da(n);await Yt(yt(e),JSON.stringify(s));let i=await Pa({inputFormat:t.inputFormat,framework:t.framework,parsedXMLArray:n}),c=await Ct((0,v.join)(e,"artifacts")),m=process.cwd();return await Promise.all(Array.from(i.values()).map(async d=>{if(await Qe(d.artifacts,d.spec,c,m),d._stdout){let f=`${et(d.spec)}.stdout.txt`;await Yt((0,v.join)(c,f),d._stdout),d.artifacts||(d.artifacts=[]),d.artifacts.push({path:(0,v.join)("artifacts",f),type:"stdout",contentType:"text/plain",level:"spec"}),delete d._stdout}for(let f of d.results.tests){await Qe(f.artifacts,f.testId,c,m);for(let u of f.attempts)await Qe(u.artifacts,f.testId+u.attempt,c,m)}})),await Promise.all(Array.from(i.entries()).map(([d,f])=>Yt((0,v.join)(r,`${et(d)}.json`),JSON.stringify(f)))),T("[currents] Conversion completed, report saved to: %s",e),e}catch(t){throw p("Failed to convert: %o",t),t}}async function uu(t,e){let r=(0,v.resolve)(t),o=new Set(e.map(c=>(0,v.resolve)(c))),n=[(0,v.join)(r,"config.json"),yt(r),(0,v.join)(r,"instances"),(0,v.join)(r,"artifacts")],s=[...o].find(c=>n.some(m=>c===m||c.startsWith(m+v.sep)));if(s)throw new Error(`The report "${s}" is where the conversion writes its own files. Move the reports out of "${t}", or leave out --output-dir to convert into a new folder in .currents.`);if(await _o.default.pathExists(r)?await Fa(r,o):void 0)throw new Error(`The folder "${t}" is not empty. Reports already in it would be uploaded with the converted ones. Remove the folder, or leave out --output-dir to convert into a new folder in .currents.`)}async function Fa(t,e){for(let r of await _o.default.readdir(t,{withFileTypes:!0})){let o=(0,v.join)(t,r.name),n=r.isDirectory()?await Fa(o,e):e.has(o)?void 0:o;if(n)return n}}var lu=p.extend("cli");async function Oo(t){return Ca(Ta(t)),lu("Config: %o",qe()),Ba()}async function Ma(t){await R(async e=>{await Oo(e)},t)}var xo="convert",fu=t=>[{comment:"Convert JUnit test reports to the Currents format, to check the result before an upload",commands:[`${t} ${xo} --input-format junit --input-file "./*.xml" --framework postman`]}],ja=t=>new ka.Command().name(xo).command(xo).showHelpAfterError("(add --help for additional information)").allowUnknownOption().summary("Convert JUnit XML reports to the Currents format").description("Convert JUnit XML reports to the Currents format, without uploading them. The converted reports are saved to --output-dir or a new folder in .currents").addHelpText("after",y(fu(t))).addOption(b()).addOption(er("(required)")).addOption(rr("(required)")).addOption(or).addOption(nr("(required)")).addOption(sr).action(r=>Ma(r));var Ka=require("@commander-js/extra-typings");var So=l(require("fs-extra")),ir=l(require("path"));function gu(t=__dirname){let e=le("package.json",t);if(!e)throw new Error("The docs folder is missing from this package");return ir.default.join(e,"docs")}function hu(t,e){let r=e.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n)+/),o=r?.[1].match(/^description:[ \t]*(.+?)\r?$/m)?.[1];if(!r||!o)throw new Error(`docs/${t}.md has no description in its front matter`);return{name:t,description:o,body:e.slice(r[0].length)}}async function Eu(t=gu()){let e=(await So.default.readdir(t)).filter(r=>r.endsWith(".md")).sort();return Promise.all(e.map(async r=>hu(ir.default.basename(r,".md"),await So.default.readFile(ir.default.join(t,r),"utf8"))))}function $a(t){let e=Math.max(...t.map(r=>r.name.length));return t.map(r=>` ${r.name.padEnd(e)} ${r.description}
38
+ `).join("")}async function Ga(t,e){let r=await Eu();if(!e){await Qt(`Topics:
39
+ ${$a(r)}
40
+ Run '${t} docs <topic>' to print a guide.
41
+ `);return}let o=r.find(n=>n.name===e);if(!o)throw new Error(`Unknown topic "${e}". Topics:
42
+ ${$a(r)}`);await Qt(o.body)}var Ao="docs",Iu=t=>[{comment:"List the topics",commands:[`${t} ${Ao}`]},{comment:"Print the guide to CI setup",commands:[`${t} ${Ao} ci-setup`]}],Ha=t=>new Ka.Command().name(Ao).summary("Print a guide, such as the CI setup steps").description("Print the guide of a topic as Markdown. Without a topic, list the topics.").argument("[topic]","the topic of the guide").addHelpText("after",y(Iu(t))).action(async e=>{await R(()=>Ga(t,e),{})});var jo=require("@commander-js/extra-typings");var{apiKey:Cu,recordKey:Tu,projectId:yu,ciBuildId:Ru,machineId:wu,debug:_u}=_,k={apiKey:Cu,recordKey:Tu,projectId:yu,ciBuildId:Ru,machineId:wu,sessionId:{name:"Session ID",env:"CURRENTS_SESSION_ID",cli:"--session-id"},title:{name:"Title",cli:"--title"},debug:_u};var ar=p.extend("config");function Ja(t){let e=U(k,["projectId","title"],t,cr);return ar("Resolved config: %o",h(e)),e}function Va(t){let e=U(k,[],t,cr);return ar("Resolved config: %o",h(e)),e}function Ya(t){let e=U(k,[],t,cr);return ar("Resolved config: %o",h(e)),e}function Wa(t){let e=U(k,["projectId"],t,cr);return ar("Resolved config: %o",h(e)),e}function cr(t){if(!(t.recordKey||t.apiKey))throw new z(`${k.recordKey.name} or ${k.apiKey.name} is required. Set ${k.recordKey.env} or ${k.apiKey.env}, or pass ${k.recordKey.cli} or ${k.apiKey.cli}`)}var se=l(require("fs-extra")),Ot=l(require("path"));var za=l(require("path"));var qa=["trace","screenshot","video","attachment"];var Ou=["image/png","image/jpeg","image/webp","image/gif"],Qa=t=>za.default.extname(t).toLowerCase()===".zip";function Xa(t){return qa.includes(t)}function Do(t){return Qa(t)?"application/zip":eo(t)?.contentType??"application/octet-stream"}function xu(t){return Qa(t)?"trace":eo(t)?.type??"attachment"}function Uo(t,e){let r=xu(t);return e.includes(r)?r:"attachment"}function Za(t,e,r){if(!r.includes(e))throw new Error(`Cannot attach "${t}" as type "${e}" here. The target takes: ${r.join(", ")}`)}function tc(t,e){let r=Do(t);if(!(e==="attachment"||e==="trace"&&r==="application/zip"||e==="screenshot"&&Ou.includes(r)||e==="video"&&r.startsWith("video/")))throw new Error(`Cannot attach "${t}" as type "${e}": its content type is ${r}`)}var ec=l(require("archiver")),_t=l(require("fs-extra")),pr=l(require("path")),rc=l(require("unzipper")),oc=require("tmp-promise");async function nc(t){try{return(await rc.default.Open.file(t)).files.some(r=>/^(trace|test|\d+-trace)\.trace$/.test(r.path))}catch{return!1}}var sc=/^trace-.*\.trace$/,Su=/^trace-.*\.network$/;async function Po(t){return(await _t.default.readdir(t)).some(r=>sc.test(r))}function Au(t){if(!t)return!1;try{let e=JSON.parse(t),r=e.snapshot?.response;if(e.type!=="resource-snapshot"||!r)return!0;let o=r.status>=200&&r.status<400,n=/javascript|ecmascript/i.test(r.content?.mimeType??"");return!(o&&n)}catch{return!0}}async function ic(t,e){return(await _t.default.readdir(t)).filter(o=>e.test(o)).sort().map(o=>pr.default.join(t,o))}async function Du(t){return(await Promise.all((await ic(t,sc)).map(r=>_t.default.readFile(r,"utf8")))).map(r=>r.endsWith(`
38
43
  `)?r:r+`
39
- `).join("")}async function Eu(t){let e=await Qa(t,fu),r=[];for(let o of e)r.push(...(await _t.default.readFile(o,"utf8")).split(`
40
- `));return r.filter(gu).join(`
41
- `)}async function Xa(t){let{path:e,cleanup:r}=await(0,Wa.dir)({unsafeCleanup:!0}),o=ir.default.join(e,"trace.zip");try{let n=(0,Va.default)("zip",{zlib:{level:9}}),s=_t.default.createWriteStream(o),i=new Promise((c,m)=>{s.on("close",()=>c()),s.on("error",m),n.on("error",m)});n.pipe(s),n.append(await hu(t),{name:"trace.trace"}),n.append(await Eu(t),{name:"trace.network"});for(let c of["screencast","resources"]){let m=ir.default.join(t,c);await _t.default.pathExists(m)&&n.directory(m,c)}await n.finalize(),await i}catch(n){throw await r(),n}return{zipPath:o,cleanup:r}}var Iu=1024**3,Za=/^\.env($|[._-])|^\.envrc$|\.env$/i,Cu=/\.(pem|key)$|^id_(rsa|ed25519|ecdsa|dsa)/i;function Tu(t){if(Za.test(t))throw new Error(`"${t}" looks like an environment file with secrets and is not attached`)}async function So(t,e,r){Tu(e);let o=r.type??Oo(e,r.allowedTypes);r.type?(Ja(e,r.type),Ha(e,r.type,r.allowedTypes)):o==="trace"&&!await qa(t)&&(o="attachment");let n=await ne.default.stat(t);if(n.size>Iu)throw new Error(`"${e}" is larger than 1 GiB`);if(n.size===0)throw new Error(`"${e}" is empty`);return{path:t,name:e,type:o,contentType:wo(e),sizeBytes:n.size}}async function yu(t,e,r){let o=[],n=async s=>{for(let i of await ne.default.readdir(s,{withFileTypes:!0})){let c=wt.default.join(s,i.name),m=wt.default.relative(t,c).split(wt.default.sep).join("/");if(i.name.startsWith("."))I(`Skipping the hidden file "${c}"`);else if(Cu.test(i.name)||Za.test(i.name))I(`Skipping "${c}", which looks like a key or secrets file`);else if(i.isSymbolicLink())I(`Skipping the link "${c}"`);else if(i.isDirectory())await xo(c)?await r(c,wt.default.posix.dirname(m)):await n(c);else if(i.isFile()){if((await ne.default.stat(c)).size===0){I(`Skipping the empty file "${c}"`);continue}o.push(await So(c,m,e))}}};return await n(t),o}async function tc(t,e){let r=[],o=[],n=async()=>{await Promise.all(o.map(i=>i()))},s=async(i,c=".")=>{let m=await Xa(i);o.push(m.cleanup);let d=wt.default.posix.join(c,`trace-${wr(8)}.zip`);r.push(await So(m.zipPath,d,{...e,type:e.type??Oo("trace.zip",e.allowedTypes)}))};try{for(let i of t){let c=await ne.default.stat(i).catch(()=>null);if(!c)throw new Error(`"${i}" does not exist`);if(!c.isDirectory()){r.push(await So(i,wt.default.basename(i),e));continue}if(await xo(i)){await s(i);continue}r.push(...await yu(i,e,s))}}catch(i){throw await n(),i}if(r.length===0)throw new Error("There are no files to attach");return{files:r,cleanup:n}}var ec={run:["attachment"],instance:["attachment","video","screenshot"],test:["attachment"],attempt:["attachment","video","screenshot","trace"]},rc=["attachment","video","screenshot","trace"];function oc(t){return t.testId||t.testTitle?t.attempt===void 0?"test":"attempt":t.instanceId||t.spec?"instance":"run"}var nc=4;async function sc(t){let e=[];for(let r=0;r<t.length;r+=nc)e.push(...await Promise.all(t.slice(r,r+nc).map(async({file:o,uploadUrl:n,uploadHeaders:s})=>{try{return await hs({name:o.name,path:o.path,sizeBytes:o.sizeBytes,uploadUrl:n,contentType:o.contentType,headers:s}),{file:o}}catch(i){return{file:o,error:i}}})));return e}var Ru=p.extend("files");function _u(t=[]){let e=new Map;for(let r of t){let o=r.indexOf("=");if(o<1)throw new Error(`--meta expects key=value, got "${r}"`);let n=r.slice(0,o);if(!/^[A-Za-z0-9_-]{1,64}$/.test(n))throw new Error(`--meta key "${n}" can only hold up to 64 letters, digits, "_" and "-"`);let s=r.slice(o+1);if(s.length>256)throw new Error(`--meta value of "${n}" is longer than 256 characters`);e.set(n,s)}return e.size>0?Object.fromEntries(e):void 0}function wu(t){if(t!==void 0){if(!Ka(t))throw new Error(`--type must be one of trace, screenshot, video, attachment, got "${t}"`);return t}}var Ou=50,xu=100*1024**2,ic=200;function Su(t,e={count:Ou,bytes:xu}){let r=[],o=0;for(let n of t){let s=r[r.length-1];!s||s.length>=e.count||o+n.sizeBytes>e.bytes?(r.push([n]),o=n.sizeBytes):(s.push(n),o+=n.sizeBytes)}return r}async function Ao(t){if(!t.credentials.apiKey&&!t.credentials.recordKey)throw new Error("Pass an API key or a record key");let e=wu(t.type),r=_u(t.meta),o=t.target??{},n="sessionId"in t.owner?rc:ec[oc(o)],{files:s,cleanup:i}=await tc(t.paths,{type:e,allowedTypes:n});if(s.length>ic)throw await i(),new Error(`Found ${s.length} files to attach; the API takes at most ${ic}. Pass the folders or files you need instead`);let c=[],m=[];try{for(let d of Su(s)){let f=d.map(g=>({name:g.name,type:g.type,contentType:g.contentType,sizeBytes:g.sizeBytes,caption:t.caption,meta:r})),u;try{u=await Un(t.credentials,t.owner,o,f)}catch(g){throw new Error(`${g.message}
42
- ${c.length} of ${s.length} files were attached before this`)}if(Ru("Created %d attachments at level %s",u.attachments.length,u.level??"session"),u.attachments.length!==d.length)throw new Error(`The API returned ${u.attachments.length} upload URLs for ${d.length} files`);let E=await sc(d.map((g,A)=>{if(u.attachments[A].name!==g.name)throw new Error(`The API answered "${u.attachments[A].name}" where "${g.name}" was declared`);let{uploadUrl:V,uploadHeaders:xt}=u.attachments[A];return{file:g,uploadUrl:V,uploadHeaders:xt}}));for(let g of E)g.error?(C("Failed %s: %s",g.file.name,g.error.message),m.push(g)):(T("Attached %s (%s)",g.file.name,g.file.type),c.push(g.file))}}finally{await i().catch(d=>I("Could not remove temporary files: %s",d.message))}if(m.length>0)throw new Error(`${m.length} of ${s.length} files could not be uploaded`);return{files:c.map(({name:d,type:f,sizeBytes:u})=>({name:d,type:f,sizeBytes:u}))}}var Ot=l(require("fs-extra")),se=l(require("path")),Au=".currents-session",ac=()=>se.default.join(process.cwd(),Au,"session.json");async function Du(t){let e=se.default.join(t,".gitignore");await Ot.default.pathExists(e)||await Ot.default.writeFile(e,`*
43
- `)}async function cc(t){let e=ac();await Ot.default.ensureDir(se.default.dirname(e)),await Du(se.default.dirname(e)),await Ot.default.writeJson(e,t,{spaces:2})}async function Uu(){let t=ac();if(!await Ot.default.pathExists(t))return null;let e=await Ot.default.readJson(t),r=e?.sessionId||e?.runId;if(typeof r!="string"||!r.trim())return null;let o=typeof e.projectId=="string"?e.projectId:void 0;return{sessionId:r,projectId:o}}async function Do(t){if(t)return t;let e=await Uu();if(!e)throw new Error('No session found. Run "currents session start" first, or pass --session-id');return e.sessionId}var Pu=p.extend("session");async function bu(){try{let{sha:t,branch:e,message:r,authorName:o,authorEmail:n,remoteOrigin:s}=await Ae();return{sha:t,branch:e,message:r,authorName:o,authorEmail:n,remoteOrigin:s}}catch(t){Pu("No git info: %o",t);return}}function Nu(t){if(t)return/^\d+$/.test(t)?{id:t}:{link:t}}function pc(){let{provider:t,params:e}=ot();return{provider:t,params:e}}function Lu(){if(ot().ciBuildId.source!=="server")throw new Error("The CI build ID is unknown. Pass --ci-build-id or set CURRENTS_CI_BUILD_ID to the value the run was recorded with")}async function dc(t){let e=await Dn({apiKey:t.apiKey,recordKey:t.recordKey},{projectId:t.projectId,title:t.title,status:t.status,error:t.error,tags:t.tag,commit:await bu(),ci:pc(),pr:Nu(t.pr)});return await cc({sessionId:e.sessionId,projectId:t.projectId}),t.json?process.stdout.write(JSON.stringify({sessionId:e.sessionId})+`
44
- `):T("Session started: %s",e.sessionId),e}async function mc(t,e){let r=await Do(t.sessionId);return Ao({credentials:{apiKey:t.apiKey,recordKey:t.recordKey},owner:{sessionId:r},paths:e,type:t.type,caption:t.caption,meta:t.meta})}async function uc(t){let e=await Do(t.sessionId),r=await Pn({apiKey:t.apiKey,recordKey:t.recordKey},{sessionId:e,purpose:"report",expiresInDays:t.expiresInDays});return T(r.pageUrl),T("Markdown: %s",r.url),r}async function lc(t,e){if(t.testTitle&&!t.spec)throw new Error("--test-title needs --spec, the spec file of the test");if(t.attempt!==void 0&&!t.testTitle)throw new Error("--attempt needs --test-title");if(t.group&&!t.spec)throw new Error("--group needs --spec: it picks the spec file of a group");return t.ciBuildId||Lu(),Ao({credentials:{apiKey:t.apiKey,recordKey:t.recordKey},owner:t.ciBuildId?{projectId:t.projectId,ciBuildId:t.ciBuildId}:{projectId:t.projectId,ci:pc()},target:{spec:t.spec,testTitle:t.testTitle,groupId:t.group,attempt:t.attempt,machineId:t.spec?void 0:t.machineId},paths:e,type:t.type,caption:t.caption,meta:t.meta})}var S=require("@commander-js/extra-typings");var fc=t=>L(k,t),Mt="(required unless --api-key is set)",kt="(used when --key is not set; needs write access)",gc=Lt(". Leave it out only if the run was recorded without one, on a CI the reporters recognize"),hc=new S.Option("--machine-id <id>","the CI machine the files come from; run-level files are listed by machine when it is set").env(fc("machineId")),Po=new S.Option("--session-id <id>",'the session to use instead of the one saved by "session start"').env(fc("sessionId")),Ec=new S.Option("--title <text>","what the session shows, used as the session title (required)"),Ic=new S.Option("--status <status>","the result of the session").choices(["passed","failed"]).default("passed"),Cc=new S.Option("--error <text>","what went wrong, for a failed session"),Tc=vt("tags to add to the session"),yc=new S.Option("--pr <url|number>","the pull request the session is about; by default taken from the CI environment"),Rc=new S.Option("--json",'print the session ID as JSON on stdout, e.g. {"sessionId": "..."}'),_c=new S.Option("--spec <spec>","attach to this spec file of the run"),wc=new S.Option("--test-title <title>",'attach to this test of --spec: the full title joined with " > ", or its last part'),Oc=new S.Option("--group <id>","the group of the spec file; a spec that runs once per Playwright project matches more than once without it"),xc=new S.Option("--attempt <n>","attach to this attempt of the test; the first attempt is 0").argParser(t=>{let e=Number(t);if(!Number.isInteger(e)||e<0)throw new Error("--attempt must be a whole number from 0");return e}),Sc=["trace","screenshot","video","attachment"],Ac="by default taken from the file: a .zip holding trace.trace is a trace; .png, .jpg, .jpeg, .webp and .gif are screenshots; .webm and .mp4 are videos; anything else is an attachment",Dc=new S.Option("--type <type>",`the type of every file; ${Ac}`).choices(Sc),Uc=new S.Option("--type <type>",`the type of every file; ${Ac}. The whole run and a test take attachments only, a spec file also takes screenshots and videos, and an attempt (--attempt) takes all four types, including traces. A file of a type its target does not take is attached as an attachment, and a --type the target does not take is an error`).choices(Sc),ar="files or folders to attach. A folder adds every file under it, named by its path in the folder, such as login-chromium/trace.zip, so a Playwright test-results folder attaches in one go; hidden files and folders, links and empty files in it are skipped. A folder of Playwright MCP trace-*.trace files, at the top or inside, is packed into one trace and nothing else in it is attached. At most 200 files, each at most 1 GiB; files named .env or .env.* are refused",cr=new S.Option("--caption <text>","a short description shown with each file"),vu=(t,e=[])=>[...e,t],pr=new S.Option("--meta <key=value>","a label for each file; repeat for more").argParser(vu),Uo=["1","3","7"],Pc=new S.Option("--expires-in-days <days>","the number of days the link works").choices(Uo).default(7).argParser(t=>{if(!Uo.includes(t))throw new S.InvalidArgumentError(`Allowed choices are ${Uo.join(", ")}.`);return Number(t)});var Kc=require("@commander-js/extra-typings");var jt=require("@commander-js/extra-typings");var bc=new jt.Option("--ci-build-id <id>","the CI build ID to record the run with; by default taken from the CI environment, or a random value").env(L(st,"ciBuildId")),Nc=vt("tags to add to the run").env(L(st,"tag")),Lc=new jt.Option("--remove-title-tags","remove tags from test names in Currents, e.g. `Test name @smoke` becomes `Test name` in the dashboard").env(L(st,"removeTitleTags")).default(!1),vc=new jt.Option("--disable-title-tags","do not read tags from test names, e.g. `Test name @smoke` is not tagged with `smoke` in the dashboard").env(L(st,"disableTitleTags")).default(!1),Bc=new jt.Option("--machine-id <id>","the ID of the machine that ran the tests; by default a random value").env(L(st,"machineId")),Fc=new jt.Option("--report-dir <folder>","the folder of the reports to upload; by default the newest folder in .currents").env(L(st,"reportDir"));var No=require("path");var jc=l(require("fs"));var Mc=require("tmp-promise"),kc=async()=>{let{path:t}=await(0,Mc.file)();return t};var bo=p.extend("cli"),dr=class{constructor(e){this.configFilePath=null;this.cliOptions=e,bo("CLI options: %o",h(this.cliOptions)),this.parsedConfig=Gs(this.cliOptions),bo("Parsed config from CLI options: %o",h(this.parsedConfig))}async getConfigFilePath(){if(this.configFilePath)return this.configFilePath;let e=await kc();return jc.default.writeFileSync(e,JSON.stringify(this.parsedConfig)),bo("CLI options temp file path: %s",e),this.configFilePath=e,e}};async function Gc(t){await w(async e=>{let r=e.inputFormat?await Bu(e):e.reportDir,o=new dr({...e,reportDir:r});js(o.parsedConfig);let n=De();T("Currents config: %o",h(n)),await so()},t)}async function Bu({inputFormat:t,inputFile:e,framework:r,frameworkVersion:o,outputDir:n,reportDir:s,debug:i}){if(n&&s&&(0,No.resolve)(n)!==(0,No.resolve)(s))throw new Error("--output-dir and --report-dir name different folders. With --input-format, the converted reports are saved to one folder and uploaded from it: pass one of the two options.");return Ro({inputFormat:t,inputFile:e,framework:r,frameworkVersion:o,outputDir:n??s,debug:i})}var Gt="upload",$c="(required with --input-format)",mr="run",$t=t=>[{comment:"Upload test results to Currents",commands:[`${t} ${mr} ${Gt} --key <record-key> --project-id <id> --ci-build-id <build-id>`]},{comment:"Convert JUnit XML reports to the Currents format, then upload them",commands:[`${t} ${mr} ${Gt} --key <record-key> --project-id <id> --ci-build-id <build-id> --input-format junit --input-file "./*.xml" --framework postman`]},{comment:'Upload test results and add the tags "tagA" and "tagB" to the run',commands:[`${t} ${mr} ${Gt} --key <record-key> --project-id <id> --ci-build-id <build-id> --tag tagA --tag tagB`]},{comment:"Upload test results from another folder",commands:[`${t} ${mr} ${Gt} --key <record-key> --project-id <id> --ci-build-id <build-id> --report-dir <report-dir>`]}],ur=t=>new Kc.Command().name(Gt).command(Gt).showHelpAfterError("(add --help for additional information)").allowUnknownOption().summary("Upload test results of Currents reporters or JUnit").description(`Upload test results created by Currents reporters to https://currents.dev
44
+ `).join("")}async function Uu(t){let e=await ic(t,Su),r=[];for(let o of e)r.push(...(await _t.default.readFile(o,"utf8")).split(`
45
+ `));return r.filter(Au).join(`
46
+ `)}async function ac(t){let{path:e,cleanup:r}=await(0,oc.dir)({unsafeCleanup:!0}),o=pr.default.join(e,"trace.zip");try{let n=(0,ec.default)("zip",{zlib:{level:9}}),s=_t.default.createWriteStream(o),i=new Promise((c,m)=>{s.on("close",()=>c()),s.on("error",m),n.on("error",m)});n.pipe(s),n.append(await Du(t),{name:"trace.trace"}),n.append(await Uu(t),{name:"trace.network"});for(let c of["screencast","resources"]){let m=pr.default.join(t,c);await _t.default.pathExists(m)&&n.directory(m,c)}await n.finalize(),await i}catch(n){throw await r(),n}return{zipPath:o,cleanup:r}}var Pu=1024**3,cc=/^\.env($|[._-])|^\.envrc$|\.env$/i,bu=/\.(pem|key)$|^id_(rsa|ed25519|ecdsa|dsa)/i;function Nu(t){if(cc.test(t))throw new Error(`"${t}" looks like an environment file with secrets and is not attached`)}async function bo(t,e,r){Nu(e);let o=r.type??Uo(e,r.allowedTypes);r.type?(tc(e,r.type),Za(e,r.type,r.allowedTypes)):o==="trace"&&!await nc(t)&&(o="attachment");let n=await se.default.stat(t);if(n.size>Pu)throw new Error(`"${e}" is larger than 1 GiB`);if(n.size===0)throw new Error(`"${e}" is empty`);return{path:t,name:e,type:o,contentType:Do(e),sizeBytes:n.size}}async function Lu(t,e,r){let o=[],n=async s=>{for(let i of await se.default.readdir(s,{withFileTypes:!0})){let c=Ot.default.join(s,i.name),m=Ot.default.relative(t,c).split(Ot.default.sep).join("/");if(i.name.startsWith("."))I(`Skipping the hidden file "${c}"`);else if(bu.test(i.name)||cc.test(i.name))I(`Skipping "${c}", which looks like a key or secrets file`);else if(i.isSymbolicLink())I(`Skipping the link "${c}"`);else if(i.isDirectory())await Po(c)?await r(c,Ot.default.posix.dirname(m)):await n(c);else if(i.isFile()){if((await se.default.stat(c)).size===0){I(`Skipping the empty file "${c}"`);continue}o.push(await bo(c,m,e))}}};return await n(t),o}async function pc(t,e){let r=[],o=[],n=async()=>{await Promise.all(o.map(i=>i()))},s=async(i,c=".")=>{let m=await ac(i);o.push(m.cleanup);let d=Ot.default.posix.join(c,`trace-${Sr(8)}.zip`);r.push(await bo(m.zipPath,d,{...e,type:e.type??Uo("trace.zip",e.allowedTypes)}))};try{for(let i of t){let c=await se.default.stat(i).catch(()=>null);if(!c)throw new Error(`"${i}" does not exist`);if(!c.isDirectory()){r.push(await bo(i,Ot.default.basename(i),e));continue}if(await Po(i)){await s(i);continue}r.push(...await Lu(i,e,s))}}catch(i){throw await n(),i}if(r.length===0)throw new Error("There are no files to attach");return{files:r,cleanup:n}}var dc={run:["attachment"],instance:["attachment","video","screenshot"],test:["attachment"],attempt:["attachment","video","screenshot","trace"]},mc=["attachment","video","screenshot","trace"];function uc(t){return t.testId||t.testTitle?t.attempt===void 0?"test":"attempt":t.instanceId||t.spec?"instance":"run"}var lc=4;async function fc(t){let e=[];for(let r=0;r<t.length;r+=lc)e.push(...await Promise.all(t.slice(r,r+lc).map(async({file:o,uploadUrl:n,uploadHeaders:s})=>{try{return await ys({name:o.name,path:o.path,sizeBytes:o.sizeBytes,uploadUrl:n,contentType:o.contentType,headers:s}),{file:o}}catch(i){return{file:o,error:i}}})));return e}var vu=p.extend("files");function Bu(t=[]){let e=new Map;for(let r of t){let o=r.indexOf("=");if(o<1)throw new Error(`--meta expects key=value, got "${r}"`);let n=r.slice(0,o);if(!/^[A-Za-z0-9_-]{1,64}$/.test(n))throw new Error(`--meta key "${n}" can only hold up to 64 letters, digits, "_" and "-"`);let s=r.slice(o+1);if(s.length>256)throw new Error(`--meta value of "${n}" is longer than 256 characters`);e.set(n,s)}return e.size>0?Object.fromEntries(e):void 0}function Fu(t){if(t!==void 0){if(!Xa(t))throw new Error(`--type must be one of trace, screenshot, video, attachment, got "${t}"`);return t}}var Mu=50,ku=100*1024**2,gc=200;function ju(t,e={count:Mu,bytes:ku}){let r=[],o=0;for(let n of t){let s=r[r.length-1];!s||s.length>=e.count||o+n.sizeBytes>e.bytes?(r.push([n]),o=n.sizeBytes):(s.push(n),o+=n.sizeBytes)}return r}async function No(t){if(!t.credentials.apiKey&&!t.credentials.recordKey)throw new Error("Pass an API key or a record key");let e=Fu(t.type),r=Bu(t.meta),o=t.target??{},n="sessionId"in t.owner?mc:dc[uc(o)],{files:s,cleanup:i}=await pc(t.paths,{type:e,allowedTypes:n});if(s.length>gc)throw await i(),new Error(`Found ${s.length} files to attach; the API takes at most ${gc}. Pass the folders or files you need instead`);let c=[],m=[];try{for(let d of ju(s)){let f=d.map(g=>({name:g.name,type:g.type,contentType:g.contentType,sizeBytes:g.sizeBytes,caption:t.caption,meta:r})),u;try{u=await vn(t.credentials,t.owner,o,f)}catch(g){throw new Error(`${g.message}
47
+ ${c.length} of ${s.length} files were attached before this`)}if(vu("Created %d attachments at level %s",u.attachments.length,u.level??"session"),u.attachments.length!==d.length)throw new Error(`The API returned ${u.attachments.length} upload URLs for ${d.length} files`);let E=await fc(d.map((g,A)=>{if(u.attachments[A].name!==g.name)throw new Error(`The API answered "${u.attachments[A].name}" where "${g.name}" was declared`);let{uploadUrl:Y,uploadHeaders:St}=u.attachments[A];return{file:g,uploadUrl:Y,uploadHeaders:St}}));for(let g of E)g.error?(C("Failed %s: %s",g.file.name,g.error.message),m.push(g)):(T("Attached %s (%s)",g.file.name,g.file.type),c.push(g.file))}}finally{await i().catch(d=>I("Could not remove temporary files: %s",d.message))}if(m.length>0)throw new Error(`${m.length} of ${s.length} files could not be uploaded`);return{files:c.map(({name:d,type:f,sizeBytes:u})=>({name:d,type:f,sizeBytes:u}))}}var xt=l(require("fs-extra")),ie=l(require("path")),$u=".currents-session",hc=()=>ie.default.join(process.cwd(),$u,"session.json");async function Gu(t){let e=ie.default.join(t,".gitignore");await xt.default.pathExists(e)||await xt.default.writeFile(e,`*
48
+ `)}async function Ec(t){let e=hc();await xt.default.ensureDir(ie.default.dirname(e)),await Gu(ie.default.dirname(e)),await xt.default.writeJson(e,t,{spaces:2})}async function Ku(){let t=hc();if(!await xt.default.pathExists(t))return null;let e=await xt.default.readJson(t),r=e?.sessionId||e?.runId;if(typeof r!="string"||!r.trim())return null;let o=typeof e.projectId=="string"?e.projectId:void 0;return{sessionId:r,projectId:o}}async function Lo(t){if(t)return t;let e=await Ku();if(!e)throw new Error('No session found. Run "currents session start" first, or pass --session-id');return e.sessionId}var Hu=p.extend("session");async function Ju(){try{let{sha:t,branch:e,message:r,authorName:o,authorEmail:n,remoteOrigin:s}=await Ue();return{sha:t,branch:e,message:r,authorName:o,authorEmail:n,remoteOrigin:s}}catch(t){Hu("No git info: %o",t);return}}function Vu(t){if(t)return/^\d+$/.test(t)?{id:t}:{link:t}}function Ic(){let{provider:t,params:e}=rt();return{provider:t,params:e}}function Yu(){if(rt().ciBuildId.source!=="server")throw new Error("The CI build ID is unknown. Pass --ci-build-id or set CURRENTS_CI_BUILD_ID to the value the run was recorded with")}async function Cc(t){let e=await Ln({apiKey:t.apiKey,recordKey:t.recordKey},{projectId:t.projectId,title:t.title,status:t.status,error:t.error,tags:t.tag,commit:await Ju(),ci:Ic(),pr:Vu(t.pr)});return await Ec({sessionId:e.sessionId,projectId:t.projectId}),t.json?process.stdout.write(JSON.stringify({sessionId:e.sessionId})+`
49
+ `):T("Session started: %s",e.sessionId),e}async function Tc(t,e){let r=await Lo(t.sessionId);return No({credentials:{apiKey:t.apiKey,recordKey:t.recordKey},owner:{sessionId:r},paths:e,type:t.type,caption:t.caption,meta:t.meta})}async function yc(t){let e=await Lo(t.sessionId),r=await Bn({apiKey:t.apiKey,recordKey:t.recordKey},{sessionId:e,purpose:"report",expiresInDays:t.expiresInDays});return T(r.pageUrl),T("Markdown: %s",r.url),r}async function Rc(t,e){if(t.testTitle&&!t.spec)throw new Error("--test-title needs --spec, the spec file of the test");if(t.attempt!==void 0&&!t.testTitle)throw new Error("--attempt needs --test-title");if(t.group&&!t.spec)throw new Error("--group needs --spec: it picks the spec file of a group");return t.ciBuildId||Yu(),No({credentials:{apiKey:t.apiKey,recordKey:t.recordKey},owner:t.ciBuildId?{projectId:t.projectId,ciBuildId:t.ciBuildId}:{projectId:t.projectId,ci:Ic()},target:{spec:t.spec,testTitle:t.testTitle,groupId:t.group,attempt:t.attempt,machineId:t.spec?void 0:t.machineId},paths:e,type:t.type,caption:t.caption,meta:t.meta})}var S=require("@commander-js/extra-typings");var wc=t=>L(k,t),kt="(required unless --api-key is set)",jt="(used when --key is not set; needs write access)",_c=vt(". Leave it out only if the run was recorded without one, on a CI the reporters recognize"),Oc=new S.Option("--machine-id <id>","the CI machine the files come from; run-level files are listed by machine when it is set").env(wc("machineId")),Bo=new S.Option("--session-id <id>",'the session to use instead of the one saved by "session start"').env(wc("sessionId")),xc=new S.Option("--title <text>","what the session shows, used as the session title (required)"),Sc=new S.Option("--status <status>","the result of the session").choices(["passed","failed"]).default("passed"),Ac=new S.Option("--error <text>","what went wrong, for a failed session"),Dc=Bt("tags to add to the session"),Uc=new S.Option("--pr <url|number>","the pull request the session is about; by default taken from the CI environment"),Pc=new S.Option("--json",'print the session ID as JSON on stdout, e.g. {"sessionId": "..."}'),bc=new S.Option("--spec <spec>","attach to this spec file of the run"),Nc=new S.Option("--test-title <title>",'attach to this test of --spec: the full title joined with " > ", or its last part'),Lc=new S.Option("--group <id>","the group of the spec file; a spec that runs once per Playwright project matches more than once without it"),vc=new S.Option("--attempt <n>","attach to this attempt of the test; the first attempt is 0").argParser(t=>{let e=Number(t);if(!Number.isInteger(e)||e<0)throw new Error("--attempt must be a whole number from 0");return e}),Bc=["trace","screenshot","video","attachment"],Fc="by default taken from the file: a .zip holding trace.trace is a trace; .png, .jpg, .jpeg, .webp and .gif are screenshots; .webm and .mp4 are videos; anything else is an attachment",Mc=new S.Option("--type <type>",`the type of every file; ${Fc}`).choices(Bc),kc=new S.Option("--type <type>",`the type of every file; ${Fc}. The whole run and a test take attachments only, a spec file also takes screenshots and videos, and an attempt (--attempt) takes all four types, including traces. A file of a type its target does not take is attached as an attachment, and a --type the target does not take is an error`).choices(Bc),dr="files or folders to attach. A folder adds every file under it, named by its path in the folder, such as login-chromium/trace.zip, so a Playwright test-results folder attaches in one go; hidden files and folders, links and empty files in it are skipped. A folder of Playwright MCP trace-*.trace files, at the top or inside, is packed into one trace and nothing else in it is attached. At most 200 files, each at most 1 GiB; files named .env or .env.* are refused",mr=new S.Option("--caption <text>","a short description shown with each file"),Wu=(t,e=[])=>[...e,t],ur=new S.Option("--meta <key=value>","a label for each file; repeat for more").argParser(Wu),vo=["1","3","7"],jc=new S.Option("--expires-in-days <days>","the number of days the link works").choices(vo).default(7).argParser(t=>{if(!vo.includes(t))throw new S.InvalidArgumentError(`Allowed choices are ${vo.join(", ")}.`);return Number(t)});var Xc=require("@commander-js/extra-typings");var $t=require("@commander-js/extra-typings");var $c=new $t.Option("--ci-build-id <id>","the CI build ID to record the run with; by default taken from the CI environment, or a random value").env(L(nt,"ciBuildId")),Gc=Bt("tags to add to the run").env(L(nt,"tag")),Kc=new $t.Option("--remove-title-tags","remove tags from test names in Currents, e.g. `Test name @smoke` becomes `Test name` in the dashboard").env(L(nt,"removeTitleTags")).default(!1),Hc=new $t.Option("--disable-title-tags","do not read tags from test names, e.g. `Test name @smoke` is not tagged with `smoke` in the dashboard").env(L(nt,"disableTitleTags")).default(!1),Jc=new $t.Option("--machine-id <id>","the ID of the machine that ran the tests; by default a random value").env(L(nt,"machineId")),Vc=new $t.Option("--report-dir <folder>","the folder of the reports to upload; by default the newest folder in .currents").env(L(nt,"reportDir"));var Mo=require("path");var qc=l(require("fs"));var Yc=require("tmp-promise"),Wc=async()=>{let{path:t}=await(0,Yc.file)();return t};var Fo=p.extend("cli"),lr=class{constructor(e){this.configFilePath=null;this.cliOptions=e,Fo("CLI options: %o",h(this.cliOptions)),this.parsedConfig=Vs(this.cliOptions),Fo("Parsed config from CLI options: %o",h(this.parsedConfig))}async getConfigFilePath(){if(this.configFilePath)return this.configFilePath;let e=await Wc();return qc.default.writeFileSync(e,JSON.stringify(this.parsedConfig)),Fo("CLI options temp file path: %s",e),this.configFilePath=e,e}};async function zc(t){await R(async e=>{let r=e.inputFormat?await qu(e):e.reportDir,o=new lr({...e,reportDir:r});Js(o.parsedConfig);let n=Pe();T("Currents config: %o",h(n)),await co()},t)}async function qu({inputFormat:t,inputFile:e,framework:r,frameworkVersion:o,outputDir:n,reportDir:s,debug:i}){if(n&&s&&(0,Mo.resolve)(n)!==(0,Mo.resolve)(s))throw new Error("--output-dir and --report-dir name different folders. With --input-format, the converted reports are saved to one folder and uploaded from it: pass one of the two options.");return Oo({inputFormat:t,inputFile:e,framework:r,frameworkVersion:o,outputDir:n??s,debug:i})}var Gt="upload",Qc="(required with --input-format)",fr="run",Kt=t=>[{comment:"Upload test results to Currents",commands:[`${t} ${fr} ${Gt} --key <record-key> --project-id <id> --ci-build-id <build-id>`]},{comment:"Convert JUnit XML reports to the Currents format, then upload them",commands:[`${t} ${fr} ${Gt} --key <record-key> --project-id <id> --ci-build-id <build-id> --input-format junit --input-file "./*.xml" --framework postman`]},{comment:'Upload test results and add the tags "tagA" and "tagB" to the run',commands:[`${t} ${fr} ${Gt} --key <record-key> --project-id <id> --ci-build-id <build-id> --tag tagA --tag tagB`]},{comment:"Upload test results from another folder",commands:[`${t} ${fr} ${Gt} --key <record-key> --project-id <id> --ci-build-id <build-id> --report-dir <report-dir>`]}],gr=t=>new Xc.Command().name(Gt).command(Gt).showHelpAfterError("(add --help for additional information)").allowUnknownOption().summary("Upload test results of Currents reporters or JUnit").description(`Upload test results created by Currents reporters to https://currents.dev
45
50
 
46
51
  With --input-format, first convert the reports in --input-file to the Currents
47
52
  format, then upload the converted reports. They are saved to --output-dir, or
48
53
  --report-dir, or a new folder in .currents. A folder you name may hold only the
49
- reports being converted.`).addHelpText("after",y($t(t))).addOption(bc).addOption(M()).addOption(tt()).addOption(Nc).addOption(Lc).addOption(vc).addOption(Bc).addOption(b()).addOption(Fc).addOption(Ze()).addOption(tr($c)).addOption(rr($c)).addOption(or).addOption(er).action(r=>Gc(r));var Lo="run",lr=t=>[{comment:"Attach the Docker logs of a CI machine to the run, after the tests finished",commands:[`${t} ${Lo} attach --key <record-key> --project-id <id> --ci-build-id <build-id> --machine-id shard-1 docker-logs.zip`]},{comment:"Attach a screenshot to the first attempt of a test",commands:[`${t} ${Lo} attach --key <record-key> --project-id <id> --ci-build-id <build-id> --spec tests/cart.spec.ts --test-title "adds an item" --attempt 0 screenshot.png`]}],Fu=t=>new vo.Command().name("attach").addHelpText("after",y(lr(t))).description("Upload files to a run recorded in CI").argument("<paths...>",ar).addOption(M(Mt)).addOption(ct(kt)).addOption(tt()).addOption(gc).addOption(hc).addOption(_c).addOption(Oc).addOption(wc).addOption(xc).addOption(Uc).addOption(cr).addOption(pr).addOption(b()).action(async(e,r)=>{await w(async({key:o,...n})=>{await lc(ka({...n,recordKey:o}),e)},r)}),Hc=t=>new vo.Command().name(Lo).summary("Upload test results, attach files, get or cancel a run").description("Upload test results to a run, attach files to it, get its data or cancel it").addHelpText("after",y([...$t(t).slice(0,2),lr(t)[0],mo(t)[0],re(t)[0]])).showHelpAfterError("(add --help for additional information)").addCommand(ur(t)).addCommand(Fu(t)).addCommand(uo(t)).addCommand(Ve(t));var ie=require("@commander-js/extra-typings");var fr="session",Kt=t=>{let e=`${t} ${fr} start --api-key <api-key> --project-id <id> --title "Checkout fails on empty cart" --status failed`,r=`${t} ${fr} attach before.png .playwright-mcp/traces`,o=`${t} ${fr} share --expires-in-days 7`;return{session:[{comment:"Start a session, attach what you captured and get a link to share",commands:[e,r,o]}],start:[{comment:"Start a session for a failed check",commands:[e]}],attach:[{comment:"Attach a screenshot and a Playwright MCP trace folder",commands:[r]}],share:[{comment:"Print a link that expires in 7 days",commands:[o]}]}},Mu=t=>new ie.Command().name("start").addHelpText("after",y(Kt(t).start)).summary("Create a session").description('Create a session and save its ID to .currents-session/session.json in the current folder, where "attach" and "share" read it').addOption(M(Mt)).addOption(ct(kt)).addOption(tt()).addOption(Ec).addOption(Ic).addOption(Cc).addOption(Tc).addOption(yc).addOption(Rc).addOption(b()).action(async e=>{await w(async({key:r,...o})=>{o.json&&bt(),await dc(Ba({...o,recordKey:r}))},e)}),ku=t=>new ie.Command().name("attach").summary("Upload screenshots, traces and other files").addHelpText("after",y(Kt(t).attach)).description("Upload files, folders or a Playwright MCP trace folder to the session").argument("<paths...>",ar).addOption(M(Mt)).addOption(ct(kt)).addOption(Po).addOption(Dc).addOption(cr).addOption(pr).addOption(b()).action(async(e,r)=>{await w(async({key:o,...n})=>{await mc(Fa({...n,recordKey:o}),e)},r)}),ju=t=>new ie.Command().name("share").addHelpText("after",y(Kt(t).share)).summary("Print a public link to the session page").description('Create a public link to the session page and print it. The second line, "Markdown: <url>", is the address of the same content as Markdown, for agents').addOption(M(Mt)).addOption(ct(kt)).addOption(Po).addOption(Pc).addOption(b()).action(async e=>{await w(async({key:r,...o})=>{await uc(Ma({...o,recordKey:r}))},e)}),Jc=t=>new ie.Command().name(fr).summary("Capture agent or browser sessions as evidence").description("Capture ad-hoc, one-off agent or browser sessions as evidence: a bug before and after a fix, or proof that something works. Create a session, attach screenshots, traces, videos and other files to it, and print a link to share it.").addHelpText("after",y(Kt(t).session)).showHelpAfterError("(add --help for additional information)").addCommand(Mu(t)).addCommand(ku(t)).addCommand(ju(t));var Jt=require("@commander-js/extra-typings");var et=l(require("fs-extra")),G=l(require("path")),pt="currents-cli",Ht=G.default.join(".agents","skills");function Vc(t=__dirname){let e=t;for(;;){let r=G.default.join(e,"skills",pt);if(et.default.existsSync(G.default.join(r,"SKILL.md")))return r;let o=G.default.dirname(e);if(o===e)throw new Error(`The ${pt} skill is missing from this package`);e=o}}async function Bo(t,e=""){let r=[];for(let o of await et.default.readdir(G.default.join(t,e),{withFileTypes:!0})){let n=G.default.join(e,o.name);o.isDirectory()?r.push(...await Bo(t,n)):r.push(n)}return r.sort()}async function Gu(t,e){let[r,o]=await Promise.all([Bo(t),Bo(e)]);if(r.join(`
54
+ reports being converted.`).addHelpText("after",y(Kt(t))).addOption($c).addOption(M()).addOption(tt()).addOption(Gc).addOption(Kc).addOption(Hc).addOption(Jc).addOption(b()).addOption(Vc).addOption(er()).addOption(rr(Qc)).addOption(nr(Qc)).addOption(sr).addOption(or).action(r=>zc(r));var ko="run",hr=t=>[{comment:"Attach the Docker logs of a CI machine to the run, after the tests finished",commands:[`${t} ${ko} attach --key <record-key> --project-id <id> --ci-build-id <build-id> --machine-id shard-1 docker-logs.zip`]},{comment:"Attach a screenshot to the first attempt of a test",commands:[`${t} ${ko} attach --key <record-key> --project-id <id> --ci-build-id <build-id> --spec tests/cart.spec.ts --test-title "adds an item" --attempt 0 screenshot.png`]}],zu=t=>new jo.Command().name("attach").addHelpText("after",y(hr(t))).description("Upload files to a run recorded in CI").argument("<paths...>",dr).addOption(M(kt)).addOption(at(jt)).addOption(tt()).addOption(_c).addOption(Oc).addOption(bc).addOption(Lc).addOption(Nc).addOption(vc).addOption(kc).addOption(mr).addOption(ur).addOption(b()).action(async(e,r)=>{await R(async({key:o,...n})=>{await Rc(Wa({...n,recordKey:o}),e)},r)}),Zc=t=>new jo.Command().name(ko).summary("Upload test results, attach files, get or cancel a run").description("Upload test results to a run, attach files to it, get its data or cancel it").addHelpText("after",y([...Kt(t).slice(0,2),hr(t)[0],fo(t)[0],oe(t)[0]])).showHelpAfterError("(add --help for additional information)").addCommand(gr(t)).addCommand(zu(t)).addCommand(go(t)).addCommand(We(t));var ae=require("@commander-js/extra-typings");var Er="session",Ht=t=>{let e=`${t} ${Er} start --api-key <api-key> --project-id <id> --title "Checkout fails on empty cart" --status failed`,r=`${t} ${Er} attach before.png .playwright-mcp/traces`,o=`${t} ${Er} share --expires-in-days 7`;return{session:[{comment:"Start a session, attach what you captured and get a link to share",commands:[e,r,o]}],start:[{comment:"Start a session for a failed check",commands:[e]}],attach:[{comment:"Attach a screenshot and a Playwright MCP trace folder",commands:[r]}],share:[{comment:"Print a link that expires in 7 days",commands:[o]}]}},Qu=t=>new ae.Command().name("start").addHelpText("after",y(Ht(t).start)).summary("Create a session").description('Create a session and save its ID to .currents-session/session.json in the current folder, where "attach" and "share" read it').addOption(M(kt)).addOption(at(jt)).addOption(tt()).addOption(xc).addOption(Sc).addOption(Ac).addOption(Dc).addOption(Uc).addOption(Pc).addOption(b()).action(async e=>{await R(async({key:r,...o})=>{o.json&&Nt(),await Cc(Ja({...o,recordKey:r}))},e)}),Xu=t=>new ae.Command().name("attach").summary("Upload screenshots, traces and other files").addHelpText("after",y(Ht(t).attach)).description("Upload files, folders or a Playwright MCP trace folder to the session").argument("<paths...>",dr).addOption(M(kt)).addOption(at(jt)).addOption(Bo).addOption(Mc).addOption(mr).addOption(ur).addOption(b()).action(async(e,r)=>{await R(async({key:o,...n})=>{await Tc(Va({...n,recordKey:o}),e)},r)}),Zu=t=>new ae.Command().name("share").addHelpText("after",y(Ht(t).share)).summary("Print a public link to the session page").description('Create a public link to the session page and print it. The second line, "Markdown: <url>", is the address of the same content as Markdown, for agents').addOption(M(kt)).addOption(at(jt)).addOption(Bo).addOption(jc).addOption(b()).action(async e=>{await R(async({key:r,...o})=>{await yc(Ya({...o,recordKey:r}))},e)}),tp=t=>new ae.Command().name(Er).summary("Capture agent or browser sessions as evidence").description("Capture ad-hoc, one-off agent or browser sessions as evidence: a bug before and after a fix, or proof that something works. Create a session, attach screenshots, traces, videos and other files to it, and print a link to share it.").addHelpText("after",y(Ht(t).session)).showHelpAfterError("(add --help for additional information)").addCommand(Qu(t)).addCommand(Xu(t)).addCommand(Zu(t));var Vt=require("@commander-js/extra-typings");var ct=l(require("fs-extra")),$=l(require("path"));var pt="currents-cli",Jt=$.default.join(".agents","skills");function ep(t=__dirname){let e=$.default.join("skills",pt),r=le($.default.join(e,"SKILL.md"),t);if(!r)throw new Error(`The ${pt} skill is missing from this package`);return $.default.join(r,e)}async function $o(t,e=""){let r=[];for(let o of await ct.default.readdir($.default.join(t,e),{withFileTypes:!0})){let n=$.default.join(e,o.name);o.isDirectory()?r.push(...await $o(t,n)):r.push(n)}return r.sort()}async function tl(t,e){let[r,o]=await Promise.all([$o(t),$o(e)]);if(r.join(`
50
55
  `)!==o.join(`
51
- `))return!1;for(let n of r){let[s,i]=await Promise.all([et.default.readFile(G.default.join(t,n)),et.default.readFile(G.default.join(e,n))]);if(!s.equals(i))return!1}return!0}async function Yc(){let t=await et.default.readFile(G.default.join(Vc(),"SKILL.md"),"utf8");await new Promise((e,r)=>process.stdout.write(t,o=>o?r(o):e()))}async function Wc({dir:t=Ht,force:e=!1}){let r=Vc(),o=G.default.resolve(t,pt),n=G.default.relative(process.cwd(),o)||".";if(await et.default.pathExists(o)){if(!(await et.default.stat(o)).isDirectory())throw new Error(`${n} exists and is not a folder`);if(await Gu(r,o))return T("The %s skill is already in %s",pt,n),o;if(!e)throw new Error(`${n} exists and differs from the skill of this version. Pass --force to replace it`);await et.default.remove(o)}return await et.default.copy(r,o),T("Wrote the %s skill to %s",pt,n),o}var gr="skill",$u=t=>[{comment:"Print the skill",commands:[`${t} ${gr}`]},{comment:`Add the skill to the project, in ${Ht}/${pt}`,commands:[`${t} ${gr} --install`]},{comment:"Add the skill for Claude Code",commands:[`${t} ${gr} --install --dir .claude/skills`]}],qc=t=>new Jt.Command().name(gr).summary("Print or install the agent skill for this CLI").description(`Print SKILL.md of the ${pt} skill, which tells coding agents how to use this CLI, or install the skill in the project. Install it to get the reference files too.
56
+ `))return!1;for(let n of r){let[s,i]=await Promise.all([ct.default.readFile($.default.join(t,n)),ct.default.readFile($.default.join(e,n))]);if(!s.equals(i))return!1}return!0}async function rp(){await Qt(await ct.default.readFile($.default.join(ep(),"SKILL.md"),"utf8"))}async function op({dir:t=Jt,force:e=!1}){let r=ep(),o=$.default.resolve(t,pt),n=$.default.relative(process.cwd(),o)||".";if(await ct.default.pathExists(o)){if(!(await ct.default.stat(o)).isDirectory())throw new Error(`${n} exists and is not a folder`);if(await tl(r,o))return T("The %s skill is already in %s",pt,n),o;if(!e)throw new Error(`${n} exists and differs from the skill of this version. Pass --force to replace it`);await ct.default.remove(o)}return await ct.default.copy(r,o),T("Wrote the %s skill to %s",pt,n),o}var Ir="skill",el=t=>[{comment:"Print the skill",commands:[`${t} ${Ir}`]},{comment:`Add the skill to the project, in ${Jt}/${pt}`,commands:[`${t} ${Ir} --install`]},{comment:"Add the skill for Claude Code",commands:[`${t} ${Ir} --install --dir .claude/skills`]}],np=t=>new Vt.Command().name(Ir).summary("Print or install the agent skill for this CLI").description(`Print SKILL.md of the ${pt} skill, which tells coding agents how to use this CLI, or install the skill in the project.
52
57
 
53
58
  Agents read project skills from these folders:
54
- Codex, Cursor ${Ht}
55
- Claude Code .claude/skills`).addHelpText("after",y($u(t))).addOption(new Jt.Option("--install",`write the skill folder to <dir>/${pt}`)).addOption(new Jt.Option("--dir <path>","the skills folder to install to").default(Ht)).addOption(new Jt.Option("--force","replace an installed copy of the skill that differs from this version")).action(async e=>{await w(async r=>{if(!r.install&&(r.force||r.dir!==Ht))throw new Error("--dir and --force work with --install only");r.install?await Wc({dir:r.dir,force:r.force}):await Yc()},e)});var O="currents",Qc=()=>{let t=ur(O),e=new zc.Command(O).version(St).description("Currents CLI: upload test results and files to Currents, get and cancel runs, capture agent or browser sessions as evidence, and cache files between CI jobs").showHelpAfterError(`(run '${O} --help' for usage)`).enablePositionalOptions().hook("preAction",(i,c)=>{vn(c),Bn(c)}).addCommand(t,{hidden:!0}).addCommand(va(O),{hidden:!0}).addCommand(Ve(O,{deprecated:!0}),{hidden:!0}).commandsGroup("Test runs:").addCommand(Hc(O)).commandsGroup("Evidence:").addCommand(Jc(O)).commandsGroup("CI utilities:").addCommand(aa(O)).commandsGroup("Other:").addCommand(na(O)).addCommand(qc(O)).helpCommand(!0).addHelpText("after",`${y([$t(O)[0],$t(O)[1],Ke(O)[1],He(O)[1],re(O)[0],lr(O)[0],...Kt(O).session])}
59
+ Codex, Cursor ${Jt}
60
+ Claude Code .claude/skills`).addHelpText("after",y(el(t))).addOption(new Vt.Option("--install",`write the skill folder to <dir>/${pt}`)).addOption(new Vt.Option("--dir <path>","the skills folder to install to").default(Jt)).addOption(new Vt.Option("--force","replace an installed copy of the skill that differs from this version")).action(async e=>{await R(async r=>{if(!r.install&&(r.force||r.dir!==Jt))throw new Error("--dir and --force work with --install only");r.install?await op({dir:r.dir,force:r.force}):await rp()},e)});var O="currents",ip=()=>{let t=gr(O),e=new sp.Command(O).version(At).description("Currents CLI: upload test results and files to Currents, get and cancel runs, capture agent or browser sessions as evidence, and cache files between CI jobs").showHelpAfterError(`(run '${O} --help' for usage)`).enablePositionalOptions().hook("preAction",(i,c)=>{jn(c),$n(c)}).addCommand(t,{hidden:!0}).addCommand(ja(O),{hidden:!0}).addCommand(We(O,{deprecated:!0}),{hidden:!0}).commandsGroup("Test runs:").addCommand(Zc(O)).commandsGroup("Evidence:").addCommand(tp(O)).commandsGroup("CI utilities:").addCommand(ua(O)).commandsGroup("Other:").addCommand(pa(O)).addCommand(Ha(O)).addCommand(np(O)).helpCommand(!0).addHelpText("after",`${y([Kt(O)[0],Kt(O)[1],Je(O)[1],Ve(O)[1],oe(O)[0],hr(O)[0],...Ht(O).session])}
56
61
  Run '${O} <command> --help' for the options and examples of a command.
57
62
 
58
63
  Agent skill: ${O} skill --install
59
64
  Documentation: https://docs.currents.dev
60
65
  Support: support@currents.dev
61
66
  `),r=`upload is no longer the default command. Run '${O} run upload ...' instead.`,o=t.options.flatMap(i=>[i.long,i.short]),n=e,s=n.unknownOption.bind(e);return n.unknownOption=i=>{if(!o.includes(i.split("=")[0]))return s(i);e.error(r)},e.addHelpText("before",({error:i})=>i&&(process.env.CURRENTS_RECORD_KEY||process.env.CURRENTS_PROJECT_ID)?`error: ${r}
62
- `:""),e};import("dotenv/config");function Ku(){Qc().parse()}Ku();
67
+ `:""),e};import("dotenv/config");function rl(){ip().parse()}rl();
63
68
  /*! For license information please see index.js.LEGAL.txt */
64
69
  //# sourceMappingURL=index.js.map