ripplo 0.7.9 → 0.7.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,60 +0,0 @@
1
- #!/usr/bin/env node
2
- import{$a as q,A as D,D as T,I as K,L as F,Ma as ue,N as V,Na as pe,O as X,Oa as fe,Pa as me,Qa as ye,S as Z,V as Y,Va as w,Wa as x,Xa as ke,Ya as H,Za as ge,ab as we,b as d,ba as ee,bb as Se,c as L,db as h,e as U,ea as re,f as P,fa as oe,fb as ve,g as M,ga as ne,ha as A,hb as Re,ja as te,jb as Pe,kb as xe,la as ie,lb as he,mb as be,nb as Ee,oa as ae,ob as Ie,pb as Ce,q as B,qa as se,qb as We,sb as Le,t as z,ta as le,u as G,ua as de,w as Q,wa as R,x as J,xa as ce,z as f}from"./chunk-63KRWFSY.js";import Hr from"path";import{createClient as qr}from"graphql-sse";import jr,{AbortError as Nr}from"p-retry";import{graphql as I}from"gql.tada";import{print as Or}from"graphql";import lr from"fs";import Ae from"net";import{err as He,ok as dr}from"neverthrow";async function qe({cwd:e,onConnection:o}){M(e);let r=ce(e),n=await De({onConnection:o,socketPath:r});return n.isOk()||n.error.kind!=="stale-candidate"?n.map(Te(r)).mapErr(Fe(r)):await cr(r)?He({kind:"already-running",socketPath:r}):(je(r),(await De({onConnection:o,socketPath:r})).map(Te(r)).mapErr(Fe(r)))}function cr(e){return new Promise(o=>{let r=Ae.connect(e);r.once("connect",()=>{r.destroy(),o(!0)}),r.once("error",()=>{o(!1)})})}async function De(e){let o=await ur(e);return o.kind==="listening"?dr(o.server):He(o.error)}function ur({onConnection:e,socketPath:o}){return new Promise(r=>{let n=Ae.createServer(e);n.once("error",t=>{r({error:t.code==="EADDRINUSE"?{kind:"stale-candidate"}:{kind:"listen-failed",message:t.message},kind:"failed"})}),n.listen(o,()=>{r({kind:"listening",server:n})})})}function Te(e){return o=>({socketPath:e,close:()=>{o.close(),je(e)}})}function je(e){lr.rmSync(e,{force:!0})}function Fe(e){return o=>o.kind==="stale-candidate"?{kind:"already-running",socketPath:e}:{kind:"bind-failed",message:o.message}}function j(e){return{priority:e,next:()=>null,onResult:()=>{}}}function Ne({config:e,explore:o,exploreConcurrency:r,pool:n}){return pr({appUrl:e.appUrl,cwd:e.cwd,explore:o,exploreConcurrency:r,executeTrail:async(t,i)=>(await n).exploreTrail(t,i)})}function pr({appUrl:e,cwd:o,executeTrail:r,explore:n,exploreConcurrency:t}){let i={notify:()=>{}},a=n?fr({appUrl:e,cwd:o,executeTrail:r,notifyWork:()=>{i.notify()}}):le(),s=Le({exploreConcurrency:t,exploreEnabled:n,now:Date.now,probe:mr,setTimer:yr,sources:[j("p0"),j("p1"),a],execute:({job:u,priority:p,signal:c})=>w({headed:!1,workClass:kr(p),task:()=>u.run(c)})});H(()=>{s.notifyQueueChange()}),i.notify=()=>{s.notifyQueueChange()};let l=n?se({onChange:u=>{s.setExplorerHolder(u)}}):null;return{status:()=>({explorer:gr({explore:n,holder:s.explorerHolder()}),exploring:s.explorationActive(),progress:a.status()}),stop:()=>{l?.stop(),s.stop(),H(null),a.stop()}}}function fr({appUrl:e,cwd:o,executeTrail:r,notifyWork:n}){return de({cwd:o,executeTrail:r,notifyWork:n,loadLockfile:async()=>{let{fingerprint:t,result:i}=await f(o);return i.match(a=>({fingerprint:t,lockfile:a}),()=>null)},probeApp:async()=>await Z(e)==null})}function mr(){let e=ke();return{headedActive:e.headedActive,interactiveActive:e.active,interactiveQueued:e.queued,poolSize:e.poolSize}}function yr(e,o){let r=setTimeout(e,o);return()=>{clearTimeout(r)}}function kr(e){switch(e){case"p0":return"p0-ui";case"p1":return"p1-cli";case"p2":return"p2-cover";case"p3":return"p3-explore"}}function gr({explore:e,holder:o}){return e?o?"holder":"standby":"off"}async function Oe({cwd:e,finding:o}){let r={at:new Date().toISOString(),kind:"resolution",signature:o.signature};await A(R(e),[r]).match(()=>{},n=>{d.warn("explore ledger append failed: %s",n.kind)})}async function $e({cwd:e,finding:o,outcome:r}){let n=r.kind==="clean"?[...r.rows,{at:new Date().toISOString(),kind:"resolution",signature:o.signature}]:r.rows;n.length!==0&&await A(R(e),n).match(()=>{},t=>{d.warn("explore ledger append failed: %s",t.kind)})}function _e({cwd:e,pool:o}){let r={cwd:e,executeTrail:(n,t)=>w({headed:!1,workClass:"p1-cli",task:async()=>(await o).exploreTrail(n,t)}),loadLockfile:async()=>{let n=await f(e);return n.result.match(t=>({fingerprint:n.fingerprint,lockfile:t}),()=>null)}};return(n,t)=>wr(r,{findingId:n,signal:t})}async function wr(e,o){let r=await Sr(e.cwd,o.findingId);if("reply"in r)return r.reply;let n=await e.loadLockfile();if(n==null)return{kind:"error",reason:"lockfile-unavailable"};let t=vr(n,r.finding);if("reply"in t)return t.reply;let i=await e.executeTrail(t.assign,o.signal);return Pr({cwd:e.cwd,finding:r.finding,outcome:i})}async function Sr(e,o){return ne(R(e)).match(r=>{let t=[...oe(r).findings.entries()].find(([a])=>re(a)===o);if(t==null)return{reply:{kind:"finding-not-found"}};let[,i]=t;return i.resolvedAt!=null?{reply:{kind:"finding-not-found"}}:{finding:i.latest}},()=>({reply:{kind:"unreplayable",reason:"ledger-unreadable"}}))}function vr(e,o){let r=ie(e.lockfile,{sweep:!1}).find(t=>t.name===o.depot);if(r==null)return{reply:{kind:"unreplayable",reason:"depot-missing"}};let n=Rr(e.lockfile,o);return n==null?{reply:{kind:"unreplayable",reason:"transition-missing"}}:{assign:{depotTest:r.test,firings:n,lensId:o.lensId,lockfileFingerprint:e.fingerprint,lockfileHash:te(e.lockfile),maxLength:n.length,shrinkBudget:0}}}function Rr(e,o){let n=Y(e).map(a=>`${a.test}#${String(a.index)}`),i=o.trail.map((a,s)=>{let l=n.indexOf(a),u=o.trailParams[s];return l===-1||u==null?null:{idx:l,params:u}}).flatMap(a=>a==null?[]:[a]);return i.length===o.trail.length?i:null}async function Pr({cwd:e,finding:o,outcome:r}){return r.kind==="aborted"?{kind:"aborted"}:r.kind==="error"?xr({cwd:e,finding:o,reason:r.reason}):(await $e({cwd:e,finding:o,outcome:r}),r.kind==="clean"?{kind:"resolved"}:r.kind==="flaky"?{kind:"flaky"}:hr(o,r))}async function xr({cwd:e,finding:o,reason:r}){return r==="empty-trail"?(await Oe({cwd:e,finding:o}),{kind:"unreachable"}):{kind:"error",reason:r??"trail-error"}}function hr(e,o){let r=o.rows.find(t=>t.kind==="finding"),n=r?.kind==="finding"?r.runId:void 0;return r!=null&&r.signature===e.signature?{kind:"still-failing",runId:n}:{kind:"diverged",runId:n}}async function Ue({config:e,cwd:o,headed:r,pool:n,runId:t,signal:i,workClass:a,workflowSlug:s}){let{fingerprint:l,result:u}=await f(o);if(u.isErr())return await h(e,t,`lockfile:${u.error.kind}`),{detail:`lockfile:${u.error.kind}`,kind:"dispatch-error"};if(u.value.tests.find(k=>J(k.name)===s)==null)return await h(e,t,`no-test:${s}`),{detail:`no-test:${s}`,kind:"dispatch-error"};let c=await w({headed:r,workClass:a,task:()=>n.execute({headed:r,lockfileFingerprint:l,runId:t,workflowSlug:s},i)});return!c.serverNotified&&c.outcome.kind==="error"&&await h(e,t,c.outcome.detail),c.outcome}import{fork as br}from"child_process";import Me from"os";import{CancellationTokenSource as Be,ResponseError as ze}from"vscode-jsonrpc/node";function Ge(e,o){return()=>{let r=br(e,["run-worker"],{cwd:o,stdio:["ignore","inherit","inherit","ipc"]});return{connection:We(r),kill:()=>{r.kill("SIGKILL")},onExit:n=>{r.once("exit",n)}}}}function Qe(e){let o={closed:!1,lockfileProvider:e.lockfileProvider,nextId:0,size:e.initialSize,spawn:e.spawn,waiters:[],workers:[]};return{close:async()=>{o.closed=!0,await Promise.all([...o.workers].map(r=>N(r,o)))},execute:(r,n)=>Ir(r,n,o),exploreTrail:(r,n)=>Lr(r,n,o),routeSpan:(r,n)=>{let t=o.workers.find(i=>i.runId===r);t?.worker.connection.sendNotification(Ie,{runId:r,span:n})},setSize:r=>{Tr(r,o)}}}var Er=1e4,Je=-32800;async function Ir(e,o,r){let n=await Ke(r);if(n.runId=e.runId,!n.alive)return b(n,r),{outcome:{detail:"worker-exit",kind:"error"},serverNotified:!1};let t=new Be,i=()=>{t.cancel()};o.aborted&&t.cancel(),o.addEventListener("abort",i,{once:!0});try{let a=await n.worker.connection.sendRequest(he,e,t.token),s=Re.safeParse(a);return s.success?s.data:{outcome:{detail:"bad-outcome-frame",kind:"error"},serverNotified:!1}}catch(a){return Wr(a,n)}finally{o.removeEventListener("abort",i),t.dispose(),b(n,r)}}async function Ke(e){let o=e.workers.find(r=>r.alive&&r.runId===void 0);if(o!=null)return o.runId="pending",o;if(e.workers.length<e.size){let r=Cr(e);return r.runId="pending",await r.ready,r}return new Promise(r=>{e.waiters.push(n=>{n.runId="pending",r(n)})})}function Cr(e){let o=e.spawn(),r={resolve:()=>{}},n={alive:!0,id:e.nextId,ready:new Promise(t=>{r.resolve=t,o.connection.onNotification(xe,t)}),runId:void 0,worker:o};return e.nextId+=1,o.connection.onRequest(be,async t=>{let i=ve.safeParse(t);return i.success?e.lockfileProvider(i.data.fingerprint):{unavailable:"bad-lockfile-request"}}),o.onExit(()=>{n.alive=!1,e.workers=e.workers.filter(t=>t!==n),o.connection.dispose(),r.resolve()}),e.workers.push(n),n}function b(e,o){if(e.runId=void 0,!e.alive||o.closed)return;if(o.workers.length>o.size){N(e,o);return}let r=o.waiters.shift();r?.(e)}async function N(e,o){if(o.workers=o.workers.filter(t=>t!==e),!e.alive)return;let r=new Promise(t=>{e.worker.onExit(t)});await e.worker.connection.sendNotification(Ce).catch(()=>{});let n=setTimeout(()=>{e.worker.kill()},Er);await r,clearTimeout(n)}function Wr(e,o){return e instanceof ze&&e.code===Je?{outcome:{detail:"aborted",kind:"error"},serverNotified:!1}:o.alive?{outcome:{detail:e instanceof Error?e.message:String(e),kind:"error"},serverNotified:!1}:{outcome:{detail:"worker-exit",kind:"error"},serverNotified:!1}}async function Lr(e,o,r){let n=await Ke(r);if(n.runId="explore",!n.alive)return b(n,r),{kind:"error",rows:[],trail:[]};let t=new Be,i=()=>{t.cancel()};o.aborted&&t.cancel(),o.addEventListener("abort",i,{once:!0});try{let a=await n.worker.connection.sendRequest(Ee,e,t.token),s=Pe.safeParse(a);return s.success?s.data:{kind:"error",rows:[],trail:[]}}catch(a){return Dr(a)}finally{o.removeEventListener("abort",i),t.dispose(),b(n,r)}}function Dr(e){return e instanceof ze&&e.code===Je?{kind:"aborted",rows:[],trail:[]}:{kind:"error",reason:`transport:${e instanceof Error?e.message.slice(0,120):"unknown"}`,rows:[],trail:[]}}function Tr(e,o){o.size=e,e>Me.availableParallelism()&&d.warn({cores:Me.availableParallelism(),size:e},"worker pool size exceeds available cores");let r=o.workers.filter(t=>t.alive&&t.runId===void 0),n=o.workers.length-e;r.slice(0,Math.max(0,n)).forEach(t=>{N(t,o)})}import E from"fs";import{graphql as Ve}from"gql.tada";import{print as Xe}from"graphql";var Fr=Ve(`
3
- subscription HooksPausedWatch($projectId: String!) {
4
- hooksPausedRequested(projectId: $projectId) {
5
- paused
6
- projectId
7
- }
8
- }
9
- `),Ar=Ve(`
10
- subscription WatchLocalConcurrencyChanged {
11
- myMaxLocalConcurrentRunsChanged
12
- }
13
- `);function Ze({pool:e,sseClient:o}){return o.subscribe({query:Xe(Ar)},{complete:()=>{},error:r=>{d.error(r,"localConcurrency subscription error")},next:r=>{let n=r.data?.myMaxLocalConcurrentRunsChanged;n!=null&&(x(n),e.setSize(n))}})}function Ye({cwd:e,projectId:o,sseClient:r}){return r.subscribe({query:Xe(Fr),variables:{projectId:o}},{complete:()=>{},error:n=>{d.error(n,"hooksPaused subscription error")},next:n=>{let t=n.data?.hooksPausedRequested?.paused;t!=null&&O({cwd:e,paused:t})}})}function O({cwd:e,paused:o}){let r=ae(e);if(o&&!E.existsSync(r)){E.writeFileSync(r,"");return}!o&&E.existsSync(r)&&E.unlinkSync(r)}var $r=6e4,er=500,_r=15e3,Ur=I(`
14
- subscription RunRequestedWatch($devSessionId: String!) {
15
- runRequested(devSessionId: $devSessionId) {
16
- runId
17
- workflowId
18
- workflowSlug
19
- }
20
- }
21
- `),Mr=I(`
22
- mutation HeartbeatDevSessionWatch($id: String!) {
23
- heartbeatDevSession(id: $id) {
24
- __typename
25
- ... on DevSession {
26
- id
27
- }
28
- ... on DevSessionEndedError {
29
- message
30
- }
31
- }
32
- }
33
- `),Br=I(`
34
- query WatchLocalConcurrency {
35
- currentUser {
36
- id
37
- maxLocalConcurrentRuns
38
- }
39
- }
40
- `),zr=I(`
41
- mutation EndDevSessionWatch($projectId: String!, $cwd: String!) {
42
- endDevSession(projectId: $projectId, cwd: $cwd) {
43
- __typename
44
- ... on DevSession {
45
- id
46
- }
47
- ... on NoActiveDevSessionError {
48
- message
49
- }
50
- }
51
- }
52
- `);async function hn({explore:e,exploreConcurrency:o}){no();let r=eo(process.cwd()),n=r.cwd,t=Kr(n),i=Yr(),a=Ne({config:r,explore:e,exploreConcurrency:o,pool:i.pool}),s={handler:()=>{}},l=Xr(),u=Se({config:r,cwd:n,explorationStatus:a.status,ready:l.promise,replayFinding:_e({cwd:n,pool:i.pool}),onShutdownRequest:()=>{s.handler()}}),p=await Zr({cwd:n,ipc:u,releasePid:t}),c=await D(n);c.isErr()&&(process.stderr.write(`ripplo: ${T(c.error)}
53
- `),process.exit(1));let k=c.value,m=await rr(()=>q({config:r,cwd:n,lockfile:k}),{config:r,label:"initial sync"}),C=await io(r);O({cwd:n,paused:m.hooksPaused});let $=ge(n);$!=null&&d.info("watching branch %s in %s",$,n);let W=qr({headers:{Authorization:`Bearer ${r.token}`},retryAttempts:1/0,url:`${r.ripploServerUrl}/graphql`}),S=Qe({initialSize:C,spawn:Ge(ao(),n),lockfileProvider:async g=>{let y=await f(n);return y.result.isErr()?{unavailable:`daemon-load-failed:${y.result.error.kind}`}:y.fingerprint!==g?{unavailable:"fingerprint-mismatch"}:{lockfileJson:G(Q,y.result.value)}}});i.provide(S);let or=await ee({localDir:Hr.join(n,".ripplo",".local"),writePortFile:!0,onRrwebBatch:()=>{},onSpan:g=>{let y=g.attributes["ripplo.run"];y!=null&&S.routeSpan(y,g)}}),_=Jr({claim:u.claim,config:r,cwd:n,initialId:m.devSessionId,pool:S,sseClient:W}),nr=Ye({cwd:n,projectId:r.projectId,sseClient:W}),tr=Ze({pool:S,sseClient:W}),ir=Qr({config:r,session:_}),ar=oo();l.resolve(),process.stdout.write(`${fe({devSessionId:m.devSessionId,version:z()})}
54
- `);let sr=async()=>{ir(),ar(),a.stop(),p.close(),_.stop(),nr(),tr(),await S.close(),await or.stop().catch(()=>{}),await Promise.race([P({config:r,document:zr,variables:{cwd:r.cwd,projectId:r.projectId}}).catch(()=>{}),new Promise(g=>setTimeout(g,3e3))]),t()},v=()=>{sr().finally(()=>process.exit(0))};s.handler=v,process.on("SIGINT",v),process.on("SIGTERM",v),process.on("SIGHUP",v),process.on("SIGBREAK",v),await new Promise(()=>{})}function Gr({claim:e,cwd:o,devSessionId:r,onSubscriptionDead:n,pool:t,sseClient:i}){let a=new Set;return i.subscribe({query:Or(Ur),variables:{devSessionId:r}},{complete:()=>{},error:s=>{d.warn("runRequested SSE failed: %s; re-registering session",s instanceof Error?s.message:String(s)),n()},next:s=>{let l=s.data?.runRequested;if(l==null)return;if(a.has(l.runId)){d.warn({runId:l.runId,workflowSlug:l.workflowSlug},"duplicate runRequested event; skipping dispatch");return}a.add(l.runId),process.stdout.write(`ripplo: run ${l.workflowSlug}
55
- `),B(o);let u=F(o).match(c=>c,c=>{d.error({failure:c,runId:l.runId},"failed to load env for run dispatch; skipping")});if(u==null){a.delete(l.runId);return}let p=e(l.workflowSlug);p?.started(l.runId),Ue({config:u,cwd:o,headed:p?.headed??!1,pool:t,runId:l.runId,signal:p==null?new AbortController().signal:we(p.token),workClass:p==null?"p0-ui":"p1-cli",workflowSlug:l.workflowSlug}).then(c=>{p?.finished(l.runId,c)}).catch(c=>{d.error({err:c,runId:l.runId,workflowSlug:l.workflowSlug},"run execution failed; daemon continuing"),p?.finished(l.runId,{detail:c instanceof Error?c.message:String(c),kind:"error"})}).finally(()=>{a.delete(l.runId)})}},{connecting:s=>{s&&d.warn("runRequested SSE reconnecting")}})}function Qr({config:e,session:o}){let r=async()=>{try{let t=await P({config:e,document:Mr,variables:{id:o.getId()}});t.heartbeatDevSession?.__typename==="DevSessionEndedError"&&(d.warn("dev session ended server-side (%s); re-registering",t.heartbeatDevSession.message),await o.reregister())}catch(t){d.warn("heartbeat failed: %s",t instanceof Error?t.message:String(t))}},n=setInterval(()=>{r()},_r);return()=>{clearInterval(n)}}function Jr({claim:e,config:o,cwd:r,initialId:n,pool:t,sseClient:i}){let a=n,s=null,l=()=>{k()},u=()=>Gr({claim:e,cwd:r,devSessionId:a,onSubscriptionDead:l,pool:t,sseClient:i}),p=u(),c=async()=>{let m=await D(r);if(m.isErr()){d.error("re-register: compile failed: %s",T(m.error));return}let C=await rr(()=>q({config:o,cwd:r,lockfile:m.value}),{config:o,label:"re-register sync"});p(),a=C.devSessionId,p=u(),d.info("re-registered dev session as %s",a)},k=()=>(s!=null||(s=c().finally(()=>{s=null})),s);return{reregister:k,getId:()=>a,stop:()=>{p()}}}function Kr(e){try{return X({cwd:e,onCompromised:Vr})}catch(o){throw o instanceof V&&(process.stderr.write(`${me({cwd:o.cwd,pid:o.pid})}
56
- `),process.exit(1)),o}}function Vr(){d.error("daemon lock compromised; shutting down"),process.stderr.write(`${ye()}
57
- `),process.exit(1)}function Xr(){let e={handler:()=>{}};return{promise:new Promise(r=>{e.handler=r}),resolve:()=>{e.handler()}}}async function Zr({cwd:e,ipc:o,releasePid:r}){return(await qe({cwd:e,onConnection:o.handleConnection})).match(t=>t,t=>{process.stderr.write(`${ue(t)}
58
- `),r(),process.exit(1)})}function Yr(){let e={provide:()=>{}};return{pool:new Promise(r=>{e.provide=r}),provide:r=>{e.provide(r)}}}function eo(e){return F(e).match(o=>o,o=>{process.stderr.write(`${K(o)}
59
- `),process.exit(1)})}function rr(e,{config:o,label:r}){let n=o.ripploServerUrl.includes("localhost")||o.ripploServerUrl.includes("127.0.0.1");return jr(async()=>{try{return await e()}catch(t){let i=t instanceof Error?t.message:String(t);throw U(t)==="FORBIDDEN"&&(process.stderr.write(`ripplo: ${pe({projectId:o.projectId,serverUrl:o.ripploServerUrl})}
60
- `),process.exit(1)),ro(i)?t:(d.error("%s failed: %s",r,i),new Nr(i))}},{factor:2,maxTimeout:n?2e3:1e4,minTimeout:n?100:1e3,retries:1/0,onFailedAttempt:({attemptNumber:t,error:i})=>{d.warn("%s attempt %d failed \u2014 retrying: %s",r,t,i.message)}})}function ro(e){return e.includes("status 502")||e.includes("ECONNREFUSED")||e.includes("Failed to connect")||e.includes("fetch failed")}function oo(){L({maxRuns:er});let e=setInterval(()=>{L({maxRuns:er})},$r);return()=>{clearInterval(e)}}function no(){process.on("unhandledRejection",e=>{d.error({err:e},"unhandledRejection in watch; continuing")}),process.on("uncaughtException",e=>{d.error({err:e},"uncaughtException in watch; continuing")})}var to=4;async function io(e){try{let r=(await P({config:e,document:Br,variables:void 0})).currentUser?.maxLocalConcurrentRuns;if(r!=null)return x(r),r}catch(o){d.warn({err:o},"failed to fetch local concurrency setting; using default")}return to}function ao(){let e=process.argv[1];if(e==null)throw new Error("cli entry unavailable");return e}export{hn as runDaemon};