@currents/cmd 2.1.0 → 2.3.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/README.md +22 -1
- package/dist/bin/index.js +49 -41
- package/dist/index.js +9 -8
- package/dist/skills/currents-cli/SKILL.md +22 -104
- package/{dist/skills/currents-cli/references → docs}/ci-setup.md +12 -1
- package/{dist/skills/currents-cli/references → docs}/sessions.md +4 -0
- package/package.json +3 -1
package/dist/bin/index.js
CHANGED
|
@@ -1,64 +1,72 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
-
"use strict";var
|
|
3
|
-
`)),
|
|
2
|
+
"use strict";var Dp=Object.create;var Pr=Object.defineProperty;var Up=Object.getOwnPropertyDescriptor;var bp=Object.getOwnPropertyNames;var Np=Object.getPrototypeOf,vp=Object.prototype.hasOwnProperty;var Lp=(t,e)=>{for(var r in e)Pr(t,r,{get:e[r],enumerable:!0})},Bp=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of bp(e))!vp.call(t,o)&&o!==r&&Pr(t,o,{get:()=>e[o],enumerable:!(n=Up(e,o))||n.enumerable});return t};var f=(t,e,r)=>(r=t!=null?Dp(Np(t)):{},Bp(e||!t||!t.__esModule?Pr(r,"default",{value:t,enumerable:!0}):r,t));var tS=require("source-map-support/register");var Ap=require("@commander-js/extra-typings");var zn={name:"@currents/cmd",version:"2.3.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","@currents/rules":"^0.1.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 bt=zn.version;var yn=require("@commander-js/extra-typings");var Mp=[];function Dr(t){Mp.push(t)}var v=f(require("chalk")),Z=f(require("util"));var Ur=require("debug"),kp=f(require("fs-extra")),p=(0,Ur.debug)("currents"),jp=null;function Qn(){Ur.debug.enable("currents,currents:*")}function Xn(t){jp=t}var Zn=[],to=[];var ge=(...t)=>{let e=Z.default.format(...t);Dr(e),console.log(e)},eo=(...t)=>{let e=Z.default.format(...t);Dr(e),console.error(e)},T=ge,I=(...t)=>{let e=Z.default.format(...t);return to.push(e),p("WARNING: ",e),ge(v.default.bgYellow.black(" WARNING "),e)},Ct=(...t)=>{let e=Z.default.format(...ro(t));return p("WARNING: ",Z.default.format(...t)),ge(v.default.bgYellow.black(" WARNING "),e)},he=(...t)=>eo(v.default.bgYellow.black(" WARNING "),Z.default.format(...t)),Ie=(...t)=>ge(v.default.green.bold(Z.default.format(...t))),C=(...t)=>{let e=Z.default.format(...ro(t));return Zn.push(e),p("ERROR: ",Z.default.format(...t)),eo(v.default.bgRed.white(" ERROR "),e)};var ro=t=>t.map(e=>e instanceof Error?e.message:e),Ee=(t=2)=>console.log(Array(t).fill("").join(`
|
|
3
|
+
`)),nf=v.default.cyan,of=v.default.blueBright,sf=v.default.red,af=v.default.yellow,cf=v.default.green,pf=v.default.gray,df=v.default.white,uf=v.default.black,mf=v.default.magenta,S=v.default.dim,lf=v.default.bold;var no=80,br=" ",Gp=" ";function Kp(t){let e=t.match(/"[^"]*"|'[^']*'|\S+/g)??[],r=[];for(let n of e){let o=r[r.length-1];o?.startsWith("-")&&!o.includes(" ")&&!n.startsWith("-")?r[r.length-1]=`${o} ${n}`:r.push(n)}return r}function Hp(t){if(t.includes(`
|
|
4
4
|
`))return t.split(`
|
|
5
|
-
`).map(
|
|
5
|
+
`).map(n=>br+n);let e=[],r=br;for(let n of Kp(t)){let o=r.trim()==="";!o&&r.length+1+n.length+2>no?(e.push(`${r} \\`),r=Gp+n):r=o?r+n:`${r} ${n}`}return[...e,r]}function Jp(t){let e=`${br}# `,r=[],n=e;for(let o of t.split(" "))n!==e&&n.length+1+o.length>no?(r.push(n),n=e+o):n=n===e?n+o:`${n} ${o}`;return[...r,n].map(o=>S(o))}function y(t){return`
|
|
6
6
|
Examples:
|
|
7
|
-
${t.map(r=>[...
|
|
7
|
+
${t.map(r=>[...Jp(r.comment),...r.commands.flatMap(Hp)].join(`
|
|
8
8
|
`)).join(`
|
|
9
9
|
|
|
10
10
|
`)}
|
|
11
|
-
`}var
|
|
12
|
-
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status,payload:t.response?.config.data})})}function
|
|
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,()=>{
|
|
14
|
-
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}function
|
|
15
|
-
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}var
|
|
11
|
+
`}var Nr=f(require("lodash")),Vp=["apiKey","recordKey","key"];function oo(t,e){return Nr.default.isPlainObject(t)?Nr.default.mapValues(t,(r,n)=>e.includes(n)&&r!==void 0?"*****":oo(r,e)):t}function E(t){return oo(t,Vp)}var tt=class extends Error{};var Y=f(require("fs-extra")),Tt=require("path"),so=require("uuid");async function yt(t){try{return await Y.default.readJson(t)}catch(e){throw C("Error while reading JSON file: %s",t,e),C}}async function Rt(t,e){try{return await Y.default.writeFile(t,e,"utf8"),t}catch(r){throw C(`Error writing file at ${t}:`,r),r}}async function wt(t,e){try{try{return await Y.default.access(t),t}catch{return await Y.default.writeFile(t,e,"utf8"),t}}catch(r){throw C(`Error writing file at ${t}:`,r),r}}async function io(t,e){if(e){await Y.default.ensureDir(t);return}let r=(0,Tt.dirname)(t);await Y.default.ensureDir(r)}function Yp(){let t=new Date().toISOString().replace(/[:.]/g,"-"),e=(0,so.v4)();return`${t}-${e}`}async function ao(t,e){let r=Yp(),n=(0,Tt.join)(t,e,r);return _t(n)}async function _t(t){try{return await Y.default.ensureDir(t),p("Folder created",t),t}catch(e){throw C(`Failed to create folder at ${t}:`,e),e}}async function Ce(t,e){try{return await Y.default.ensureDir((0,Tt.dirname)(e)),await Y.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 Te(t,e){let r=e;for(;!Y.default.existsSync((0,Tt.join)(r,t));){let n=(0,Tt.dirname)(r);if(n===r)return;r=n}return r}var co=f(require("crypto"));function W(t){return co.createHash("sha256").update(t).digest("base64").slice(0,8).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var ye={};Lp(ye,{getNanoid:()=>Lr,userFacingNanoid:()=>Br});var vr=require("nanoid"),po="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Lr=(t=16)=>(0,vr.customAlphabet)(po,t)(),Br=(0,vr.customAlphabet)(po,12);function Fr(t){return t.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^/?#\s]*@/i,"$1")}function Nt(t){return Fr(t).replace(/[?#].*$/,"")}function Wp(t){return Object.entries(t??{}).reduce((e,[r,n])=>n===void 0?e:{...e,[r]:n},{})}function uo(t){if(!(t===void 0||t.trim()===""))return!["false","0","no","off"].includes(t.trim().toLowerCase())}function P(t,e){return"env"in t[e]&&t[e].env?t[e].env:""}function Re(t,e){return t[e].cli}function we(t,e){return t[e].name}function U(t,e,r,n){let o=Wp(r);return e.forEach(s=>{if(!o[s]){let i=s,a=P(t,i);throw C(`${we(t,i)} is required: pass ${S(Re(t,i))}${a?` or set ${S(a)}`:""}`),new tt("Missing required config variable")}}),typeof n=="function"&&n(o),o}var O={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:qp,debug:zp,ciBuildId:Qp,projectId:Xp,tag:Zp}=O,_e={apiKey:qp,debug:zp,ciBuildId:Qp,projectId:Xp,tag:Zp,branch:{name:"Branch",cli:"--branch"},output:{name:"Output file",env:"CURRENTS_OUTPUT",cli:"--output"}};var td=p.extend("config"),ed=["apiKey","projectId"],rd=t=>{let{ciBuildId:e,tag:r,branch:n}=t;if(!([e,r,n].filter(Boolean).length===1||r&&n&&!e))throw C("Pass --ci-build-id, or --branch, --tag or both"),new tt("Missing or invalid parameters")},Mr=null;function mo(t){Mr=U(_e,ed,t,rd),td("Resolved config: %o",E(Mr))}function Oe(){return Mr}var Yo=require("fs/promises");function vt({apiKey:t,recordKey:e}){return e?{"x-currents-key":e}:t?{Authorization:`Bearer ${t}`}:{}}var Po=f(require("lodash"));var yo=f(require("axios")),Ro=f(require("axios-retry")),Kr=f(require("lodash"));var lo=()=>process.env.CURRENTS_API_URL??"https://cy.currents.dev",Qt=()=>process.env.CURRENTS_REST_API_URL??"https://api.currents.dev",fo=()=>3e4;var xe=require("axios"),kr=f(require("pretty-ms"));var ho=p.extend("http"),go=[3*1e3,15*1e3,30*1e3],Io=60*1e3;function Pe(t,e=Date.now()){let r=t?.response?.headers?.["retry-after"];if(r==null||r==="")return;let n=Number(r);if(Number.isFinite(n))return Math.max(0,n*1e3);let o=Date.parse(String(r));return Number.isNaN(o)?void 0:Math.max(0,o-e)}var Ae=(t,e)=>{let r=go[Math.min(t,go.length)-1],n=Pe(e);return n===void 0?r:Math.min(Math.max(n,r),Io)},jr=t=>(ho("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,xe.isAxiosError)(t)}),"code"in t&&t.code&&["ECONNABORTED","ECONNREFUSED","ECONNRESET","ETIMEDOUT","ENETRESET"].includes(t.code)?!0:(0,xe.isAxiosError)(t)?[408,429,502,503,504].includes(t.response?.status??0):!1),nd=["get","head","options","put","delete"],Eo=t=>{if(!(0,xe.isAxiosError)(t))return!1;let e=t.response?.status;if(e===429){let r=Pe(t);return r===void 0||r<=Io}return nd.includes(t.config?.method?.toLowerCase()??"get")?jr(t):e===408||t.code==="ECONNREFUSED"||t.code==="ENOTFOUND"},Se=()=>3;function Co(t,e,r){ho("Network request '%s' failed: '%s'. Next attempt is in %s (%d/%d).",`${r.method?.toUpperCase()} ${r.url}`,e.message,(0,kr.default)(Ae(t,e)??0),t,Se()),I("Network request '%s' failed: '%s'. Next attempt is in %s (%d/%d).",`${r.method?.toUpperCase()} ${r.url}`,e.message,(0,kr.default)(Ae(t,e)??0),t,Se())}var $r=p.extend("http");var Gr={api:null,restApi:null};function od(t){let e=t==="api"?lo():Qt();$r("client base url: %s",e);let r=yo.default.create({baseURL:e,timeout:fo(),transitional:{clarifyTimeoutError:!0}});return r.interceptors.request.use(n=>{let o=n["axios-retry"]?.retryCount??0;n.headers.set({"x-cmd-version":bt}),n.headers.get("Content-Type")||n.headers.set("Content-Type","application/json");let s={...Kr.default.pick(n,"method","url","headers"),baseURL:e,data:Buffer.isBuffer(n.data)?"buffer":n.data,params:n.params};return o?$r("network request retry: %o",To({...s,baseURL:e,isRetry:!0})):$r("network request: %o",To(s)),n}),(0,Ro.default)(r,{retries:Se(),retryCondition:t==="restApi"?Eo:jr,retryDelay:(n,o)=>Ae(n,o),shouldResetTimeout:!0,onRetry:Co}),r}function Lt(t){return Gr[t]===null&&(Gr[t]=od(t)),Gr[t]}function To(t){return{method:t.method,baseURL:t.baseURL,url:t.url,data:t.isRetry?"<retry>":sd(t.data),params:t.isRetry?"<retry>":t.params,headers:{...t.headers,Authorization:"Bearer ***","x-currents-key":"***"}}}function sd(t){if(t?.results?.raw)return E({...t,results:{...t.results,raw:"***"}});if(typeof t=="string")try{return E(JSON.parse(t))}catch{return t}return Kr.default.isPlainObject(t)?E(t):t}var Oo=require("axios"),xo=f(require("lodash")),F=require("ts-pattern");function Ao(t){(0,F.match)(t).when(Oo.isAxiosError,id).otherwise(()=>{I("Unexpected error while sending network request: %s",t)})}function id(t){return(0,F.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:F.P.not(F.P.nullish)},e=>{ad(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 ad(t,{status:e,data:r}){(0,F.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,()=>{cd(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 cd(t,e){(0,F.match)(e).with({code:wo.MISSING_SUITE,message:F.P.string,errors:F.P.array(F.P.string)},async r=>{let{message:n,errors:o}=r;Ee(1),C(..._o(n,o))}).with({code:wo.RUN_EXPIRED,message:F.P.string},r=>{I(r.message)}).with({message:F.P.string,errors:F.P.array(F.P.string)},r=>{let{message:n,errors:o}=r;Ee(1),I(..._o(n,o)),Ee(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 wo={RUN_CANCELLED:"RUN_CANCELLED",RUN_EXPIRED:"RUN_EXPIRED",MISSING_SUITE:"MISSING_SUITE"};function _o(t,e){return xo.default.isString(t)?e?.length===0?[t]:[t,`
|
|
16
16
|
${(e??[]).map(r=>` - ${r}`).join(`
|
|
17
17
|
`)}
|
|
18
|
-
`]:["Unexpected network error"]}var
|
|
18
|
+
`]:["Unexpected network error"]}var So=p.extend("http");async function H(t,e,r=Lt){try{let n=await r(t).request(e);return So("network response: %o",{...Po.default.omit(n,"request","config"),url:n.config.url,method:n.config.method}),n}catch(n){let o=n;throw So("network error: %o",{code:o.code,message:o.message,url:o.config?.url,method:o.config?.method,status:o.response?.status,headers:o.response?.headers,data:o.response?.data}),Ao(o),o}}var Bt=p.extend("api");async function Do(t){try{return Bt("Request params: %o",E(t)),H("api",{url:"cache/upload",method:"POST",data:t}).then(e=>e.data)}catch(e){throw Bt("Failed to create cache:",e),e}}async function Uo(t){try{return Bt("Request params: %o",E(t)),H("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 bo(t){try{return Bt("Request params: %o",E(t)),H("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 pd=p.extend("api");async function No(t){return pd("Cancel params: %o",E(t)),(await H("api",{url:"v1/runs/cancel",method:"POST",data:t})).data}var Lo=require("util"),Bo=require("zlib");var vo=p.extend("api"),dd=(0,Lo.promisify)(Bo.gzip);async function Fo(t){try{vo("Run params: %o",E(t));let e=await ud(JSON.stringify(t));return H("api",{url:"v1/runs",method:"POST",headers:{"Content-Type":"application/json","Content-Encoding":"gzip"},data:e}).then(r=>r.data)}catch(e){throw vo("Failed to create the run:",e),e}}async function ud(t){try{return await dd(t)}catch(e){throw C("Failed to compress run payload:",e),e}}var Mo=p.extend("api");async function ko(t,e){try{return Mo("Run params: %o",e),H("restApi",{url:"v1/runs/find",params:e,method:"GET",headers:{"Content-Type":"application/json",...vt({apiKey:t})}}).then(r=>r.data)}catch(r){throw Mo("Failed to obtain run data:",r),r}}function jo(t,e){return Lt("restApi").request({...e,headers:{...vt({apiKey:t}),...e.headers},responseType:"text",transformResponse:r=>r})}var md=p.extend("api");async function $o(t,e){try{return await H("api",{url:`rules/project/${encodeURIComponent(t)}`,method:"GET",headers:{"x-currents-key":e}}).then(r=>r.data.rules)}catch(r){throw md("Failed to get the project actions:",r),r}}var Go=require("axios");var Ko=p.extend("api");function ld(t){if(!(0,Go.isAxiosError)(t)||!t.response)return t;let e=t.response.data,r=[`${t.response.status}`];e?.code&&r.push(e.code);let n=e?.error??t.message,o=Pe(t),s=o?` Retry in ${Math.ceil(o/1e3)} seconds.`:"",i=fd(e?.candidates);return new Error(`${r.join(" ")}: ${n}${s}${i}`)}function fd(t){return!Array.isArray(t)||t.length===0?"":`
|
|
19
19
|
Matches:
|
|
20
|
-
${t.map(({spec:r,title:
|
|
21
|
-
`)}`}async function
|
|
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}"
|
|
23
|
-
EXTRA_PWCP_FLAGS="${
|
|
20
|
+
${t.map(({spec:r,title:n,instanceId:o,testId:s,runId:i,ciBuildId:a})=>i?` - run ${i} (CI build ID ${a})`:` - ${[r,n].filter(Boolean).join(" > ")} (instance ${o}${s?`, test ${s}`:""})`).join(`
|
|
21
|
+
`)}`}async function Xt(t,e,r){try{return(await Lt("restApi").post(t,r,{headers:vt(e)})).data.data}catch(n){throw ld(n)}}function Ho(t,e){return Ko("Create session params: %o",e),Xt("v1/sessions",t,e)}function Jo(t,e,r,n){return Ko("Create attachments: %o",{owner:e,target:r,attachments:n}),"sessionId"in e?Xt(`v1/sessions/${encodeURIComponent(e.sessionId)}/attachments`,t,{attachments:n}):"runId"in e?Xt(`v1/runs/${encodeURIComponent(e.runId)}/attachments`,t,{...r,attachments:n}):Xt("v1/runs/attachments",t,{...e,...r,attachments:n})}function Vo(t,e){return Xt("v1/share",t,e)}async function Hr(){try{let t=Oe();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 ko(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 gd(t.pwLastRun?r.data.pwLastRun:r.data,t)}catch(t){throw p("Failed to get run data"),t}}async function gd(t,e){let r=JSON.stringify(t,null,2);e.output?(await io(e.output),await(0,Yo.writeFile)(e.output,r,"utf-8"),T(`Successfully written to ${e.output}`)):process.stdout.write(r+`
|
|
22
|
+
`)}var Hs=require("axios"),rn=f(require("path"));var M=require("@commander-js/extra-typings");var Wo=require("@commander-js/extra-typings");function De(t,e=[]){return t?e.concat(t.split(",").map(r=>r.trim())):e}function qo(t){for(let e of t.options){let r=e.attributeName();if(!e.envVar||!e.isBoolean()||t.getOptionValueSource(r)!=="env")continue;let n=uo(process.env[e.envVar]);t.setOptionValueWithSource(r,n??e.defaultValue,n===void 0?"default":"env")}}function hd(t,e){if(!Array.isArray(t))return String(t)===e;let r=n=>n.map(o=>o.trim()).filter(Boolean).join(",");return r(t.map(String))===r(e.split(","))}function zo(t){for(let e of t.options){let r=e.attributeName(),n=e.envVar?process.env[e.envVar]:void 0,o=t.getOptionValue(r);!n||e.isBoolean()||t.getOptionValueSource(r)!=="cli"||hd(o,n)||he(`${e.long} and ${e.envVar} are set to different values; using ${e.long}`)}}function Mt(){console.log=(...t)=>console.error(...t)}async function R(t,e){try{e.debug&&Qn(),await t(e),process.exit(0)}catch(r){C(r.message);let n=r instanceof Wo.CommanderError?r.exitCode:1;process.exit(n)}}function Zt(t){return new Promise((e,r)=>process.stdout.write(t,n=>n?r(n):e()))}var Qo="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",Xo=new M.Option("--id <id>",`the ID to save the files under. ${Qo}`),Zo=new M.Option("--id <id>",`the ID the files were saved under. ${Qo}`),ts=new M.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(De),te=(e=>(e.lastRun="last-run",e))(te||{}),es=new M.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(te)),rs=new M.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(te)),ns=new M.Option("--output-dir <folder>","the folder to restore the files to; by default the current folder"),os=new M.Option("--pw-output-dir <folder>","the Playwright output folder that holds .last-run.json").default("test-results"),ee=".currents_env",ss=new M.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(ee),Jr=new M.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(is),Vr=new M.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(is);function is(t){let e=parseInt(t,10);if(isNaN(e)||e<=0||!Number.isInteger(e))throw new M.InvalidArgumentError("A positive integer is expected.");return e}var as=new M.Option("--continue","exit with 0 when the cache is not found").default(!1),cs=new M.Option("--continue","exit with 0 when no files are found, and save the cache without files").default(!1);var Id={recordKey:O.recordKey,debug:O.debug},Ed={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"}},Cd={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"}},Yr={...Id,...Ed,...Cd};var ps=p.extend("config"),ds=["recordKey"],Ot;function us(t){Ot={type:"SET_COMMAND_CONFIG",values:U(Yr,ds,t)},ps("Resolved config: %o",{...Ot,values:E(Ot.values)})}function ms(t){Ot={type:"GET_COMMAND_CONFIG",values:U(Yr,ds,t)},ps("Resolved config: %o",{...Ot,values:E(Ot.values)})}function mt(){return Ot}function ls(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 fs(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 Ue=p.extend("ci"),Td=(t,e)=>(0,w.set)(t,(0,w.camelCase)(e),process.env[e]),b=t=>(0,w.transform)(t,Td,{}),yd=()=>process.env.TF_BUILD&&process.env.AZURE_HTTP_USER_AGENT,Rd=()=>(0,w.some)(process.env,(t,e)=>/^CODEBUILD_/.test(e)),wd=()=>process.env.bamboo_buildNumber,_d=()=>(0,w.some)(process.env,(t,e)=>/^CONCOURSE_/.test(e)),Od=()=>process.env.GITLAB_CI||process.env.CI_SERVER_NAME&&/^GitLab/.test(process.env.CI_SERVER_NAME),xd=()=>!!(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),Ad=()=>process.env.JENKINS_URL||process.env.JENKINS_HOME||process.env.JENKINS_VERSION||process.env.HUDSON_URL||process.env.HUDSON_HOME,Sd={appveyor:"APPVEYOR",azure:yd,awsCodeBuild:Rd,bamboo:wd,bitbucket:"BITBUCKET_BUILD_NUMBER",buildkite:"BUILDKITE",circle:"CIRCLECI",concourse:_d,codeFresh:"CF_BUILD_ID",drone:"DRONE",githubActions:"GITHUB_ACTIONS",gitlab:Od,goCD:"GO_JOB_NAME",jenkins:Ad,googleCloud:xd,semaphore:"SEMAPHORE",teamcity:"TEAMCITY_VERSION",travis:"TRAVIS",netlify:"NETLIFY"};function Pd(){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 gs=()=>({appveyor:b(["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:b(["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:b(["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:b(["bamboo_buildNumber","bamboo_buildResultsUrl","bamboo_planRepository_repositoryUrl","bamboo_buildKey"]),bitbucket:b(["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:b(["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:b(["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:b(["BUILD_ID","BUILD_NAME","BUILD_JOB_NAME","BUILD_PIPELINE_NAME","BUILD_TEAM_NAME","ATC_EXTERNAL_URL"]),codeFresh:b(["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:b(["DRONE_BUILD_LINK","DRONE_BUILD_NUMBER","DRONE_PULL_REQUEST"]),githubActions:b(["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:b(["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:b(["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:b(["BUILD_ID","PROJECT_ID","REPO_NAME","BRANCH_NAME","TAG_NAME","COMMIT_SHA","SHORT_SHA"]),jenkins:b(["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:b(["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:b(["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:b(["BUILD_ID","CONTEXT","URL","DEPLOY_URL","DEPLOY_PRIME_URL","DEPLOY_ID"])}),Dd=t=>{let e=hs();return e?(0,w.chain)(t()).get(e).value():{}};function Ud(){return(0,w.chain)(gs()).omitBy(w.isNull).keys().value()}function bd(t){return t&&Ud().includes(t)}function hs(){let t=Pd();return Ue("detected CI provider name: %s",t),t||null}function Nd(){let t=Dd(gs);return(0,w.mapValues)(t,e=>(0,w.isString)(e)?Fr(e):e)}function st(t){let e=Nd(),r=hs(),n=vd(t,r);return Ue("detected CI provider: %s",r),Ue("detected CI params: %O",e),Ue("detected CI build ID: %o",n),{params:e,provider:r,ciBuildId:n}}function vd(t,e){return t?{source:"user",value:t}:bd(e)?{source:"server",value:null}:{source:"random",value:`auto:${Br()}`}}var Is=f(require("archiver")),Es=f(require("fs-extra")),Wr=f(require("path")),Cs=f(require("unzipper"));var Ld=50*1024*1024;async function Ts(t,e=Ld){return new Promise((r,n)=>{let o=(0,Is.default)("zip",{zlib:{level:9}}),s=[],i=0;o.on("data",d=>{s.push(d),i+=d.length,i>e&&n(new Error(`Zip size exceeded the limit of ${e} bytes`))}),o.on("warning",d=>{d.code==="ENOENT"?I(d):n(d)}),o.on("error",d=>n(d)),o.on("end",()=>{let d=Buffer.concat(s);r(d)});let a=async d=>{let l=process.cwd(),m=Wr.default.normalize(d),h=Wr.default.relative(l,m),g=await Es.default.stat(d);g.isDirectory()?o.directory(d,h):o.file(d,{name:h,stats:g})};(async d=>{for(let l of d)await a(l);await o.finalize()})(t).catch(n)})}async function ys(t,e){return Cs.default.Open.buffer(t).then(r=>r.extract({path:e,concurrency:3}))}var Rs=require("lodash");var Bd={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?Bd[t]:null;return!r||!e?!1:r.every(n=>!!e[(0,Rs.camelCase)(n)])}function be(t,e){e||Fd(t)||he("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 As=f(require("async-retry")),Ss=f(require("fs")),Ps=require("stream"),re=require("axios");var ws=f(require("axios")),_s=require("https-proxy-agent"),Os=f(require("proxy-from-env"));var Md=p.extend("axios");function qr(t={}){let e=ws.default.create(t);return e.interceptors.request.use(r=>{let n={...r},o=e.getUri(r),s=Os.default.getProxyForUrl(o);return s&&(Md("Using HTTP proxy %s for %s",Nt(s),Nt(o)),n.proxy=!1,n.httpsAgent=kd(s)),n}),e}var Ne=null;function kd(t){return Ne||(Ne=new _s.HttpsProxyAgent(t),Ne)}var ne=p.extend("upload"),ve=5;async function zr(t,e,r){return ne("Uploading buffer %s",t.name,{buffer:Buffer.byteLength(t.buffer)}),vs(t.buffer,t.uploadUrl,e,r,t.headers,Us(Buffer.byteLength(t.buffer)))}var jd=256*1024,$d=120*1e3;async function Ds(t){return ne("Uploading file %s",t.name,{bytes:t.sizeBytes}),vs(()=>t.sizeBytes>0?Ss.default.createReadStream(t.path,{end:t.sizeBytes-1}):Ps.Readable.from([]),t.uploadUrl,t.contentType,void 0,{...t.headers??{"Content-Type":t.contentType},"Content-Length":String(t.sizeBytes)},Us(t.sizeBytes))}function Us(t){return $d+Math.ceil(t/jd)*1e3}async function Gd(t,e,r,n,o,s){return qr().request({method:"put",url:e,timeout:s,data:typeof t=="function"?t():t,...typeof t=="function"&&{maxRedirects:0},onUploadProgress:n,headers:o??{"Content-Disposition":"inline","Content-Type":r}})}async function Qr(t,e){try{let r=await qr().get(t,{responseType:"arraybuffer",onDownloadProgress:e});return Buffer.isBuffer(r.data)?r.data:Buffer.from(r.data)}catch(r){throw(0,re.isAxiosError)(r)&&ne("Failed to download %s: %s",Nt(t),r.message),r}}var Kd=["RequestTimeout","OperationAborted","SlowDown"];function bs(t){if(t)return t.replace(/[\u0000-\u001f\u007f-\u009f]/g,"").replace(/\b[a-z][a-z0-9+.-]*:\/\/\S+/gi,e=>Nt(e)).slice(0,200)}function Ns(t){let e=(0,re.isAxiosError)(t)?t.response?.data:void 0,r=typeof e=="string"?e:"";return{code:r.match(/<Code>([^<]*)<\/Code>/)?.[1],message:bs(r.match(/<Message>([^<]*)<\/Message>/)?.[1])}}function Hd(t){let e=(0,re.isAxiosError)(t)?t.response?.status:void 0;if(e===void 0||e<400||e>=500||e===408||e===429)return!1;let{code:r}=Ns(t);return!(r&&Kd.includes(r))}function Jd(t){if(!(0,re.isAxiosError)(t)||!t.response)return t instanceof Error?t:new Error(String(t));let{code:e,message:r}=Ns(t),n=[bs(e),r].filter(Boolean).join(": ");return new Error(`storage answered ${t.response.status}${n?` ${n}`:""}`)}async function vs(...t){try{await Vd(t)}catch(e){throw Jd(e)}}async function Vd(t){await(0,As.default)(async e=>{try{await Gd(...t)}catch(r){if(Hd(r)){e(r);return}throw r}},{retries:ve,onRetry:(e,r)=>{if(ne("Upload failed %d out of %d attempts: %s",r,ve,e.message),r===ve){C(`Cannot upload after ${r} times: ${e.message}`);return}I(`Upload failed ${r} out of ${ve} attempts: ${e.message}`)}})}var Xr=t=>({total:e,loaded:r})=>{ne("Uploading %s: %d / %d",t,xs(r),xs(e??0))};function xs(t){return t/1e3/1e3}var en=f(require("lodash"));var it=f(require("path")),tn=f(require("globby"));var Ls=require("lodash");function Zr({config:t,cacheId:e,orgId:r,path:n,ci:o,cacheKey:s,metaCacheKey:i}){let a={id:e,orgId:r,config:(0,Ls.omit)(t,"recordKey"),path:n,ci:o,createdAt:new Date().toISOString(),cacheKey:s,metaCacheKey:i};return Buffer.from(JSON.stringify(a))}function Bs(t,e){t instanceof Error?Ct("%s. %s.",e,t.message):Ct("%s. %s.",e,"Unknown error")}var Fs=async t=>{let e=it.default.resolve(t??"./test-results"),r=[it.default.posix.join(e.replace(/\\/g,"/"),"**/.last-run.json"),it.default.posix.join(e.replace(/\\/g,"/"),".last-run.json")];return tn.sync(r)},Ms=async(t=[])=>{let e=Yd(t);return e.length===0?[]:tn.sync(e.map(r=>r.replace(/\\/g,"/")))};function Yd(t){let e=process.cwd();return t.filter(r=>{let n=it.default.relative(e,it.default.resolve(r));return n===".."||n.startsWith(`..${it.default.sep}`)||it.default.isAbsolute(n)?(Bs(null,`Invalid path: "${r}". Path traversal detected. The path was skipped.`),!1):!0})}function Le(t){return t?t.path.some(e=>it.default.basename(e)===".last-run.json"):!1}async function ks(t,e){switch(e.provider){case"githubActions":await Gs(t,e);break;case"gitlab":await $s(t,e);break;case"circle":await Ks(t,e);break;default:break}}async function js(t,e,r){switch(e.provider){case"githubActions":await Gs(t,e,r);break;case"gitlab":await $s(t,e,r);break;case"circle":await Ks(t,e,r);break;default:break}}async function $s(t,e,r=null){let n=e.params,o=r?.ci.params,i=(o?kt(o.runAttempt,0):0)+1,a=kt(n.ciNodeIndex,1),u=kt(n.ciNodeTotal,1),d=Le(r),l=i>1&&d,m=l?"--last-failed":"",h="";u>1&&(h=l?"--shard=1/1":`--shard=${a}/${u}`);let g=[m,h].filter(Boolean).join(" ");await Rt(t.presetOutput??ee,`EXTRA_PW_FLAGS="${g}"
|
|
23
|
+
EXTRA_PWCP_FLAGS="${m}"
|
|
24
24
|
RUN_ATTEMPT=${i}
|
|
25
|
-
`)}async function
|
|
26
|
-
`+t.map(e=>`${
|
|
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
|
|
29
|
-
`)}function
|
|
30
|
-
`}
|
|
31
|
-
`)
|
|
32
|
-
`)
|
|
25
|
+
`)}async function Gs(t,e,r=null){let{matrixIndex:n,matrixTotal:o}=t,s=e.params,i=kt(s.githubRunAttempt,1),a=Le(r),u=i>1&&a,d=u?"--last-failed":"",l="";o>1&&(l=u?"--shard=1/1":`--shard=${n}/${o}`);let m=[d,l].filter(Boolean).join(" "),h=t.presetOutput??ee;await Rt(h,m),p('Dumped PW config: "%s" for GHA to %s',m,h)}async function Ks(t,e,r=null){let n=e.params,o=r?.ci.params,s=o?.circleWorkflowId,i=o?.circleWorkflowWorkspaceId,a=kt(n.circleNodeIndex,0),u=kt(n.circleNodeTotal,1),d=i==n.circleWorkflowWorkspaceId&&s!==n.circleWorkflowId,l=Le(r),m=d&&l,h=m?"--last-failed":"",g="";u>1&&(g=m?"--shard=1/1":`--shard=${a+1}/${u}`);let _=[h,g].filter(Boolean).join(" "),k=t.presetOutput??ee;await Rt(k,_),p('Dumped PW config: "%s" for Circle to %s',_,k)}var kt=(t,e)=>{let r=en.default.toNumber(t);return en.default.isNaN(r)?e:r};async function nn(){let t=mt();if(t.type!=="GET_COMMAND_CONFIG"||!t.values)throw new Error("Config is missing!");let{recordKey:e,id:r,preset:n,matrixIndex:o,matrixTotal:s,continue:i}=t.values,a=t.values.outputDir,u=st();be(u,r),n==="last-run"&&await ks(t.values,u);let{cacheId:d,refMetaReadUrl:l}=await bo({recordKey:e,ci:u,id:r,config:{matrixIndex:o,matrixTotal:s}});try{let m=await zd(l),{readUrl:h}=await Uo({recordKey:e,cacheKey:m.cacheKey}),g=await Wd({readUrl:h,outputDir:a});n==="last-run"&&await js(t.values,u,m),T(S("- restoring cache to"),g),Ie("Cache restored. Cache ID: %s",d)}catch(m){if((0,Hs.isAxiosError)(m)&&(m.response?.status===403||m.response?.status===404)){let h=`Cache with ID "${d}" not found`;if(i){Ct(h);return}throw new Error(h)}throw m}}async function Wd({readUrl:t,outputDir:e}){let r=await Qr(t),n=qd(e);return await ys(r,n),p("Cache downloaded",{readUrl:t,destination:n}),n}function qd(t){let e=t??process.cwd();return rn.default.isAbsolute(e)?e:rn.default.resolve(process.cwd(),e)}async function zd(t){let e=await Qr(t),r=JSON.parse(e.toString("utf-8"));return p("Meta file downloaded: %O",r),r}var Vs=require("lodash");async function on(){let t=mt();if(t.type!=="SET_COMMAND_CONFIG"||!t.values)throw new Error("Config is missing!");let{recordKey:e,id:r,preset:n,pwOutputDir:o,matrixIndex:s,matrixTotal:i,continue:a}=t.values,u=await Ms(t.values.path),d=t.values.path||[],l=st();if(be(l,r),n==="last-run"&&(d.push(o),u.push(...await Fs(o))),u.length===0){let k=`No files available to upload: ${d.filter(Boolean).join(",")}`;if(!a)throw new Error(k);Ct(k)}let m=await Do({recordKey:e,ci:l,id:r,config:{matrixIndex:s,matrixTotal:i}});p("Cache upload url created",{result:m});let h=Xd(l),g=u.length>0?await Ts(u):null,_=[];g&&_.push(Qd({archive:g,cacheId:m.cacheId,uploadUrl:m.uploadUrl}).then(()=>{Zd(u),p("Cache archive uploaded",{uploadUrl:m.uploadUrl})})),_.push(Js({meta:Zr({cacheId:m.cacheId,config:t.values,ci:h,orgId:m.orgId,path:u}),cacheId:m.cacheId,uploadUrl:m.metaUploadUrl}).then(()=>p("Meta uploaded",{uploadUrl:m.metaUploadUrl})),Js({meta:Zr({cacheId:m.cacheId,config:t.values,ci:h,orgId:m.orgId,path:u,cacheKey:m.cacheKey,metaCacheKey:m.metaCacheKey}),cacheId:m.cacheId,uploadUrl:m.refMetaUploadUrl}).then(()=>p("Ref meta uploaded",{uploadUrl:m.refMetaUploadUrl}))),await Promise.all(_),Ie("Cache uploaded. Cache ID: %s",m.cacheId)}async function Qd({archive:t,cacheId:e,uploadUrl:r}){try{let n="application/zip";await zr({buffer:t,contentType:n,name:e,uploadUrl:r},n,Xr(e)),p("Cache archive uploaded",{cacheId:e})}catch(n){throw p("Failed to upload cache archive",n),n}}async function Js({meta:t,cacheId:e,uploadUrl:r}){try{let n=`${e}_meta`,o="application/json";await zr({buffer:t,contentType:o,name:n,uploadUrl:r},o,Xr(n)),p("Cache meta uploaded",{cacheId:e})}catch(n){throw p("Failed to upload cache meta",n),n}}function Xd(t){return t.ciBuildId.source==="server"||t.ciBuildId.source==="random"?(0,Vs.omit)(t,"ciBuildId"):t}function Zd(t){T(`Cache upload paths:
|
|
26
|
+
`+t.map(e=>`${S("- uploading")} ${e}`).join(`
|
|
27
|
+
`))}var{recordKey:tu,projectId:eu,ciBuildId:ru,debug:nu}=O,et={recordKey:tu,projectId:eu,ciBuildId:ru,runId:{name:"Run ID",env:"CURRENTS_RUN_ID",cli:"--run-id"},debug:nu};var ou=p.extend("config"),su=["recordKey","projectId"];function iu(t){if(!(t.runId||t.ciBuildId))throw C(`${we(et,"runId")} or ${we(et,"ciBuildId")} is required: pass ${S(Re(et,"runId"))} or ${S(Re(et,"ciBuildId"))}, or set ${S(P(et,"runId"))} or ${S(P(et,"ciBuildId"))}`),new tt("Missing required config variable")}var sn=null;function Ys(t){sn=U(et,su,t,iu),ou("Resolved config: %o",E(sn))}function Be(){return sn}async function an(){let t=Be();if(!t)throw new Error("Config is missing!");let e=t.runId?`runId: ${t.runId}`:`ciBuildId: ${t.ciBuildId}`;try{let r=await No({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 Ws=require("@currents/commit-info"),qs=require("lodash");var au=p.extend("git"),cu=async()=>{let t=await(0,Ws.commitInfo)();return au("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}},oe=(0,qs.memoize)(cu);var zs=f(require("getos")),Qs=require("lodash"),q=require("os"),Xs=require("util"),pu=async()=>{if((0,q.platform)()==="linux")try{let t=await(0,Xs.promisify)(zs.default)();return"dist"in t&&"release"in t?[t.dist,t.release].join(" - "):(0,q.release)()}catch{return(0,q.release)()}return(0,q.release)()},du=async()=>{let t=await pu();return{osName:(0,q.platform)(),osVersion:t,osCpus:[],osMemory:{free:(0,q.freemem)(),total:(0,q.totalmem)()}}},Zs=(0,Qs.memoize)(du);var na=f(require("axios")),hn=f(require("fs-extra")),We=f(require("path")),oa=f(require("semver"));var{debug:uu,ciBuildId:mu,recordKey:lu,projectId:fu,machineId:gu}=O,z={debug:uu,ciBuildId:mu,recordKey:lu,projectId:fu,machineId:gu,tag:{...O.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"},environment:{name:"Environment",env:"CURRENTS_ENVIRONMENT",cli:"--environment"},failOnFailures:{name:"Fail on failures",env:"CURRENTS_FAIL_ON_FAILURES",cli:"--fail-on-failures"},reportDir:{name:"Report folder",env:"CURRENTS_REPORT_DIR",cli:"--report-dir"}};var hu=p.extend("config"),Iu=["projectId","recordKey"],cn=null;function ti(t){cn=U(z,Iu,t),hu("Resolved Currents config: %o",E(cn))}function Fe(){return cn}function ei(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,environment:t.environment,reportDir:t.reportDir,failOnFailures:t.failOnFailures}}var L=require("@currents/rules");var Me=p.extend("actions"),Eu=512;async function oi(t,e){try{let r=await $o(t,e);if(!Array.isArray(r))throw new Error("The project actions are not a list");return Me("Fetched %d project actions",r.length),r}catch(r){return I("Failed to fetch the project actions, uploading without them"),Me("Failed to fetch the project actions: %o",r),[]}}function si({actions:t,instances:e,fullTestSuite:r,gitInfo:n,runTags:o,disableTitleTags:s=!1,group:i}){let a={skipped:0,quarantined:0,tagged:0};if(t.length===0)return a;let u=new L.RulesEvalBase(t,Me);for(let d of e){let l=i??d.groupId;for(let m of d.results.tests){let h=s?[]:pi(r,{groupId:l,spec:d.spec,testId:m.testId})?.test.tags??[],g=u.getMatchedRules(Cu({groupId:l,spec:d.spec,test:m,gitInfo:n,tags:[...h,...o]}));if(g.length===0)continue;Me("Test %s matched actions: %j",m.testId,g);let _=Tu(m,g);_.length>0&&(yu(r,{groupId:l,spec:d.spec,testId:m.testId,tags:_}),a.tagged++);let k=ri(g,L.ACTION_TYPE.SKIP),Ut=ri(g,L.ACTION_TYPE.QUARANTINE);k?(ni(m,k,L.ACTION_ANNOTATIONS.SKIP_POST),a.skipped++):Ut&&m.state==="failed"&&(ni(m,Ut,L.ACTION_ANNOTATIONS.QUARANTINE_POST),a.quarantined++)}}return a}function ii(t){t.skipped+t.quarantined+t.tagged!==0&&T("[currents] Actions: %d tests skipped, %d quarantined, %d tagged",t.skipped,t.quarantined,t.tagged)}function Cu({groupId:t,spec:e,test:r,gitInfo:n,tags:o}){return{title:r.title[r.title.length-1],titlePath:[e,...r.title],file:e,project:t,testId:r.testId,tag:Array.from(new Set([...r.tags??[],...o])),gitInfo:n&&{branch:n.branch,authorName:n.authorName,authorEmail:n.authorEmail,remoteOrigin:n.remoteOrigin,message:n.message},errors:r.attempts.flatMap(s=>s.errors).filter(s=>!!s.message).map(s=>({message:s.message}))}}function ri(t,e){return t.find(r=>r.action.some(n=>n.op===e))}function Tu(t,e){let r=[];for(let n of e)for(let o of n.action){if(o.op!==L.ACTION_TYPE.TAG)continue;let s=(0,L.normalizeTagMatcherValue)(o.details?.tags??[]);s.length!==0&&(ai(t,L.ACTION_ANNOTATIONS.TAG,ci({action:n,type:L.ACTION_TYPE.TAG,testId:t.testId,extraDetails:{tags:s}})),r.push(...(0,L.normalizeTagMatcherValue)(s,{removeAtPrefix:!0})))}return r.length>0&&(t.tags=Array.from(new Set([...t.tags??[],...r]))),r}function ni(t,e,r){let n=t.state;ai(t,r,ci({action:e,type:r===L.ACTION_ANNOTATIONS.SKIP_POST?L.ACTION_TYPE.SKIP:L.ACTION_TYPE.QUARANTINE,testId:t.testId,extraDetails:{status:n}})),t.state="pending"}function ai(t,e,r){t.annotations=[...t.annotations??[],{type:e,description:JSON.stringify(r),source:"test"}]}function ci({action:t,type:e,testId:r,extraDetails:n}){return{rule:{v:t.v,id:t._id,name:t.name.slice(0,Eu),type:e,extraDetails:n,appliedAt:Date.now()},testInfo:{testId:r,status:n.status}}}function pi(t,{groupId:e,spec:r,testId:n}){let o=t.find(i=>i.name===e),s=o?.tests.find(i=>i.spec===r&&i.testId===n);return o&&s?{project:o,test:s}:null}function yu(t,{groupId:e,spec:r,testId:n,tags:o}){let s=pi(t,{groupId:e,spec:r,testId:n});if(!s)return;let{project:i,test:a}=s;a.tags=Array.from(new Set([...a.tags,...o])),i.tags=Array.from(new Set([...i.tags,...o]))}var mn=f(require("fs-extra")),at=require("path");var di=f(require("path")),pn={".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"}},dn=t=>pn[di.default.extname(t).toLowerCase()];var ui=f(require("fs-extra")),mi=require("path"),un=p.extend("detox"),Ru="detox.json";function li(t){return[...t].sort((e,r)=>(e.session??0)-(r.session??0)||e.invocations-r.invocations)}async function fi(t){let e=(0,mi.join)(t,Ru);try{let r=await ui.default.readJson(e);if(typeof r?.artifactsRootDir!="string"||!Array.isArray(r?.tests)){un("Unexpected Detox manifest contents at %s",e);return}return un("Detox manifest: %o",r),r}catch{un("No Detox manifest at %s",e);return}}var ke=require("path"),wu=p.extend("detox"),gi=255,_u=/[/\\?<>:*|"$\u0000-\u001f]/g,hi=4;function Ii(t){return Ou(t)??xu(t)}function Ou({rootDir:t,fullName:e,status:r,invocations:n}){try{let o=require.resolve("detox/src/artifacts/utils/ArtifactPathBuilder",{paths:[process.cwd()]}),s=require(o),i=new s({rootDir:t});return(0,ke.dirname)(i.buildPathForTestArtifact("test.mp4",{fullName:e,status:r,invocations:n}))}catch(o){wu("Detox path builder is not available: %o",o);return}}function xu({rootDir:t,fullName:e,status:r,invocations:n}){let o=Su(r),s=n>1?` (${n})`:"",i=e.slice(-gi+o.length+s.length),a=`${o}${i}${s}`.replace(_u,"_");return(0,ke.join)(t,Au(a,gi))}function Au(t,e){let r=Buffer.from(t,"utf8");return r.length<=e?t:r.subarray(0,e).toString("utf8").replace(/\uFFFD$/,"")}function Su(t){switch(t){case"passed":return"\u2713 ";case"failed":return"\u2717 ";default:return""}}var Ci=f(require("fs-extra")),Ti=require("path"),Ei=p.extend("detox"),je="detox.trace.json",Pu="ws-client-invocation";async function yi(t){let e=(0,Ti.join)(t,je),r=new Map,n;try{n=await Ci.default.readJson(e)}catch{return Ei("No Detox trace at %s",e),r}if(!Array.isArray(n))return Ei("Unexpected Detox trace contents at %s",e),r;let o=Du(n);return bu(n).forEach(({pid:i,ts:a,step:u})=>{o.filter(l=>l.pid===i&&a>=l.startTs&&a<=l.endTs).sort((l,m)=>l.startTs-m.startTs).pop()?.steps.push(u)}),o.forEach(({fullName:i,invocations:a,steps:u})=>{let d=r.get(i)??[];d.push({fullName:i,invocations:a,steps:u.sort((l,m)=>+new Date(l.startTime)-+new Date(m.startTime))}),r.set(i,d)}),r}function Du(t){let e=new Map,r=[];t.forEach(o=>{let s=`${o.pid}:${o.tid}`,i=e.get(s)??[];if(e.set(s,i),o.ph==="B"){i.push(Uu(o));return}if(o.ph==="E"){let a=i.pop();a&&r.push({...a,endTs:Number(o.ts)})}});let n=[...e.values()].flatMap(o=>o.filter(s=>s!==void 0));return[...r,...n]}function Uu(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 bu(t){let e=new Map,r=[];return t.forEach(n=>{if(!n.cat?.includes(Pu))return;let o=`${n.pid}:${n.tid}`,s=e.get(o)??[];if(n.ph==="B"){s.push({name:n.name??"action",cat:n.cat,ts:Number(n.ts)}),e.set(o,s);return}if(n.ph==="E"){let i=s.pop();if(!i)return;r.push({pid:Number(n.pid),ts:i.ts,step:{title:i.name,category:"detox",startTime:new Date(i.ts/1e3).toISOString(),duration:Math.round((Number(n.ts)-i.ts)/1e3),steps:[]}})}}),r}var se=p.extend("detox"),Ri="artifacts",Nu=[".mp4",".png",".jpg",".log",".txt",".json",".viewhierarchy"],vu=t=>{let e=(0,at.extname)(t);return Nu.includes(e)?pn[e]:void 0};async function wi({instances:t,reportDir:e,manifest:r}){let n=Bu(r),o=await yi(r.artifactsRootDir),s=await _t((0,at.join)(e,Ri)),i={artifacts:0,steps:0};for(let a of t)for(let u of a.results.tests){let d=n.get(u.testId);if(!d){se("No Detox manifest entry for %s",u.testId);continue}await Fu({test:u,manifestTest:d,rootDir:r.artifactsRootDir,artifactsDir:s,traceSlices:o.get(d.fullName)??[],result:i})}return i.artifacts+=await Lu({instances:t,rootDir:r.artifactsRootDir,artifactsDir:s}),i}async function Lu({instances:t,rootDir:e,artifactsDir:r}){if(!await mn.default.pathExists((0,at.join)(e,je)))return 0;let[n]=await _i(e,[je],r),o=t.map(s=>s.results.tests[0]).filter(s=>s!==void 0);return o.forEach(s=>{s.artifacts=[...s.artifacts??[],n]}),o.length}function Bu(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 n=e.get(r.fullName)?.length===1;return n||se("Ambiguous Detox test name, skipping: %s",r.fullName),n}).map(r=>[r.testId,r]))}async function Fu({test:t,manifestTest:e,rootDir:r,artifactsDir:n,traceSlices:o,result:s}){let i=[...t.attempts].sort((d,l)=>d.attempt-l.attempt),a=li(e.attempts),u=1;for(let[d,l]of a.entries()){let m=i[d];if(!m){se("No reported attempt %d of %s",d,e.fullName);continue}let h=await Mu({fullName:e.fullName,status:l.status,rootDir:r,artifactsDir:n,fromInvocation:u});h&&(u=h.invocation+1,m.artifacts=[...m.artifacts??[],...h.artifacts],s.artifacts+=h.artifacts.length);let g=ju(o,d,h?.invocation);g.length&&(m.steps=[...m.steps??[],...g],s.steps+=g.length)}}async function Mu({fullName:t,status:e,rootDir:r,artifactsDir:n,fromInvocation:o}){for(let s=o;s<o+hi;s++){let i=Ii({rootDir:r,fullName:t,status:e,invocations:s}),a=await ku(i);if(a)return{invocation:s,artifacts:await _i(i,a,n)}}se("No Detox artifacts for %s [%s]",t,e)}async function ku(t){try{return(await mn.default.readdir(t)).sort()}catch{return}}async function _i(t,e,r){let n=[];for(let o of e){let s=vu(o);if(!s){se("Skipping unsupported Detox artifact %s",o);continue}let i=(0,at.join)(t,o),a=`${W(i)}${(0,at.extname)(o)}`;await Ce(i,(0,at.join)(r,a)),n.push({...s,path:(0,at.join)(Ri,a),name:o})}return n}function ju(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 lt=class{constructor(e){this.config=e}async getFullTestSuite(){return[]}};var Gu=f(require("crypto"));var Oi=f(require("fs-extra")),$u=f(require("path"));async function $e(t){let e=await Oi.default.pathExists(t);if(!e)throw new Error("File does not exist");return e}function xi(){return"root"}function Ai(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 Ku=/^[0-9a-f]{32}$/;function Si(t){let e=[];for(let r of t){let n=e.find(o=>o.name===r.groupId);n||(n={name:r.groupId,tags:[],tests:[]},e.push(n)),n.tests.push(...Di(r))}return e.length===1&&Ku.test(e[0].name)&&(e[0].name=xi()),e}function Pi(t,e,r){let n=[];for(let{projectId:o,spec:s}of e){let i=r.find(u=>u.spec===s&&u.groupId===o)??(t.length===1?r.find(u=>u.spec===s):void 0);if(!i){n.push(s);continue}let a=t.length===1?t[0]:t.find(u=>u.name===o);a||(a={name:o,tags:[],tests:[]},t.push(a)),a.tests.push(...Di(i))}return n}function Di(t){return t.results.tests.map(e=>({spec:t.spec,testId:e.testId,title:e.title,tags:e.tags??Ai(e.title)}))}var Ji=f(require("fs-extra")),Vi=f(require("tmp"));var Ki=require("lodash");function Ui(t){let e=[];for(let[r,n]of Object.entries(t))r==="_"||r==="$0"||r.includes("-")||(typeof n=="boolean"?n&&e.push(`--${r}`):Array.isArray(n)?n.forEach(o=>{e.push(`--${r}=${o}`)}):e.push(`--${r}=${n}`));return e.join(" ")}var bi=require("lodash"),Hu=["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 Ni(t){return(0,bi.omit)(t,...Hu)}var $i=f(require("fs")),Je=require("lodash"),fn=f(require("path"));var ln=f(require("fs")),Ge=require("module"),Ke=f(require("path")),vi=f(require("semver")),Ju=">=29.5.0";function Vu(){let t=(0,Ge.createRequire)(Ke.default.join(process.cwd(),"package.json"));if(Yu(t)==="jest-cli")return t.resolve("jest-cli");try{return(0,Ge.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 Yu(t){for(let e of t.resolve.paths("jest")??[]){if(ln.default.existsSync(Ke.default.join(e,"jest","package.json")))return"jest";if(ln.default.existsSync(Ke.default.join(e,"jest-cli","package.json")))return"jest-cli"}return null}function Li(){let t=(0,Ge.createRequire)(Vu()),{version:e}=t("jest-cli/package.json");if(!vi.default.satisfies(e,Ju,{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 Bi(){return Li()("jest-cli")}function Fi(){return Li()("jest-config")}function He(t,e){return(...r)=>new Promise((n,o)=>{let s=0,i=()=>{s++;try{let a=t(...r);n(a)}catch(a){if(s>=e.length)o(a);else{let u=e[s-1];setTimeout(i,u)}}};i()})}var Mi=p.extend("jest-discovery");function ki(t){return["testEnvironment","globalSetup","globalTeardown"].some(e=>String(t[e]??"").includes("detox"))}function ji(t){return{...(0,Je.omit)(t,["globalSetup","globalTeardown","testEnvironmentOptions"]),testEnvironment:"node"}}async function Gi(t,e){let r=e.detox;try{let{readInitialOptions:n}=Fi(),{config:o,configPath:s}=await n(t);r||=[o,...o.projects??[]].some(h=>typeof h!="string"&&ki(h));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"],a=["collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","detectLeaks","detectOpenHandles","errorOnDeprecated","forceCoverageMatch","openHandlesTimeout","runner","watchPathIgnorePatterns"],u=h=>e.detox||ki(h),d=(0,Je.omit)(o,i);if(u(d)&&(d=ji(d)),d.projects&&(d.projects=d.projects.map(h=>{if(typeof h=="string")return h;let g=(0,Je.omit)(h,a);return u(g)?ji(g):g})),d.rootDir&&Object.keys(d).length===1)return null;let l=fn.default.resolve(s?fn.default.dirname(s):process.cwd(),`.jest-scanner-${new Date().getTime()}.config.cjs`),m=`module.exports=${JSON.stringify(d,null,2)}`;return Mi("configFileContent: %O",m),$i.default.writeFileSync(l,m),await He($e,[200,200,200,200,200,1e3])(l),l}catch(n){if(Mi("error %o",n),r)throw new Error(`Failed to recreate the Jest config for discovery: ${n.message}`);return C("Failed to recreate the config file"),null}}async function Hi(t,e){let r="!!##ThisPatternWillNotMatchAnyTestName##!!",n=t.options,o=Ni(n),s=Ui(o),i=n.config,a=await Gi(i,e);return{cliArgs:[s,"--testNamePattern",r,"--reporters",require.resolve("@currents/cmd/discovery/jest"),"--shard=1/1","--testFailureExitCode=0",a?`--config=${a}`:"",...t.args].filter(d=>!(0,Ki.isEmpty)(d)),configFilePath:a}}var Wu=p.extend("jest-discovery");async function Yi(t,e){console.time(S("@currents/jest:fullTestSuite-ready"));let{run:r}=Bi(),{cliArgs:n,configFilePath:o}=await Hi(t,e);try{let s=Vi.default.fileSync({postfix:".json"});return Wu("running scanner: %o",n),process.env.CURRENTS_DISCOVERY_PATH=s.name,await r(n.concat(["--openHandlesTimeout=0"])),await He($e,Array.from({length:300},()=>100))(s.name),console.timeEnd(S("@currents/jest:fullTestSuite-ready")),await yt(s.name)}catch(s){return C("Failed to obtain the jest full test suite:",s),{fullTestSuite:[],specsWithoutResults:[]}}finally{o&&Ji.default.unlinkSync(o)}}var Wi=p.extend("jest-discovery"),Ve=class extends lt{constructor(r,n){super(r);this.instances=n}async getFullTestSuite(){if(!this.config.frameworkConfig?.shard)return Wi("Not a sharded run, listing the tests of the results"),Si(this.instances);let{fullTestSuite:r,specsWithoutResults:n}=await Yi(this.config.cliArgs,{detox:this.config.frameworkConfig.originFramework==="detox"});if(n.length===0)return r;for(let{spec:s,message:i}of n)I("Discovery could not load %s: %s",s,qu(i));let o=Pi(r,n,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."),Wi("Files that did not run on this shard: %o",o),r.filter(s=>s.tests.length>0)}};function qu(t){return t.split(`
|
|
28
|
+
`).map(e=>e.trim()).find(e=>e&&!e.startsWith("\u25CF"))??""}var zi=f(require("fs-extra"));var qi=f(require("path"));function ft(t){return qi.default.join(t,"fullTestSuite.json")}var zu=p.extend("junit-discovery");async function Qi(t){console.time(S("@currents/junit:fullTestSuite-ready"));try{zu("running scanner: %o",t);let e=ft(t);process.env.CURRENTS_DISCOVERY_PATH=e;let r=zi.default.readFileSync(e,"utf-8");return JSON.parse(r)}catch(e){return C("Failed to obtain the junit full test suite:",e),[]}}var Ye=class extends lt{constructor(e,r){super(e),this.reportDir=r}async getFullTestSuite(){return Qi(this.reportDir)}};function Xi(t,e,r){switch(t.framework){case"jest":return new Ve(t,r);case"junit":return new Ye(t,e);default:return new lt(t)}}var gt=f(require("fs-extra")),ct=f(require("path"));async function Zi(t){let e=await Qu(t?.reportDir);return{reportDir:e,configFilePath:t?.configFilePath??ct.default.join(e,"config.json")}}async function Qu(t){if(t){if(!await gt.default.pathExists(t))throw new Error(`No reports found: the folder "${t}" does not exist.`);return t}let e=(0,ct.join)(process.cwd(),".currents"),r=await gt.default.pathExists(e)?await Xu(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 Xu(t){let e=await gt.default.readdir(t),r=null;for(let n of e){let o=ct.default.join(t,n),s=await gt.default.stat(o);s.isDirectory()&&(!r||s.birthtime>r.birthtime)&&(r={name:n,birthtime:s.birthtime})}return r?(0,ct.resolve)(t,r.name):null}async function gn(t){try{return await gt.default.pathExists(t)}catch{return C("Error checking if path exists:",C),!1}}async function ta(t){let e=ct.default.join(t,"instances");return Zu(e)}async function Zu(t){let e=await gt.default.readdir(t),r=[];for(let n of e){let o=ct.default.join(t,n);(await gt.default.stat(o)).isFile()&&r.push(o)}return r}var tm=t=>Buffer.byteLength(JSON.stringify(t),"utf8"),ea=(t,e=1048576)=>{let r=[],n=[],o=0;for(let s of t){let i=tm(s);o+i>e&&(r.push(n),n=[],o=0),n.push(s),o+=i}return n.length>0&&r.push(n),r};var em=3e4;async function In(){let t=Fe();if(!t)throw new Error("Currents config is missing!");let e=await Zi(t);Xn(sm(e.reportDir)),p("Reporter options: %o",e),T("Report directory: %s",e.reportDir);let r=await yt(e.configFilePath);p("Report config: %o",r);let n=await ta(e.reportDir);p("Found %d instance results in the reportDir: %s",n.length,e.reportDir);let o=om(e.reportDir),s=await gn(o),i=ft(e.reportDir),a=null;if(s){let x=await yt(o);I("Marker file detected. The report was already uploaded: %o",{runUrl:x.response.runUrl,isoDate:x.isoDate})}let u=[];for(let x of n)u.push(await yt(x));if(a=await im(i),a)p("Full test suite file detected: %s",i);else{let X=await Xi(r,e.reportDir,u).getFullTestSuite();if(!sa(X)||ia(X))throw new Error("Failed to discover the full test suite!");a=X,await Rt(i,JSON.stringify(a))}t.environment&&(a=a.map(x=>({...x,environment:x.environment??t.environment})));let d=a.length===1?a[0].name:null,l={currents:t},m={type:r.framework,version:r.frameworkVersion,clientVersion:bt,frameworkConfig:{originFramework:r.frameworkConfig?.originFramework,originFrameworkVersion:r.frameworkConfig?.originFrameworkVersion}},h=ye.userFacingNanoid(),g=st(t.ciBuildId),_={};for(let x of u)_[x.groupId]||(_[x.groupId]=[]),_[x.groupId].push(x);let k=await fi(e.reportDir);if(k){let x=await wi({instances:Object.values(_).flat(),reportDir:e.reportDir,manifest:k});T("[currents] Attached %d Detox artifacts and %d steps",x.artifacts,x.steps)}let Ut=await oi(t.projectId,t.recordKey);ii(si({actions:Ut,instances:Object.values(_).flat(),fullTestSuite:a,gitInfo:await oe(),runTags:t.tag??[],disableTitleTags:t.disableTitleTags,group:d}));let fe=new Map;Object.values(_).forEach(x=>{x.forEach(X=>{X.artifacts?.forEach(V=>{V&&fe.set(V.path,V.contentType)}),X.results.tests.forEach(V=>{V.artifacts?.forEach(K=>{K&&fe.set(K.path,K.contentType)}),V.attempts.forEach(K=>{K.artifacts?.forEach(Et=>{Et&&fe.set(Et.path,Et.contentType)})})})})});for await(let x of Object.keys(_)){let X=_[x],V=x;d&&(p("Default group found: %s, overwriting the group in the results",d),V=d,X=X.map(K=>({...K,groupId:d})));try{let K=ea(X),Et=await ra({ci:g,group:V,instances:[],fullTestSuite:a,config:l,machineId:h,framework:m});for(let Ar=0;Ar<K.length;Ar++){let Sr=await ra({ci:g,group:V,instances:K[Ar],fullTestSuite:[],config:l,machineId:h,framework:m});Sr.artifactUploadUrls&&Sr.artifactUploadUrls.length>0&&await am(Sr.artifactUploadUrls,e.reportDir,fe)}p("Api response: %o",Et),T("[%s] Run created: %s",V,Et.runUrl);let Pp={response:Et,isoDate:new Date().toISOString()};await Rt(o,JSON.stringify(Pp)),p("Marker file %s: %s",s?"overwritten":"created",o)}catch(K){throw p("Failed to upload the results to the dashboard"),K}}t.failOnFailures&&nm(u)}var rm=10;function nm(t){let e=t.flatMap(o=>o.results.tests.filter(s=>s.state==="failed").map(s=>`${o.spec}: ${s.title.join(" > ")}`));if(e.length===0)return;let r=e.slice(0,rm),n=e.length-r.length;throw new Error([`${e.length} ${e.length===1?"test":"tests"} failed (--fail-on-failures):`,...r.map(o=>` - ${o}`),...n>0?[` and ${n} more`]:[]].join(`
|
|
29
|
+
`))}async function ra({ci:t,group:e,instances:r,fullTestSuite:n,config:o,machineId:s,framework:i}){let a=await oe(),u=await Zs(),d={browserName:"node",browserVersion:oa.default.coerce(process.version)?.version},{currents:l}=o,h={platform:{...d,...u},ci:t,commit:a,group:e,fullTestSuite:n,config:o,projectId:l.projectId,recordKey:l.recordKey,ciBuildId:t.ciBuildId.value??void 0,tags:l.tag??[],machineId:l.machineId??s,framework:i,instances:r,previousCiBuildId:process.env.CURRENTS_PREVIOUS_CI_BUILD_ID};return p("Creating run: %o",E(h)),Fo(h)}function om(t){return We.default.join(t,"upload.marker.json")}function sm(t){return We.default.join(t,`.debug-${new Date().toISOString()}.log`)}async function im(t){if(!await gn(t))return null;try{let e=await yt(t);return!sa(e)||ia(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 sa(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(n=>typeof n=="string")))}function ia(t){return t.length===0||t.some(e=>e.tests.length===0)}async function am(t,e,r){p("Uploading %d artifacts",t.length),await Promise.all(t.map(n=>{let o=We.default.join(e,n.path),s=r.get(n.path)||"application/octet-stream";return cm(o,s,n.uploadUrl)}))}var cm=async(t,e,r)=>{try{if(!await hn.default.pathExists(t)){I("Artifact file not found: %s",t);return}let n=await hn.default.readFile(t);await na.default.put(r,n,{headers:{"Content-Type":e},timeout:em})}catch(n){p("Failed to upload artifact %s: %o",t,n)}};var pm=p.extend("cli");async function aa(t,e){await R(async r=>{r.output||Mt(),e.getOptionValueSource("ciBuildId")==="env"&&(r.branch||r.tag)&&(r={...r,ciBuildId:void 0}),mo(r);let o=Oe();pm("Config: %o",E(o)),await Hr()},t)}var rt=require("@commander-js/extra-typings");var da=require("axios"),ua=f(require("fs-extra"));var dm=p.extend("api");function um(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 ${Qt()}`);let e=t.replace(/^\/+/,""),r=n=>/^(\.|%2e){1,2}$/i.test(n);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 mm(t){let e=Object.create(null);for(let[r,n]of t)if(r.endsWith("[]")){let o=r.slice(0,-2);e[o]=[...Array.isArray(e[o])?e[o]:[],n]}else e[r]=n;return e}function lm(t){let e=new URLSearchParams;for(let[r,n]of t)e.append(r,String(n));return e}async function fm(t){let e=t==="-"?await new Promise((r,n)=>{let o="";process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>o+=s),process.stdin.on("end",()=>r(o)),process.stdin.on("error",n)}):await ua.default.readFile(t,"utf8");try{return JSON.parse(e)}catch(r){throw new Error(`--input ${t} is not valid JSON: ${r.message}`)}}async function gm(t,e){let r=[...e.field??[],...e.rawField??[]],n=e.input!==void 0,o=e.method??(n||r.length>0?"POST":"GET"),s=n||o==="GET"||o==="HEAD";return{method:o,url:um(t),params:s&&r.length>0?lm(r):void 0,data:n?JSON.stringify(await fm(e.input)):!s&&r.length>0?JSON.stringify(mm(r)):void 0,headers:Object.fromEntries(e.header??[])}}function ca(t){let e=Object.entries(t.headers).map(([r,n])=>`${r}: ${Array.isArray(n)?n.join(", "):n}`);return[`HTTP/1.1 ${t.status} ${t.statusText}`,...e,"",""].join(`
|
|
30
|
+
`)}function pa(t,e){let r=t.data??"",n=String(t.headers["content-type"]??"").toLowerCase().includes("json");if(!e||!n||!r)return r;try{return JSON.stringify(JSON.parse(r),null,2)+`
|
|
31
|
+
`}catch{return r}}async function ma(t,e){let{apiKey:r}=U(O,["apiKey"],e),n=s=>s?.map(([i])=>i);dm("Options: %o",E({...e,field:n(e.field),rawField:n(e.rawField),header:n(e.header)}));let o=await gm(t,e);try{let s=await jo(r,o);e.include&&process.stdout.write(ca(s)),process.stdout.write(pa(s,!!process.stdout.isTTY))}catch(s){if(!(0,da.isAxiosError)(s))throw s;let i=s.response;if(!i)throw new Error(`Could not reach the REST API at ${Qt()}: ${s.message}`);e.include&&process.stderr.write(ca(i));let a=pa(i,!!process.stderr.isTTY);throw a&&process.stderr.write(a.endsWith(`
|
|
32
|
+
`)?a:`${a}
|
|
33
|
+
`),new Error(`${o.method} ${o.url.split("?")[0]} failed: the REST API answered ${i.status} ${i.statusText}`)}}var la=["GET","POST","PUT","PATCH","DELETE","HEAD"];function En(t,e){let r=t.indexOf(e),n=r<0?"":t.slice(0,r).trim();if(!n)throw new rt.InvalidArgumentError(`Expected key${e}value.`);let o=t.slice(r+1);return[n,e===":"?o.trim():o]}function hm(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 Im=(t,e=[])=>{let[r,n]=En(t,"=");return[...e,[r,hm(n)]]},Em=(t,e=[])=>[...e,En(t,"=")],Cm=(t,e=[])=>[...e,En(t,":")],fa=new rt.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(!la.includes(e))throw new rt.InvalidArgumentError(`Use one of ${la.join(", ")}.`);return e}),ga=new rt.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(Im),ha=new rt.Option("-F, --raw-field <key=value>","like --field, but the value is always a string").argParser(Em),Ia=new rt.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 rt.Option("-H, --header <key:value>","an HTTP header to send; repeat for more").argParser(Cm),Ca=new rt.Option("-i, --include","print the HTTP status line and the response headers before the body");async function Ta(t,e){await R(async r=>{Mt(),await ma(t,r)},e)}var xt=require("@commander-js/extra-typings");var Cn="(required)",j=(t=Cn)=>new xt.Option("-k, --key <record-key>",`the record key from the Currents dashboard ${t}`).env(O.recordKey.env),pt=(t=Cn)=>new xt.Option("--api-key <api-key>",`an API key from the Currents dashboard ${t}`).env(O.apiKey.env),nt=()=>new xt.Option("-p, --project-id <id>",`the project ID from the Currents dashboard ${Cn}`).env(O.projectId.env),jt=t=>new xt.Option("--ci-build-id <id>",`the CI build ID the run was recorded with${t}`).env(O.ciBuildId.env),$t=t=>new xt.Option("-t, --tag <tag>",`${t}; comma-separated or repeated`).argParser(De),N=()=>new xt.Option("--debug","print debug logs; keys are hidden in them").env(O.debug.env).default(!1);var qe=require("@commander-js/extra-typings");var ya=new qe.Option("-o, --output <path>","write the JSON to this file instead of stdout").env(P(_e,"output")),Ra=jt("; cannot be combined with --branch or --tag. The environment variable is ignored when --branch or --tag is set"),wa=$t("find the last run with these tags"),_a=new qe.Option("-b, --branch <branch>","find the last run of this git branch"),Oa=new qe.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 ze="get",Tn="run",Rn=t=>[{comment:"Get the data of the run recorded under a CI build ID",commands:[`${t} ${Tn} ${ze} --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} ${Tn} ${ze} --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} ${Tn} ${ze} --api-key <api-key> --project-id <project-id> --ci-build-id <ci-build-id> --pw-last-run --output test-results/.last-run.json`]}],Tm=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`]}],xa=t=>new yn.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
34
|
|
|
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(
|
|
35
|
-
run: npx ${t} ${
|
|
36
|
-
`)}),r};var
|
|
37
|
-
`)
|
|
35
|
+
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(pt()).addOption(fa).addOption(ga).addOption(ha).addOption(Ia).addOption(Ea).addOption(Ca).addOption(N()).addHelpText("after",y(Tm(t))).showHelpAfterError("(add --help for additional information)").addCommand(wn(t).name("get-run"),{hidden:!0}).action((r,n,o)=>r==="help"?o.help():Ta(r,n)),wn=t=>new yn.Command().name(ze).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(Rn(t))).allowUnknownOption().addOption(pt()).addOption(N()).addOption(Ra).addOption(nt()).addOption(_a).addOption(wa).addOption(ya).addOption(Oa).action(aa);var Qe=require("@commander-js/extra-typings");var ym=p.extend("cli");async function Aa(t){await R(async e=>{ms(ls(e));let r=mt();ym("Config: %o",E(r.values)),await nn()},t)}var Rm=p.extend("cli");async function Sa(t){await R(async e=>{us(fs(e));let r=mt();Rm("Config: %o",E(r.values)),await on()},t)}var Gt="cache",Xe=t=>[{comment:"Save files to the cache under an ID",commands:[`${t} ${Gt} 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} ${Gt} set --key <record-key> --preset last-run`]}],Ze=t=>[{comment:"Restore the files saved in the cache under an ID",commands:[`${t} ${Gt} get --key <record-key> --id <id>`]},{comment:"Restore Playwright's .last-run.json from the cache, to rerun only the failed tests",commands:[`${t} ${Gt} get --key <record-key> --preset last-run`]},{comment:"Restore Playwright's .last-run.json to another folder",commands:[`${t} ${Gt} get --key <record-key> --preset last-run --output-dir <output-dir>`]}],Pa=t=>new Qe.Command().command(Gt).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([...Xe(t),...Ze(t)])).showHelpAfterError("(add --help for additional information)").allowUnknownOption().addCommand(wm(t)).addCommand(_m(t)),wm=t=>new Qe.Command().name("set").description("Save files to the cache").addHelpText("after",y(Xe(t))).allowUnknownOption().addOption(j()).addOption(Xo).addOption(es).addOption(ts).addOption(N()).addOption(os).addOption(Jr).addOption(Vr).addOption(cs).action(Sa),_m=t=>new Qe.Command().name("get").description("Restore files from the cache").addHelpText("after",y(Ze(t))).allowUnknownOption().addOption(j()).addOption(Zo).addOption(rs).addOption(ns).addOption(ss).addOption(N()).addOption(Jr).addOption(Vr).addOption(as).action(Aa);var va=require("@commander-js/extra-typings");var Om=p.extend("cli");async function Da(t){await R(async({key:e,...r})=>{Ys({...r,recordKey:e});let n=Be();Om("Config: %o",E(n??{})),await an()},t)}var Ua=require("@commander-js/extra-typings");var ba=jt(" (required unless --run-id is set)"),Na=new Ua.Option("--run-id <id>","the ID of the run to cancel, as printed when the run was created; wins over --ci-build-id").env(P(et,"runId"));var Kt="cancel",tr="run",ie=t=>[{comment:"Cancel the run recorded under a CI build ID",commands:[`${t} ${tr} ${Kt} --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} ${tr} ${Kt} --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() }}
|
|
36
|
+
run: npx ${t} ${tr} ${Kt}`]}],er=(t,{deprecated:e=!1}={})=>{let r=new va.Command().name(Kt).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(ie(t))).allowUnknownOption().addOption(j()).addOption(nt()).addOption(ba).addOption(Na).addOption(N()).action(Da);return e&&r.hook("preAction",()=>{process.stderr.write(`'${t} ${Kt}' is deprecated and will be removed in a future version. Use '${t} ${tr} ${Kt}'.
|
|
37
|
+
`)}),r};var ic=require("@commander-js/extra-typings");var ht=require("@commander-js/extra-typings"),La=f(require("globby")),ae=(r=>(r.junit="junit",r.cypressJson="cypress-json",r))(ae||{}),rr=t=>new ht.Option("--input-format <format>",["the format of the reports to convert",t].filter(Boolean).join(" ")).choices(Object.values(ae)),nr=t=>new ht.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(xm),or=new ht.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"),ce=(s=>(s.cypress="cypress",s.postman="postman",s.node="node",s.vitest="vitest",s.wdio="wdio",s))(ce||{}),sr=t=>new ht.Option("--framework <framework>",`the test framework that wrote the reports ${t}`).choices(Object.values(ce)),ir=new ht.Option("--framework-version <version>","the version of the test framework that wrote the reports");function xm(t){let e=t.split(",").map(n=>n.trim()),r=La.sync(e);if(r.length===0)throw new ht.InvalidArgumentError("No files found with the provided patterns");return r}var Ba={debug:O.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 Am=p.extend("config"),Sm=["inputFormat","inputFiles","framework"],_n=null;function Fa(t){_n=U(Ba,Sm,{...t,framework:t?.framework??(t?.inputFormat==="cypress-json"?"cypress":void 0)}),Am("Resolved config: %o",_n)}function ar(){return _n}function Ma(t){return{inputFiles:t.inputFile,inputFormat:t.inputFormat,outputDir:t.outputDir,framework:t.framework,frameworkVersion:t.frameworkVersion,debug:t.debug}}var bn=f(require("fs-extra")),B=require("path");var Ka=require("lodash"),Ha=f(require("crypto"));var Q=require("path"),pr=async(t,e,r,n)=>{if(t)for(let o of t)try{let s=(0,Q.resolve)(n,o.path),i=(0,Q.relative)(n,s);if(i.startsWith("..")||(0,Q.isAbsolute)(i)){p("Skipping artifact outside workspace: %s (resolved: %s)",o.path,s);continue}let a=`${W(e+o.path)}.${(0,Q.extname)(o.path).slice(1)||"bin"}`;await Ce(s,(0,Q.join)(r,a)),o.path=(0,Q.join)("artifacts",a)}catch(s){p("Failed to copy artifact %s: %o",o.path,s)}};function ja(t){let e=Ga(t.properties?.property??t.property);return cr(e,"currents.artifact.instance.","spec")}function $a(t){let e=Ga(t.properties?.property),r=cr(e,"currents.artifact.test.","test"),n=new Map;Pm(e).forEach((i,a)=>{n.has(a)||n.set(a,[]),n.get(a).push(...i)});let s=cr(e,"currents.artifact.attempt.","attempt");return s.length>0&&(n.has(0)||n.set(0,[]),n.get(0).push(...s)),{testArtifacts:r,attemptArtifacts:n}}function Pm(t){let e=new Map,r=/^currents\.artifact\.attempt\.(\d+)\.(.+)$/,n=new Map;for(let o of t){let s=o.value??o._;if(!o.name||!s)continue;let i=o.name.match(r);if(!i)continue;let[,a,u]=i,d=parseInt(a,10);n.has(d)||n.set(d,[]),n.get(d).push({name:`currents.artifact.attempt.${u}`,value:s})}for(let[o,s]of n.entries()){let i=cr(s,"currents.artifact.attempt.","attempt");i.length>0&&e.set(o,i)}return e}function cr(t,e,r){let n=[],o={};for(let s of t){let i=s.value??s._;if(!s.name||!i||!s.name.startsWith(e))continue;let a=s.name.slice(e.length);/^\d+\./.test(a)||["path","type","contentType","name"].includes(a)&&(o[a]&&(ka(o)&&n.push({...o,level:r}),o={}),o[a]=i)}return ka(o)&&n.push({...o,level:r}),n}function ka(t){return!!(t.path&&t.type&&t.contentType)}function Ga(t){return t?Array.isArray(t)?t:[t]:[]}function Ja(t,e,r,n){let o=ot(t.failure),s=o.length>0,i=e?.timestamp??"",a="skipped"in t,u=a?"pending":s?"failed":"passed",{testArtifacts:d,attemptArtifacts:l}=$a(t);return{_t:mr(i),testId:dr(pe(t.name,n).join(", "),n),title:pe(t.name,n),state:u,isFlaky:Dm(),expectedStatus:"passed",timeout:Um(),location:bm(e?.file??""),retries:Nm(o),artifacts:d,attempts:vm(t,o,Sn(i),r,l,a)}}function dr(t,e){let r=`${t}${e}`;return Ha.default.createHash("sha256").update(r).digest("hex").substring(0,16)}function ur(t,e){let r=t.slice(0,-1).join(" "),n=t[t.length-1];return dr([r,n].filter(Boolean).join(", "),e)}function mr(t){return Va(t)?new Date(t).getTime():new Date().getTime()}function Sn(t){return Va(t)?new Date(t).toISOString():new Date().toISOString()}function Va(t){let e=new Date(t);return!isNaN(e.getTime())}function pe(t,e){return[e,t].filter(Boolean)}function Dm(){return!1}function Um(){return 0}function bm(t){return{column:1,file:t,line:1}}function Nm(t){let e=0;return t.forEach(r=>{typeof r!="string"&&e++}),e}function vm(t,e,r,n,o,s){let i=t.time?lr(t.time):0,a=Array.from(o.values()).flat();return s?[{_s:"pending",attempt:0,startTime:r,steps:[],duration:i,status:"skipped",stdout:On(t?.["system-out"]),stderr:xn(t?.["system-err"]),artifacts:a,errors:[],error:void 0}]:e.length===0?[{_s:"passed",attempt:0,startTime:r,steps:[],duration:i,status:"passed",stdout:On(t?.["system-out"]),stderr:xn(t?.["system-err"]),artifacts:a,errors:[],error:void 0}]:e.reduce((u,d,l)=>{if(d!=="true"&&d!=="false"){let m=Lm(d);u.push({_s:"failed",attempt:l,startTime:Bm(n,r),steps:[],duration:i,status:"failed",stdout:On(t?.["system-out"]),stderr:xn(t?.["system-err"]),artifacts:o.get(l),errors:m,error:m[0]})}return u},[])}function On(t){return t?[t]:[]}function xn(t){return t?[t]:[]}function Lm(t){return t==="true"||t==="false"?[]:[typeof t=="string"?{message:t}:{message:t.message,stack:t._,value:t.type}]}function Bm(t,e){let r=mr(e)+t;return new Date(r).toISOString()}function ot(t){return t?Array.isArray(t)?t:[t]:[]}function Fm(t){return Math.round(t*1e3)}function lr(t){let e=parseFloat(t);return isNaN(e)?0:Fm(e)}function fr(t,e,r){let n=(0,Ka.isNumber)(r)&&r>0,o=!!t.id&&An(e,"id",t.id);if(t.file){let s=An(e,"file",t.file);return s&&!o?`${t.file} - ${t.id}`:s&&n?`${t.file} - ${r}`:t.file}if(t.name){let s=An(e,"name",t.name);return s&&!o?`${t.name} - ${t.id}`:s&&n?`${t.name} - ${r}`:t.name}return t.id?o&&n?`${t.id} - ${r}`:t.id:n?`unknown - ${r}`:"unknown"}function An(t,e,r){return t.filter(o=>o[e]===r).length>1}function Ya(t){let e=[];return t.forEach(r=>{let n=ot(r.testsuites?.testsuite),o={name:r.testsuites?.name??"No name",tags:[],tests:[]};n?.forEach(s=>{let i=fr(s,n);ot(s?.testcase)?.forEach(u=>{let d={title:pe(u.name,i),spec:i,tags:[],testId:dr(pe(u.name,i).join(", "),i)};o.tests.push(d)})}),e.push(o)}),e}function Pn(t){let e=new Map;return t.forEach(({groupId:r,spec:n,results:o})=>{let s=e.get(r)??{name:r,tags:[],tests:[]};e.set(r,s),o.tests.forEach(({title:i,testId:a})=>{s.tests.push({title:i,spec:n,tags:[],testId:a})})}),Array.from(e.values())}var qa=require("fs-extra"),Ht=require("path");async function za(t){return Promise.all(t.map(async e=>{let r=await(0,qa.readJson)(e);if(!Array.isArray(r?.runs))throw new Error(`${e} is not a Cypress run result: it has no "runs" list. Save the results of the "after:run" event or of cypress.run().`);return r}))}function Qa(t){let e=new Map;for(let r of t)for(let n of r.runs){if(n.tests.length===0){n.error&&I("Skipping %s, Cypress could not load it and it has no test results: %s",n.spec.relative,$m(n.error));continue}let o=Mm(n,r.browserName),s=`${o.groupId}${o.spec}`;if(e.has(s))throw new Error(`The results have ${o.spec} in ${o.groupId} more than once. Upload the results of each spec file once: split the spec files between the machines, or upload the files of each run with its own --ci-build-id.`);e.set(s,o)}return e}function Mm(t,e){let r=t.spec.relative,n=t.spec.absolute.slice(0,-r.length),o=d=>(0,Ht.relative)(n,d),s=t.screenshots.map(d=>({...d,path:o(d.path)})),i=[],a=new Date(t.stats.startedAt).getTime(),u=t.tests.map(d=>{let l=km(d,r,a);return a+=d.duration,l});for(let d of s){let l={path:d.path,type:"screenshot",contentType:"image/png",name:(0,Ht.basename)(d.path)},m=jm(d.path,t.tests),h=m&&u[m.testIndex].attempts[m.attempt];h?h.artifacts=[...h.artifacts??[],l]:i.push(l)}if(t.video){let d={path:o(t.video),type:"video",contentType:"video/mp4",name:(0,Ht.basename)(t.video)},l=u.flatMap(m=>m.attempts).filter(m=>m.status==="failed");for(let m of l)m.artifacts=[...m.artifacts??[],{...d}];l.length===0&&i.push(d)}return{groupId:e,spec:r,startTime:t.stats.startedAt,artifacts:i,results:{stats:{suites:t.stats.suites,tests:t.stats.tests,passes:t.stats.passes,pending:t.stats.pending,skipped:t.stats.skipped,failures:t.stats.failures,flaky:u.filter(d=>d.isFlaky).length,wallClockStartedAt:t.stats.startedAt,wallClockEndedAt:t.stats.endedAt,wallClockDuration:t.stats.duration},tests:u}}}function km(t,e,r){let n=Math.round(t.duration/t.attempts.length),o=t.attempts.map(i=>i.state).lastIndexOf("failed"),s=t.attempts.map((i,a)=>{let u=a===o&&t.displayError?[Gm(t.displayError)]:[];return{_s:Wa(i.state),attempt:a,startTime:new Date(r+a*n).toISOString(),steps:[],duration:n,status:Km(i.state),artifacts:[],errors:u,error:u[0]}});return{_t:r,testId:ur(t.title,e),title:t.title,state:Wa(t.state),isFlaky:t.state==="passed"&&t.attempts.some(i=>i.state==="failed"),retries:t.attempts.length-1,expectedStatus:"passed",timeout:0,location:{file:e,line:1,column:1},artifacts:[],attempts:s}}function jm(t,e){let r=(0,Ht.basename)(t,".png").match(/^(.*?)(?: \(failed\))?(?: \(attempt (\d+)\))?$/);if(!r)return null;let[,n,o]=r,s=e.findIndex(i=>i.title.join(" -- ")===n);return s===-1?null:{testIndex:s,attempt:o?Number(o)-1:0}}function $m(t){let e=t.split(`
|
|
38
|
+
`).map(r=>r.trim());return e.find(r=>/^\w*Error\b/.test(r))??e[0]}function Gm(t){let[e]=t.split(`
|
|
39
|
+
`),r=e.match(/^(\w*Error): (.*)$/);return{message:r?r[2]:e,value:r?.[1],stack:t}}function Wa(t){return t==="passed"||t==="failed"?t:"pending"}function Km(t){return t==="passed"||t==="failed"?t:"skipped"}async function $(t){let e=new Map;return t.forEach(r=>{let n=ot(r.testsuites?.testsuite),o=r.testsuites?.name??"No name";n.forEach((s,i)=>{let a=fr(s,n,i),u=Dn(s,o,a),d=W(o+a);u.results.tests.length!==0&&e.set(d,u)})}),e}function Dn(t,e,r){let n=Sn(t.timestamp??""),o=t.time?lr(t.time):0,s=new Date(mr(t.timestamp??"")+o),i=ot(t.testcase),a=[t["system-out"],t["system-err"],...i.flatMap(g=>[g["system-out"],g["system-err"]])].filter(g=>g).join(`
|
|
40
|
+
`),u=0,d=i.filter(g=>"failure"in g).length,l=i.filter(g=>"skipped"in g).length,m=i.length-d-l;return{groupId:e,spec:r,startTime:n,artifacts:ja(t),_stdout:a,results:{stats:{suites:1,tests:i.length,passes:m,pending:l,skipped:0,failures:d,flaky:0,wallClockStartedAt:n,wallClockEndedAt:s.toISOString(),wallClockDuration:o},tests:i?.map(g=>(i[0]?.time&&(u+=lr(i[0].time)),Ja(g,t,u,r)))}}}async function Xa(t){let e=new Map;for(let r of t){let n=ot(r.testsuites?.testsuite),o=n.find(u=>u.file)?.file;if(!o){(await $([r])).forEach((d,l)=>e.set(l,d));continue}let s=r.testsuites?.name??"No name",i=n.flatMap(u=>ot(u.testcase)),a=Dn({...n[0],file:o,timestamp:Jm(n[0].timestamp),time:r.testsuites?.time,testcase:i},s,o);a.results.tests.forEach((u,d)=>{u.title=Hm(i[d]),u.testId=ur(u.title,o)}),a.results.tests.length!==0&&e.set(W(s+o),a)}return e}function Hm({name:t="",classname:e=""}){return!e||!t.endsWith(e)?[t||e]:[t.slice(0,-e.length).trim(),e].filter(Boolean)}function Jm(t){return!t||/(Z|[+-]\d\d:?\d\d)$/.test(t)?t:`${t}Z`}async function Za({inputFormat:t,framework:e,parsedXMLArray:r}){return t==="junit"?Vm(e,r):new Map}async function Vm(t,e){switch(t){case"cypress":return Xa(e);case"node":return $(e);case"postman":return $(e);case"vitest":return $(e);case"wdio":return $(e);default:return I("Unsupported framework: %s",t),new Map}}var tc=require("fs-extra"),ec=require("xml2js");async function rc(t){let e=await Promise.all(t.map(n=>(0,tc.readFile)(n,"utf-8"))),r=(await Promise.all(e.map(Ym))).filter(Boolean);return e.length!==r.length&&I("Some files could not be parsed. Enable debug logging for more details"),r}async function Ym(t){let e=t.trim();if(!e)return null;try{return await(0,ec.parseStringPromise)(e,{explicitArray:!1,mergeAttrs:!0})||null}catch(r){return p("Error parsing XML input",r),null}}function Un(t){return{framework:"junit",frameworkVersion:t.frameworkVersion??null,frameworkConfig:{originFramework:t.framework,originFrameworkVersion:t.frameworkVersion}}}async function nc(){try{let t=ar();if(!t)throw new Error("Config is missing!");t.outputDir&&await zm(t.outputDir,t.inputFiles);let e=t.outputDir?await _t(t.outputDir):await ao(process.cwd(),".currents"),r=await _t((0,B.join)(e,"instances")),n=t.inputFormat==="cypress-json"?await qm(t,e):await Wm(t,e);if(n.size===0)throw new Error(`No test results found in ${t.inputFiles.join(", ")}. Check that the tests ran and that the reports are the files the tests wrote.`);let o=await _t((0,B.join)(e,"artifacts")),s=process.cwd();return await Promise.all(Array.from(n.values()).map(async i=>{if(await pr(i.artifacts,i.spec,o,s),i._stdout){let a=`${W(i.spec)}.stdout.txt`;await wt((0,B.join)(o,a),i._stdout),i.artifacts||(i.artifacts=[]),i.artifacts.push({path:(0,B.join)("artifacts",a),type:"stdout",contentType:"text/plain",level:"spec"}),delete i._stdout}for(let a of i.results.tests){await pr(a.artifacts,a.testId,o,s);for(let u of a.attempts)await pr(u.artifacts,a.testId+u.attempt,o,s)}})),await Promise.all(Array.from(n.entries()).map(([i,a])=>wt((0,B.join)(r,`${W(i)}.json`),JSON.stringify(a)))),T("[currents] Conversion completed, report saved to: %s",e),e}catch(t){throw p("Failed to convert: %o",t),t}}async function Wm(t,e){let r=Un(t);p("Report config:",r),T("[currents] Convertion files: %s",t.inputFiles.join(", ")),await wt((0,B.join)(e,"config.json"),JSON.stringify(r));let n=await rc(t.inputFiles);if(n.length===0)throw new Error("No valid XML JUnit report was found.");let o=await Za({inputFormat:t.inputFormat,framework:t.framework,parsedXMLArray:n}),s=t.framework==="cypress"?Pn(o):Ya(n);return await wt(ft(e),JSON.stringify(s)),o}async function qm(t,e){T("[currents] Convertion files: %s",t.inputFiles.join(", "));let r=await za(t.inputFiles),n=Un({...t,frameworkVersion:t.frameworkVersion??r[0]?.cypressVersion});p("Report config:",n),await wt((0,B.join)(e,"config.json"),JSON.stringify(n));let o=Qa(r);return await wt(ft(e),JSON.stringify(Pn(o))),o}async function zm(t,e){let r=(0,B.resolve)(t),n=new Set(e.map(a=>(0,B.resolve)(a))),o=[(0,B.join)(r,"config.json"),ft(r),(0,B.join)(r,"instances"),(0,B.join)(r,"artifacts")],s=[...n].find(a=>o.some(u=>a===u||a.startsWith(u+B.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 bn.default.pathExists(r)?await oc(r,n):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 oc(t,e){for(let r of await bn.default.readdir(t,{withFileTypes:!0})){let n=(0,B.join)(t,r.name),o=r.isDirectory()?await oc(n,e):e.has(n)?void 0:n;if(o)return o}}var Qm=p.extend("cli");async function Nn(t){return Fa(Ma(t)),Qm("Config: %o",ar()),nc()}async function sc(t){await R(async e=>{await Nn(e)},t)}var vn="convert",Xm=t=>[{comment:"Convert JUnit test reports to the Currents format, to check the result before an upload",commands:[`${t} ${vn} --input-format junit --input-file "./*.xml" --framework postman`]}],ac=t=>new ic.Command().name(vn).command(vn).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(Xm(t))).addOption(N()).addOption(rr("(required)")).addOption(nr("(required)")).addOption(or).addOption(sr("(required, except with cypress-json)")).addOption(ir).action(r=>sc(r));var dc=require("@commander-js/extra-typings");var Ln=f(require("fs-extra")),gr=f(require("path"));function Zm(t=__dirname){let e=Te("package.json",t);if(!e)throw new Error("The docs folder is missing from this package");return gr.default.join(e,"docs")}function tl(t,e){let r=e.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n)+/),n=r?.[1].match(/^description:[ \t]*(.+?)\r?$/m)?.[1];if(!r||!n)throw new Error(`docs/${t}.md has no description in its front matter`);return{name:t,description:n,body:e.slice(r[0].length)}}async function el(t=Zm()){let e=(await Ln.default.readdir(t)).filter(r=>r.endsWith(".md")).sort();return Promise.all(e.map(async r=>tl(gr.default.basename(r,".md"),await Ln.default.readFile(gr.default.join(t,r),"utf8"))))}function cc(t){let e=Math.max(...t.map(r=>r.name.length));return t.map(r=>` ${r.name.padEnd(e)} ${r.description}
|
|
41
|
+
`).join("")}async function pc(t,e){let r=await el();if(!e){await Zt(`Topics:
|
|
42
|
+
${cc(r)}
|
|
43
|
+
Run '${t} docs <topic>' to print a guide.
|
|
44
|
+
`);return}let n=r.find(o=>o.name===e);if(!n)throw new Error(`Unknown topic "${e}". Topics:
|
|
45
|
+
${cc(r)}`);await Zt(n.body)}var Bn="docs",rl=t=>[{comment:"List the topics",commands:[`${t} ${Bn}`]},{comment:"Print the guide to CI setup",commands:[`${t} ${Bn} ci-setup`]}],uc=t=>new dc.Command().name(Bn).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(rl(t))).action(async e=>{await R(()=>pc(t,e),{})});var Wn=require("@commander-js/extra-typings");var{apiKey:nl,recordKey:ol,projectId:sl,ciBuildId:il,machineId:al,debug:cl}=O,G={apiKey:nl,recordKey:ol,projectId:sl,ciBuildId:il,machineId:al,sessionId:{name:"Session ID",env:"CURRENTS_SESSION_ID",cli:"--session-id"},title:{name:"Title",cli:"--title"},debug:cl};var hr=p.extend("config");function mc(t){let e=U(G,["projectId","title"],t,Ir);return hr("Resolved config: %o",E(e)),e}function lc(t){let e=U(G,[],t,Ir);return hr("Resolved config: %o",E(e)),e}function fc(t){let e=U(G,[],t,Ir);return hr("Resolved config: %o",E(e)),e}function gc(t){let e=U(G,["projectId"],t,Ir);return hr("Resolved config: %o",E(e)),e}function Ir(t){if(!(t.recordKey||t.apiKey))throw new tt(`${G.recordKey.name} or ${G.apiKey.name} is required. Set ${G.recordKey.env} or ${G.apiKey.env}, or pass ${G.recordKey.cli} or ${G.apiKey.cli}`)}var de=f(require("fs-extra")),St=f(require("path"));var Ic=f(require("path"));var hc=["trace","screenshot","video","attachment"];var pl=["image/png","image/jpeg","image/webp","image/gif"],Ec=t=>Ic.default.extname(t).toLowerCase()===".zip";function Cc(t){return hc.includes(t)}function Fn(t){return Ec(t)?"application/zip":dn(t)?.contentType??"application/octet-stream"}function dl(t){return Ec(t)?"trace":dn(t)?.type??"attachment"}function Mn(t,e){let r=dl(t);return e.includes(r)?r:"attachment"}function Tc(t,e,r){if(!r.includes(e))throw new Error(`Cannot attach "${t}" as type "${e}" here. The target takes: ${r.join(", ")}`)}function yc(t,e){let r=Fn(t);if(!(e==="attachment"||e==="trace"&&r==="application/zip"||e==="screenshot"&&pl.includes(r)||e==="video"&&r.startsWith("video/")))throw new Error(`Cannot attach "${t}" as type "${e}": its content type is ${r}`)}var Rc=f(require("archiver")),At=f(require("fs-extra")),Er=f(require("path")),wc=f(require("unzipper")),_c=require("tmp-promise");async function Oc(t){try{return(await wc.default.Open.file(t)).files.some(r=>/^(trace|test|\d+-trace)\.trace$/.test(r.path))}catch{return!1}}var xc=/^trace-.*\.trace$/,ul=/^trace-.*\.network$/;async function kn(t){return(await At.default.readdir(t)).some(r=>xc.test(r))}function ml(t){if(!t)return!1;try{let e=JSON.parse(t),r=e.snapshot?.response;if(e.type!=="resource-snapshot"||!r)return!0;let n=r.status>=200&&r.status<400,o=/javascript|ecmascript/i.test(r.content?.mimeType??"");return!(n&&o)}catch{return!0}}async function Ac(t,e){return(await At.default.readdir(t)).filter(n=>e.test(n)).sort().map(n=>Er.default.join(t,n))}async function ll(t){return(await Promise.all((await Ac(t,xc)).map(r=>At.default.readFile(r,"utf8")))).map(r=>r.endsWith(`
|
|
38
46
|
`)?r:r+`
|
|
39
|
-
`).join("")}async function
|
|
40
|
-
`));return r.filter(
|
|
41
|
-
`)}async function
|
|
42
|
-
${
|
|
43
|
-
`)}async function
|
|
44
|
-
`):T("Session started: %s",e.sessionId),e}async function
|
|
47
|
+
`).join("")}async function fl(t){let e=await Ac(t,ul),r=[];for(let n of e)r.push(...(await At.default.readFile(n,"utf8")).split(`
|
|
48
|
+
`));return r.filter(ml).join(`
|
|
49
|
+
`)}async function Sc(t){let{path:e,cleanup:r}=await(0,_c.dir)({unsafeCleanup:!0}),n=Er.default.join(e,"trace.zip");try{let o=(0,Rc.default)("zip",{zlib:{level:9}}),s=At.default.createWriteStream(n),i=new Promise((a,u)=>{s.on("close",()=>a()),s.on("error",u),o.on("error",u)});o.pipe(s),o.append(await ll(t),{name:"trace.trace"}),o.append(await fl(t),{name:"trace.network"});for(let a of["screencast","resources"]){let u=Er.default.join(t,a);await At.default.pathExists(u)&&o.directory(u,a)}await o.finalize(),await i}catch(o){throw await r(),o}return{zipPath:n,cleanup:r}}var gl=1024**3,Pc=/^\.env($|[._-])|^\.envrc$|\.env$/i,hl=/\.(pem|key)$|^id_(rsa|ed25519|ecdsa|dsa)/i;function Il(t){if(Pc.test(t))throw new Error(`"${t}" looks like an environment file with secrets and is not attached`)}async function jn(t,e,r){Il(e);let n=r.type??Mn(e,r.allowedTypes);r.type?(yc(e,r.type),Tc(e,r.type,r.allowedTypes)):n==="trace"&&!await Oc(t)&&(n="attachment");let o=await de.default.stat(t);if(o.size>gl)throw new Error(`"${e}" is larger than 1 GiB`);if(o.size===0)throw new Error(`"${e}" is empty`);return{path:t,name:e,type:n,contentType:Fn(e),sizeBytes:o.size}}async function El(t,e,r){let n=[],o=async s=>{for(let i of await de.default.readdir(s,{withFileTypes:!0})){let a=St.default.join(s,i.name),u=St.default.relative(t,a).split(St.default.sep).join("/");if(i.name.startsWith("."))I(`Skipping the hidden file "${a}"`);else if(hl.test(i.name)||Pc.test(i.name))I(`Skipping "${a}", which looks like a key or secrets file`);else if(i.isSymbolicLink())I(`Skipping the link "${a}"`);else if(i.isDirectory())await kn(a)?await r(a,St.default.posix.dirname(u)):await o(a);else if(i.isFile()){if((await de.default.stat(a)).size===0){I(`Skipping the empty file "${a}"`);continue}n.push(await jn(a,u,e))}}};return await o(t),n}async function Dc(t,e){let r=[],n=[],o=async()=>{await Promise.all(n.map(i=>i()))},s=async(i,a=".")=>{let u=await Sc(i);n.push(u.cleanup);let d=St.default.posix.join(a,`trace-${Lr(8)}.zip`);r.push(await jn(u.zipPath,d,{...e,type:e.type??Mn("trace.zip",e.allowedTypes)}))};try{for(let i of t){let a=await de.default.stat(i).catch(()=>null);if(!a)throw new Error(`"${i}" does not exist`);if(!a.isDirectory()){r.push(await jn(i,St.default.basename(i),e));continue}if(await kn(i)){await s(i);continue}r.push(...await El(i,e,s))}}catch(i){throw await o(),i}if(r.length===0)throw new Error("There are no files to attach");return{files:r,cleanup:o}}var Uc={run:["attachment"],instance:["attachment","video","screenshot"],test:["attachment"],attempt:["attachment","video","screenshot","trace"]},bc=["attachment","video","screenshot","trace"];function Nc(t){return t.testId||t.testTitle?t.attempt===void 0?"test":"attempt":t.instanceId||t.spec?"instance":"run"}var vc=4;async function Lc(t){let e=[];for(let r=0;r<t.length;r+=vc)e.push(...await Promise.all(t.slice(r,r+vc).map(async({file:n,uploadUrl:o,uploadHeaders:s})=>{try{return await Ds({name:n.name,path:n.path,sizeBytes:n.sizeBytes,uploadUrl:o,contentType:n.contentType,headers:s}),{file:n}}catch(i){return{file:n,error:i}}})));return e}var Cl=p.extend("files");function Tl(t=[]){let e=new Map;for(let r of t){let n=r.indexOf("=");if(n<1)throw new Error(`--meta expects key=value, got "${r}"`);let o=r.slice(0,n);if(!/^[A-Za-z0-9_-]{1,64}$/.test(o))throw new Error(`--meta key "${o}" can only hold up to 64 letters, digits, "_" and "-"`);let s=r.slice(n+1);if(s.length>256)throw new Error(`--meta value of "${o}" is longer than 256 characters`);e.set(o,s)}return e.size>0?Object.fromEntries(e):void 0}function yl(t){if(t!==void 0){if(!Cc(t))throw new Error(`--type must be one of trace, screenshot, video, attachment, got "${t}"`);return t}}var Rl=50,wl=100*1024**2,Bc=200;function _l(t,e={count:Rl,bytes:wl}){let r=[],n=0;for(let o of t){let s=r[r.length-1];!s||s.length>=e.count||n+o.sizeBytes>e.bytes?(r.push([o]),n=o.sizeBytes):(s.push(o),n+=o.sizeBytes)}return r}async function $n(t){if(!t.credentials.apiKey&&!t.credentials.recordKey)throw new Error("Pass an API key or a record key");let e=yl(t.type),r=Tl(t.meta),n=t.target??{},o="sessionId"in t.owner?bc:Uc[Nc(n)],{files:s,cleanup:i}=await Dc(t.paths,{type:e,allowedTypes:o});if(s.length>Bc)throw await i(),new Error(`Found ${s.length} files to attach; the API takes at most ${Bc}. Pass the folders or files you need instead`);let a=[],u=[];try{for(let d of _l(s)){let l=d.map(g=>({name:g.name,type:g.type,contentType:g.contentType,sizeBytes:g.sizeBytes,caption:t.caption,meta:r})),m;try{m=await Jo(t.credentials,t.owner,n,l)}catch(g){throw new Error(`${g.message}
|
|
50
|
+
${a.length} of ${s.length} files were attached before this`)}if(Cl("Created %d attachments at level %s",m.attachments.length,m.level??"session"),m.attachments.length!==d.length)throw new Error(`The API returned ${m.attachments.length} upload URLs for ${d.length} files`);let h=await Lc(d.map((g,_)=>{if(m.attachments[_].name!==g.name)throw new Error(`The API answered "${m.attachments[_].name}" where "${g.name}" was declared`);let{uploadUrl:k,uploadHeaders:Ut}=m.attachments[_];return{file:g,uploadUrl:k,uploadHeaders:Ut}}));for(let g of h)g.error?(C("Failed %s: %s",g.file.name,g.error.message),u.push(g)):(T("Attached %s (%s)",g.file.name,g.file.type),a.push(g.file))}}finally{await i().catch(d=>I("Could not remove temporary files: %s",d.message))}if(u.length>0)throw new Error(`${u.length} of ${s.length} files could not be uploaded`);return{files:a.map(({name:d,type:l,sizeBytes:m})=>({name:d,type:l,sizeBytes:m}))}}var Pt=f(require("fs-extra")),ue=f(require("path")),Ol=".currents-session",Fc=()=>ue.default.join(process.cwd(),Ol,"session.json");async function xl(t){let e=ue.default.join(t,".gitignore");await Pt.default.pathExists(e)||await Pt.default.writeFile(e,`*
|
|
51
|
+
`)}async function Mc(t){let e=Fc();await Pt.default.ensureDir(ue.default.dirname(e)),await xl(ue.default.dirname(e)),await Pt.default.writeJson(e,t,{spaces:2})}async function Al(){let t=Fc();if(!await Pt.default.pathExists(t))return null;let e=await Pt.default.readJson(t),r=e?.sessionId||e?.runId;if(typeof r!="string"||!r.trim())return null;let n=typeof e.projectId=="string"?e.projectId:void 0;return{sessionId:r,projectId:n}}async function Gn(t){if(t)return t;let e=await Al();if(!e)throw new Error('No session found. Run "currents session start" first, or pass --session-id');return e.sessionId}var Sl=p.extend("session");async function Pl(){try{let{sha:t,branch:e,message:r,authorName:n,authorEmail:o,remoteOrigin:s}=await oe();return{sha:t,branch:e,message:r,authorName:n,authorEmail:o,remoteOrigin:s}}catch(t){Sl("No git info: %o",t);return}}function Dl(t){if(t)return/^\d+$/.test(t)?{id:t}:{link:t}}function kc(){let{provider:t,params:e}=st();return{provider:t,params:e}}function Ul(){if(st().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 jc(t){let e=await Ho({apiKey:t.apiKey,recordKey:t.recordKey},{projectId:t.projectId,title:t.title,status:t.status,error:t.error,tags:t.tag,commit:await Pl(),ci:kc(),pr:Dl(t.pr)});return await Mc({sessionId:e.sessionId,projectId:t.projectId}),t.json?process.stdout.write(JSON.stringify({sessionId:e.sessionId})+`
|
|
52
|
+
`):T("Session started: %s",e.sessionId),e}async function $c(t,e){let r=await Gn(t.sessionId);return $n({credentials:{apiKey:t.apiKey,recordKey:t.recordKey},owner:{sessionId:r},paths:e,type:t.type,caption:t.caption,meta:t.meta})}async function Gc(t){let e=await Gn(t.sessionId),r=await Vo({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 Kc(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||Ul(),$n({credentials:{apiKey:t.apiKey,recordKey:t.recordKey},owner:t.ciBuildId?{projectId:t.projectId,ciBuildId:t.ciBuildId}:{projectId:t.projectId,ci:kc()},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 D=require("@commander-js/extra-typings");var Hc=t=>P(G,t),Jt="(required unless --api-key is set)",Vt="(used when --key is not set; needs write access)",Jc=jt(". Leave it out only if the run was recorded without one, on a CI the reporters recognize"),Vc=new D.Option("--machine-id <id>","the CI machine the files come from; run-level files are listed by machine when it is set").env(Hc("machineId")),Hn=new D.Option("--session-id <id>",'the session to use instead of the one saved by "session start"').env(Hc("sessionId")),Yc=new D.Option("--title <text>","what the session shows, used as the session title (required)"),Wc=new D.Option("--status <status>","the result of the session").choices(["passed","failed"]).default("passed"),qc=new D.Option("--error <text>","what went wrong, for a failed session"),zc=$t("tags to add to the session"),Qc=new D.Option("--pr <url|number>","the pull request the session is about; by default taken from the CI environment"),Xc=new D.Option("--json",'print the session ID as JSON on stdout, e.g. {"sessionId": "..."}'),Zc=new D.Option("--spec <spec>","attach to this spec file of the run"),tp=new D.Option("--test-title <title>",'attach to this test of --spec: the full title joined with " > ", or its last part'),ep=new D.Option("--group <id>","the group of the spec file; a spec that runs once per Playwright project matches more than once without it"),rp=new D.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}),np=["trace","screenshot","video","attachment"],op="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",sp=new D.Option("--type <type>",`the type of every file; ${op}`).choices(np),ip=new D.Option("--type <type>",`the type of every file; ${op}. 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(np),Cr="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",Tr=new D.Option("--caption <text>","a short description shown with each file"),bl=(t,e=[])=>[...e,t],yr=new D.Option("--meta <key=value>","a label for each file; repeat for more").argParser(bl),Kn=["1","3","7"],ap=new D.Option("--expires-in-days <days>","the number of days the link works").choices(Kn).default(7).argParser(t=>{if(!Kn.includes(t))throw new D.InvalidArgumentError(`Allowed choices are ${Kn.join(", ")}.`);return Number(t)});var Tp=require("@commander-js/extra-typings");var It=require("@commander-js/extra-typings");var cp=new It.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(P(z,"ciBuildId")),pp=$t("tags to add to the run").env(P(z,"tag")),dp=new It.Option("--remove-title-tags","remove tags from test names in Currents, e.g. `Test name @smoke` becomes `Test name` in the dashboard").env(P(z,"removeTitleTags")).default(!1),up=new It.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(P(z,"disableTitleTags")).default(!1),mp=new It.Option("--environment <name>","the environment to label the run with, e.g. staging").env(P(z,"environment")),lp=new It.Option("--machine-id <id>","the ID of the machine that ran the tests; by default a random value").env(P(z,"machineId")),fp=new It.Option("--fail-on-failures","exit with 1 when a test failed, after the results are uploaded; a test quarantined or skipped by a Currents action does not count").env(P(z,"failOnFailures")).default(!1),gp=new It.Option("--report-dir <folder>","the folder of the reports to upload; by default the newest folder in .currents").env(P(z,"reportDir"));var Vn=require("path");var Ep=f(require("fs"));var hp=require("tmp-promise"),Ip=async()=>{let{path:t}=await(0,hp.file)();return t};var Jn=p.extend("cli"),Rr=class{constructor(e){this.configFilePath=null;this.cliOptions=e,Jn("CLI options: %o",E(this.cliOptions)),this.parsedConfig=ei(this.cliOptions),Jn("Parsed config from CLI options: %o",E(this.parsedConfig))}async getConfigFilePath(){if(this.configFilePath)return this.configFilePath;let e=await Ip();return Ep.default.writeFileSync(e,JSON.stringify(this.parsedConfig)),Jn("CLI options temp file path: %s",e),this.configFilePath=e,e}};async function Cp(t){await R(async e=>{let r=e.inputFormat?await Nl(e):e.reportDir,n=new Rr({...e,reportDir:r});ti(n.parsedConfig);let o=Fe();T("Currents config: %o",E(o)),await In()},t)}async function Nl({inputFormat:t,inputFile:e,framework:r,frameworkVersion:n,outputDir:o,reportDir:s,debug:i}){if(o&&s&&(0,Vn.resolve)(o)!==(0,Vn.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 Nn({inputFormat:t,inputFile:e,framework:r,frameworkVersion:n,outputDir:o??s,debug:i})}var Dt="upload",vl="(required with --input-format)",me="run",Yt=t=>[{comment:"Upload test results to Currents",commands:[`${t} ${me} ${Dt} --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} ${me} ${Dt} --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} ${me} ${Dt} --key <record-key> --project-id <id> --ci-build-id <build-id> --tag tagA --tag tagB`]},{comment:"Upload test results, then fail if a test failed that no Currents action quarantined or skipped",commands:[`${t} ${me} ${Dt} --key <record-key> --project-id <id> --ci-build-id <build-id> --fail-on-failures`]},{comment:"Upload test results from another folder",commands:[`${t} ${me} ${Dt} --key <record-key> --project-id <id> --ci-build-id <build-id> --report-dir <report-dir>`]}],wr=t=>new Tp.Command().name(Dt).command(Dt).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
53
|
|
|
46
54
|
With --input-format, first convert the reports in --input-file to the Currents
|
|
47
55
|
format, then upload the converted reports. They are saved to --output-dir, or
|
|
48
56
|
--report-dir, or a new folder in .currents. A folder you name may hold only the
|
|
49
|
-
reports being converted.`).addHelpText("after",y(
|
|
50
|
-
`)!==
|
|
51
|
-
`))return!1;for(let
|
|
57
|
+
reports being converted.`).addHelpText("after",y(Yt(t))).addOption(cp).addOption(j()).addOption(nt()).addOption(pp).addOption(dp).addOption(up).addOption(mp).addOption(lp).addOption(fp).addOption(N()).addOption(gp).addOption(rr()).addOption(nr(vl)).addOption(sr("(required with --input-format junit)")).addOption(ir).addOption(or).action(r=>Cp(r));var Yn="run",_r=t=>[{comment:"Attach the Docker logs of a CI machine to the run, after the tests finished",commands:[`${t} ${Yn} 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} ${Yn} 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`]}],Ll=t=>new Wn.Command().name("attach").addHelpText("after",y(_r(t))).description("Upload files to a run recorded in CI").argument("<paths...>",Cr).addOption(j(Jt)).addOption(pt(Vt)).addOption(nt()).addOption(Jc).addOption(Vc).addOption(Zc).addOption(ep).addOption(tp).addOption(rp).addOption(ip).addOption(Tr).addOption(yr).addOption(N()).action(async(e,r)=>{await R(async({key:n,...o})=>{await Kc(gc({...o,recordKey:n}),e)},r)}),yp=t=>new Wn.Command().name(Yn).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([...Yt(t).slice(0,2),_r(t)[0],Rn(t)[0],ie(t)[0]])).showHelpAfterError("(add --help for additional information)").addCommand(wr(t)).addCommand(Ll(t)).addCommand(wn(t)).addCommand(er(t));var le=require("@commander-js/extra-typings");var Or="session",Wt=t=>{let e=`${t} ${Or} start --api-key <api-key> --project-id <id> --title "Checkout fails on empty cart" --status failed`,r=`${t} ${Or} attach before.png .playwright-mcp/traces`,n=`${t} ${Or} share --expires-in-days 7`;return{session:[{comment:"Start a session, attach what you captured and get a link to share",commands:[e,r,n]}],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:[n]}]}},Bl=t=>new le.Command().name("start").addHelpText("after",y(Wt(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(j(Jt)).addOption(pt(Vt)).addOption(nt()).addOption(Yc).addOption(Wc).addOption(qc).addOption(zc).addOption(Qc).addOption(Xc).addOption(N()).action(async e=>{await R(async({key:r,...n})=>{n.json&&Mt(),await jc(mc({...n,recordKey:r}))},e)}),Fl=t=>new le.Command().name("attach").summary("Upload screenshots, traces and other files").addHelpText("after",y(Wt(t).attach)).description("Upload files, folders or a Playwright MCP trace folder to the session").argument("<paths...>",Cr).addOption(j(Jt)).addOption(pt(Vt)).addOption(Hn).addOption(sp).addOption(Tr).addOption(yr).addOption(N()).action(async(e,r)=>{await R(async({key:n,...o})=>{await $c(lc({...o,recordKey:n}),e)},r)}),Ml=t=>new le.Command().name("share").addHelpText("after",y(Wt(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(j(Jt)).addOption(pt(Vt)).addOption(Hn).addOption(ap).addOption(N()).action(async e=>{await R(async({key:r,...n})=>{await Gc(fc({...n,recordKey:r}))},e)}),Rp=t=>new le.Command().name(Or).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(Wt(t).session)).showHelpAfterError("(add --help for additional information)").addCommand(Bl(t)).addCommand(Fl(t)).addCommand(Ml(t));var zt=require("@commander-js/extra-typings");var dt=f(require("fs-extra")),J=f(require("path"));var ut="currents-cli",qt=J.default.join(".agents","skills");function wp(t=__dirname){let e=J.default.join("skills",ut),r=Te(J.default.join(e,"SKILL.md"),t);if(!r)throw new Error(`The ${ut} skill is missing from this package`);return J.default.join(r,e)}async function qn(t,e=""){let r=[];for(let n of await dt.default.readdir(J.default.join(t,e),{withFileTypes:!0})){let o=J.default.join(e,n.name);n.isDirectory()?r.push(...await qn(t,o)):r.push(o)}return r.sort()}async function kl(t,e){let[r,n]=await Promise.all([qn(t),qn(e)]);if(r.join(`
|
|
58
|
+
`)!==n.join(`
|
|
59
|
+
`))return!1;for(let o of r){let[s,i]=await Promise.all([dt.default.readFile(J.default.join(t,o)),dt.default.readFile(J.default.join(e,o))]);if(!s.equals(i))return!1}return!0}async function _p(){await Zt(await dt.default.readFile(J.default.join(wp(),"SKILL.md"),"utf8"))}async function Op({dir:t=qt,force:e=!1}){let r=wp(),n=J.default.resolve(t,ut),o=J.default.relative(process.cwd(),n)||".";if(await dt.default.pathExists(n)){if(!(await dt.default.stat(n)).isDirectory())throw new Error(`${o} exists and is not a folder`);if(await kl(r,n))return T("The %s skill is already in %s",ut,o),n;if(!e)throw new Error(`${o} exists and differs from the skill of this version. Pass --force to replace it`);await dt.default.remove(n)}return await dt.default.copy(r,n),T("Wrote the %s skill to %s",ut,o),n}var xr="skill",jl=t=>[{comment:"Print the skill",commands:[`${t} ${xr}`]},{comment:`Add the skill to the project, in ${qt}/${ut}`,commands:[`${t} ${xr} --install`]},{comment:"Add the skill for Claude Code",commands:[`${t} ${xr} --install --dir .claude/skills`]}],xp=t=>new zt.Command().name(xr).summary("Print or install the agent skill for this CLI").description(`Print SKILL.md of the ${ut} skill, which tells coding agents how to use this CLI, or install the skill in the project.
|
|
52
60
|
|
|
53
61
|
Agents read project skills from these folders:
|
|
54
|
-
Codex, Cursor ${
|
|
55
|
-
Claude Code .claude/skills`).addHelpText("after",y(
|
|
56
|
-
Run '${
|
|
62
|
+
Codex, Cursor ${qt}
|
|
63
|
+
Claude Code .claude/skills`).addHelpText("after",y(jl(t))).addOption(new zt.Option("--install",`write the skill folder to <dir>/${ut}`)).addOption(new zt.Option("--dir <path>","the skills folder to install to").default(qt)).addOption(new zt.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!==qt))throw new Error("--dir and --force work with --install only");r.install?await Op({dir:r.dir,force:r.force}):await _p()},e)});var A="currents",Sp=()=>{let t=wr(A),e=new Ap.Command(A).version(bt).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 '${A} --help' for usage)`).enablePositionalOptions().hook("preAction",(i,a)=>{qo(a),zo(a)}).addCommand(t,{hidden:!0}).addCommand(ac(A),{hidden:!0}).addCommand(er(A,{deprecated:!0}),{hidden:!0}).commandsGroup("Test runs:").addCommand(yp(A)).commandsGroup("Evidence:").addCommand(Rp(A)).commandsGroup("CI utilities:").addCommand(Pa(A)).commandsGroup("Other:").addCommand(xa(A)).addCommand(uc(A)).addCommand(xp(A)).helpCommand(!0).addHelpText("after",`${y([Yt(A)[0],Yt(A)[1],Xe(A)[1],Ze(A)[1],ie(A)[0],_r(A)[0],...Wt(A).session])}
|
|
64
|
+
Run '${A} <command> --help' for the options and examples of a command.
|
|
57
65
|
|
|
58
|
-
Agent skill: ${
|
|
66
|
+
Agent skill: ${A} skill --install
|
|
59
67
|
Documentation: https://docs.currents.dev
|
|
60
68
|
Support: support@currents.dev
|
|
61
|
-
`),r=`upload is no longer the default command. Run '${
|
|
62
|
-
`:""),e};import("dotenv/config");function
|
|
69
|
+
`),r=`upload is no longer the default command. Run '${A} run upload ...' instead.`,n=t.options.flatMap(i=>[i.long,i.short]),o=e,s=o.unknownOption.bind(e);return o.unknownOption=i=>{if(!n.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}
|
|
70
|
+
`:""),e};import("dotenv/config");function $l(){Sp().parse()}$l();
|
|
63
71
|
/*! For license information please see index.js.LEGAL.txt */
|
|
64
72
|
//# sourceMappingURL=index.js.map
|