@shipfox/api-workflows 12.4.0 → 12.6.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.
Files changed (84) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +24 -0
  3. package/dist/core/entities/job-execution.d.ts +1 -0
  4. package/dist/core/entities/job-execution.d.ts.map +1 -1
  5. package/dist/core/entities/job-execution.js.map +1 -1
  6. package/dist/core/entities/job.d.ts +1 -1
  7. package/dist/core/entities/job.d.ts.map +1 -1
  8. package/dist/core/entities/job.js +3 -1
  9. package/dist/core/entities/job.js.map +1 -1
  10. package/dist/core/errors.d.ts +3 -1
  11. package/dist/core/errors.d.ts.map +1 -1
  12. package/dist/core/errors.js +4 -2
  13. package/dist/core/errors.js.map +1 -1
  14. package/dist/core/step-config/job-output-limits.d.ts.map +1 -1
  15. package/dist/core/step-config/job-output-limits.js +2 -2
  16. package/dist/core/step-config/job-output-limits.js.map +1 -1
  17. package/dist/core/step-config/materialize-workflow-model.js +2 -2
  18. package/dist/core/step-config/materialize-workflow-model.js.map +1 -1
  19. package/dist/db/db.d.ts +42 -8
  20. package/dist/db/db.d.ts.map +1 -1
  21. package/dist/db/index.d.ts +1 -1
  22. package/dist/db/index.d.ts.map +1 -1
  23. package/dist/db/index.js.map +1 -1
  24. package/dist/db/schema/job-executions.d.ts +19 -2
  25. package/dist/db/schema/job-executions.d.ts.map +1 -1
  26. package/dist/db/schema/job-executions.js +2 -0
  27. package/dist/db/schema/job-executions.js.map +1 -1
  28. package/dist/db/schema/jobs.d.ts +3 -3
  29. package/dist/db/schema/jobs.d.ts.map +1 -1
  30. package/dist/db/schema/jobs.js +3 -0
  31. package/dist/db/schema/jobs.js.map +1 -1
  32. package/dist/db/workflow-runs/job-executions.d.ts +7 -0
  33. package/dist/db/workflow-runs/job-executions.d.ts.map +1 -1
  34. package/dist/db/workflow-runs/job-executions.js +26 -4
  35. package/dist/db/workflow-runs/job-executions.js.map +1 -1
  36. package/dist/db/workflow-runs/jobs.d.ts.map +1 -1
  37. package/dist/db/workflow-runs/jobs.js +4 -2
  38. package/dist/db/workflow-runs/jobs.js.map +1 -1
  39. package/dist/db/workflow-runs/queries.d.ts +14 -2
  40. package/dist/db/workflow-runs/queries.d.ts.map +1 -1
  41. package/dist/db/workflow-runs/queries.js +52 -13
  42. package/dist/db/workflow-runs/queries.js.map +1 -1
  43. package/dist/db/workflow-runs.d.ts +1 -1
  44. package/dist/db/workflow-runs.d.ts.map +1 -1
  45. package/dist/db/workflow-runs.js.map +1 -1
  46. package/dist/presentation/dto/job.d.ts.map +1 -1
  47. package/dist/presentation/dto/job.js +1 -0
  48. package/dist/presentation/dto/job.js.map +1 -1
  49. package/dist/presentation/dto/workflow-run.d.ts.map +1 -1
  50. package/dist/presentation/dto/workflow-run.js +10 -2
  51. package/dist/presentation/dto/workflow-run.js.map +1 -1
  52. package/dist/presentation/subscribers/on-failure-annotations.d.ts.map +1 -1
  53. package/dist/presentation/subscribers/on-failure-annotations.js +6 -3
  54. package/dist/presentation/subscribers/on-failure-annotations.js.map +1 -1
  55. package/dist/tsconfig.test.tsbuildinfo +1 -1
  56. package/drizzle/0002_output_failure_details.sql +2 -0
  57. package/drizzle/0003_output_invalid_reason.sql +1 -0
  58. package/drizzle/meta/0002_snapshot.json +1718 -0
  59. package/drizzle/meta/0003_snapshot.json +1719 -0
  60. package/drizzle/meta/_journal.json +14 -0
  61. package/package.json +2 -2
  62. package/src/core/entities/job-execution.ts +1 -0
  63. package/src/core/entities/job.ts +2 -0
  64. package/src/core/errors.test.ts +18 -0
  65. package/src/core/errors.ts +9 -2
  66. package/src/core/step-config/job-output-limits.ts +2 -2
  67. package/src/core/step-config/materialize-workflow-model.test.ts +67 -3
  68. package/src/core/step-config/materialize-workflow-model.ts +2 -2
  69. package/src/db/index.ts +1 -0
  70. package/src/db/schema/job-executions.ts +2 -0
  71. package/src/db/schema/jobs.ts +3 -0
  72. package/src/db/workflow-runs/job-executions.test.ts +149 -4
  73. package/src/db/workflow-runs/job-executions.ts +44 -9
  74. package/src/db/workflow-runs/job-status.test.ts +30 -0
  75. package/src/db/workflow-runs/jobs.ts +5 -1
  76. package/src/db/workflow-runs/queries.test.ts +169 -2
  77. package/src/db/workflow-runs/queries.ts +86 -11
  78. package/src/db/workflow-runs.ts +1 -0
  79. package/src/presentation/dto/job.ts +1 -0
  80. package/src/presentation/dto/workflow-run.ts +6 -2
  81. package/src/presentation/subscribers/on-failure-annotations.test.ts +47 -1
  82. package/src/presentation/subscribers/on-failure-annotations.ts +10 -2
  83. package/test/helpers/workflow-runs.ts +1 -0
  84. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/dto/job.ts"],"sourcesContent":["import type {JobDto, JobExecutionDto} from '@shipfox/api-workflows-dto';\nimport type {Job} from '#core/entities/job.js';\nimport type {JobExecution} from '#core/entities/job-execution.js';\nimport {toEvaluationTraceDto} from './evaluation-trace.js';\n\nexport function toJobDto(job: Job): JobDto {\n return {\n id: job.id,\n run_attempt_id: job.workflowRunAttemptId,\n key: job.key,\n name: job.name,\n mode: job.mode,\n status: job.status,\n status_reason: job.statusReason,\n carried_over: job.carriedOver,\n success: job.success ?? null,\n runner: job.runner,\n evaluation_trace: toEvaluationTraceDto(job.evaluationTrace),\n listening:\n job.listeningOn === null\n ? null\n : {\n on: job.listeningOn,\n until: job.listeningUntil,\n timeout_ms: job.listeningTimeoutMs,\n max_executions: job.maxExecutions,\n batch:\n job.batchDebounceMs === null &&\n job.batchMaxSize === null &&\n job.batchMaxWaitMs === null\n ? null\n : {\n ...(job.batchDebounceMs === null ? {} : {debounce_ms: job.batchDebounceMs}),\n ...(job.batchMaxSize === null ? {} : {max_size: job.batchMaxSize}),\n ...(job.batchMaxWaitMs === null ? {} : {max_wait_ms: job.batchMaxWaitMs}),\n },\n on_resolve: job.onResolve ?? 'finish',\n execution_timeout_ms: job.executionTimeoutMs ?? null,\n name: job.name,\n },\n listener_status: job.listenerStatus,\n resolution_reason: job.resolutionReason,\n outputs: job.outputs,\n dependencies: job.dependencies,\n position: job.position,\n created_at: job.createdAt.toISOString(),\n updated_at: job.updatedAt.toISOString(),\n };\n}\n\nexport function toJobExecutionDto(jobExecution: JobExecution): JobExecutionDto {\n return {\n id: jobExecution.id,\n job_id: jobExecution.jobId,\n sequence: jobExecution.sequence,\n name: jobExecution.name,\n status: jobExecution.status,\n status_reason: jobExecution.statusReason,\n runner: jobExecution.runner,\n trigger_events: jobExecution.triggerEvents,\n outputs: jobExecution.outputs,\n evaluation_trace: toEvaluationTraceDto(jobExecution.evaluationTrace),\n queued_at: jobExecution.queuedAt?.toISOString() ?? null,\n started_at: jobExecution.startedAt?.toISOString() ?? null,\n finished_at: jobExecution.finishedAt?.toISOString() ?? null,\n timed_out_at: jobExecution.timedOutAt?.toISOString() ?? null,\n created_at: jobExecution.createdAt.toISOString(),\n updated_at: jobExecution.updatedAt.toISOString(),\n };\n}\n"],"names":["toEvaluationTraceDto","toJobDto","job","id","run_attempt_id","workflowRunAttemptId","key","name","mode","status","status_reason","statusReason","carried_over","carriedOver","success","runner","evaluation_trace","evaluationTrace","listening","listeningOn","on","until","listeningUntil","timeout_ms","listeningTimeoutMs","max_executions","maxExecutions","batch","batchDebounceMs","batchMaxSize","batchMaxWaitMs","debounce_ms","max_size","max_wait_ms","on_resolve","onResolve","execution_timeout_ms","executionTimeoutMs","listener_status","listenerStatus","resolution_reason","resolutionReason","outputs","dependencies","position","created_at","createdAt","toISOString","updated_at","updatedAt","toJobExecutionDto","jobExecution","job_id","jobId","sequence","trigger_events","triggerEvents","queued_at","queuedAt","started_at","startedAt","finished_at","finishedAt","timed_out_at","timedOutAt"],"mappings":"AAGA,SAAQA,oBAAoB,QAAO,wBAAwB;AAE3D,OAAO,SAASC,SAASC,GAAQ;IAC/B,OAAO;QACLC,IAAID,IAAIC,EAAE;QACVC,gBAAgBF,IAAIG,oBAAoB;QACxCC,KAAKJ,IAAII,GAAG;QACZC,MAAML,IAAIK,IAAI;QACdC,MAAMN,IAAIM,IAAI;QACdC,QAAQP,IAAIO,MAAM;QAClBC,eAAeR,IAAIS,YAAY;QAC/BC,cAAcV,IAAIW,WAAW;QAC7BC,SAASZ,IAAIY,OAAO,IAAI;QACxBC,QAAQb,IAAIa,MAAM;QAClBC,kBAAkBhB,qBAAqBE,IAAIe,eAAe;QAC1DC,WACEhB,IAAIiB,WAAW,KAAK,OAChB,OACA;YACEC,IAAIlB,IAAIiB,WAAW;YACnBE,OAAOnB,IAAIoB,cAAc;YACzBC,YAAYrB,IAAIsB,kBAAkB;YAClCC,gBAAgBvB,IAAIwB,aAAa;YACjCC,OACEzB,IAAI0B,eAAe,KAAK,QACxB1B,IAAI2B,YAAY,KAAK,QACrB3B,IAAI4B,cAAc,KAAK,OACnB,OACA;gBACE,GAAI5B,IAAI0B,eAAe,KAAK,OAAO,CAAC,IAAI;oBAACG,aAAa7B,IAAI0B,eAAe;gBAAA,CAAC;gBAC1E,GAAI1B,IAAI2B,YAAY,KAAK,OAAO,CAAC,IAAI;oBAACG,UAAU9B,IAAI2B,YAAY;gBAAA,CAAC;gBACjE,GAAI3B,IAAI4B,cAAc,KAAK,OAAO,CAAC,IAAI;oBAACG,aAAa/B,IAAI4B,cAAc;gBAAA,CAAC;YAC1E;YACNI,YAAYhC,IAAIiC,SAAS,IAAI;YAC7BC,sBAAsBlC,IAAImC,kBAAkB,IAAI;YAChD9B,MAAML,IAAIK,IAAI;QAChB;QACN+B,iBAAiBpC,IAAIqC,cAAc;QACnCC,mBAAmBtC,IAAIuC,gBAAgB;QACvCC,SAASxC,IAAIwC,OAAO;QACpBC,cAAczC,IAAIyC,YAAY;QAC9BC,UAAU1C,IAAI0C,QAAQ;QACtBC,YAAY3C,IAAI4C,SAAS,CAACC,WAAW;QACrCC,YAAY9C,IAAI+C,SAAS,CAACF,WAAW;IACvC;AACF;AAEA,OAAO,SAASG,kBAAkBC,YAA0B;IAC1D,OAAO;QACLhD,IAAIgD,aAAahD,EAAE;QACnBiD,QAAQD,aAAaE,KAAK;QAC1BC,UAAUH,aAAaG,QAAQ;QAC/B/C,MAAM4C,aAAa5C,IAAI;QACvBE,QAAQ0C,aAAa1C,MAAM;QAC3BC,eAAeyC,aAAaxC,YAAY;QACxCI,QAAQoC,aAAapC,MAAM;QAC3BwC,gBAAgBJ,aAAaK,aAAa;QAC1Cd,SAASS,aAAaT,OAAO;QAC7B1B,kBAAkBhB,qBAAqBmD,aAAalC,eAAe;QACnEwC,WAAWN,aAAaO,QAAQ,EAAEX,iBAAiB;QACnDY,YAAYR,aAAaS,SAAS,EAAEb,iBAAiB;QACrDc,aAAaV,aAAaW,UAAU,EAAEf,iBAAiB;QACvDgB,cAAcZ,aAAaa,UAAU,EAAEjB,iBAAiB;QACxDF,YAAYM,aAAaL,SAAS,CAACC,WAAW;QAC9CC,YAAYG,aAAaF,SAAS,CAACF,WAAW;IAChD;AACF"}
