plum-e2e 2.9.17 → 2.10.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/backend/constants/socketEvents.js +8 -14
- package/backend/lib/serverBootstrap.js +4 -4
- package/backend/mcp/server.js +3 -3
- package/backend/prisma/migrations/20260829000000_add_run_queue/migration.sql +29 -0
- package/backend/prisma/schema.prisma +30 -0
- package/backend/routes/active-runs.routes.js +10 -6
- package/backend/routes/node.routes.js +7 -0
- package/backend/routes/trigger.routes.js +8 -5
- package/backend/server.js +5 -1
- package/backend/services/cronService.js +15 -443
- package/backend/services/nodeExecutionService.js +13 -1
- package/backend/services/runExecutorService.js +423 -0
- package/backend/services/runQueueService.js +276 -0
- package/backend/services/runnerService.js +22 -4
- package/backend/services/triggerService.js +13 -231
- package/backend/websockets/socketHandler.js +32 -590
- package/frontend/.svelte-kit/adapter-node/.vite/manifest.json +35 -35
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/BackLink.DRrgBGDC.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_layout.HkPnpRl9.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.B9H_IpSU.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.Be5c3USL.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.COwSGmmy.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.ClS4XkkN.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.Dp6vaGRc.css +6 -0
- package/frontend/.svelte-kit/adapter-node/chunks/BackLink.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/Badge.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/ConfirmModal.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/EmptyState.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/Modal.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/Toast.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/constants.js +6 -4
- package/frontend/.svelte-kit/adapter-node/chunks/format.js +3 -3
- package/frontend/.svelte-kit/adapter-node/chunks/index.js +4 -4
- package/frontend/.svelte-kit/adapter-node/chunks/internal.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/reports.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/reports2.js +38 -40
- package/frontend/.svelte-kit/adapter-node/chunks/repository.js +8 -0
- package/frontend/.svelte-kit/adapter-node/chunks/runner.js +10 -20
- package/frontend/.svelte-kit/adapter-node/entries/pages/live/_id_/_page.svelte.js +254 -0
- package/frontend/.svelte-kit/adapter-node/entries/pages/login/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/adapter-node/entries/pages/reports/_id_/_page.svelte.js +29 -24
- package/frontend/.svelte-kit/adapter-node/entries/pages/reports/_page.svelte.js +23 -19
- package/frontend/.svelte-kit/adapter-node/entries/pages/scheduled-tests/_page.svelte.js +3 -3
- package/frontend/.svelte-kit/adapter-node/entries/pages/settings/_page.svelte.js +173 -51
- package/frontend/.svelte-kit/adapter-node/entries/pages/setup/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/adapter-node/entries/pages/test-repository/runs/_id_/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/adapter-node/entries/pages/test-repository/suites/_id_/_page.svelte.js +63 -11
- package/frontend/.svelte-kit/adapter-node/manifest-full.js +10 -10
- package/frontend/.svelte-kit/adapter-node/manifest.js +10 -10
- package/frontend/.svelte-kit/adapter-node/nodes/0.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/1.js +1 -1
- package/frontend/.svelte-kit/adapter-node/nodes/10.js +1 -1
- package/frontend/.svelte-kit/adapter-node/nodes/11.js +1 -1
- package/frontend/.svelte-kit/adapter-node/nodes/12.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/2.js +1 -1
- package/frontend/.svelte-kit/adapter-node/nodes/3.js +3 -3
- package/frontend/.svelte-kit/adapter-node/nodes/4.js +3 -3
- package/frontend/.svelte-kit/adapter-node/nodes/5.js +3 -3
- package/frontend/.svelte-kit/adapter-node/nodes/6.js +3 -3
- package/frontend/.svelte-kit/adapter-node/nodes/7.js +1 -1
- package/frontend/.svelte-kit/adapter-node/nodes/8.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/9.js +1 -1
- package/frontend/.svelte-kit/ambient.d.ts +28 -28
- package/frontend/.svelte-kit/generated/client/app.js +4 -4
- package/frontend/.svelte-kit/generated/client/nodes/13.js +6 -0
- package/frontend/.svelte-kit/generated/client/nodes/3.js +1 -1
- package/frontend/.svelte-kit/generated/client/nodes/4.js +1 -1
- package/frontend/.svelte-kit/generated/client/nodes/5.js +1 -1
- package/frontend/.svelte-kit/generated/client/nodes/6.js +1 -1
- package/frontend/.svelte-kit/generated/client-optimized/app.js +4 -4
- package/frontend/.svelte-kit/generated/client-optimized/nodes/3.js +1 -1
- package/frontend/.svelte-kit/generated/client-optimized/nodes/4.js +1 -1
- package/frontend/.svelte-kit/generated/client-optimized/nodes/5.js +1 -1
- package/frontend/.svelte-kit/generated/client-optimized/nodes/6.js +1 -1
- package/frontend/.svelte-kit/generated/server/internal.js +1 -1
- package/frontend/.svelte-kit/output/client/.vite/manifest.json +413 -401
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/0.CmJTG5mP.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/12.B9H_IpSU.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/3.Be5c3USL.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/5.ClS4XkkN.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/6.BN5XbLUX.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/8.COwSGmmy.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/BackLink.DRrgBGDC.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_layout.HkPnpRl9.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.B9H_IpSU.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.Be5c3USL.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.COwSGmmy.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.ClS4XkkN.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.Dp6vaGRc.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/2-KCkWZO.js +6 -0
- package/frontend/{build/client/_app/immutable/chunks/CNdcuGR0.js → .svelte-kit/output/client/_app/immutable/chunks/B00vxw57.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/B0_HKFXV.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{t-La0hgu.js → BAvTKHxT.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BJ_ypKl3.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BbYY_TzB.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/Beula-TH.js +11 -0
- package/frontend/{build/client/_app/immutable/chunks/CKDtmZUQ.js → .svelte-kit/output/client/_app/immutable/chunks/C00jnSU2.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/C2_rQ4aY.js +175 -0
- package/frontend/{build/client/_app/immutable/chunks/DCgHuuvs.js → .svelte-kit/output/client/_app/immutable/chunks/C7uEQ-LH.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/C8S7qQjQ.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{CzlPaHY9.js → CZWchtW8.js} +1 -1
- package/frontend/{build/client/_app/immutable/chunks/2zMvi6fR.js → .svelte-kit/output/client/_app/immutable/chunks/CboYYxrf.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CeH-RgMb.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{CgnwuKKO.js → CegSvdD-.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CfkUW1vA.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/Cfmt4_tJ.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/Cgw8TOOy.js +6 -0
- package/frontend/{build/client/_app/immutable/chunks/C1Vid6wz.js → .svelte-kit/output/client/_app/immutable/chunks/Ck6C3Fl0.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CoTEzvLa.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{DMZwI8Cj.js → DAmOMhaf.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DB3YXVFP.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{w0D4Uzlq.js → DWzEJYIF.js} +1 -1
- package/frontend/{build/client/_app/immutable/chunks/CMEtqUfQ.js → .svelte-kit/output/client/_app/immutable/chunks/DgQy0SB2.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{kkA1mrsH.js → DiVmSEJa.js} +2 -2
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/Dl-F6VCo.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DuAVKaL3.js +6 -0
- package/frontend/{build/client/_app/immutable/chunks/BmZ9upwL.js → .svelte-kit/output/client/_app/immutable/chunks/GDjpV3r7.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/K1h4wprj.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{DDZw0L0T.js → d2K3c8Kx.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/entry/app.DRjRA71t.js +7 -0
- package/frontend/{build/client/_app/immutable/entry/start.4qxHHAcl.js → .svelte-kit/output/client/_app/immutable/entry/start.BXOLyf9R.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.CRb8Nyce.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{1.Df9sLw8b.js → 1.BI97il3r.js} +1 -1
- package/frontend/{build/client/_app/immutable/nodes/10.DEbnxfND.js → .svelte-kit/output/client/_app/immutable/nodes/10.kyazROhw.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{11.BViaDK2m.js → 11.B3vMgT2v.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/12.DkPcIrgW.js +6 -0
- package/frontend/{build/client/_app/immutable/nodes/2.BCPSg7H4.js → .svelte-kit/output/client/_app/immutable/nodes/2.Dr6yugXz.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/3.DUiL7fb5.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{3.8BFAJoHT.js → 4.DDADylfF.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/5.N4CeDeoD.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/6.DWd93Bv5.js +10 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/7.c8d1cQQM.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/8.Cvd3MauU.js +9 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{9.CvfGx3Hu.js → 9.BOK0GNF_.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/version.json +1 -1
- package/frontend/.svelte-kit/output/server/.vite/manifest.json +35 -35
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/BackLink.DRrgBGDC.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_layout.HkPnpRl9.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.B9H_IpSU.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Be5c3USL.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.COwSGmmy.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.ClS4XkkN.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Dp6vaGRc.css +6 -0
- package/frontend/.svelte-kit/output/server/chunks/BackLink.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/Badge.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/ConfirmModal.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/EmptyState.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/Modal.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/Toast.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/constants.js +6 -4
- package/frontend/.svelte-kit/output/server/chunks/format.js +3 -3
- package/frontend/.svelte-kit/output/server/chunks/index.js +4 -4
- package/frontend/.svelte-kit/output/server/chunks/internal.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/reports.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/reports2.js +38 -40
- package/frontend/.svelte-kit/output/server/chunks/repository.js +8 -0
- package/frontend/.svelte-kit/output/server/chunks/runner.js +10 -20
- package/frontend/.svelte-kit/output/server/entries/pages/live/_id_/_page.svelte.js +254 -0
- package/frontend/.svelte-kit/output/server/entries/pages/login/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/output/server/entries/pages/reports/_id_/_page.svelte.js +29 -24
- package/frontend/.svelte-kit/output/server/entries/pages/reports/_page.svelte.js +23 -19
- package/frontend/.svelte-kit/output/server/entries/pages/scheduled-tests/_page.svelte.js +3 -3
- package/frontend/.svelte-kit/output/server/entries/pages/settings/_page.svelte.js +173 -51
- package/frontend/.svelte-kit/output/server/entries/pages/setup/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/output/server/entries/pages/test-repository/runs/_id_/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/output/server/entries/pages/test-repository/suites/_id_/_page.svelte.js +63 -11
- package/frontend/.svelte-kit/output/server/manifest-full.js +10 -10
- package/frontend/.svelte-kit/output/server/manifest.js +10 -10
- package/frontend/.svelte-kit/output/server/nodes/0.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/1.js +1 -1
- package/frontend/.svelte-kit/output/server/nodes/10.js +1 -1
- package/frontend/.svelte-kit/output/server/nodes/11.js +1 -1
- package/frontend/.svelte-kit/output/server/nodes/12.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/2.js +1 -1
- package/frontend/.svelte-kit/output/server/nodes/3.js +3 -3
- package/frontend/.svelte-kit/output/server/nodes/4.js +3 -3
- package/frontend/.svelte-kit/output/server/nodes/5.js +3 -3
- package/frontend/.svelte-kit/output/server/nodes/6.js +3 -3
- package/frontend/.svelte-kit/output/server/nodes/7.js +1 -1
- package/frontend/.svelte-kit/output/server/nodes/8.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/9.js +1 -1
- package/frontend/build/client/_app/immutable/assets/0.CmJTG5mP.css +6 -0
- package/frontend/build/client/_app/immutable/assets/0.CmJTG5mP.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/0.CmJTG5mP.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/12.B9H_IpSU.css +6 -0
- package/frontend/build/client/_app/immutable/assets/12.B9H_IpSU.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/12.B9H_IpSU.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/3.Be5c3USL.css +6 -0
- package/frontend/build/client/_app/immutable/assets/3.Be5c3USL.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/3.Be5c3USL.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/5.ClS4XkkN.css +6 -0
- package/frontend/build/client/_app/immutable/assets/5.ClS4XkkN.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/5.ClS4XkkN.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/6.BN5XbLUX.css +6 -0
- package/frontend/build/client/_app/immutable/assets/6.BN5XbLUX.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/6.BN5XbLUX.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/8.COwSGmmy.css +6 -0
- package/frontend/build/client/_app/immutable/assets/8.COwSGmmy.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/8.COwSGmmy.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.DRrgBGDC.css +6 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.DRrgBGDC.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.DRrgBGDC.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_layout.HkPnpRl9.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_layout.HkPnpRl9.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_layout.HkPnpRl9.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.B9H_IpSU.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.B9H_IpSU.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.B9H_IpSU.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Be5c3USL.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.Be5c3USL.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Be5c3USL.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.COwSGmmy.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.COwSGmmy.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.COwSGmmy.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.ClS4XkkN.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.ClS4XkkN.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.ClS4XkkN.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Dp6vaGRc.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.Dp6vaGRc.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Dp6vaGRc.css.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/2-KCkWZO.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/2-KCkWZO.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/2-KCkWZO.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/CNdcuGR0.js → build/client/_app/immutable/chunks/B00vxw57.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/B00vxw57.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/B00vxw57.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/B0_HKFXV.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/B0_HKFXV.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/B0_HKFXV.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{t-La0hgu.js → BAvTKHxT.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/BAvTKHxT.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAvTKHxT.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BJ_ypKl3.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/BJ_ypKl3.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BJ_ypKl3.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BbYY_TzB.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/BbYY_TzB.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BbYY_TzB.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/Beula-TH.js +11 -0
- package/frontend/build/client/_app/immutable/chunks/Beula-TH.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/Beula-TH.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/CKDtmZUQ.js → build/client/_app/immutable/chunks/C00jnSU2.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/C00jnSU2.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C00jnSU2.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/C2_rQ4aY.js +175 -0
- package/frontend/build/client/_app/immutable/chunks/C2_rQ4aY.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C2_rQ4aY.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/DCgHuuvs.js → build/client/_app/immutable/chunks/C7uEQ-LH.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/C7uEQ-LH.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C7uEQ-LH.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/C8S7qQjQ.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/C8S7qQjQ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C8S7qQjQ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{CzlPaHY9.js → CZWchtW8.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/CZWchtW8.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CZWchtW8.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/2zMvi6fR.js → build/client/_app/immutable/chunks/CboYYxrf.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/CboYYxrf.js.br +6 -0
- package/frontend/build/client/_app/immutable/chunks/CboYYxrf.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CeH-RgMb.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/CeH-RgMb.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CeH-RgMb.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{CgnwuKKO.js → CegSvdD-.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/CegSvdD-.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CegSvdD-.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CfkUW1vA.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/CfkUW1vA.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CfkUW1vA.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/Cfmt4_tJ.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/Cfmt4_tJ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/Cfmt4_tJ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/Cgw8TOOy.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/Cgw8TOOy.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/Cgw8TOOy.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/C1Vid6wz.js → build/client/_app/immutable/chunks/Ck6C3Fl0.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/Ck6C3Fl0.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/Ck6C3Fl0.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CoTEzvLa.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/CoTEzvLa.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CoTEzvLa.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{DMZwI8Cj.js → DAmOMhaf.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/DAmOMhaf.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DAmOMhaf.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DB3YXVFP.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/DB3YXVFP.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DB3YXVFP.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{w0D4Uzlq.js → DWzEJYIF.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/DWzEJYIF.js.br +7 -0
- package/frontend/build/client/_app/immutable/chunks/DWzEJYIF.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/CMEtqUfQ.js → build/client/_app/immutable/chunks/DgQy0SB2.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/DgQy0SB2.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DgQy0SB2.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{kkA1mrsH.js → DiVmSEJa.js} +2 -2
- package/frontend/build/client/_app/immutable/chunks/DiVmSEJa.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DiVmSEJa.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/Dl-F6VCo.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/Dl-F6VCo.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/Dl-F6VCo.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DuAVKaL3.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/DuAVKaL3.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DuAVKaL3.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/BmZ9upwL.js → build/client/_app/immutable/chunks/GDjpV3r7.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/GDjpV3r7.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/GDjpV3r7.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/K1h4wprj.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/K1h4wprj.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/K1h4wprj.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{DDZw0L0T.js → d2K3c8Kx.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/d2K3c8Kx.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/d2K3c8Kx.js.gz +0 -0
- package/frontend/build/client/_app/immutable/entry/app.DRjRA71t.js +7 -0
- package/frontend/build/client/_app/immutable/entry/app.DRjRA71t.js.br +0 -0
- package/frontend/build/client/_app/immutable/entry/app.DRjRA71t.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/entry/start.4qxHHAcl.js → build/client/_app/immutable/entry/start.BXOLyf9R.js} +1 -1
- package/frontend/build/client/_app/immutable/entry/{start.4qxHHAcl.js.br → start.BXOLyf9R.js.br} +1 -1
- package/frontend/build/client/_app/immutable/entry/{start.4qxHHAcl.js.gz → start.BXOLyf9R.js.gz} +0 -0
- package/frontend/build/client/_app/immutable/nodes/0.CRb8Nyce.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/0.CRb8Nyce.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/0.CRb8Nyce.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/{1.Df9sLw8b.js → 1.BI97il3r.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/1.BI97il3r.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/1.BI97il3r.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/10.DEbnxfND.js → build/client/_app/immutable/nodes/10.kyazROhw.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/10.kyazROhw.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/10.kyazROhw.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/{11.BViaDK2m.js → 11.B3vMgT2v.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/11.B3vMgT2v.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/11.B3vMgT2v.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/12.DkPcIrgW.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/12.DkPcIrgW.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/12.DkPcIrgW.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/2.BCPSg7H4.js → build/client/_app/immutable/nodes/2.Dr6yugXz.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/2.Dr6yugXz.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/2.Dr6yugXz.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/3.DUiL7fb5.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/3.DUiL7fb5.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/3.DUiL7fb5.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/{3.8BFAJoHT.js → 4.DDADylfF.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/4.DDADylfF.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/4.DDADylfF.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/5.N4CeDeoD.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/5.N4CeDeoD.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/5.N4CeDeoD.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/6.DWd93Bv5.js +10 -0
- package/frontend/build/client/_app/immutable/nodes/6.DWd93Bv5.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/6.DWd93Bv5.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/7.c8d1cQQM.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/7.c8d1cQQM.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/7.c8d1cQQM.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/8.Cvd3MauU.js +9 -0
- package/frontend/build/client/_app/immutable/nodes/8.Cvd3MauU.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/8.Cvd3MauU.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/{9.CvfGx3Hu.js → 9.BOK0GNF_.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/9.BOK0GNF_.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/9.BOK0GNF_.js.gz +0 -0
- package/frontend/build/client/_app/version.json +1 -1
- package/frontend/build/client/_app/version.json.br +0 -0
- package/frontend/build/client/_app/version.json.gz +0 -0
- package/frontend/build/server/chunks/0-_rljpEay.js +22 -0
- package/frontend/build/server/chunks/0-_rljpEay.js.map +5 -0
- package/frontend/build/server/chunks/{1-Kxn9d30Z.js → 1-B3HpigzL.js} +3 -3
- package/frontend/build/server/chunks/{1-Kxn9d30Z.js.map → 1-B3HpigzL.js.map} +1 -1
- package/frontend/build/server/chunks/10-BQBBYpxV.js +14 -0
- package/frontend/build/server/chunks/10-BQBBYpxV.js.map +5 -0
- package/frontend/build/server/chunks/11-10xw0TIP.js +14 -0
- package/frontend/build/server/chunks/11-10xw0TIP.js.map +5 -0
- package/frontend/build/server/chunks/12-CZ3_Uw3c.js +14 -0
- package/frontend/build/server/chunks/{12-De6Ol6pu.js.map → 12-CZ3_Uw3c.js.map} +1 -1
- package/frontend/build/server/chunks/2-DioMbKbC.js +14 -0
- package/frontend/build/server/chunks/{2-Dc_rKWoK.js.map → 2-DioMbKbC.js.map} +1 -1
- package/frontend/build/server/chunks/3-CgiZg_9v.js +14 -0
- package/frontend/build/server/chunks/3-CgiZg_9v.js.map +5 -0
- package/frontend/build/server/chunks/4-BM-49dbE.js +14 -0
- package/frontend/build/server/chunks/4-BM-49dbE.js.map +5 -0
- package/frontend/build/server/chunks/5-Brx_KOzy.js +14 -0
- package/frontend/build/server/chunks/5-Brx_KOzy.js.map +5 -0
- package/frontend/build/server/chunks/6-C5swINND.js +14 -0
- package/frontend/build/server/chunks/6-C5swINND.js.map +5 -0
- package/frontend/build/server/chunks/7-B8e4y3CB.js +14 -0
- package/frontend/build/server/chunks/{7-DiQJZEF_.js.map → 7-B8e4y3CB.js.map} +1 -1
- package/frontend/build/server/chunks/8-BZtkZMIZ.js +14 -0
- package/frontend/build/server/chunks/8-BZtkZMIZ.js.map +5 -0
- package/frontend/build/server/chunks/9-BMAKiAem.js +14 -0
- package/frontend/build/server/chunks/{9-DirZG_Lu.js.map → 9-BMAKiAem.js.map} +1 -1
- package/frontend/build/server/chunks/{BackLink-BJ8NaemM.js → BackLink-CMpNTYqE.js} +2 -2
- package/frontend/build/server/chunks/BackLink-CMpNTYqE.js.map +5 -0
- package/frontend/build/server/chunks/{Badge-44ZTDx0V.js → Badge-BTWnF9pA.js} +2 -2
- package/frontend/build/server/chunks/Badge-BTWnF9pA.js.map +5 -0
- package/frontend/build/server/chunks/{ConfirmModal-C0EAXcq_.js → ConfirmModal-CtGWHl0v.js} +3 -3
- package/frontend/build/server/chunks/ConfirmModal-CtGWHl0v.js.map +5 -0
- package/frontend/build/server/chunks/{EmptyState-BA_eXaeR.js → EmptyState-Zpm9tJe1.js} +2 -2
- package/frontend/build/server/chunks/EmptyState-Zpm9tJe1.js.map +5 -0
- package/frontend/build/server/chunks/{Modal-DChG187n.js → Modal-BJJMnfIg.js} +2 -2
- package/frontend/build/server/chunks/Modal-BJJMnfIg.js.map +5 -0
- package/frontend/build/server/chunks/{Toast-v-q4ZnYq.js → Toast-CHB87F8k.js} +2 -2
- package/frontend/build/server/chunks/Toast-CHB87F8k.js.map +5 -0
- package/frontend/build/server/chunks/{_layout.svelte-CHVI3Prt.js → _layout.svelte-C_6nsIpT.js} +7 -7
- package/frontend/build/server/chunks/{_layout.svelte-CHVI3Prt.js.map → _layout.svelte-C_6nsIpT.js.map} +1 -1
- package/frontend/build/server/chunks/{_page.svelte-1jo8MapI.js → _page.svelte-BNwU9zza.js} +11 -10
- package/frontend/build/server/chunks/_page.svelte-BNwU9zza.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-04WxjOuH.js → _page.svelte-Bamoq11m.js} +8 -8
- package/frontend/build/server/chunks/{_page.svelte-04WxjOuH.js.map → _page.svelte-Bamoq11m.js.map} +1 -1
- package/frontend/build/server/chunks/{_page.svelte-Kg69DDaM.js → _page.svelte-BrYksycU.js} +5 -5
- package/frontend/build/server/chunks/_page.svelte-BrYksycU.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-BuFusRK1.js → _page.svelte-CAlhaCzS.js} +12 -12
- package/frontend/build/server/chunks/_page.svelte-CAlhaCzS.js.map +5 -0
- package/frontend/build/server/chunks/_page.svelte-CTebwzwy.js +62 -0
- package/frontend/build/server/chunks/_page.svelte-CTebwzwy.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-1as75nPc.js → _page.svelte-CbTrCeeX.js} +32 -28
- package/frontend/build/server/chunks/_page.svelte-CbTrCeeX.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-D3E6Eojd.js → _page.svelte-Cf6bI1Y2.js} +5 -5
- package/frontend/build/server/chunks/_page.svelte-Cf6bI1Y2.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-CWWeZuid.js → _page.svelte-CmJKt3-H.js} +71 -19
- package/frontend/build/server/chunks/_page.svelte-CmJKt3-H.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-CB8-QBNg.js → _page.svelte-DHZhNTPg.js} +11 -10
- package/frontend/build/server/chunks/{_page.svelte-CB8-QBNg.js.map → _page.svelte-DHZhNTPg.js.map} +1 -1
- package/frontend/build/server/chunks/_page.svelte-DObTHQe2.js +257 -0
- package/frontend/build/server/chunks/_page.svelte-DObTHQe2.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-8gELc_B1.js → _page.svelte-ywHy9KCh.js} +182 -59
- package/frontend/build/server/chunks/_page.svelte-ywHy9KCh.js.map +5 -0
- package/frontend/build/server/chunks/{auth-Chw-wBpI.js → auth-DDPlushv.js} +2 -2
- package/frontend/build/server/chunks/{auth-Chw-wBpI.js.map → auth-DDPlushv.js.map} +1 -1
- package/frontend/build/server/chunks/{client-DEmxR_a-.js → client-CsTiGNZy.js} +2 -2
- package/frontend/build/server/chunks/{client-DEmxR_a-.js.map → client-CsTiGNZy.js.map} +1 -1
- package/frontend/build/server/chunks/{constants-CXTaQaB6.js → constants-BYVkTZ-O.js} +3 -2
- package/frontend/build/server/chunks/constants-BYVkTZ-O.js.map +5 -0
- package/frontend/build/server/chunks/{error.svelte-BD3xNemk.js → error.svelte-BXr4lXlB.js} +3 -3
- package/frontend/build/server/chunks/{error.svelte-BD3xNemk.js.map → error.svelte-BXr4lXlB.js.map} +1 -1
- package/frontend/build/server/chunks/{format-CiNRMfHu.js → format-2pqy61MU.js} +2 -2
- package/frontend/build/server/chunks/{format-CiNRMfHu.js.map → format-2pqy61MU.js.map} +1 -1
- package/frontend/build/server/chunks/{index-server-B3M9vyh2.js → index-server-53nOZg5X.js} +2 -2
- package/frontend/build/server/chunks/{index-server-B3M9vyh2.js.map → index-server-53nOZg5X.js.map} +1 -1
- package/frontend/build/server/chunks/{index2-5R1tbrep.js → index2-DGcbugKe.js} +2 -2
- package/frontend/build/server/chunks/{index2-5R1tbrep.js.map → index2-DGcbugKe.js.map} +1 -1
- package/frontend/build/server/chunks/{reports-D_ApeeNh.js → reports-WuXG6tj3.js} +2 -2
- package/frontend/build/server/chunks/{reports-D_ApeeNh.js.map → reports-WuXG6tj3.js.map} +1 -1
- package/frontend/build/server/chunks/{reports2-BtElN_53.js → reports2-CCpI0xkQ.js} +7 -8
- package/frontend/build/server/chunks/reports2-CCpI0xkQ.js.map +5 -0
- package/frontend/build/server/chunks/{repository-FYYV_vKE.js → repository-TYWcFuWP.js} +6 -2
- package/frontend/build/server/chunks/repository-TYWcFuWP.js.map +5 -0
- package/frontend/build/server/chunks/runner-D5yCWOsy.js +27 -0
- package/frontend/build/server/chunks/runner-D5yCWOsy.js.map +5 -0
- package/frontend/build/server/chunks/{stores-BLenR3c1.js → stores-C4ZkywTG.js} +3 -3
- package/frontend/build/server/chunks/{stores-BLenR3c1.js.map → stores-C4ZkywTG.js.map} +1 -1
- package/frontend/build/server/chunks/{theme-nAx-GvX_.js → theme-C81wSe5T.js} +2 -2
- package/frontend/build/server/chunks/{theme-nAx-GvX_.js.map → theme-C81wSe5T.js.map} +1 -1
- package/frontend/build/server/index.js +2 -2
- package/frontend/build/server/index.js.map +1 -1
- package/frontend/build/server/manifest.js +23 -23
- package/frontend/build/server/manifest.js.map +1 -1
- package/frontend/src/lib/components/layout/RunnerPanel.svelte +186 -266
- package/frontend/src/lib/copy/reports.js +9 -0
- package/frontend/src/lib/copy/runners.js +9 -6
- package/frontend/src/lib/socketEvents.js +3 -15
- package/frontend/src/lib/stores/runner.js +62 -46
- package/frontend/src/routes/{reports/live → live/[id]}/+page.svelte +112 -183
- package/frontend/src/routes/scheduled-tests/+page.svelte +2 -2
- package/package.json +1 -1
- package/backend/services/activeRunsService.js +0 -55
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/BackLink.CvWWuO3h.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_layout.BuhMvMUj.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.0Eln51hV.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.BZfe6nWe.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.Bj_a_5lv.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.BwgOqeMo.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.CFnbmY-D.css +0 -6
- package/frontend/.svelte-kit/adapter-node/entries/pages/reports/live/_page.svelte.js +0 -247
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/0.BhSG-jZH.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/12.Bj_a_5lv.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/4.0Eln51hV.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/5.DFV9OgAu.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/6.CFnbmY-D.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/8.BwgOqeMo.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/BackLink.CvWWuO3h.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_layout.BuhMvMUj.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.0Eln51hV.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.BZfe6nWe.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.Bj_a_5lv.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.BwgOqeMo.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.CFnbmY-D.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/3InFPLvE.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BAACMRH5.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BAMUGSh7.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BKuh57WU.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BUwxRmHf.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/C8OURRSs.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CGeZlCaI.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CMBQQ9RZ.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CUC98kMZ.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/Co3xKhEp.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CuqnZUex.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DHM6H-es.js +0 -7
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DSLBMEpr.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DbgD7JLa.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/TOCyHP97.js +0 -11
- package/frontend/.svelte-kit/output/client/_app/immutable/entry/app.KrtMZ3my.js +0 -7
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.C8DodwXs.js +0 -11
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/12.BMSCSd88.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/4.D-YT_JJe.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/5.DVeH2eQP.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/6.DI7-IJhN.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/7.C-pKvVZy.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/8.93Mb3ofT.js +0 -9
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/BackLink.CvWWuO3h.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_layout.BuhMvMUj.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.0Eln51hV.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.BZfe6nWe.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bj_a_5lv.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.BwgOqeMo.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CFnbmY-D.css +0 -6
- package/frontend/.svelte-kit/output/server/entries/pages/reports/live/_page.svelte.js +0 -247
- package/frontend/build/client/_app/immutable/assets/0.BhSG-jZH.css +0 -6
- package/frontend/build/client/_app/immutable/assets/0.BhSG-jZH.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/0.BhSG-jZH.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/12.Bj_a_5lv.css +0 -6
- package/frontend/build/client/_app/immutable/assets/12.Bj_a_5lv.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/12.Bj_a_5lv.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/4.0Eln51hV.css +0 -6
- package/frontend/build/client/_app/immutable/assets/4.0Eln51hV.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/4.0Eln51hV.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/5.DFV9OgAu.css +0 -6
- package/frontend/build/client/_app/immutable/assets/5.DFV9OgAu.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/5.DFV9OgAu.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/6.CFnbmY-D.css +0 -6
- package/frontend/build/client/_app/immutable/assets/6.CFnbmY-D.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/6.CFnbmY-D.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/8.BwgOqeMo.css +0 -6
- package/frontend/build/client/_app/immutable/assets/8.BwgOqeMo.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/8.BwgOqeMo.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.CvWWuO3h.css +0 -6
- package/frontend/build/client/_app/immutable/assets/BackLink.CvWWuO3h.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.CvWWuO3h.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_layout.BuhMvMUj.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_layout.BuhMvMUj.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_layout.BuhMvMUj.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.0Eln51hV.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.0Eln51hV.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.0Eln51hV.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BZfe6nWe.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.BZfe6nWe.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BZfe6nWe.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Bj_a_5lv.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.Bj_a_5lv.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Bj_a_5lv.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BwgOqeMo.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.BwgOqeMo.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BwgOqeMo.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.CFnbmY-D.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.CFnbmY-D.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.CFnbmY-D.css.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/2zMvi6fR.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/2zMvi6fR.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/3InFPLvE.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/3InFPLvE.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/3InFPLvE.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAACMRH5.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/BAACMRH5.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAACMRH5.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAMUGSh7.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/BAMUGSh7.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAMUGSh7.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BKuh57WU.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/BKuh57WU.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BKuh57WU.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BUwxRmHf.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/BUwxRmHf.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BUwxRmHf.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BmZ9upwL.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BmZ9upwL.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/C1Vid6wz.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C1Vid6wz.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/C8OURRSs.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/C8OURRSs.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C8OURRSs.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CGeZlCaI.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CGeZlCaI.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CGeZlCaI.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CKDtmZUQ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CKDtmZUQ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CMBQQ9RZ.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CMBQQ9RZ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CMBQQ9RZ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CMEtqUfQ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CMEtqUfQ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CNdcuGR0.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CNdcuGR0.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CUC98kMZ.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CUC98kMZ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CUC98kMZ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CgnwuKKO.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CgnwuKKO.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/Co3xKhEp.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/Co3xKhEp.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/Co3xKhEp.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CuqnZUex.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CuqnZUex.js.br +0 -5
- package/frontend/build/client/_app/immutable/chunks/CuqnZUex.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CzlPaHY9.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CzlPaHY9.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DCgHuuvs.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DCgHuuvs.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DDZw0L0T.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DDZw0L0T.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DHM6H-es.js +0 -7
- package/frontend/build/client/_app/immutable/chunks/DHM6H-es.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DHM6H-es.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DMZwI8Cj.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DMZwI8Cj.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DSLBMEpr.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/DSLBMEpr.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DSLBMEpr.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DbgD7JLa.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/DbgD7JLa.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DbgD7JLa.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/TOCyHP97.js +0 -11
- package/frontend/build/client/_app/immutable/chunks/TOCyHP97.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/TOCyHP97.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/kkA1mrsH.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/kkA1mrsH.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/t-La0hgu.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/t-La0hgu.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/w0D4Uzlq.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/w0D4Uzlq.js.gz +0 -0
- package/frontend/build/client/_app/immutable/entry/app.KrtMZ3my.js +0 -7
- package/frontend/build/client/_app/immutable/entry/app.KrtMZ3my.js.br +0 -0
- package/frontend/build/client/_app/immutable/entry/app.KrtMZ3my.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/0.C8DodwXs.js +0 -11
- package/frontend/build/client/_app/immutable/nodes/0.C8DodwXs.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/0.C8DodwXs.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/1.Df9sLw8b.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/1.Df9sLw8b.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/10.DEbnxfND.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/10.DEbnxfND.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/11.BViaDK2m.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/11.BViaDK2m.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/12.BMSCSd88.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/12.BMSCSd88.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/12.BMSCSd88.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/2.BCPSg7H4.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/2.BCPSg7H4.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/3.8BFAJoHT.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/3.8BFAJoHT.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/4.D-YT_JJe.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/4.D-YT_JJe.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/4.D-YT_JJe.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/5.DVeH2eQP.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/5.DVeH2eQP.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/5.DVeH2eQP.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/6.DI7-IJhN.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/6.DI7-IJhN.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/6.DI7-IJhN.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/7.C-pKvVZy.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/7.C-pKvVZy.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/7.C-pKvVZy.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/8.93Mb3ofT.js +0 -9
- package/frontend/build/client/_app/immutable/nodes/8.93Mb3ofT.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/8.93Mb3ofT.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/9.CvfGx3Hu.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/9.CvfGx3Hu.js.gz +0 -0
- package/frontend/build/server/chunks/0-D5YWFygh.js +0 -22
- package/frontend/build/server/chunks/0-D5YWFygh.js.map +0 -5
- package/frontend/build/server/chunks/10-l6_ikL_D.js +0 -14
- package/frontend/build/server/chunks/10-l6_ikL_D.js.map +0 -5
- package/frontend/build/server/chunks/11-CNLerze_.js +0 -14
- package/frontend/build/server/chunks/11-CNLerze_.js.map +0 -5
- package/frontend/build/server/chunks/12-De6Ol6pu.js +0 -14
- package/frontend/build/server/chunks/2-Dc_rKWoK.js +0 -14
- package/frontend/build/server/chunks/3-DrRqVrcX.js +0 -14
- package/frontend/build/server/chunks/3-DrRqVrcX.js.map +0 -5
- package/frontend/build/server/chunks/4-Bo04DC5Z.js +0 -14
- package/frontend/build/server/chunks/4-Bo04DC5Z.js.map +0 -5
- package/frontend/build/server/chunks/5-CFeE5dPZ.js +0 -14
- package/frontend/build/server/chunks/5-CFeE5dPZ.js.map +0 -5
- package/frontend/build/server/chunks/6-DZk37MZH.js +0 -14
- package/frontend/build/server/chunks/6-DZk37MZH.js.map +0 -5
- package/frontend/build/server/chunks/7-DiQJZEF_.js +0 -14
- package/frontend/build/server/chunks/8-CKPVFOqJ.js +0 -14
- package/frontend/build/server/chunks/8-CKPVFOqJ.js.map +0 -5
- package/frontend/build/server/chunks/9-DirZG_Lu.js +0 -14
- package/frontend/build/server/chunks/BackLink-BJ8NaemM.js.map +0 -5
- package/frontend/build/server/chunks/Badge-44ZTDx0V.js.map +0 -5
- package/frontend/build/server/chunks/ConfirmModal-C0EAXcq_.js.map +0 -5
- package/frontend/build/server/chunks/EmptyState-BA_eXaeR.js.map +0 -5
- package/frontend/build/server/chunks/Modal-DChG187n.js.map +0 -5
- package/frontend/build/server/chunks/Toast-v-q4ZnYq.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-1as75nPc.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-1jo8MapI.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-8gELc_B1.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-BuFusRK1.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-CAVyp70V.js +0 -250
- package/frontend/build/server/chunks/_page.svelte-CAVyp70V.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-CWWeZuid.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-D3E6Eojd.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-Kg69DDaM.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-L9fuiN_q.js +0 -57
- package/frontend/build/server/chunks/_page.svelte-L9fuiN_q.js.map +0 -5
- package/frontend/build/server/chunks/constants-CXTaQaB6.js.map +0 -5
- package/frontend/build/server/chunks/reports2-BtElN_53.js.map +0 -5
- package/frontend/build/server/chunks/repository-FYYV_vKE.js.map +0 -5
- package/frontend/build/server/chunks/runner-DC7hXbnY.js +0 -37
- package/frontend/build/server/chunks/runner-DC7hXbnY.js.map +0 -5
- /package/frontend/.svelte-kit/output/client/_app/immutable/assets/{3.BR3wgXcZ.css → 4.BR3wgXcZ.css} +0 -0
- /package/frontend/build/client/_app/immutable/assets/{3.BR3wgXcZ.css → 4.BR3wgXcZ.css} +0 -0
- /package/frontend/build/client/_app/immutable/assets/{3.BR3wgXcZ.css.br → 4.BR3wgXcZ.css.br} +0 -0
- /package/frontend/build/client/_app/immutable/assets/{3.BR3wgXcZ.css.gz → 4.BR3wgXcZ.css.gz} +0 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of Plum.
|
|
3
|
+
* Licensed under the MIT License. See LICENSE file in the project root for details.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { spawn } = require('child_process');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const runnerService = require('./runnerService');
|
|
11
|
+
const reportService = require('./reportService');
|
|
12
|
+
const settingsService = require('./settingsService');
|
|
13
|
+
const notificationService = require('./notificationService');
|
|
14
|
+
const { startRRwebPoller } = require('../lib/rrwebPoller');
|
|
15
|
+
const { runWithRetries } = require('../lib/retryRunner');
|
|
16
|
+
const { BUILT_IN_RUNNER_ID, TRIGGER_REMOTE } = require('../constants/triggers');
|
|
17
|
+
const { PLUM_MODE_NODE } = require('../constants/env');
|
|
18
|
+
const { SOCKET_EVENTS } = require('../constants/socketEvents');
|
|
19
|
+
const { JOB_STATUS, REPORT_STATUS } = require('../constants/jobStatus');
|
|
20
|
+
const { getTestIdsForTag, chunkTests, buildTagExpression } = require('../lib/testChunker');
|
|
21
|
+
const { getTestSuites } = require('./testService');
|
|
22
|
+
const { readCucumberReportFile } = require('../lib/reportFilename');
|
|
23
|
+
|
|
24
|
+
const BACKEND_DIR = path.resolve(__dirname, '..');
|
|
25
|
+
const CANCEL_CODE = 130;
|
|
26
|
+
|
|
27
|
+
// runId → live handles, so cancel() can stop every process and remote job a run owns.
|
|
28
|
+
const inflight = new Map();
|
|
29
|
+
|
|
30
|
+
function handles(runId) {
|
|
31
|
+
let rec = inflight.get(runId);
|
|
32
|
+
if (!rec) {
|
|
33
|
+
rec = { procs: new Set(), remoteJobs: [], cancelled: false };
|
|
34
|
+
inflight.set(runId, rec);
|
|
35
|
+
}
|
|
36
|
+
return rec;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isCancelled(runId) {
|
|
40
|
+
return inflight.get(runId)?.cancelled === true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Best-effort stop of everything a run owns — local child processes and remote node jobs. */
|
|
44
|
+
async function cancel(runId) {
|
|
45
|
+
const rec = inflight.get(runId);
|
|
46
|
+
if (!rec) return false;
|
|
47
|
+
rec.cancelled = true;
|
|
48
|
+
for (const proc of rec.procs) {
|
|
49
|
+
try {
|
|
50
|
+
proc.kill('SIGTERM');
|
|
51
|
+
} catch {}
|
|
52
|
+
}
|
|
53
|
+
await Promise.allSettled(
|
|
54
|
+
rec.remoteJobs.map(({ runnerId, jobId }) => runnerService.cancelRemoteJob(runnerId, jobId))
|
|
55
|
+
);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Stand-in Cucumber JSON for a lane that never produced a real report (process
|
|
60
|
+
// crashed, node unreachable) so its scenarios still show as failed by name
|
|
61
|
+
// instead of silently vanishing from the combined report.
|
|
62
|
+
function makeSyntheticFailReport(laneName, testIds, reason) {
|
|
63
|
+
const nameMap = {};
|
|
64
|
+
try {
|
|
65
|
+
const { suites } = getTestSuites();
|
|
66
|
+
for (const suite of suites) {
|
|
67
|
+
for (const test of suite.tests) {
|
|
68
|
+
for (const id of Array.isArray(test.id) ? test.id : [test.id]) {
|
|
69
|
+
nameMap[id] = test.testCase;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch {}
|
|
74
|
+
|
|
75
|
+
return JSON.stringify([
|
|
76
|
+
{
|
|
77
|
+
id: 'runner-error',
|
|
78
|
+
uri: 'runner-error',
|
|
79
|
+
name: `Runner: ${laneName}`,
|
|
80
|
+
keyword: 'Feature',
|
|
81
|
+
elements: testIds.map((id) => ({
|
|
82
|
+
id: id.replace(/^@/, '').toLowerCase(),
|
|
83
|
+
name: nameMap[id] || id.replace(/^@/, ''),
|
|
84
|
+
keyword: 'Scenario',
|
|
85
|
+
type: 'scenario',
|
|
86
|
+
tags: [{ name: id.startsWith('@') ? id : `@${id}` }],
|
|
87
|
+
steps: [
|
|
88
|
+
{
|
|
89
|
+
keyword: 'Given ',
|
|
90
|
+
name: 'the scenario was assigned to this runner',
|
|
91
|
+
result: {
|
|
92
|
+
status: 'failed',
|
|
93
|
+
error_message: `Runner "${laneName}" did not complete: ${reason}`,
|
|
94
|
+
duration: 0
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}))
|
|
99
|
+
}
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Built-in (local) attempt
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
// Always spawned with PLUM_MODE=node so generate-report.js skips its own DB
|
|
108
|
+
// write — this service persists exactly one report per run itself. The queue
|
|
109
|
+
// serialises every run that targets the built-in runner, so the shared
|
|
110
|
+
// reports/cucumber_report.json is never contended.
|
|
111
|
+
function spawnBuiltInAttempt({
|
|
112
|
+
runId,
|
|
113
|
+
laneId,
|
|
114
|
+
tag,
|
|
115
|
+
workers,
|
|
116
|
+
browser,
|
|
117
|
+
testRunId,
|
|
118
|
+
baseUrl,
|
|
119
|
+
onLog,
|
|
120
|
+
io
|
|
121
|
+
}) {
|
|
122
|
+
return new Promise((resolve) => {
|
|
123
|
+
const ssDir = path.join(os.tmpdir(), `plum-ss-${runId}-${laneId}-${Date.now()}`);
|
|
124
|
+
fs.mkdirSync(ssDir, { recursive: true });
|
|
125
|
+
|
|
126
|
+
const env = {
|
|
127
|
+
...process.env,
|
|
128
|
+
TAG: tag,
|
|
129
|
+
TRIGGER: TRIGGER_REMOTE,
|
|
130
|
+
BROWSER: browser,
|
|
131
|
+
REPORT_RUNNERS: String(workers),
|
|
132
|
+
PLUM_MODE: PLUM_MODE_NODE,
|
|
133
|
+
PLUM_SS_DIR: ssDir
|
|
134
|
+
};
|
|
135
|
+
if (Number(workers) > 1) env.PARALLEL = String(workers);
|
|
136
|
+
if (testRunId) env.TEST_RUN_ID = testRunId;
|
|
137
|
+
if (baseUrl) env.BASE_URL = baseUrl;
|
|
138
|
+
|
|
139
|
+
const proc = spawn('npm', ['run', 'test'], { env, shell: true, cwd: BACKEND_DIR });
|
|
140
|
+
handles(runId).procs.add(proc);
|
|
141
|
+
|
|
142
|
+
const ssPoller = startRRwebPoller(ssDir, (batch) => {
|
|
143
|
+
io && io.emit(SOCKET_EVENTS.BG_RUN_LANE_RRWEB_BATCH, { runId, id: laneId, ...batch });
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
proc.stdout.on('data', (d) => onLog(d.toString()));
|
|
147
|
+
proc.stderr.on('data', (d) => onLog(`[ERROR] ${d.toString()}`));
|
|
148
|
+
|
|
149
|
+
proc.on('close', (code) => {
|
|
150
|
+
ssPoller.stop();
|
|
151
|
+
fs.rm(ssDir, { recursive: true, force: true }, () => {});
|
|
152
|
+
handles(runId).procs.delete(proc);
|
|
153
|
+
resolve({ code, raw: readCucumberReportFile() });
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// Single built-in runner
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
|
|
162
|
+
async function runBuiltIn(run, io, emit) {
|
|
163
|
+
const startedAt = Date.now();
|
|
164
|
+
const { maxRetries } = await settingsService.getProject();
|
|
165
|
+
const laneId = BUILT_IN_RUNNER_ID;
|
|
166
|
+
|
|
167
|
+
let logBuffer = '';
|
|
168
|
+
const onLog = (text) => {
|
|
169
|
+
logBuffer += text;
|
|
170
|
+
emit(SOCKET_EVENTS.BG_RUN_LANE_LOG, { laneId, log: text });
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
emit(SOCKET_EVENTS.BG_RUN_LANES_INIT, {
|
|
174
|
+
lanes: [{ id: laneId, name: 'Built-in', testCount: getTestIdsForTag(run.tag).length }]
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const { code, rawJson, attempts } = await runWithRetries({
|
|
178
|
+
maxRetries,
|
|
179
|
+
spawnAttempt: async (tagOverride) => {
|
|
180
|
+
const { code, raw } = await spawnBuiltInAttempt({
|
|
181
|
+
runId: run.id,
|
|
182
|
+
laneId,
|
|
183
|
+
tag: tagOverride ?? run.tag,
|
|
184
|
+
workers: run.workers,
|
|
185
|
+
browser: run.browser,
|
|
186
|
+
testRunId: run.testRunId,
|
|
187
|
+
baseUrl: run.baseUrl,
|
|
188
|
+
onLog,
|
|
189
|
+
io
|
|
190
|
+
});
|
|
191
|
+
return { code, rawJson: raw ? JSON.parse(raw) : [] };
|
|
192
|
+
},
|
|
193
|
+
onLog
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const cancelled = isCancelled(run.id) || code === CANCEL_CODE;
|
|
197
|
+
emit(SOCKET_EVENTS.BG_RUN_LANE_STATUS, {
|
|
198
|
+
laneId,
|
|
199
|
+
status: cancelled ? JOB_STATUS.CANCELLED : code === 0 ? JOB_STATUS.DONE : JOB_STATUS.ERROR
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
if (cancelled) return { code: CANCEL_CODE, reportId: null };
|
|
203
|
+
|
|
204
|
+
const report = await reportService.saveReport({
|
|
205
|
+
rawCucumberJson: rawJson,
|
|
206
|
+
tags: run.tag,
|
|
207
|
+
triggerType: run.triggerType,
|
|
208
|
+
workerCount: run.workers,
|
|
209
|
+
browser: run.browser,
|
|
210
|
+
testRunId: run.testRunId ?? null,
|
|
211
|
+
logs: logBuffer || null,
|
|
212
|
+
duration: Date.now() - startedAt,
|
|
213
|
+
attempts
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
io && io.emit(SOCKET_EVENTS.REPORT_READY);
|
|
217
|
+
await maybeNotify(run, report);
|
|
218
|
+
return { code: report.status === REPORT_STATUS.PASS ? 0 : 1, reportId: report.id };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
// Distributed (multi-runner) path
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
|
|
225
|
+
async function runDistributed(run, io, emit, laneInfos, chunks) {
|
|
226
|
+
const startedAt = Date.now();
|
|
227
|
+
const { maxRetries } = await settingsService.getProject();
|
|
228
|
+
|
|
229
|
+
emit(SOCKET_EVENTS.BG_RUN_LANES_INIT, {
|
|
230
|
+
lanes: laneInfos.map((l, i) => ({ id: l.id, name: l.name, testCount: chunks[i].length }))
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const total = laneInfos.length;
|
|
234
|
+
const collectedReports = new Array(total).fill(null);
|
|
235
|
+
const laneAttempts = new Array(total).fill(null);
|
|
236
|
+
const laneLogs = {};
|
|
237
|
+
for (const l of laneInfos) laneLogs[l.id] = '';
|
|
238
|
+
|
|
239
|
+
const laneResults = await Promise.all(
|
|
240
|
+
laneInfos.map((lane, i) => runLane(run, io, emit, lane, chunks[i], maxRetries, laneLogs))
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
let overallCode = 0;
|
|
244
|
+
laneResults.forEach((res, i) => {
|
|
245
|
+
if (res.code !== 0) overallCode = res.code;
|
|
246
|
+
collectedReports[i] = res.content;
|
|
247
|
+
laneAttempts[i] = res.attempts;
|
|
248
|
+
emit(SOCKET_EVENTS.BG_RUN_LANE_STATUS, {
|
|
249
|
+
laneId: laneInfos[i].id,
|
|
250
|
+
status: res.code === 0 ? JOB_STATUS.DONE : JOB_STATUS.ERROR
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
if (isCancelled(run.id)) return { code: CANCEL_CODE, reportId: null };
|
|
255
|
+
|
|
256
|
+
const saved = await reportService.saveCombinedReport({
|
|
257
|
+
reports: collectedReports,
|
|
258
|
+
runners: laneInfos,
|
|
259
|
+
workers: run.workers,
|
|
260
|
+
overallCode,
|
|
261
|
+
tag: run.tag,
|
|
262
|
+
triggerType: run.triggerType,
|
|
263
|
+
browser: run.browser,
|
|
264
|
+
testRunId: run.testRunId ?? null,
|
|
265
|
+
laneLogs,
|
|
266
|
+
duration: Date.now() - startedAt,
|
|
267
|
+
attemptsByLane: laneAttempts
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
io && io.emit(SOCKET_EVENTS.REPORT_READY);
|
|
271
|
+
await maybeNotify(run, saved);
|
|
272
|
+
return { code: saved.status === REPORT_STATUS.PASS ? 0 : 1, reportId: saved.id };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function runLane(run, io, emit, lane, chunkIds, maxRetries, laneLogs) {
|
|
276
|
+
const laneId = lane.id;
|
|
277
|
+
const chunkTag = buildTagExpression(chunkIds);
|
|
278
|
+
const onLog = (log) => {
|
|
279
|
+
laneLogs[laneId] += log;
|
|
280
|
+
emit(SOCKET_EVENTS.BG_RUN_LANE_LOG, { laneId, log });
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const attempt =
|
|
284
|
+
lane.id === BUILT_IN_RUNNER_ID
|
|
285
|
+
? (currentTag) =>
|
|
286
|
+
spawnBuiltInAttempt({
|
|
287
|
+
runId: run.id,
|
|
288
|
+
laneId,
|
|
289
|
+
tag: currentTag,
|
|
290
|
+
workers: run.workers,
|
|
291
|
+
browser: run.browser,
|
|
292
|
+
testRunId: run.testRunId,
|
|
293
|
+
baseUrl: run.baseUrl,
|
|
294
|
+
onLog,
|
|
295
|
+
io
|
|
296
|
+
}).then(({ code, raw }) => ({
|
|
297
|
+
code,
|
|
298
|
+
rawJson: JSON.parse(
|
|
299
|
+
raw ?? makeSyntheticFailReport(lane.name, chunkIds, 'process exited with error')
|
|
300
|
+
)
|
|
301
|
+
}))
|
|
302
|
+
: (currentTag) =>
|
|
303
|
+
new Promise((resolve) => {
|
|
304
|
+
runnerService.dispatchAndPoll(
|
|
305
|
+
laneId,
|
|
306
|
+
{
|
|
307
|
+
tags: currentTag,
|
|
308
|
+
browser: run.browser,
|
|
309
|
+
workers: run.workers,
|
|
310
|
+
baseUrl: run.baseUrl
|
|
311
|
+
},
|
|
312
|
+
onLog,
|
|
313
|
+
(code, content) =>
|
|
314
|
+
resolve({
|
|
315
|
+
code,
|
|
316
|
+
rawJson: JSON.parse(
|
|
317
|
+
content ??
|
|
318
|
+
makeSyntheticFailReport(
|
|
319
|
+
lane.name,
|
|
320
|
+
chunkIds,
|
|
321
|
+
'could not fetch report from runner'
|
|
322
|
+
)
|
|
323
|
+
)
|
|
324
|
+
}),
|
|
325
|
+
(batch) =>
|
|
326
|
+
io &&
|
|
327
|
+
io.emit(SOCKET_EVENTS.BG_RUN_LANE_RRWEB_BATCH, {
|
|
328
|
+
runId: run.id,
|
|
329
|
+
id: laneId,
|
|
330
|
+
...batch
|
|
331
|
+
}),
|
|
332
|
+
(jobId) => handles(run.id).remoteJobs.push({ runnerId: laneId, jobId })
|
|
333
|
+
);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
return runWithRetries({
|
|
337
|
+
maxRetries,
|
|
338
|
+
spawnAttempt: (t) => attempt(t ?? chunkTag),
|
|
339
|
+
onLog
|
|
340
|
+
}).then(({ code, rawJson, attempts }) => ({
|
|
341
|
+
code,
|
|
342
|
+
content: JSON.stringify(rawJson),
|
|
343
|
+
attempts
|
|
344
|
+
}));
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// ---------------------------------------------------------------------------
|
|
348
|
+
// Shared
|
|
349
|
+
// ---------------------------------------------------------------------------
|
|
350
|
+
|
|
351
|
+
async function maybeNotify(run, report) {
|
|
352
|
+
if (!report || (!run.notifyDiscord && !run.notifySlack)) return;
|
|
353
|
+
try {
|
|
354
|
+
await notificationService.send({
|
|
355
|
+
jobName: run.label,
|
|
356
|
+
status: report.status,
|
|
357
|
+
content: report.content,
|
|
358
|
+
browser: run.browser,
|
|
359
|
+
tags: run.tag,
|
|
360
|
+
reportId: report.id,
|
|
361
|
+
notifyDiscord: run.notifyDiscord,
|
|
362
|
+
notifySlack: run.notifySlack
|
|
363
|
+
});
|
|
364
|
+
} catch (e) {
|
|
365
|
+
console.error(`[run-executor] Notification failed: ${e.message}`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Runs one queued job (a plain RunQueue row) to completion and resolves with
|
|
370
|
+
// { code, reportId, note? }. Takes only plain fields — no closure — so the queue
|
|
371
|
+
// can re-dispatch a persisted row after a server restart.
|
|
372
|
+
async function execute(run, io) {
|
|
373
|
+
handles(run.id); // register before any await so an early cancel is seen
|
|
374
|
+
const emit = (event, extra) => io && io.emit(event, { runId: run.id, ...extra });
|
|
375
|
+
|
|
376
|
+
// Drop runner ids that no longer exist — a stale selection or a runner
|
|
377
|
+
// deleted while this job sat in the queue must not wedge it.
|
|
378
|
+
const validated = [];
|
|
379
|
+
for (const id of run.runnerIds) {
|
|
380
|
+
if (id === BUILT_IN_RUNNER_ID || (await runnerService.getById(id))) validated.push(id);
|
|
381
|
+
}
|
|
382
|
+
if (validated.length === 0) {
|
|
383
|
+
return { code: 0, reportId: null, note: 'Target runner no longer exists — run skipped.' };
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
emit(SOCKET_EVENTS.BG_RUN_START, {
|
|
387
|
+
kind: run.kind,
|
|
388
|
+
label: run.label,
|
|
389
|
+
meta: {
|
|
390
|
+
tag: run.tag,
|
|
391
|
+
workers: run.workers,
|
|
392
|
+
browser: run.browser,
|
|
393
|
+
startedBy: run.startedBy ?? null
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
const isSingleBuiltIn = validated.length === 1 && validated[0] === BUILT_IN_RUNNER_ID;
|
|
399
|
+
if (isSingleBuiltIn) return await runBuiltIn(run, io, emit);
|
|
400
|
+
|
|
401
|
+
const allIds = getTestIdsForTag(run.tag);
|
|
402
|
+
const chunks = chunkTests(allIds, validated.length);
|
|
403
|
+
// Surplus runners beyond the non-empty chunk count would each re-run the
|
|
404
|
+
// full tag expression and duplicate scenarios — drop them.
|
|
405
|
+
const activeIds = validated.slice(0, chunks.length);
|
|
406
|
+
if (activeIds.length === 0) {
|
|
407
|
+
emit(SOCKET_EVENTS.BG_RUN_LOG, { log: 'No tests found matching the selected tag.\n' });
|
|
408
|
+
return { code: 0, reportId: null, note: 'No tests matched — run skipped.' };
|
|
409
|
+
}
|
|
410
|
+
const laneInfos = await Promise.all(
|
|
411
|
+
activeIds.map(async (id) => {
|
|
412
|
+
if (id === BUILT_IN_RUNNER_ID) return { id, name: 'Built-in', dbId: null };
|
|
413
|
+
const r = await runnerService.getById(id);
|
|
414
|
+
return { id, name: r?.name ?? id, dbId: r?.id ?? null };
|
|
415
|
+
})
|
|
416
|
+
);
|
|
417
|
+
return await runDistributed(run, io, emit, laneInfos, chunks);
|
|
418
|
+
} finally {
|
|
419
|
+
inflight.delete(run.id);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
module.exports = { execute, cancel, isCancelled };
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of Plum.
|
|
3
|
+
* Licensed under the MIT License. See LICENSE file in the project root for details.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { randomUUID } = require('crypto');
|
|
7
|
+
const prisma = require('./prisma');
|
|
8
|
+
const runExecutorService = require('./runExecutorService');
|
|
9
|
+
const { BUILT_IN_RUNNER_ID } = require('../constants/triggers');
|
|
10
|
+
const { DEFAULT_BROWSER } = require('../constants/defaults');
|
|
11
|
+
const { SOCKET_EVENTS } = require('../constants/socketEvents');
|
|
12
|
+
const { JOB_STATUS } = require('../constants/jobStatus');
|
|
13
|
+
|
|
14
|
+
const QUEUED = 'queued';
|
|
15
|
+
const RUNNING = 'running';
|
|
16
|
+
const DONE = 'done';
|
|
17
|
+
const CANCEL_CODE = 130;
|
|
18
|
+
const PRUNE_MS = 60 * 60 * 1000;
|
|
19
|
+
|
|
20
|
+
let _io = null;
|
|
21
|
+
function setSocketIO(io) {
|
|
22
|
+
_io = io;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseRunnerIds(str) {
|
|
26
|
+
const ids = (str || '')
|
|
27
|
+
.split(',')
|
|
28
|
+
.map((s) => s.trim())
|
|
29
|
+
.filter(Boolean);
|
|
30
|
+
return ids.length > 0 ? ids : [BUILT_IN_RUNNER_ID];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normaliseRunnerIds(arr) {
|
|
34
|
+
return Array.isArray(arr) && arr.length > 0 ? arr : [BUILT_IN_RUNNER_ID];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function rowToJob(row) {
|
|
38
|
+
return {
|
|
39
|
+
id: row.id,
|
|
40
|
+
kind: row.kind,
|
|
41
|
+
triggerType: row.triggerType,
|
|
42
|
+
label: row.label,
|
|
43
|
+
tag: row.tag,
|
|
44
|
+
workers: row.workers,
|
|
45
|
+
browser: row.browser,
|
|
46
|
+
runnerIds: parseRunnerIds(row.runnerIds),
|
|
47
|
+
testRunId: row.testRunId,
|
|
48
|
+
baseUrl: row.baseUrl,
|
|
49
|
+
notifyDiscord: row.notifyDiscord,
|
|
50
|
+
notifySlack: row.notifySlack,
|
|
51
|
+
startedBy: row.startedBy
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function meta(job) {
|
|
56
|
+
return {
|
|
57
|
+
tag: job.tag ?? '',
|
|
58
|
+
workers: Number(job.workers) > 1 ? Number(job.workers) : 1,
|
|
59
|
+
browser: job.browser ?? DEFAULT_BROWSER,
|
|
60
|
+
startedBy: job.startedBy ?? null
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Pump — decides which queued rows may start
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
let pumping = false;
|
|
69
|
+
let pumpAgain = false;
|
|
70
|
+
|
|
71
|
+
async function pump() {
|
|
72
|
+
if (pumping) {
|
|
73
|
+
pumpAgain = true;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
pumping = true;
|
|
77
|
+
try {
|
|
78
|
+
do {
|
|
79
|
+
pumpAgain = false;
|
|
80
|
+
await pumpOnce();
|
|
81
|
+
} while (pumpAgain);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
console.error('[run-queue] pump failed:', e.message);
|
|
84
|
+
} finally {
|
|
85
|
+
pumping = false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function pumpOnce() {
|
|
90
|
+
const rows = await prisma.runQueue.findMany({
|
|
91
|
+
where: { status: { in: [QUEUED, RUNNING] } },
|
|
92
|
+
orderBy: { queuedAt: 'asc' }
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// A runner is busy if a running row holds it. A queued row that can't start
|
|
96
|
+
// yet still reserves its runners so a later job on the same runner waits
|
|
97
|
+
// behind it (FIFO per runner) instead of jumping the line.
|
|
98
|
+
const busy = new Set();
|
|
99
|
+
for (const r of rows) {
|
|
100
|
+
if (r.status === RUNNING) parseRunnerIds(r.runnerIds).forEach((id) => busy.add(id));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (const r of rows) {
|
|
104
|
+
if (r.status !== QUEUED) continue;
|
|
105
|
+
const ids = parseRunnerIds(r.runnerIds);
|
|
106
|
+
const blocked = ids.some((id) => busy.has(id));
|
|
107
|
+
ids.forEach((id) => busy.add(id));
|
|
108
|
+
if (blocked) continue;
|
|
109
|
+
|
|
110
|
+
await prisma.runQueue.update({
|
|
111
|
+
where: { id: r.id },
|
|
112
|
+
data: { status: RUNNING, startedAt: new Date() }
|
|
113
|
+
});
|
|
114
|
+
dispatch(r);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function dispatch(row) {
|
|
119
|
+
runExecutorService
|
|
120
|
+
.execute(rowToJob(row), _io)
|
|
121
|
+
.then((res) => finalise(row.id, res))
|
|
122
|
+
.catch((err) => {
|
|
123
|
+
console.error(`[run-queue] run ${row.id} threw:`, err);
|
|
124
|
+
finalise(row.id, { code: 1, reportId: null, note: err.message });
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function finalise(id, { code, reportId, note }) {
|
|
129
|
+
await prisma.runQueue.update({
|
|
130
|
+
where: { id },
|
|
131
|
+
data: {
|
|
132
|
+
status: DONE,
|
|
133
|
+
exitCode: code,
|
|
134
|
+
reportId: reportId ?? null,
|
|
135
|
+
note: note ?? null,
|
|
136
|
+
finishedAt: new Date()
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
if (_io) _io.emit(SOCKET_EVENTS.BG_RUN_DONE, { runId: id, code, reportId: reportId ?? null });
|
|
140
|
+
prune().catch(() => {});
|
|
141
|
+
pump();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function prune() {
|
|
145
|
+
await prisma.runQueue.deleteMany({
|
|
146
|
+
where: { status: DONE, finishedAt: { lt: new Date(Date.now() - PRUNE_MS) } }
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Public API
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
// Adds a run request to the queue and returns its id. It starts as soon as
|
|
155
|
+
// every runner it targets is free; disjoint runner sets run in parallel.
|
|
156
|
+
async function enqueue(job) {
|
|
157
|
+
const id = job.id || randomUUID();
|
|
158
|
+
const runnerIds = normaliseRunnerIds(job.runnerIds);
|
|
159
|
+
|
|
160
|
+
await prisma.runQueue.create({
|
|
161
|
+
data: {
|
|
162
|
+
id,
|
|
163
|
+
kind: job.kind,
|
|
164
|
+
triggerType: job.triggerType,
|
|
165
|
+
label: job.label ?? '',
|
|
166
|
+
status: QUEUED,
|
|
167
|
+
tag: job.tag ?? '',
|
|
168
|
+
workers: Number(job.workers) > 1 ? Number(job.workers) : 1,
|
|
169
|
+
browser: job.browser ?? DEFAULT_BROWSER,
|
|
170
|
+
runnerIds: runnerIds.join(','),
|
|
171
|
+
testRunId: job.testRunId ?? null,
|
|
172
|
+
baseUrl: job.baseUrl ?? null,
|
|
173
|
+
runTitle: job.runTitle ?? null,
|
|
174
|
+
startedBy: job.startedBy ?? null,
|
|
175
|
+
notifyDiscord: job.notifyDiscord === true,
|
|
176
|
+
notifySlack: job.notifySlack === true
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (_io) {
|
|
181
|
+
_io.emit(SOCKET_EVENTS.BG_RUN_QUEUED, {
|
|
182
|
+
runId: id,
|
|
183
|
+
kind: job.kind,
|
|
184
|
+
label: job.label ?? '',
|
|
185
|
+
meta: meta(job),
|
|
186
|
+
runnerIds
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
pump();
|
|
191
|
+
return id;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Stops a run in any state: a queued row is dropped, a running one has its local
|
|
195
|
+
// processes and remote node jobs killed. Emits bg-run-done either way.
|
|
196
|
+
async function cancel(id) {
|
|
197
|
+
const row = await prisma.runQueue.findUnique({ where: { id } });
|
|
198
|
+
if (!row || row.status === DONE) return false;
|
|
199
|
+
|
|
200
|
+
if (row.status === QUEUED) {
|
|
201
|
+
await prisma.runQueue.update({
|
|
202
|
+
where: { id },
|
|
203
|
+
data: {
|
|
204
|
+
status: DONE,
|
|
205
|
+
exitCode: CANCEL_CODE,
|
|
206
|
+
note: 'Cancelled before it started',
|
|
207
|
+
finishedAt: new Date()
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
if (_io) _io.emit(SOCKET_EVENTS.BG_RUN_DONE, { runId: id, code: CANCEL_CODE, reportId: null });
|
|
211
|
+
pump();
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Running — the executor's own promise then resolves with code 130 and
|
|
216
|
+
// finalise() emits bg-run-done.
|
|
217
|
+
await runExecutorService.cancel(id);
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Back-compat shape for the HTTP trigger poll (GET /trigger/:jobId).
|
|
222
|
+
async function getJob(id) {
|
|
223
|
+
const row = await prisma.runQueue.findUnique({ where: { id } });
|
|
224
|
+
if (!row) return null;
|
|
225
|
+
let status = JOB_STATUS.RUNNING;
|
|
226
|
+
if (row.status === DONE) {
|
|
227
|
+
status =
|
|
228
|
+
row.exitCode === CANCEL_CODE
|
|
229
|
+
? JOB_STATUS.CANCELLED
|
|
230
|
+
: row.exitCode === 0
|
|
231
|
+
? JOB_STATUS.DONE
|
|
232
|
+
: JOB_STATUS.ERROR;
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
status,
|
|
236
|
+
exitCode: row.exitCode,
|
|
237
|
+
reportId: row.reportId ?? null,
|
|
238
|
+
startedAt: (row.startedAt ?? row.queuedAt).getTime()
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async function listActive() {
|
|
243
|
+
const rows = await prisma.runQueue.findMany({
|
|
244
|
+
where: { status: { in: [QUEUED, RUNNING] } },
|
|
245
|
+
orderBy: { queuedAt: 'asc' }
|
|
246
|
+
});
|
|
247
|
+
let queuePos = 0;
|
|
248
|
+
return rows.map((r) => ({
|
|
249
|
+
runId: r.id,
|
|
250
|
+
status: r.status,
|
|
251
|
+
kind: r.kind,
|
|
252
|
+
label: r.label,
|
|
253
|
+
runnerIds: parseRunnerIds(r.runnerIds),
|
|
254
|
+
position: r.status === QUEUED ? ++queuePos : 0,
|
|
255
|
+
meta: { tag: r.tag, workers: r.workers, browser: r.browser, startedBy: r.startedBy }
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function init(io) {
|
|
260
|
+
setSocketIO(io);
|
|
261
|
+
// Running rows can only be stale here — this process just started, so their
|
|
262
|
+
// child processes died with the previous one.
|
|
263
|
+
await prisma.runQueue.updateMany({
|
|
264
|
+
where: { status: RUNNING },
|
|
265
|
+
data: {
|
|
266
|
+
status: DONE,
|
|
267
|
+
exitCode: 1,
|
|
268
|
+
note: 'Interrupted by a server restart',
|
|
269
|
+
finishedAt: new Date()
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
await prune();
|
|
273
|
+
await pump();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
module.exports = { setSocketIO, enqueue, cancel, getJob, listActive, init };
|