Skip to content

feat(ci-traces): failure reasons, runner wait spans, stable step names - #1474

Merged
Makisuo merged 4 commits into
mainfrom
feat/ci-traces-richer
Oct 14, 2026
Merged

Makisuo merged 4 commits into
mainfrom
feat/ci-traces-richer

fix(ci-traces): prefer a located failure, repo URL for a repo named a…

c028fb0
Select commit
Loading
Failed to load commit list.
Maple Review Bot / Maple / review succeeded Oct 14, 2026 in 2m 58s

Confidence 9/10 · No issues found

🟢 Confidence 9/10 · safe to merge
One info-level regex edge case; the wait span, failure reason and repo-URL paths each have a test that pins them.
quality 98/100 · 1 note · tests covered · risk low · 1/1 new units observable

Reads a failed job's GitHub check-run annotations for a failure reason, adds a "Waiting for a runner" child span, and normalizes step names, following the OTel CI/CD span conventions. One narrow step-name edge case; otherwise safe to merge.

  • workflowJobToOtlp sets the job status message from the best annotation
  • A Waiting for a runner child span spans queuedAt to startedAt
  • Run spans are SERVER RUN {workflow}; steps get their own task ids
  • fetchWorkflowJobAnnotations reads check-run annotations, bounded and timed out

Findings

🔵 Note · F4 · ciStepName strips @ + hex runs that are not action pins

correctness · packages/backend/src/services/integrations/ci-traces/otlp.ts:93

The regex removes any @ followed by 7 to 40 hex characters, so a step named Run notify ops@deadbeef.example.com becomes Run notify ops.example.com in both the span name and cicd.pipeline.task.name (verified with node on the head). Requiring whitespace, an opening paren or the end of the name after the pin keeps the intended normalization and spares such names.

const ciStepName = (name: string) => name.replace(/@[0-9a-f]{7,40}(?=[\s(]|$)/g, "")

Fixed since the last review

  • ✅ F3 · repositoryUrlOf returns the wrong repo URL when a path segment is actions

Production impact

Production traffic of the changed files (last 7 days)
File Calls/day Busiest operations
packages/backend/src/services/integrations/vcs/VcsSyncService.ts 7.4k VcsSyncService.processMessage 7.3k/day, 0.0% err
VcsSyncService.handleWorkflowJob 95/day, 0.0% err
Telemetry this change adds and removes (8)
  • ➕ attribute maple.cicd.job.name · packages/backend/src/services/integrations/ci-traces/otlp.ts:270
  • ➕ attribute maple.cicd.annotation.level · packages/backend/src/services/integrations/ci-traces/otlp.ts:312
  • ➕ attribute maple.cicd.annotation.title · packages/backend/src/services/integrations/ci-traces/otlp.ts:313
  • ➕ attribute maple.cicd.annotation.message · packages/backend/src/services/integrations/ci-traces/otlp.ts:314
  • ➕ attribute vcs.workflow.annotations_error · packages/backend/src/services/integrations/vcs/VcsSyncService.ts:916
  • ➕ attribute vcs.workflow.annotation_count · packages/backend/src/services/integrations/vcs/VcsSyncService.ts:921
  • ➕ span name GithubAppClient.listCheckRunAnnotations · packages/backend/src/services/integrations/vcs/vendor/github/GithubAppClient.ts:1877
  • ➕ span name GithubProvider.fetchWorkflowJobAnnotations · packages/backend/src/services/integrations/vcs/vendor/github/GithubProvider.ts:1737
What was checked
  • repositoryUrlOf now cuts at the last /actions/runs/, so octo/actions keeps its full URL (otlp.ts:181, test CiTraceService.test.ts:295)
  • Annotation events cap at 20, failures first (otlp.ts:303), matching the docs text
  • A job that never started gets no wait span and no length: the startedAtMs === completedAtMs guard (otlp.ts:257, test CiTraceService.test.ts:372)
Observability coverage: 1 of 1 changes observable
Change Kind Observable Evidence
GitHub check-run annotations read, one per failed CI job client yes GithubProvider.fetchWorkflowJobAnnotations span with cicd.pipeline.task.run.id (GithubProvider.ts:1737), bounded to 3 pages and a 10s budget annotated on the handler span (VcsSyncService.ts:910)

c028fb0 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

Annotations

Check notice on line 93 in packages/backend/src/services/integrations/ci-traces/otlp.ts

See this annotation in the file changed.

@maple-review-bot maple-review-bot / Maple / review

correctness: `ciStepName` strips `@` + hex runs that are not action pins

The regex removes any `@` followed by 7 to 40 hex characters, so a step named `Run notify ops@deadbeef.example.com` becomes `Run notify ops.example.com` in both the span name and `cicd.pipeline.task.name` (verified with node on the head). Requiring whitespace, an opening paren or the end of the name after the pin keeps the intended normalization and spares such names.