1
+ {"version":3,"sources":["../../../src/presentation/dto/job.ts"],"sourcesContent":["import type {JobDto, JobExecutionDto} from '@shipfox/api-workflows-dto';\nimport type {Job} from '#core/entities/job.js';\nimport type {JobExecution} from '#core/entities/job-execution.js';\nimport {toEvaluationTraceDto} from './evaluation-trace.js';\n\nexport function toJobDto(job: Job): JobDto {\n return {\n id: job.id,\n run_attempt_id: job.workflowRunAttemptId,\n key: job.key,\n name: job.name,\n mode: job.mode,\n status: job.status,\n status_reason: job.statusReason,\n carried_over: job.carriedOver,\n success: job.success ?? null,\n runner: job.runner,\n evaluation_trace: toEvaluationTraceDto(job.evaluationTrace),\n listening:\n job.listeningOn === null\n ? null\n : {\n on: job.listeningOn,\n until: job.listeningUntil,\n timeout_ms: job.listeningTimeoutMs,\n max_executions: job.maxExecutions,\n batch:\n job.batchDebounceMs === null &&\n job.batchMaxSize === null &&\n job.batchMaxWaitMs === null\n ? null\n : {\n ...(job.batchDebounceMs === null ? {} : {debounce_ms: job.batchDebounceMs}),\n ...(job.batchMaxSize === null ? {} : {max_size: job.batchMaxSize}),\n ...(job.batchMaxWaitMs === null ? {} : {max_wait_ms: job.batchMaxWaitMs}),\n },\n on_resolve: job.onResolve ?? 'finish',\n execution_timeout_ms: job.executionTimeoutMs ?? null,\n name: job.name,\n },\n listener_status: job.listenerStatus,\n resolution_reason: job.resolutionReason,\n outputs: job.outputs,\n dependencies: job.dependencies,\n position: job.position,\n created_at: job.createdAt.toISOString(),\n updated_at: job.updatedAt.toISOString(),\n };\n}\n\nexport function toJobExecutionDto(jobExecution: JobExecution): JobExecutionDto {\n return {\n id: jobExecution.id,\n job_id: jobExecution.jobId,\n sequence: jobExecution.sequence,\n name: jobExecution.name,\n status: jobExecution.status,\n status_reason: jobExecution.statusReason,\n status_reason_message: jobExecution.statusReasonMessage,\n runner: jobExecution.runner,\n trigger_events: jobExecution.triggerEvents,\n outputs: jobExecution.outputs,\n evaluation_trace: toEvaluationTraceDto(jobExecution.evaluationTrace),\n queued_at: jobExecution.queuedAt?.toISOString() ?? null,\n started_at: jobExecution.startedAt?.toISOString() ?? null,\n finished_at: jobExecution.finishedAt?.toISOString() ?? null,\n timed_out_at: jobExecution.timedOutAt?.toISOString() ?? null,\n created_at: jobExecution.createdAt.toISOString(),\n updated_at: jobExecution.updatedAt.toISOString(),\n };\n}\n"],"names":["toEvaluationTraceDto","toJobDto","job","id","run_attempt_id","workflowRunAttemptId","key","name","mode","status","status_reason","statusReason","carried_over","carriedOver","success","runner","evaluation_trace","evaluationTrace","listening","listeningOn","on","until","listeningUntil","timeout_ms","listeningTimeoutMs","max_executions","maxExecutions","batch","batchDebounceMs","batchMaxSize","batchMaxWaitMs","debounce_ms","max_size","max_wait_ms","on_resolve","onResolve","execution_timeout_ms","executionTimeoutMs","listener_status","listenerStatus","resolution_reason","resolutionReason","outputs","dependencies","position","created_at","createdAt","toISOString","updated_at","updatedAt","toJobExecutionDto","jobExecution","job_id","jobId","sequence","status_reason_message","statusReasonMessage","trigger_events","triggerEvents","queued_at","queuedAt","started_at","startedAt","finished_at","finishedAt","timed_out_at","timedOutAt"],"mappings":"AAGA,SAAQA,oBAAoB,QAAO,wBAAwB;AAE3D,OAAO,SAASC,SAASC,GAAQ;IAC/B,OAAO;QACLC,IAAID,IAAIC,EAAE;QACVC,gBAAgBF,IAAIG,oBAAoB;QACxCC,KAAKJ,IAAII,GAAG;QACZC,MAAML,IAAIK,IAAI;QACdC,MAAMN,IAAIM,IAAI;QACdC,QAAQP,IAAIO,MAAM;QAClBC,eAAeR,IAAIS,YAAY;QAC/BC,cAAcV,IAAIW,WAAW;QAC7BC,SAASZ,IAAIY,OAAO,IAAI;QACxBC,QAAQb,IAAIa,MAAM;QAClBC,kBAAkBhB,qBAAqBE,IAAIe,eAAe;QAC1DC,WACEhB,IAAIiB,WAAW,KAAK,OAChB,OACA;YACEC,IAAIlB,IAAIiB,WAAW;YACnBE,OAAOnB,IAAIoB,cAAc;YACzBC,YAAYrB,IAAIsB,kBAAkB;YAClCC,gBAAgBvB,IAAIwB,aAAa;YACjCC,OACEzB,IAAI0B,eAAe,KAAK,QACxB1B,IAAI2B,YAAY,KAAK,QACrB3B,IAAI4B,cAAc,KAAK,OACnB,OACA;gBACE,GAAI5B,IAAI0B,eAAe,KAAK,OAAO,CAAC,IAAI;oBAACG,aAAa7B,IAAI0B,eAAe;gBAAA,CAAC;gBAC1E,GAAI1B,IAAI2B,YAAY,KAAK,OAAO,CAAC,IAAI;oBAACG,UAAU9B,IAAI2B,YAAY;gBAAA,CAAC;gBACjE,GAAI3B,IAAI4B,cAAc,KAAK,OAAO,CAAC,IAAI;oBAACG,aAAa/B,IAAI4B,cAAc;gBAAA,CAAC;YAC1E;YACNI,YAAYhC,IAAIiC,SAAS,IAAI;YAC7BC,sBAAsBlC,IAAImC,kBAAkB,IAAI;YAChD9B,MAAML,IAAIK,IAAI;QAChB;QACN+B,iBAAiBpC,IAAIqC,cAAc;QACnCC,mBAAmBtC,IAAIuC,gBAAgB;QACvCC,SAASxC,IAAIwC,OAAO;QACpBC,cAAczC,IAAIyC,YAAY;QAC9BC,UAAU1C,IAAI0C,QAAQ;QACtBC,YAAY3C,IAAI4C,SAAS,CAACC,WAAW;QACrCC,YAAY9C,IAAI+C,SAAS,CAACF,WAAW;IACvC;AACF;AAEA,OAAO,SAASG,kBAAkBC,YAA0B;IAC1D,OAAO;QACLhD,IAAIgD,aAAahD,EAAE;QACnBiD,QAAQD,aAAaE,KAAK;QAC1BC,UAAUH,aAAaG,QAAQ;QAC/B/C,MAAM4C,aAAa5C,IAAI;QACvBE,QAAQ0C,aAAa1C,MAAM;QAC3BC,eAAeyC,aAAaxC,YAAY;QACxC4C,uBAAuBJ,aAAaK,mBAAmB;QACvDzC,QAAQoC,aAAapC,MAAM;QAC3B0C,gBAAgBN,aAAaO,aAAa;QAC1ChB,SAASS,aAAaT,OAAO;QAC7B1B,kBAAkBhB,qBAAqBmD,aAAalC,eAAe;QACnE0C,WAAWR,aAAaS,QAAQ,EAAEb,iBAAiB;QACnDc,YAAYV,aAAaW,SAAS,EAAEf,iBAAiB;QACrDgB,aAAaZ,aAAaa,UAAU,EAAEjB,iBAAiB;QACvDkB,cAAcd,aAAae,UAAU,EAAEnB,iBAAiB;QACxDF,YAAYM,aAAaL,SAAS,CAACC,WAAW;QAC9CC,YAAYG,aAAaF,SAAS,CAACF,WAAW;IAChD;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/workflow-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EACd,sBAAsB,EAEvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAC,WAAW,EAA8B,MAAM,gCAAgC,CAAC;AAC7F,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,cAAc,CAAC;AAEzD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,SAAqB,GAAG,cAAc,CAuB7F;AAID,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE,sBAAmC,GACxC,sBAAsB,CAYxB;AAgBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,qBAAqB,CAWlF"}
1
+ {"version":3,"file":"workflow-run.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/workflow-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EACd,sBAAsB,EAEvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAC,WAAW,EAA8B,MAAM,gCAAgC,CAAC;AAC7F,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,cAAc,CAAC;AAEzD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,SAAqB,GAAG,cAAc,CAuB7F;AAID,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE,sBAAmC,GACxC,sBAAsB,CAgBxB;AAgBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,qBAAqB,CAWlF"}
@@ -24,7 +24,8 @@ export function toRunDto(run, latestAttempt = run.currentAttempt) {
24
24
  }
25
25
  const EMPTY_JOBS = {
26
26
  preview: [],
27
- statusCounts: []
27
+ statusCounts: [],
28
+ rawStatusCounts: []
28
29
  };
29
30
  export function toRunListItemDto(run, jobs = EMPTY_JOBS) {
30
31
  return {
@@ -34,9 +35,16 @@ export function toRunListItemDto(run, jobs = EMPTY_JOBS) {
34
35
  key: job.key,
35
36
  name: job.name,
36
37
  status: job.status,
38
+ mode: job.mode,
39
+ listener_status: job.listenerStatus,
40
+ execution_status: job.executionStatus,
37
41
  position: job.position
38
42
  })),
39
- job_status_counts: jobs.statusCounts.map(({ status, count })=>({
43
+ job_status_counts: jobs.rawStatusCounts.map(({ status, count })=>({
44
+ status,
45
+ count
46
+ })),
47
+ job_display_status_counts: jobs.statusCounts.map(({ status, count })=>({
40
48
  status,
41
49
  count
42
50
  }))
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/dto/workflow-run.ts"],"sourcesContent":["import type {\n WorkflowRunAttemptDto,\n WorkflowRunDto,\n WorkflowRunListItemDto,\n WorkflowRunTriggerReferenceDto,\n} from '@shipfox/api-workflows-dto';\nimport type {WorkflowRun, WorkflowRunTriggerReference} from '#core/entities/workflow-run.js';\nimport type {WorkflowRunAttempt} from '#core/entities/workflow-run-attempt.js';\nimport type {WorkflowRunJobsSummary} from '#db/index.js';\n\nexport function toRunDto(run: WorkflowRun, latestAttempt = run.currentAttempt): WorkflowRunDto {\n return {\n id: run.id,\n project_id: run.projectId,\n definition_id: run.definitionId,\n number: run.number,\n name: run.name,\n workflow_name: run.workflowName,\n status: run.status,\n current_attempt: run.currentAttempt,\n latest_attempt: latestAttempt,\n trigger_provider: run.triggerProvider,\n trigger_source: run.triggerSource,\n trigger_event: run.triggerEvent,\n trigger_payload: run.triggerPayload,\n trigger_reference: toTriggerReferenceDto(run.triggerReference),\n inputs: run.inputs,\n source_snapshot: run.sourceSnapshot,\n created_at: run.createdAt.toISOString(),\n updated_at: run.updatedAt.toISOString(),\n started_at: run.startedAt?.toISOString() ?? null,\n finished_at: run.finishedAt?.toISOString() ?? null,\n };\n}\n\nconst EMPTY_JOBS: WorkflowRunJobsSummary = {preview: [], statusCounts: []};\n\nexport function toRunListItemDto(\n run: WorkflowRun,\n jobs: WorkflowRunJobsSummary = EMPTY_JOBS,\n): WorkflowRunListItemDto {\n return {\n ...toRunDto(run),\n jobs: jobs.preview.map((job) => ({\n id: job.id,\n key: job.key,\n name: job.name,\n status: job.status,\n position: job.position,\n })),\n job_status_counts: jobs.statusCounts.map(({status, count}) => ({status, count})),\n };\n}\n\n// The persisted reference predates `actor` and carries an internal project id the client has\n// no use for, so each field is read defensively rather than spread onto the response.\nfunction toTriggerReferenceDto(\n reference: WorkflowRunTriggerReference | null | undefined,\n): WorkflowRunTriggerReferenceDto | null {\n if (!reference) return null;\n return {\n repository: reference.repository ?? null,\n ref: reference.ref ?? null,\n commit: reference.commit ?? null,\n actor: reference.actor ?? null,\n };\n}\n\nexport function toRunAttemptDto(attempt: WorkflowRunAttempt): WorkflowRunAttemptDto {\n return {\n id: attempt.id,\n workflow_run_id: attempt.workflowRunId,\n attempt: attempt.attempt,\n status: attempt.status,\n created_at: attempt.createdAt.toISOString(),\n started_at: attempt.startedAt?.toISOString() ?? null,\n finished_at: attempt.finishedAt?.toISOString() ?? null,\n rerun_mode: attempt.rerunMode,\n };\n}\n"],"names":["toRunDto","run","latestAttempt","currentAttempt","id","project_id","projectId","definition_id","definitionId","number","name","workflow_name","workflowName","status","current_attempt","latest_attempt","trigger_provider","triggerProvider","trigger_source","triggerSource","trigger_event","triggerEvent","trigger_payload","triggerPayload","trigger_reference","toTriggerReferenceDto","triggerReference","inputs","source_snapshot","sourceSnapshot","created_at","createdAt","toISOString","updated_at","updatedAt","started_at","startedAt","finished_at","finishedAt","EMPTY_JOBS","preview","statusCounts","toRunListItemDto","jobs","map","job","key","position","job_status_counts","count","reference","repository","ref","commit","actor","toRunAttemptDto","attempt","workflow_run_id","workflowRunId","rerun_mode","rerunMode"],"mappings":"AAUA,OAAO,SAASA,SAASC,GAAgB,EAAEC,gBAAgBD,IAAIE,cAAc;IAC3E,OAAO;QACLC,IAAIH,IAAIG,EAAE;QACVC,YAAYJ,IAAIK,SAAS;QACzBC,eAAeN,IAAIO,YAAY;QAC/BC,QAAQR,IAAIQ,MAAM;QAClBC,MAAMT,IAAIS,IAAI;QACdC,eAAeV,IAAIW,YAAY;QAC/BC,QAAQZ,IAAIY,MAAM;QAClBC,iBAAiBb,IAAIE,cAAc;QACnCY,gBAAgBb;QAChBc,kBAAkBf,IAAIgB,eAAe;QACrCC,gBAAgBjB,IAAIkB,aAAa;QACjCC,eAAenB,IAAIoB,YAAY;QAC/BC,iBAAiBrB,IAAIsB,cAAc;QACnCC,mBAAmBC,sBAAsBxB,IAAIyB,gBAAgB;QAC7DC,QAAQ1B,IAAI0B,MAAM;QAClBC,iBAAiB3B,IAAI4B,cAAc;QACnCC,YAAY7B,IAAI8B,SAAS,CAACC,WAAW;QACrCC,YAAYhC,IAAIiC,SAAS,CAACF,WAAW;QACrCG,YAAYlC,IAAImC,SAAS,EAAEJ,iBAAiB;QAC5CK,aAAapC,IAAIqC,UAAU,EAAEN,iBAAiB;IAChD;AACF;AAEA,MAAMO,aAAqC;IAACC,SAAS,EAAE;IAAEC,cAAc,EAAE;AAAA;AAEzE,OAAO,SAASC,iBACdzC,GAAgB,EAChB0C,OAA+BJ,UAAU;IAEzC,OAAO;QACL,GAAGvC,SAASC,IAAI;QAChB0C,MAAMA,KAAKH,OAAO,CAACI,GAAG,CAAC,CAACC,MAAS,CAAA;gBAC/BzC,IAAIyC,IAAIzC,EAAE;gBACV0C,KAAKD,IAAIC,GAAG;gBACZpC,MAAMmC,IAAInC,IAAI;gBACdG,QAAQgC,IAAIhC,MAAM;gBAClBkC,UAAUF,IAAIE,QAAQ;YACxB,CAAA;QACAC,mBAAmBL,KAAKF,YAAY,CAACG,GAAG,CAAC,CAAC,EAAC/B,MAAM,EAAEoC,KAAK,EAAC,GAAM,CAAA;gBAACpC;gBAAQoC;YAAK,CAAA;IAC/E;AACF;AAEA,6FAA6F;AAC7F,sFAAsF;AACtF,SAASxB,sBACPyB,SAAyD;IAEzD,IAAI,CAACA,WAAW,OAAO;IACvB,OAAO;QACLC,YAAYD,UAAUC,UAAU,IAAI;QACpCC,KAAKF,UAAUE,GAAG,IAAI;QACtBC,QAAQH,UAAUG,MAAM,IAAI;QAC5BC,OAAOJ,UAAUI,KAAK,IAAI;IAC5B;AACF;AAEA,OAAO,SAASC,gBAAgBC,OAA2B;IACzD,OAAO;QACLpD,IAAIoD,QAAQpD,EAAE;QACdqD,iBAAiBD,QAAQE,aAAa;QACtCF,SAASA,QAAQA,OAAO;QACxB3C,QAAQ2C,QAAQ3C,MAAM;QACtBiB,YAAY0B,QAAQzB,SAAS,CAACC,WAAW;QACzCG,YAAYqB,QAAQpB,SAAS,EAAEJ,iBAAiB;QAChDK,aAAamB,QAAQlB,UAAU,EAAEN,iBAAiB;QAClD2B,YAAYH,QAAQI,SAAS;IAC/B;AACF"}
1
+ {"version":3,"sources":["../../../src/presentation/dto/workflow-run.ts"],"sourcesContent":["import type {\n WorkflowRunAttemptDto,\n WorkflowRunDto,\n WorkflowRunListItemDto,\n WorkflowRunTriggerReferenceDto,\n} from '@shipfox/api-workflows-dto';\nimport type {WorkflowRun, WorkflowRunTriggerReference} from '#core/entities/workflow-run.js';\nimport type {WorkflowRunAttempt} from '#core/entities/workflow-run-attempt.js';\nimport type {WorkflowRunJobsSummary} from '#db/index.js';\n\nexport function toRunDto(run: WorkflowRun, latestAttempt = run.currentAttempt): WorkflowRunDto {\n return {\n id: run.id,\n project_id: run.projectId,\n definition_id: run.definitionId,\n number: run.number,\n name: run.name,\n workflow_name: run.workflowName,\n status: run.status,\n current_attempt: run.currentAttempt,\n latest_attempt: latestAttempt,\n trigger_provider: run.triggerProvider,\n trigger_source: run.triggerSource,\n trigger_event: run.triggerEvent,\n trigger_payload: run.triggerPayload,\n trigger_reference: toTriggerReferenceDto(run.triggerReference),\n inputs: run.inputs,\n source_snapshot: run.sourceSnapshot,\n created_at: run.createdAt.toISOString(),\n updated_at: run.updatedAt.toISOString(),\n started_at: run.startedAt?.toISOString() ?? null,\n finished_at: run.finishedAt?.toISOString() ?? null,\n };\n}\n\nconst EMPTY_JOBS: WorkflowRunJobsSummary = {preview: [], statusCounts: [], rawStatusCounts: []};\n\nexport function toRunListItemDto(\n run: WorkflowRun,\n jobs: WorkflowRunJobsSummary = EMPTY_JOBS,\n): WorkflowRunListItemDto {\n return {\n ...toRunDto(run),\n jobs: jobs.preview.map((job) => ({\n id: job.id,\n key: job.key,\n name: job.name,\n status: job.status,\n mode: job.mode,\n listener_status: job.listenerStatus,\n execution_status: job.executionStatus,\n position: job.position,\n })),\n job_status_counts: jobs.rawStatusCounts.map(({status, count}) => ({status, count})),\n job_display_status_counts: jobs.statusCounts.map(({status, count}) => ({status, count})),\n };\n}\n\n// The persisted reference predates `actor` and carries an internal project id the client has\n// no use for, so each field is read defensively rather than spread onto the response.\nfunction toTriggerReferenceDto(\n reference: WorkflowRunTriggerReference | null | undefined,\n): WorkflowRunTriggerReferenceDto | null {\n if (!reference) return null;\n return {\n repository: reference.repository ?? null,\n ref: reference.ref ?? null,\n commit: reference.commit ?? null,\n actor: reference.actor ?? null,\n };\n}\n\nexport function toRunAttemptDto(attempt: WorkflowRunAttempt): WorkflowRunAttemptDto {\n return {\n id: attempt.id,\n workflow_run_id: attempt.workflowRunId,\n attempt: attempt.attempt,\n status: attempt.status,\n created_at: attempt.createdAt.toISOString(),\n started_at: attempt.startedAt?.toISOString() ?? null,\n finished_at: attempt.finishedAt?.toISOString() ?? null,\n rerun_mode: attempt.rerunMode,\n };\n}\n"],"names":["toRunDto","run","latestAttempt","currentAttempt","id","project_id","projectId","definition_id","definitionId","number","name","workflow_name","workflowName","status","current_attempt","latest_attempt","trigger_provider","triggerProvider","trigger_source","triggerSource","trigger_event","triggerEvent","trigger_payload","triggerPayload","trigger_reference","toTriggerReferenceDto","triggerReference","inputs","source_snapshot","sourceSnapshot","created_at","createdAt","toISOString","updated_at","updatedAt","started_at","startedAt","finished_at","finishedAt","EMPTY_JOBS","preview","statusCounts","rawStatusCounts","toRunListItemDto","jobs","map","job","key","mode","listener_status","listenerStatus","execution_status","executionStatus","position","job_status_counts","count","job_display_status_counts","reference","repository","ref","commit","actor","toRunAttemptDto","attempt","workflow_run_id","workflowRunId","rerun_mode","rerunMode"],"mappings":"AAUA,OAAO,SAASA,SAASC,GAAgB,EAAEC,gBAAgBD,IAAIE,cAAc;IAC3E,OAAO;QACLC,IAAIH,IAAIG,EAAE;QACVC,YAAYJ,IAAIK,SAAS;QACzBC,eAAeN,IAAIO,YAAY;QAC/BC,QAAQR,IAAIQ,MAAM;QAClBC,MAAMT,IAAIS,IAAI;QACdC,eAAeV,IAAIW,YAAY;QAC/BC,QAAQZ,IAAIY,MAAM;QAClBC,iBAAiBb,IAAIE,cAAc;QACnCY,gBAAgBb;QAChBc,kBAAkBf,IAAIgB,eAAe;QACrCC,gBAAgBjB,IAAIkB,aAAa;QACjCC,eAAenB,IAAIoB,YAAY;QAC/BC,iBAAiBrB,IAAIsB,cAAc;QACnCC,mBAAmBC,sBAAsBxB,IAAIyB,gBAAgB;QAC7DC,QAAQ1B,IAAI0B,MAAM;QAClBC,iBAAiB3B,IAAI4B,cAAc;QACnCC,YAAY7B,IAAI8B,SAAS,CAACC,WAAW;QACrCC,YAAYhC,IAAIiC,SAAS,CAACF,WAAW;QACrCG,YAAYlC,IAAImC,SAAS,EAAEJ,iBAAiB;QAC5CK,aAAapC,IAAIqC,UAAU,EAAEN,iBAAiB;IAChD;AACF;AAEA,MAAMO,aAAqC;IAACC,SAAS,EAAE;IAAEC,cAAc,EAAE;IAAEC,iBAAiB,EAAE;AAAA;AAE9F,OAAO,SAASC,iBACd1C,GAAgB,EAChB2C,OAA+BL,UAAU;IAEzC,OAAO;QACL,GAAGvC,SAASC,IAAI;QAChB2C,MAAMA,KAAKJ,OAAO,CAACK,GAAG,CAAC,CAACC,MAAS,CAAA;gBAC/B1C,IAAI0C,IAAI1C,EAAE;gBACV2C,KAAKD,IAAIC,GAAG;gBACZrC,MAAMoC,IAAIpC,IAAI;gBACdG,QAAQiC,IAAIjC,MAAM;gBAClBmC,MAAMF,IAAIE,IAAI;gBACdC,iBAAiBH,IAAII,cAAc;gBACnCC,kBAAkBL,IAAIM,eAAe;gBACrCC,UAAUP,IAAIO,QAAQ;YACxB,CAAA;QACAC,mBAAmBV,KAAKF,eAAe,CAACG,GAAG,CAAC,CAAC,EAAChC,MAAM,EAAE0C,KAAK,EAAC,GAAM,CAAA;gBAAC1C;gBAAQ0C;YAAK,CAAA;QAChFC,2BAA2BZ,KAAKH,YAAY,CAACI,GAAG,CAAC,CAAC,EAAChC,MAAM,EAAE0C,KAAK,EAAC,GAAM,CAAA;gBAAC1C;gBAAQ0C;YAAK,CAAA;IACvF;AACF;AAEA,6FAA6F;AAC7F,sFAAsF;AACtF,SAAS9B,sBACPgC,SAAyD;IAEzD,IAAI,CAACA,WAAW,OAAO;IACvB,OAAO;QACLC,YAAYD,UAAUC,UAAU,IAAI;QACpCC,KAAKF,UAAUE,GAAG,IAAI;QACtBC,QAAQH,UAAUG,MAAM,IAAI;QAC5BC,OAAOJ,UAAUI,KAAK,IAAI;IAC5B;AACF;AAEA,OAAO,SAASC,gBAAgBC,OAA2B;IACzD,OAAO;QACL3D,IAAI2D,QAAQ3D,EAAE;QACd4D,iBAAiBD,QAAQE,aAAa;QACtCF,SAASA,QAAQA,OAAO;QACxBlD,QAAQkD,QAAQlD,MAAM;QACtBiB,YAAYiC,QAAQhC,SAAS,CAACC,WAAW;QACzCG,YAAY4B,QAAQ3B,SAAS,EAAEJ,iBAAiB;QAChDK,aAAa0B,QAAQzB,UAAU,EAAEN,iBAAiB;QAClDkC,YAAYH,QAAQI,SAAS;IAC/B;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"on-failure-annotations.d.ts","sourceRoot":"","sources":["../../../src/presentation/subscribers/on-failure-annotations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,4BAA4B,EAElC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EACV,8BAA8B,EAC9B,sCAAsC,EACvC,MAAM,4BAA4B,CAAC;AAapC,wBAAgB,wCAAwC,CACtD,WAAW,EAAE,4BAA4B,aAElB,sCAAsC,KAAG,OAAO,CAAC,IAAI,CAAC,CA8D9E;AAED,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,4BAA4B,aACjE,8BAA8B,KAAG,OAAO,CAAC,IAAI,CAAC,CA2CtE"}
1
+ {"version":3,"file":"on-failure-annotations.d.ts","sourceRoot":"","sources":["../../../src/presentation/subscribers/on-failure-annotations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,4BAA4B,EAElC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EACV,8BAA8B,EAC9B,sCAAsC,EACvC,MAAM,4BAA4B,CAAC;AAmBpC,wBAAgB,wCAAwC,CACtD,WAAW,EAAE,4BAA4B,aAElB,sCAAsC,KAAG,OAAO,CAAC,IAAI,CAAC,CA8D9E;AAED,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,4BAA4B,aACjE,8BAA8B,KAAG,OAAO,CAAC,IAAI,CAAC,CA2CtE"}
@@ -6,7 +6,9 @@ import { recordWorkflowFailureAnnotationFailed } from '#metrics/instance.js';
6
6
  const JOB_FAILURE_ANNOTATION_REASONS = new Set([
7
7
  'timed_out',
8
8
  'runner_lost',
9
- 'condition_errored'
9
+ 'condition_errored',
10
+ 'output_too_large',
11
+ 'output_invalid'
10
12
  ]);
11
13
  export function onStepAttemptTerminatedFailureAnnotation(annotations) {
12
14
  return async (payload)=>{
@@ -88,7 +90,7 @@ export function onJobTerminatedFailureAnnotation(annotations) {
88
90
  },
89
91
  context: failureContext('job', payload.jobId),
90
92
  failed: true,
91
- body: jobFailureBody(payload.statusReason, origin)
93
+ body: jobFailureBody(payload.statusReason, payload.statusReasonMessage, origin)
92
94
  });
93
95
  } catch (error) {
94
96
  recordFailureAnnotationFailure(error, 'lookup', {
@@ -134,7 +136,7 @@ function stepFailureBody(name, error, exitCode) {
134
136
  message
135
137
  ].join('\n');
136
138
  }
137
- function jobFailureBody(reason, origin) {
139
+ function jobFailureBody(reason, statusReasonMessage, origin) {
138
140
  const progress = origin.attemptStatus ? `The job stopped while processing **${origin.stepName}**.` : `The job stopped before **${origin.stepName}** started.`;
139
141
  const error = origin.attemptError ?? origin.stepError;
140
142
  const message = typeof error?.message === 'string' && error.message.trim() ? error.message : null;
@@ -144,6 +146,7 @@ function jobFailureBody(reason, origin) {
144
146
  '',
145
147
  progress,
146
148
  `Reason: \`${reason ?? 'unknown'}\``,
149
+ statusReasonMessage ? `Failure: ${statusReasonMessage}` : null,
147
150
  message ? `Failure: ${message}` : null,
148
151
  exitCode
149
152
  ].filter(Boolean).join('\n');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/subscribers/on-failure-annotations.ts"],"sourcesContent":["import {\n type AnnotationsInterModuleClient,\n annotationsInterModuleContract,\n} from '@shipfox/annotations-dto/inter-module';\nimport type {\n WorkflowsJobTerminatedEventDto,\n WorkflowsStepAttemptTerminatedEventDto,\n} from '@shipfox/api-workflows-dto';\nimport {isInterModuleKnownError} from '@shipfox/inter-module';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {\n getJobExecutionFailureOrigin,\n getJobScope,\n getStepAttemptDetail,\n getWorkflowRunAttemptById,\n} from '#db/index.js';\nimport {recordWorkflowFailureAnnotationFailed} from '#metrics/instance.js';\n\nconst JOB_FAILURE_ANNOTATION_REASONS = new Set(['timed_out', 'runner_lost', 'condition_errored']);\n\nexport function onStepAttemptTerminatedFailureAnnotation(\n annotations: AnnotationsInterModuleClient,\n) {\n return async (payload: WorkflowsStepAttemptTerminatedEventDto): Promise<void> => {\n // A first successful/cancelled attempt cannot have a stale failure annotation.\n // Keep later terminal attempts on the lookup path so recovery removes the\n // annotation created by an earlier failed attempt.\n if (payload.status !== undefined && payload.status !== 'failed' && payload.attempt === 1) {\n return;\n }\n\n try {\n const initialDetail = await getStepAttemptDetail({\n stepId: payload.stepId,\n attempt: payload.attempt,\n });\n if (!initialDetail) return;\n\n // The detail query joins the requested attempt to the step's current projection. A\n // delayed event can therefore return an old attempt alongside a newer step status. Read\n // the canonical current attempt before deciding whether to replace or remove the card.\n const detail =\n initialDetail.attempt.attempt === initialDetail.step.currentAttempt\n ? initialDetail\n : await getStepAttemptDetail({\n stepId: initialDetail.step.id,\n attempt: initialDetail.step.currentAttempt,\n });\n if (!detail || detail.attempt.attempt !== detail.step.currentAttempt) return;\n\n const runAttempt = await getWorkflowRunAttemptById(payload.workflowRunAttemptId);\n if (!runAttempt) return;\n\n await writeFailureAnnotation({\n annotations,\n target: {\n workspaceId: payload.workspaceId,\n projectId: payload.projectId,\n workflowRunId: payload.workflowRunId,\n workflowRunAttempt: runAttempt.attempt,\n workflowRunAttemptId: payload.workflowRunAttemptId,\n jobId: payload.jobId,\n jobExecutionId: detail.step.jobExecutionId,\n originStepId: detail.step.id,\n originStepAttempt: detail.attempt.attempt,\n },\n context: failureContext('step', detail.step.id),\n failed:\n detail.step.status === 'failed' ||\n (detail.attempt.status === 'failed' &&\n detail.step.status !== 'succeeded' &&\n detail.step.status !== 'cancelled'),\n body: stepFailureBody(\n detail.step.name,\n detail.attempt.error ?? detail.step.error,\n detail.attempt.exitCode,\n ),\n });\n } catch (error) {\n recordFailureAnnotationFailure(error, 'lookup', {\n stepId: payload.stepId,\n jobId: payload.jobId,\n });\n }\n };\n}\n\nexport function onJobTerminatedFailureAnnotation(annotations: AnnotationsInterModuleClient) {\n return async (payload: WorkflowsJobTerminatedEventDto): Promise<void> => {\n // Step failures already have a step-scoped annotation. Job-scoped annotations\n // are reserved for terminal causes where no step-level failure card exists.\n const isConditionEvaluationFailure =\n payload.status === 'skipped' && payload.statusReason === 'condition_errored';\n if (\n (payload.status !== 'failed' && !isConditionEvaluationFailure) ||\n !JOB_FAILURE_ANNOTATION_REASONS.has(payload.statusReason ?? '')\n ) {\n return;\n }\n\n try {\n const [scope, runAttempt] = await Promise.all([\n getJobScope(payload.jobId),\n getWorkflowRunAttemptById(payload.workflowRunAttemptId),\n ]);\n if (!scope || !runAttempt || !payload.jobExecutionId) return;\n\n const origin = await getJobExecutionFailureOrigin(payload.jobExecutionId);\n if (!origin) return;\n\n await writeFailureAnnotation({\n annotations,\n target: {\n workspaceId: scope.workspaceId,\n projectId: scope.projectId,\n workflowRunId: payload.workflowRunId,\n workflowRunAttempt: runAttempt.attempt,\n workflowRunAttemptId: payload.workflowRunAttemptId,\n jobId: payload.jobId,\n jobExecutionId: origin.jobExecutionId,\n originStepId: origin.stepId,\n originStepAttempt: origin.stepAttempt,\n },\n context: failureContext('job', payload.jobId),\n failed: true,\n body: jobFailureBody(payload.statusReason, origin),\n });\n } catch (error) {\n recordFailureAnnotationFailure(error, 'lookup', {jobId: payload.jobId});\n }\n };\n}\n\ntype FailureAnnotationTarget = {\n workspaceId: string;\n projectId: string;\n workflowRunId: string;\n workflowRunAttempt: number;\n workflowRunAttemptId: string;\n jobId: string;\n jobExecutionId: string;\n originStepId: string;\n originStepAttempt: number;\n};\n\n/**\n * Failure annotations are a best-effort projection. The workflow terminal fact is authoritative;\n * projection lookup and writes are swallowed so they cannot change the workflow outcome. Every\n * swallowed error emits a reason-labelled metric and a structured warning for operations.\n */\nasync function writeFailureAnnotation(params: {\n annotations: AnnotationsInterModuleClient;\n target: FailureAnnotationTarget;\n context: string;\n failed: boolean;\n body: string;\n}): Promise<void> {\n try {\n await params.annotations.replaceOrRemoveAnnotation({\n ...params.target,\n context: params.context,\n annotation: params.failed\n ? {op: 'replace', style: 'error', body: params.body}\n : {op: 'remove'},\n });\n } catch (error) {\n const reason = isInterModuleKnownError(\n annotationsInterModuleContract.methods.replaceOrRemoveAnnotation,\n error,\n )\n ? 'budget'\n : 'write';\n recordFailureAnnotationFailure(error, reason, params.target);\n }\n}\n\nfunction failureContext(kind: 'job' | 'step', id: string): string {\n return `failure:${kind}:${id}`;\n}\n\nfunction stepFailureBody(\n name: string,\n error: Record<string, unknown> | null,\n exitCode: number | null,\n): string {\n const reason = typeof error?.reason === 'string' ? error.reason : 'unknown';\n const message =\n typeof error?.message === 'string' && error.message.trim()\n ? error.message\n : 'No failure message was recorded.';\n return [\n `**${name} failed**`,\n '',\n `Reason: \\`${reason}\\``,\n `Exit code: \\`${exitCode ?? 'none'}\\``,\n '',\n message,\n ].join('\\n');\n}\n\nfunction jobFailureBody(\n reason: string | null,\n origin: {\n stepName: string;\n attemptStatus: string | null;\n stepError: Record<string, unknown> | null;\n attemptError: Record<string, unknown> | null;\n attemptExitCode: number | null;\n },\n): string {\n const progress = origin.attemptStatus\n ? `The job stopped while processing **${origin.stepName}**.`\n : `The job stopped before **${origin.stepName}** started.`;\n const error = origin.attemptError ?? origin.stepError;\n const message = typeof error?.message === 'string' && error.message.trim() ? error.message : null;\n const exitCode =\n origin.attemptExitCode === null ? null : `Exit code: \\`${origin.attemptExitCode}\\``;\n return [\n `**Job failed before completion**`,\n '',\n progress,\n `Reason: \\`${reason ?? 'unknown'}\\``,\n message ? `Failure: ${message}` : null,\n exitCode,\n ]\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction recordFailureAnnotationFailure(\n error: unknown,\n reason: 'lookup' | 'budget' | 'write',\n context: Record<string, string | number>,\n): void {\n recordWorkflowFailureAnnotationFailed(reason);\n logger().warn({error, reason, ...context}, 'Failed to project workflow failure annotation');\n}\n"],"names":["annotationsInterModuleContract","isInterModuleKnownError","logger","getJobExecutionFailureOrigin","getJobScope","getStepAttemptDetail","getWorkflowRunAttemptById","recordWorkflowFailureAnnotationFailed","JOB_FAILURE_ANNOTATION_REASONS","Set","onStepAttemptTerminatedFailureAnnotation","annotations","payload","status","undefined","attempt","initialDetail","stepId","detail","step","currentAttempt","id","runAttempt","workflowRunAttemptId","writeFailureAnnotation","target","workspaceId","projectId","workflowRunId","workflowRunAttempt","jobId","jobExecutionId","originStepId","originStepAttempt","context","failureContext","failed","body","stepFailureBody","name","error","exitCode","recordFailureAnnotationFailure","onJobTerminatedFailureAnnotation","isConditionEvaluationFailure","statusReason","has","scope","Promise","all","origin","stepAttempt","jobFailureBody","params","replaceOrRemoveAnnotation","annotation","op","style","reason","methods","kind","message","trim","join","progress","attemptStatus","stepName","attemptError","stepError","attemptExitCode","filter","Boolean","warn"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/presentation/subscribers/on-failure-annotations.ts"],"sourcesContent":["import {\n type AnnotationsInterModuleClient,\n annotationsInterModuleContract,\n} from '@shipfox/annotations-dto/inter-module';\nimport type {\n WorkflowsJobTerminatedEventDto,\n WorkflowsStepAttemptTerminatedEventDto,\n} from '@shipfox/api-workflows-dto';\nimport {isInterModuleKnownError} from '@shipfox/inter-module';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {\n getJobExecutionFailureOrigin,\n getJobScope,\n getStepAttemptDetail,\n getWorkflowRunAttemptById,\n} from '#db/index.js';\nimport {recordWorkflowFailureAnnotationFailed} from '#metrics/instance.js';\n\nconst JOB_FAILURE_ANNOTATION_REASONS = new Set([\n 'timed_out',\n 'runner_lost',\n 'condition_errored',\n 'output_too_large',\n 'output_invalid',\n]);\n\nexport function onStepAttemptTerminatedFailureAnnotation(\n annotations: AnnotationsInterModuleClient,\n) {\n return async (payload: WorkflowsStepAttemptTerminatedEventDto): Promise<void> => {\n // A first successful/cancelled attempt cannot have a stale failure annotation.\n // Keep later terminal attempts on the lookup path so recovery removes the\n // annotation created by an earlier failed attempt.\n if (payload.status !== undefined && payload.status !== 'failed' && payload.attempt === 1) {\n return;\n }\n\n try {\n const initialDetail = await getStepAttemptDetail({\n stepId: payload.stepId,\n attempt: payload.attempt,\n });\n if (!initialDetail) return;\n\n // The detail query joins the requested attempt to the step's current projection. A\n // delayed event can therefore return an old attempt alongside a newer step status. Read\n // the canonical current attempt before deciding whether to replace or remove the card.\n const detail =\n initialDetail.attempt.attempt === initialDetail.step.currentAttempt\n ? initialDetail\n : await getStepAttemptDetail({\n stepId: initialDetail.step.id,\n attempt: initialDetail.step.currentAttempt,\n });\n if (!detail || detail.attempt.attempt !== detail.step.currentAttempt) return;\n\n const runAttempt = await getWorkflowRunAttemptById(payload.workflowRunAttemptId);\n if (!runAttempt) return;\n\n await writeFailureAnnotation({\n annotations,\n target: {\n workspaceId: payload.workspaceId,\n projectId: payload.projectId,\n workflowRunId: payload.workflowRunId,\n workflowRunAttempt: runAttempt.attempt,\n workflowRunAttemptId: payload.workflowRunAttemptId,\n jobId: payload.jobId,\n jobExecutionId: detail.step.jobExecutionId,\n originStepId: detail.step.id,\n originStepAttempt: detail.attempt.attempt,\n },\n context: failureContext('step', detail.step.id),\n failed:\n detail.step.status === 'failed' ||\n (detail.attempt.status === 'failed' &&\n detail.step.status !== 'succeeded' &&\n detail.step.status !== 'cancelled'),\n body: stepFailureBody(\n detail.step.name,\n detail.attempt.error ?? detail.step.error,\n detail.attempt.exitCode,\n ),\n });\n } catch (error) {\n recordFailureAnnotationFailure(error, 'lookup', {\n stepId: payload.stepId,\n jobId: payload.jobId,\n });\n }\n };\n}\n\nexport function onJobTerminatedFailureAnnotation(annotations: AnnotationsInterModuleClient) {\n return async (payload: WorkflowsJobTerminatedEventDto): Promise<void> => {\n // Step failures already have a step-scoped annotation. Job-scoped annotations\n // are reserved for terminal causes where no step-level failure card exists.\n const isConditionEvaluationFailure =\n payload.status === 'skipped' && payload.statusReason === 'condition_errored';\n if (\n (payload.status !== 'failed' && !isConditionEvaluationFailure) ||\n !JOB_FAILURE_ANNOTATION_REASONS.has(payload.statusReason ?? '')\n ) {\n return;\n }\n\n try {\n const [scope, runAttempt] = await Promise.all([\n getJobScope(payload.jobId),\n getWorkflowRunAttemptById(payload.workflowRunAttemptId),\n ]);\n if (!scope || !runAttempt || !payload.jobExecutionId) return;\n\n const origin = await getJobExecutionFailureOrigin(payload.jobExecutionId);\n if (!origin) return;\n\n await writeFailureAnnotation({\n annotations,\n target: {\n workspaceId: scope.workspaceId,\n projectId: scope.projectId,\n workflowRunId: payload.workflowRunId,\n workflowRunAttempt: runAttempt.attempt,\n workflowRunAttemptId: payload.workflowRunAttemptId,\n jobId: payload.jobId,\n jobExecutionId: origin.jobExecutionId,\n originStepId: origin.stepId,\n originStepAttempt: origin.stepAttempt,\n },\n context: failureContext('job', payload.jobId),\n failed: true,\n body: jobFailureBody(payload.statusReason, payload.statusReasonMessage, origin),\n });\n } catch (error) {\n recordFailureAnnotationFailure(error, 'lookup', {jobId: payload.jobId});\n }\n };\n}\n\ntype FailureAnnotationTarget = {\n workspaceId: string;\n projectId: string;\n workflowRunId: string;\n workflowRunAttempt: number;\n workflowRunAttemptId: string;\n jobId: string;\n jobExecutionId: string;\n originStepId: string;\n originStepAttempt: number;\n};\n\n/**\n * Failure annotations are a best-effort projection. The workflow terminal fact is authoritative;\n * projection lookup and writes are swallowed so they cannot change the workflow outcome. Every\n * swallowed error emits a reason-labelled metric and a structured warning for operations.\n */\nasync function writeFailureAnnotation(params: {\n annotations: AnnotationsInterModuleClient;\n target: FailureAnnotationTarget;\n context: string;\n failed: boolean;\n body: string;\n}): Promise<void> {\n try {\n await params.annotations.replaceOrRemoveAnnotation({\n ...params.target,\n context: params.context,\n annotation: params.failed\n ? {op: 'replace', style: 'error', body: params.body}\n : {op: 'remove'},\n });\n } catch (error) {\n const reason = isInterModuleKnownError(\n annotationsInterModuleContract.methods.replaceOrRemoveAnnotation,\n error,\n )\n ? 'budget'\n : 'write';\n recordFailureAnnotationFailure(error, reason, params.target);\n }\n}\n\nfunction failureContext(kind: 'job' | 'step', id: string): string {\n return `failure:${kind}:${id}`;\n}\n\nfunction stepFailureBody(\n name: string,\n error: Record<string, unknown> | null,\n exitCode: number | null,\n): string {\n const reason = typeof error?.reason === 'string' ? error.reason : 'unknown';\n const message =\n typeof error?.message === 'string' && error.message.trim()\n ? error.message\n : 'No failure message was recorded.';\n return [\n `**${name} failed**`,\n '',\n `Reason: \\`${reason}\\``,\n `Exit code: \\`${exitCode ?? 'none'}\\``,\n '',\n message,\n ].join('\\n');\n}\n\nfunction jobFailureBody(\n reason: string | null,\n statusReasonMessage: string | null | undefined,\n origin: {\n stepName: string;\n attemptStatus: string | null;\n stepError: Record<string, unknown> | null;\n attemptError: Record<string, unknown> | null;\n attemptExitCode: number | null;\n },\n): string {\n const progress = origin.attemptStatus\n ? `The job stopped while processing **${origin.stepName}**.`\n : `The job stopped before **${origin.stepName}** started.`;\n const error = origin.attemptError ?? origin.stepError;\n const message = typeof error?.message === 'string' && error.message.trim() ? error.message : null;\n const exitCode =\n origin.attemptExitCode === null ? null : `Exit code: \\`${origin.attemptExitCode}\\``;\n return [\n `**Job failed before completion**`,\n '',\n progress,\n `Reason: \\`${reason ?? 'unknown'}\\``,\n statusReasonMessage ? `Failure: ${statusReasonMessage}` : null,\n message ? `Failure: ${message}` : null,\n exitCode,\n ]\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction recordFailureAnnotationFailure(\n error: unknown,\n reason: 'lookup' | 'budget' | 'write',\n context: Record<string, string | number>,\n): void {\n recordWorkflowFailureAnnotationFailed(reason);\n logger().warn({error, reason, ...context}, 'Failed to project workflow failure annotation');\n}\n"],"names":["annotationsInterModuleContract","isInterModuleKnownError","logger","getJobExecutionFailureOrigin","getJobScope","getStepAttemptDetail","getWorkflowRunAttemptById","recordWorkflowFailureAnnotationFailed","JOB_FAILURE_ANNOTATION_REASONS","Set","onStepAttemptTerminatedFailureAnnotation","annotations","payload","status","undefined","attempt","initialDetail","stepId","detail","step","currentAttempt","id","runAttempt","workflowRunAttemptId","writeFailureAnnotation","target","workspaceId","projectId","workflowRunId","workflowRunAttempt","jobId","jobExecutionId","originStepId","originStepAttempt","context","failureContext","failed","body","stepFailureBody","name","error","exitCode","recordFailureAnnotationFailure","onJobTerminatedFailureAnnotation","isConditionEvaluationFailure","statusReason","has","scope","Promise","all","origin","stepAttempt","jobFailureBody","statusReasonMessage","params","replaceOrRemoveAnnotation","annotation","op","style","reason","methods","kind","message","trim","join","progress","attemptStatus","stepName","attemptError","stepError","attemptExitCode","filter","Boolean","warn"],"mappings":"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"}